mirror of
https://github.com/dmduran12/pymc_console-dist.git
synced 2026-08-07 09:22:48 +02:00
Release v0.9.194
Automated sync from private repository. Built with obfuscation enabled.
This commit is contained in:
@@ -159,11 +159,11 @@ cd pymc_console
|
||||
sudo bash manage.sh install
|
||||
```
|
||||
|
||||
> **⚠️ Important: Branch Selection**
|
||||
> **Note: Branch Selection**
|
||||
>
|
||||
> During installation, you'll be asked to select a pyMC_Repeater branch. **Select `feat/dmg`** (the default/recommended option). This branch contains the login/authentication functionality required for the dashboard to work properly.
|
||||
> During installation, you'll be asked to select a pyMC_Repeater branch. **Select `dev`** (the default/recommended option). The `dev` branch contains the latest features and improvements.
|
||||
>
|
||||
> If you select `dev` or `main`, you may encounter "error 200" or login issues.
|
||||
|
||||
|
||||
The installer will:
|
||||
1. Install all system dependencies (Python, pip, etc.)
|
||||
@@ -296,7 +296,7 @@ sudo journalctl -u pymc-repeater -f
|
||||
|
||||
### "Error 200" or Login Issues
|
||||
|
||||
This typically means you installed with the wrong pyMC_Repeater branch. The login functionality is only available in the `feat/dmg` branch.
|
||||
This can occur with older installations or mismatched versions.
|
||||
|
||||
**To fix:**
|
||||
```bash
|
||||
@@ -304,9 +304,7 @@ cd pymc_console
|
||||
sudo bash manage.sh upgrade
|
||||
```
|
||||
|
||||
Select **Full pyMC Stack** upgrade and choose the `feat/dmg` branch.
|
||||
|
||||
> **Note:** When entering the branch name, use `feat/dmg` (not just `dmg`).
|
||||
Select **Full pyMC Stack** upgrade to update pyMC_Repeater and pyMC_core to the latest versions.
|
||||
|
||||
### Service won't start
|
||||
|
||||
|
||||
@@ -0,0 +1,600 @@
|
||||
# Cosmograph v2 — AI Agent Reference
|
||||
|
||||
> **Purpose**: This document provides AI coding assistants (Claude, GPT, etc.) with the essential context needed to correctly implement Cosmograph v2 visualizations. It consolidates the v2 API patterns, data requirements, and common pitfalls into a single reference optimized for agent consumption.
|
||||
|
||||
## Quick Context
|
||||
|
||||
**What is Cosmograph?**
|
||||
Cosmograph is a high-performance graph visualization library that uses WebGL and DuckDB-Wasm for rendering large networks. v2 introduced a new data pipeline requiring explicit data preparation.
|
||||
|
||||
**Packages:**
|
||||
- `@cosmograph/cosmograph` — Core library (vanilla JS/TS)
|
||||
- `@cosmograph/react` — React wrapper + Data Kit utilities
|
||||
|
||||
**Key Concept — Data Kit:**
|
||||
Raw data (arrays, CSV, JSON, etc.) must be processed through `prepareCosmographData()` before rendering. This function:
|
||||
1. Converts raw data to Arrow tables (DuckDB-compatible)
|
||||
2. Generates index columns automatically
|
||||
3. Returns a `cosmographConfig` with correct mapping props
|
||||
|
||||
---
|
||||
|
||||
## Critical Pattern: Data Preparation
|
||||
|
||||
### The Golden Rule
|
||||
|
||||
```typescript
|
||||
// ❌ WRONG - Passing raw data directly
|
||||
<Cosmograph points={rawPoints} links={rawLinks} />
|
||||
|
||||
// ✅ CORRECT - Using Data Kit
|
||||
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
|
||||
const { points, links, cosmographConfig } = result;
|
||||
<Cosmograph points={points} links={links} {...cosmographConfig} />
|
||||
```
|
||||
|
||||
### Minimal Data Config
|
||||
|
||||
**Case A: You have a points array with IDs (most common)**
|
||||
```typescript
|
||||
const dataConfig = {
|
||||
points: { pointIdBy: "id" },
|
||||
links: { linkSourceBy: "source", linkTargetsBy: ["target"] },
|
||||
};
|
||||
```
|
||||
|
||||
**Case B: Generate points from links (no separate points array)**
|
||||
```typescript
|
||||
const dataConfig = {
|
||||
points: { linkSourceBy: "source", linkTargetsBy: ["target"] },
|
||||
links: { linkSourceBy: "source", linkTargetsBy: ["target"] },
|
||||
};
|
||||
```
|
||||
|
||||
### What NOT to Include in dataConfig
|
||||
|
||||
**DO NOT manually specify index columns:**
|
||||
- `pointIndexBy` — auto-generated by Data Kit
|
||||
- `linkSourceIndexBy` — auto-generated by Data Kit
|
||||
- `linkTargetsIndexBy` — auto-generated by Data Kit
|
||||
|
||||
These are internal indices that Data Kit computes. Specifying them manually will cause errors.
|
||||
|
||||
---
|
||||
|
||||
## React Integration
|
||||
|
||||
### Complete Working Example
|
||||
|
||||
```tsx
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { Cosmograph, prepareCosmographData } from "@cosmograph/react";
|
||||
import type { CosmographConfig, CosmographData } from "@cosmograph/react";
|
||||
|
||||
export function Graph() {
|
||||
// Raw data - your actual graph data
|
||||
const rawPoints = useMemo(() => [
|
||||
{ id: "a", label: "Node A", color: "#FF0000" },
|
||||
{ id: "b", label: "Node B", color: "#00FF00" },
|
||||
{ id: "c", label: "Node C", color: "#0000FF" },
|
||||
], []);
|
||||
|
||||
const rawLinks = useMemo(() => [
|
||||
{ source: "a", target: "b" },
|
||||
{ source: "b", target: "c" },
|
||||
], []);
|
||||
|
||||
// Prepared data state
|
||||
const [preparedPoints, setPreparedPoints] = useState<CosmographData | null>(null);
|
||||
const [preparedLinks, setPreparedLinks] = useState<CosmographData | null>(null);
|
||||
const [config, setConfig] = useState<CosmographConfig>({});
|
||||
|
||||
// Prepare data on mount or when raw data changes
|
||||
useEffect(() => {
|
||||
const prepare = async () => {
|
||||
const dataConfig = {
|
||||
points: {
|
||||
pointIdBy: "id",
|
||||
pointColorBy: "color", // Optional: map color column
|
||||
pointLabelBy: "label", // Optional: map label column
|
||||
},
|
||||
links: {
|
||||
linkSourceBy: "source",
|
||||
linkTargetsBy: ["target"], // Note: array!
|
||||
linkColorBy: "color", // Optional: if links have colors
|
||||
},
|
||||
};
|
||||
|
||||
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
|
||||
if (!result) return;
|
||||
|
||||
const { points, links, cosmographConfig } = result;
|
||||
setPreparedPoints(points);
|
||||
setPreparedLinks(links);
|
||||
setConfig(cosmographConfig);
|
||||
};
|
||||
|
||||
prepare();
|
||||
}, [rawPoints, rawLinks]);
|
||||
|
||||
// Don't render until data is ready
|
||||
if (!preparedPoints) return <div>Loading...</div>;
|
||||
|
||||
return (
|
||||
<Cosmograph
|
||||
points={preparedPoints}
|
||||
links={preparedLinks}
|
||||
{...config}
|
||||
// Override with your settings (these don't conflict with mapping props)
|
||||
backgroundColor="#1a1a2e"
|
||||
fitViewOnInit={true}
|
||||
showLabels={true}
|
||||
/>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Imperative Access via onMount
|
||||
|
||||
```tsx
|
||||
const [api, setApi] = useState<any>(null);
|
||||
|
||||
<Cosmograph
|
||||
{...config}
|
||||
onMount={(cosmograph) => setApi(cosmograph)}
|
||||
/>
|
||||
|
||||
// Later: call methods imperatively
|
||||
<button onClick={() => api?.fitView(300)}>Fit View</button>
|
||||
<button onClick={() => api?.pause()}>Pause Simulation</button>
|
||||
```
|
||||
|
||||
### Using CosmographProvider + useCosmograph
|
||||
|
||||
```tsx
|
||||
import { CosmographProvider, Cosmograph, useCosmograph } from "@cosmograph/react";
|
||||
|
||||
function Controls() {
|
||||
const { cosmograph } = useCosmograph();
|
||||
return <button onClick={() => cosmograph?.fitView()}>Fit</button>;
|
||||
}
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<CosmographProvider>
|
||||
<Cosmograph {...config} />
|
||||
<Controls />
|
||||
</CosmographProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Vanilla JS/TS Integration
|
||||
|
||||
```typescript
|
||||
import { Cosmograph, prepareCosmographData } from "@cosmograph/cosmograph";
|
||||
|
||||
const container = document.getElementById("graph")!;
|
||||
|
||||
const rawPoints = [{ id: "a" }, { id: "b" }, { id: "c" }];
|
||||
const rawLinks = [{ source: "a", target: "b" }, { source: "b", target: "c" }];
|
||||
|
||||
const dataConfig = {
|
||||
points: { pointIdBy: "id" },
|
||||
links: { linkSourceBy: "source", linkTargetsBy: ["target"] },
|
||||
};
|
||||
|
||||
async function init() {
|
||||
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
|
||||
if (!result) return;
|
||||
|
||||
const { points, links, cosmographConfig } = result;
|
||||
const graph = new Cosmograph(container, { points, links, ...cosmographConfig });
|
||||
|
||||
// Wait for data to load
|
||||
await graph.dataUploaded();
|
||||
|
||||
// Sanity check
|
||||
console.log(graph.stats); // { pointsCount: 3, linksCount: 2, ... }
|
||||
|
||||
// Ensure visible
|
||||
graph.fitView();
|
||||
|
||||
// Cleanup later
|
||||
// await graph.destroy();
|
||||
}
|
||||
|
||||
init();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Data Format Requirements
|
||||
|
||||
### Points Array
|
||||
|
||||
```typescript
|
||||
interface Point {
|
||||
id: string; // Required: unique identifier
|
||||
label?: string; // Optional: display label
|
||||
color?: string; // Optional: hex color (#RRGGBB)
|
||||
size?: number; // Optional: node size
|
||||
x?: number; // Optional: fixed x position
|
||||
y?: number; // Optional: fixed y position
|
||||
[key: string]: any; // Additional columns for tooltips, filtering, etc.
|
||||
}
|
||||
```
|
||||
|
||||
### Links Array
|
||||
|
||||
```typescript
|
||||
interface Link {
|
||||
source: string; // Required: source point ID
|
||||
target: string; // Required: target point ID
|
||||
color?: string; // Optional: hex color
|
||||
width?: number; // Optional: line width (for linkWidthBy)
|
||||
strength?: number; // Optional: physics spring strength (for linkStrengthBy)
|
||||
[key: string]: any; // Additional columns
|
||||
}
|
||||
```
|
||||
|
||||
### Link Width Configuration
|
||||
|
||||
To use custom edge widths based on data (e.g., traffic volume):
|
||||
|
||||
```typescript
|
||||
const dataConfig = {
|
||||
points: { pointIdBy: "id" },
|
||||
links: {
|
||||
linkSourceBy: "source",
|
||||
linkTargetsBy: ["target"],
|
||||
linkColorBy: "color",
|
||||
// Map width column for edge thickness
|
||||
linkWidthBy: "width",
|
||||
// Auto-scale widths to this range (pixels)
|
||||
linkWidthRange: [0.5, 6.0],
|
||||
// Default width for edges without width data
|
||||
linkDefaultWidth: 0.5,
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Width Strategies** (via `linkWidthStrategy`):
|
||||
- `undefined` (default): Auto-select based on data
|
||||
- `"direct"`: Use values from `linkWidthBy` column as-is (1:1 pixel values)
|
||||
- `"sum"`: Sum of values for multi-edges between same nodes
|
||||
- `"average"`: Average of values for multi-edges
|
||||
- `"count"`: Width based on number of links between same nodes
|
||||
|
||||
**Custom Width Function** (for dynamic calculation):
|
||||
|
||||
```typescript
|
||||
const dataConfig = {
|
||||
links: {
|
||||
linkWidthBy: "rawTraffic", // Column with raw values
|
||||
linkWidthByFn: (value: number, index: number) => {
|
||||
// Custom calculation (e.g., logarithmic scaling)
|
||||
return 0.5 + Math.log1p(value) * 0.5;
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### Position Handling (x/y coordinates)
|
||||
|
||||
When you have fixed positions for some or all nodes:
|
||||
|
||||
```typescript
|
||||
const dataConfig = {
|
||||
points: {
|
||||
pointIdBy: "id",
|
||||
pointXBy: "x", // Map x position column
|
||||
pointYBy: "y", // Map y position column
|
||||
},
|
||||
links: { ... },
|
||||
};
|
||||
```
|
||||
|
||||
**Important DuckDB constraint:** If mapping x/y positions, you need **at least 2 points with valid positions**. DuckDB's STDDEV_SAMP function (used internally) requires ≥2 values. If you have fewer, omit `pointXBy`/`pointYBy` from the config.
|
||||
|
||||
---
|
||||
|
||||
## Common Config Props
|
||||
|
||||
### Layout & Simulation
|
||||
|
||||
```typescript
|
||||
{
|
||||
disableSimulation: false, // true = fixed layout, no physics
|
||||
fitViewOnInit: true, // Auto-fit view after data loads
|
||||
fitViewDelay: 300, // Delay before fitView (ms)
|
||||
fitViewPadding: 0.1, // Padding around nodes (0-1)
|
||||
|
||||
// Simulation physics (only when disableSimulation: false)
|
||||
simulationRepulsion: 1.0, // Node repulsion strength
|
||||
simulationLinkSpring: 0.5, // Link spring strength
|
||||
simulationLinkDistance: 50, // Target link length
|
||||
simulationGravity: 0.1, // Pull toward center
|
||||
simulationFriction: 0.85, // Velocity damping
|
||||
simulationAlpha: 1.0, // Initial simulation "heat"
|
||||
simulationAlphaDecay: 0.01, // How fast simulation cools
|
||||
}
|
||||
```
|
||||
|
||||
### Visual Styling
|
||||
|
||||
```typescript
|
||||
{
|
||||
backgroundColor: "#1a1a2e",
|
||||
|
||||
// Points
|
||||
pointDefaultSize: 10,
|
||||
pointDefaultColor: "#666666",
|
||||
pointGreyoutOpacity: 0.3, // Opacity when not selected
|
||||
|
||||
// Links
|
||||
linkDefaultWidth: 1,
|
||||
linkDefaultColor: "#444444",
|
||||
linkGreyoutOpacity: 0.3,
|
||||
|
||||
// Labels
|
||||
showLabels: true,
|
||||
showDynamicLabels: true, // Show labels on zoom
|
||||
showTopLabels: true, // Always show top N labels
|
||||
showTopLabelsLimit: 50,
|
||||
showHoveredPointLabel: true,
|
||||
pointLabelColor: "#ffffff",
|
||||
pointLabelFontSize: 12,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cosmograph Class API (Imperative Methods)
|
||||
|
||||
### Lifecycle
|
||||
|
||||
```typescript
|
||||
await cosmograph.dataUploaded() // Wait for async data to load
|
||||
await cosmograph.destroy() // Cleanup (important!)
|
||||
cosmograph.stats // { pointsCount, linksCount, ... }
|
||||
```
|
||||
|
||||
### View Control
|
||||
|
||||
```typescript
|
||||
cosmograph.fitView(duration?) // Fit all nodes in view
|
||||
cosmograph.fitViewByIndices(indices, duration?) // Fit specific nodes
|
||||
cosmograph.setZoomLevel(level, duration?) // Set zoom (1 = default)
|
||||
cosmograph.zoomToPoint(index, duration?, scale?) // Zoom to specific node
|
||||
```
|
||||
|
||||
### Simulation Control
|
||||
|
||||
```typescript
|
||||
cosmograph.isSimulationAvailable // Check if simulation is possible
|
||||
cosmograph.isSimulationRunning // Check if currently running
|
||||
cosmograph.start(alpha?) // Start simulation
|
||||
cosmograph.pause() // Pause simulation
|
||||
cosmograph.unpause() // Resume simulation
|
||||
cosmograph.stop() // Stop simulation
|
||||
```
|
||||
|
||||
### Selection
|
||||
|
||||
```typescript
|
||||
// Activate selection modes
|
||||
cosmograph.activateRectSelection()
|
||||
cosmograph.activatePolygonalSelection()
|
||||
cosmograph.deactivateRectSelection()
|
||||
|
||||
// Programmatic selection
|
||||
cosmograph.selectPoint(index, addToSelection?)
|
||||
cosmograph.selectPoints(indices, addToSelection?)
|
||||
cosmograph.selectPointsInRect(rect, addToSelection?)
|
||||
cosmograph.unselectAllPoints()
|
||||
|
||||
// Read selection
|
||||
cosmograph.getSelectedPointIndices() // number[] | undefined
|
||||
```
|
||||
|
||||
### ID ↔ Index Conversion
|
||||
|
||||
```typescript
|
||||
// Point ID = your data's identifier (string)
|
||||
// Point Index = Cosmograph's internal array index (number)
|
||||
|
||||
await cosmograph.getPointIndicesByIds(["node-a", "node-b"]) // [0, 1]
|
||||
await cosmograph.getPointIdsByIndices([0, 1]) // ["node-a", "node-b"]
|
||||
```
|
||||
|
||||
### Dynamic Data Updates
|
||||
|
||||
```typescript
|
||||
await cosmograph.addPoints([{ id: "new", label: "New Node" }])
|
||||
await cosmograph.addLinks([{ source: "a", target: "new" }])
|
||||
await cosmograph.removePointsByIds(["node-to-remove"])
|
||||
await cosmograph.removeLinksByPointIdPairs([["a", "b"]])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Blank Canvas / Nothing Renders
|
||||
|
||||
1. **Data not loaded:**
|
||||
```typescript
|
||||
await cosmograph.dataUploaded();
|
||||
console.log(cosmograph.stats); // Should show non-zero counts
|
||||
```
|
||||
|
||||
2. **Nodes off-screen:**
|
||||
```typescript
|
||||
cosmograph.fitView();
|
||||
```
|
||||
|
||||
3. **Config not spread correctly:**
|
||||
```typescript
|
||||
// ❌ Wrong
|
||||
<Cosmograph config={cosmographConfig} />
|
||||
|
||||
// ✅ Correct
|
||||
<Cosmograph {...cosmographConfig} points={points} links={links} />
|
||||
```
|
||||
|
||||
### "STDDEV_SAMP is out of range" Error
|
||||
|
||||
This DuckDB error occurs when computing statistics on columns with insufficient variance:
|
||||
1. Column has fewer than 2 values
|
||||
2. **All values are identical (variance = 0)** ← Common gotcha!
|
||||
|
||||
**Cause:** Mapping numeric columns (x, y, size, width, etc.) when there isn't enough variance.
|
||||
|
||||
**Fix for positions:** Check for actual variance in BOTH x AND y coordinates:
|
||||
```typescript
|
||||
// Filter to points with valid position data
|
||||
const pointsWithPos = rawPoints.filter(
|
||||
(p): p is typeof p & { x: number; y: number } =>
|
||||
'x' in p && 'y' in p && typeof p.x === 'number' && typeof p.y === 'number'
|
||||
);
|
||||
const positionCount = pointsWithPos.length;
|
||||
|
||||
// IMPORTANT: Check variance, not just count!
|
||||
// Nodes clustered at identical coordinates will still fail with positionCount >= 2
|
||||
const uniqueX = new Set(pointsWithPos.map(p => p.x));
|
||||
const uniqueY = new Set(pointsWithPos.map(p => p.y));
|
||||
const hasVaryingPositions = positionCount >= 2 && uniqueX.size >= 2 && uniqueY.size >= 2;
|
||||
|
||||
const dataConfig = {
|
||||
points: {
|
||||
pointIdBy: "id",
|
||||
// Only map positions when BOTH x and y have variance
|
||||
...(hasVaryingPositions ? { pointXBy: "x", pointYBy: "y" } : {}),
|
||||
},
|
||||
links: { ... },
|
||||
};
|
||||
```
|
||||
|
||||
**Fix for link widths:** Only include `linkWidthBy` when ≥2 links have varying widths:
|
||||
```typescript
|
||||
const linkWidths = rawLinks.map(l => l.width).filter((w): w is number => w != null);
|
||||
const uniqueWidths = new Set(linkWidths);
|
||||
const hasVaryingWidths = linkWidths.length >= 2 && uniqueWidths.size >= 2;
|
||||
|
||||
const dataConfig = {
|
||||
points: { ... },
|
||||
links: {
|
||||
linkSourceBy: "source",
|
||||
linkTargetsBy: ["target"],
|
||||
linkColorBy: "color", // String columns are safe - no STDDEV
|
||||
// Only map width when we have variance
|
||||
...(hasVaryingWidths ? {
|
||||
linkWidthBy: "width",
|
||||
linkWidthRange: [0.5, 6.0],
|
||||
} : {}),
|
||||
linkDefaultWidth: 0.5, // Fallback when no width mapping
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
**Why this happens:** DuckDB's `STDDEV_SAMP` function computes sample standard deviation, which requires variance in the data. When all values are identical (e.g., nodes at same GPS coordinates), the variance is 0, causing the "out of range" error. The count check alone is insufficient.
|
||||
|
||||
### "Missing required properties: pointIdBy" Error
|
||||
|
||||
**Cause:** Passing raw data without going through Data Kit.
|
||||
|
||||
**Fix:** Always use `prepareCosmographData()`:
|
||||
```typescript
|
||||
const result = await prepareCosmographData(dataConfig, rawPoints, rawLinks);
|
||||
// result.cosmographConfig contains the required mapping props
|
||||
```
|
||||
|
||||
### Simulation Not Working
|
||||
|
||||
```typescript
|
||||
// Check if simulation is even possible
|
||||
console.log(cosmograph.isSimulationAvailable); // Should be true
|
||||
|
||||
// If false, check:
|
||||
// - disableSimulation: true in config?
|
||||
// - No links in data?
|
||||
// - Fixed positions for all nodes?
|
||||
|
||||
// If true but not running:
|
||||
cosmograph.start(); // or cosmograph.unpause();
|
||||
```
|
||||
|
||||
### Wrong Node Selected (ID vs Index Confusion)
|
||||
|
||||
**Symptom:** Clicking node "A" selects node "B"
|
||||
|
||||
**Cause:** Confusing user IDs with internal indices.
|
||||
|
||||
```typescript
|
||||
// Your data uses string IDs
|
||||
const nodeId = "my-node-a";
|
||||
|
||||
// Cosmograph uses numeric indices internally
|
||||
const index = await cosmograph.getPointIndicesByIds([nodeId]);
|
||||
cosmograph.selectPoint(index[0]);
|
||||
|
||||
// Or convert back
|
||||
const ids = await cosmograph.getPointIdsByIndices([selectedIndex]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## External DuckDB Tables (Advanced)
|
||||
|
||||
When loading pre-existing DuckDB-Wasm tables (not using Data Kit):
|
||||
|
||||
```typescript
|
||||
<Cosmograph
|
||||
duckDBConnection={{ duckdb: db, connection }}
|
||||
points="my_points_table"
|
||||
links="my_links_table"
|
||||
// You MUST specify all mapping columns manually:
|
||||
pointIdBy="id"
|
||||
pointIndexBy="idx" // Your table must have this column
|
||||
linkSourceBy="source"
|
||||
linkSourceIndexBy="source_idx"
|
||||
linkTargetsBy={["target"]}
|
||||
linkTargetsIndexBy={["target_idx"]}
|
||||
/>
|
||||
```
|
||||
|
||||
**Required table columns for external loading:**
|
||||
- Points: `id` (string), `idx` (integer index)
|
||||
- Links: `source` (string), `source_idx` (integer), `target` (string), `target_idx` (integer)
|
||||
|
||||
---
|
||||
|
||||
## Checklist for Implementation
|
||||
|
||||
When implementing Cosmograph v2:
|
||||
|
||||
- [ ] Install `@cosmograph/react` (or `@cosmograph/cosmograph` for vanilla)
|
||||
- [ ] Create raw points array with unique `id` field
|
||||
- [ ] Create raw links array with `source` and `target` string fields
|
||||
- [ ] Define `dataConfig` with `pointIdBy: "id"` and `linkSourceBy/linkTargetsBy`
|
||||
- [ ] Call `prepareCosmographData(dataConfig, rawPoints, rawLinks)`
|
||||
- [ ] Extract `{ points, links, cosmographConfig }` from result
|
||||
- [ ] Pass to Cosmograph: `<Cosmograph points={points} links={links} {...cosmographConfig} />`
|
||||
- [ ] Add visual overrides (backgroundColor, showLabels, etc.) AFTER spreading config
|
||||
- [ ] Handle loading state (don't render until `preparedPoints` exists)
|
||||
- [ ] Call `fitView()` if nodes appear off-screen
|
||||
- [ ] Call `destroy()` on cleanup if using imperative API
|
||||
|
||||
---
|
||||
|
||||
## Version Notes
|
||||
|
||||
This document covers **Cosmograph v2**. Key differences from v1:
|
||||
- Data Kit is required (no direct raw data passing)
|
||||
- DuckDB-Wasm is used internally for data processing
|
||||
- Index columns are auto-generated (don't specify manually)
|
||||
- Arrow tables are the internal format
|
||||
- `linkTargetsBy` is an array (supports multi-target edges)
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
0.9.193
|
||||
0.9.194
|
||||
|
||||
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{i as t,bR as e,r}from"./vendor-react-LAbPDfrQ.js";const a="pymc-basemap-mode",o="dark";function s(){if("undefined"==typeof window)return o;try{const t=localStorage.getItem(a);if("light"===t||"dark"===t)return t}catch{}return o}function n(t){if("undefined"!=typeof window)try{localStorage.setItem(a,t)}catch{}}const c=t(t=>({mode:s(),toggle:()=>t(t=>{const e="light"===t.mode?"dark":"light";return n(e),{mode:e}}),setMode:e=>{n(e),t({mode:e})}})),i=()=>c(t=>t.mode),l=()=>c(t=>t.toggle),u={light:"https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",dark:"https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"},d={light:"basemap-light-",dark:"basemap-dark-"},f={};function y({mode:t}){const{current:a}=e(),[o,s]=r.useState(null),n=r.useRef({light:!1,dark:!1}),c=r.useRef({light:[],dark:[]});r.useEffect(()=>{const t=()=>{var t;const e=null==(t=null==a?void 0:a.getMap)?void 0:t.call(a);e&&!o&&s(e)};t();const e=setInterval(t,50),r=setTimeout(()=>clearInterval(e),5e3);return()=>{clearInterval(e),clearTimeout(r)}},[a,o]);const i=r.useCallback(async(t,e,r)=>{var a,o;if(n.current[e])return;const s=d[e],i=await async function(t){if(f[t])return f[t];const e=await fetch(u[t]),r=await e.json();return f[t]=r,r}(e),l=[];for(const[n,c]of Object.entries(i.sources||{})){const e=s+n;t.getSource(e)||t.addSource(e,c)}const y=null==(o=((null==(a=t.getStyle())?void 0:a.layers)||[]).find(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-")))?void 0:o.id;for(const n of i.layers||[]){const e=s+n.id;if(l.push(e),t.getLayer(e))continue;const a={...n,id:e};"source"in a&&"string"==typeof a.source&&(a.source=s+a.source),a.layout||(a.layout={}),a.layout.visibility=r?"visible":"none";try{t.addLayer(a,y)}catch(g){}}c.current[e]=l,n.current[e]=!0},[]),l=r.useCallback((t,e,r)=>{const a=c.current[e],o=r?"visible":"none";for(const s of a)if(t.getLayer(s))try{t.setLayoutProperty(s,"visibility",o)}catch{}},[]),y=r.useCallback(t=>{var e;const r=((null==(e=t.getStyle())?void 0:e.layers)||[]).filter(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-"));for(const a of r)try{t.moveLayer(a.id)}catch{}},[]);return r.useEffect(()=>{if(!o)return;let e=!1;const r=async()=>{if(!e)try{await Promise.all([i(o,"light","light"===t),i(o,"dark","dark"===t)]),e||y(o)}catch(r){}};o.isStyleLoaded()?r():(o.once("style.load",r),o.once("load",()=>{e||n.current.light||r()}));const a=()=>{e||setTimeout(()=>{!e&&n.current.light&&n.current.dark&&y(o)},100)};return o.on("styledata",a),()=>{e=!0,o.off("styledata",a)}},[o,i,y,t]),r.useEffect(()=>{o&&n.current.light&&n.current.dark&&(l(o,"light","light"===t),l(o,"dark","dark"===t))},[o,t,l]),null}export{y as B,l as a,i as u};
|
||||
import{i as t,bO as e,r}from"./vendor-react-C341c8YC.js";const a="pymc-basemap-mode",o="dark";function s(){if("undefined"==typeof window)return o;try{const t=localStorage.getItem(a);if("light"===t||"dark"===t)return t}catch{}return o}function n(t){if("undefined"!=typeof window)try{localStorage.setItem(a,t)}catch{}}const c=t(t=>({mode:s(),toggle:()=>t(t=>{const e="light"===t.mode?"dark":"light";return n(e),{mode:e}}),setMode:e=>{n(e),t({mode:e})}})),i=()=>c(t=>t.mode),l=()=>c(t=>t.toggle),u={light:"https://basemaps.cartocdn.com/gl/positron-gl-style/style.json",dark:"https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"},d={light:"basemap-light-",dark:"basemap-dark-"},f={};function y({mode:t}){const{current:a}=e(),[o,s]=r.useState(null),n=r.useRef({light:!1,dark:!1}),c=r.useRef({light:[],dark:[]});r.useEffect(()=>{const t=()=>{var t;const e=null==(t=null==a?void 0:a.getMap)?void 0:t.call(a);e&&!o&&s(e)};t();const e=setInterval(t,50),r=setTimeout(()=>clearInterval(e),5e3);return()=>{clearInterval(e),clearTimeout(r)}},[a,o]);const i=r.useCallback(async(t,e,r)=>{var a,o;if(n.current[e])return;const s=d[e],i=await async function(t){if(f[t])return f[t];const e=await fetch(u[t]),r=await e.json();return f[t]=r,r}(e),l=[];for(const[n,c]of Object.entries(i.sources||{})){const e=s+n;t.getSource(e)||t.addSource(e,c)}const y=null==(o=((null==(a=t.getStyle())?void 0:a.layers)||[]).find(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-")))?void 0:o.id;for(const n of i.layers||[]){const e=s+n.id;if(l.push(e),t.getLayer(e))continue;const a={...n,id:e};"source"in a&&"string"==typeof a.source&&(a.source=s+a.source),a.layout||(a.layout={}),a.layout.visibility=r?"visible":"none";try{t.addLayer(a,y)}catch(g){}}c.current[e]=l,n.current[e]=!0},[]),l=r.useCallback((t,e,r)=>{const a=c.current[e],o=r?"visible":"none";for(const s of a)if(t.getLayer(s))try{t.setLayoutProperty(s,"visibility",o)}catch{}},[]),y=r.useCallback(t=>{var e;const r=((null==(e=t.getStyle())?void 0:e.layers)||[]).filter(t=>!t.id.startsWith("basemap-light-")&&!t.id.startsWith("basemap-dark-"));for(const a of r)try{t.moveLayer(a.id)}catch{}},[]);return r.useEffect(()=>{if(!o)return;let e=!1;const r=async()=>{if(!e)try{await Promise.all([i(o,"light","light"===t),i(o,"dark","dark"===t)]),e||y(o)}catch(r){}};o.isStyleLoaded()?r():(o.once("style.load",r),o.once("load",()=>{e||n.current.light||r()}));const a=()=>{e||setTimeout(()=>{!e&&n.current.light&&n.current.dark&&y(o)},100)};return o.on("styledata",a),()=>{e=!0,o.off("styledata",a)}},[o,i,y,t]),r.useEffect(()=>{o&&n.current.light&&n.current.dark&&(l(o,"light","light"===t),l(o,"dark","dark"===t))},[o,t,l]),null}export{y as B,l as a,i as u};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{j as e}from"./vendor-react-LAbPDfrQ.js";import{c as s}from"./recharts-D38YBQhj.js";import{B as t}from"./index-UmM6aLcb.js";function l({title:l,icon:r,badge:i,subtitle:a,actions:c,iconColor:n="text-icon-card-title",largeTitle:x=!1,listHeader:m=!1,stackActionsOnMobile:d=!1}){return d&&c?e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]}):e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),c&&e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]})}function r({children:t,centered:l,className:r}){return e.jsx("div",{className:s("flex-1 min-h-0",l&&"flex items-center justify-center",r),children:t})}export{l as C,r as a};
|
||||
import{j as e}from"./vendor-react-C341c8YC.js";import{n as s}from"./recharts-6XUQYgRA.js";import{B as t}from"./index-CPdqYR4z.js";function l({title:l,icon:r,badge:i,subtitle:a,actions:c,iconColor:n="text-icon-card-title",largeTitle:x=!1,listHeader:m=!1,stackActionsOnMobile:d=!1}){return d&&c?e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]}):e.jsxs("div",{className:s("flex flex-col gap-1 flex-shrink-0",m?"px-4 py-3 border-b border-border-subtle bg-bg-elevated/20":"mb-3"),children:[e.jsxs("div",{className:"flex items-center justify-between gap-2 min-h-[32px]",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[r&&e.jsx("span",{className:s("icon-md flex items-center justify-center",n),children:r}),e.jsx("span",{className:s(x?"type-subheading text-text-primary":"type-micro"),children:l}),i&&e.jsx(t,{color:"teal",children:i})]}),c&&e.jsx("div",{className:"flex items-center gap-2 flex-wrap",children:c})]}),a&&e.jsx("p",{className:"type-label text-text-muted ml-8",children:a})]})}function r({children:t,centered:l,className:r}){return e.jsx("div",{className:s("flex-1 min-h-0",l&&"flex items-center justify-center",r),children:t})}export{l as C,r as a};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
@@ -1 +1 @@
|
||||
import{r as e,j as t,as as n}from"./vendor-react-LAbPDfrQ.js";import{c as s}from"./recharts-D38YBQhj.js";import{K as r,aF as o,M as a,aG as c}from"./index-UmM6aLcb.js";const i={danger:{icon:"text-accent-danger",button:"bg-accent-danger hover:brightness-110 active:brightness-90"},warning:{icon:"text-accent-secondary",button:"bg-accent-secondary hover:brightness-110 active:brightness-90 text-bg-body"},default:{icon:"text-accent-primary",button:"bg-accent-primary hover:brightness-110 active:brightness-90 text-bg-body"}},l=e.memo(function({isOpen:e,title:l="Confirm",message:b,confirmLabel:d="Confirm",cancelLabel:m="Cancel",variant:x="default",onConfirm:g,onCancel:h}){const u=i[x];return t.jsxs(r,{open:e,onClose:h,size:"sm",children:[t.jsx(o,{icon:t.jsx(n,{className:s("w-5 h-5",u.icon)}),title:l,onClose:h}),t.jsx(a,{children:t.jsx("p",{className:"text-sm text-text-secondary",children:b})}),t.jsxs(c,{children:[t.jsx("button",{onClick:h,className:"flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-secondary bg-bg-subtle hover:bg-bg-elevated border border-border-subtle transition-colors",children:m}),t.jsx("button",{onClick:g,className:s("flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-primary transition-colors",u.button),children:d})]})]})});export{l as C};
|
||||
import{r as e,j as t,at as n}from"./vendor-react-C341c8YC.js";import{n as s}from"./recharts-6XUQYgRA.js";import{N as r,aL as o,O as a,aM as c}from"./index-CPdqYR4z.js";const i={danger:{icon:"text-accent-danger",button:"bg-accent-danger hover:brightness-110 active:brightness-90"},warning:{icon:"text-accent-secondary",button:"bg-accent-secondary hover:brightness-110 active:brightness-90 text-bg-body"},default:{icon:"text-accent-primary",button:"bg-accent-primary hover:brightness-110 active:brightness-90 text-bg-body"}},l=e.memo(function({isOpen:e,title:l="Confirm",message:b,confirmLabel:d="Confirm",cancelLabel:m="Cancel",variant:x="default",onConfirm:g,onCancel:h}){const u=i[x];return t.jsxs(r,{open:e,onClose:h,size:"sm",children:[t.jsx(o,{icon:t.jsx(n,{className:s("w-5 h-5",u.icon)}),title:l,onClose:h}),t.jsx(a,{children:t.jsx("p",{className:"text-sm text-text-secondary",children:b})}),t.jsxs(c,{children:[t.jsx("button",{onClick:h,className:"flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-secondary bg-bg-subtle hover:bg-bg-elevated border border-border-subtle transition-colors",children:m}),t.jsx("button",{onClick:g,className:s("flex-1 px-4 py-2.5 rounded-lg text-sm font-medium text-text-primary transition-colors",u.button),children:d})]})]})});export{l as C};
|
||||
+2
File diff suppressed because one or more lines are too long
-2
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
@@ -0,0 +1 @@
|
||||
import{r as e,j as t,$ as o,a0 as n}from"./vendor-react-C341c8YC.js";import{n as a}from"./recharts-6XUQYgRA.js";const s={standard:"w-3 h-3",compact:"w-2.5 h-2.5",responsive:"w-2.5 h-2.5 sm:w-3 sm:h-3"};function c({children:c,copyValue:r,copy:i=!1,size:l="standard",className:p,title:u,color:d,truncate:m}){const[h,x]=e.useState(!1),[w,y]=e.useState(!1),f=e.useRef(null),v=r??("string"==typeof c?c:""),b=s[l],g=(()=>{if(!m||"string"!=typeof c)return c;const e=c,[t,o]=!0===m?[6,4]:m;return e.length<=t+o+3?e:`${e.slice(0,t)}…${e.slice(-o)}`})(),j=e.useCallback(e=>{i&&(e.preventDefault(),e.stopPropagation(),f.current&&clearTimeout(f.current),function(e){var t;if("undefined"!=typeof window&&(window.isSecureContext||"https:"===window.location.protocol||"localhost"===window.location.hostname)&&(null==(t=navigator.clipboard)?void 0:t.writeText))return navigator.clipboard.writeText(e).catch(()=>{}),!0;try{const{scrollX:t,scrollY:o}=window,n=document.createElement("textarea");n.value=e,n.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0;pointer-events:none",n.setAttribute("readonly",""),document.body.appendChild(n),n.focus({preventScroll:!0}),n.select(),n.setSelectionRange(0,e.length);const a=document.execCommand("copy");return document.body.removeChild(n),window.scrollTo(t,o),a}catch(o){return!1}}(v),x(!0),f.current=setTimeout(()=>x(!1),2e3))},[i,v]),C="compact"===l?"data-box-compact":"responsive"===l?"data-box-responsive":"",N=i?u||`Click to copy: ${v}`:u;return i?t.jsxs("button",{type:"button",onClick:j,onMouseEnter:()=>y(!0),onMouseLeave:()=>y(!1),className:a("data-box",C,"cursor-pointer select-none gap-1","hover:bg-white/[0.08] hover:border-white/[0.12]","transition-all duration-200",d,p),title:N,"aria-label":`Copy ${v}`,children:[t.jsx("span",{className:a("transition-colors duration-200",h?"text-accent-success":""),children:g}),t.jsx("span",{className:a("flex items-center justify-center","compact"===l?"w-3 h-3":"w-3.5 h-3.5"),children:h?t.jsx(o,{className:a("text-accent-success",b)}):t.jsx(n,{className:a("transition-opacity duration-200",w?"opacity-70":"opacity-40",b)})})]}):t.jsx("span",{className:a("data-box",C,d,p),title:N,children:g})}export{c as D};
|
||||
-1
@@ -1 +0,0 @@
|
||||
import{r as e,j as t,ag as o,ai as n}from"./vendor-react-LAbPDfrQ.js";import{c as a}from"./recharts-D38YBQhj.js";const s={standard:"w-3 h-3",compact:"w-2.5 h-2.5",responsive:"w-2.5 h-2.5 sm:w-3 sm:h-3"};function c({children:c,copyValue:r,copy:i=!1,size:l="standard",className:p,title:u,color:d,truncate:m}){const[h,x]=e.useState(!1),[w,y]=e.useState(!1),f=e.useRef(null),v=r??("string"==typeof c?c:""),b=s[l],g=(()=>{if(!m||"string"!=typeof c)return c;const e=c,[t,o]=!0===m?[6,4]:m;return e.length<=t+o+3?e:`${e.slice(0,t)}…${e.slice(-o)}`})(),j=e.useCallback(e=>{i&&(e.preventDefault(),e.stopPropagation(),f.current&&clearTimeout(f.current),function(e){var t;if("undefined"!=typeof window&&(window.isSecureContext||"https:"===window.location.protocol||"localhost"===window.location.hostname)&&(null==(t=navigator.clipboard)?void 0:t.writeText))return navigator.clipboard.writeText(e).catch(()=>{}),!0;try{const{scrollX:t,scrollY:o}=window,n=document.createElement("textarea");n.value=e,n.style.cssText="position:fixed;left:-9999px;top:-9999px;opacity:0;pointer-events:none",n.setAttribute("readonly",""),document.body.appendChild(n),n.focus({preventScroll:!0}),n.select(),n.setSelectionRange(0,e.length);const a=document.execCommand("copy");return document.body.removeChild(n),window.scrollTo(t,o),a}catch(o){return!1}}(v),x(!0),f.current=setTimeout(()=>x(!1),2e3))},[i,v]),C="compact"===l?"data-box-compact":"responsive"===l?"data-box-responsive":"",N=i?u||`Click to copy: ${v}`:u;return i?t.jsxs("button",{type:"button",onClick:j,onMouseEnter:()=>y(!0),onMouseLeave:()=>y(!1),className:a("data-box",C,"cursor-pointer select-none gap-1","hover:bg-white/[0.08] hover:border-white/[0.12]","transition-all duration-200",d,p),title:N,"aria-label":`Copy ${v}`,children:[t.jsx("span",{className:a("transition-colors duration-200",h?"text-accent-success":""),children:g}),t.jsx("span",{className:a("flex items-center justify-center","compact"===l?"w-3 h-3":"w-3.5 h-3.5"),children:h?t.jsx(o,{className:a("text-accent-success",b)}):t.jsx(n,{className:a("transition-opacity duration-200",w?"opacity-70":"opacity-40",b)})})]}):t.jsx("span",{className:a("data-box",C,d,p),title:N,children:g})}export{c as D};
|
||||
@@ -0,0 +1 @@
|
||||
import{r as e,j as t,m as s,$ as a,aJ as i,bW as n,aA as c,q as l,aq as r}from"./vendor-react-C341c8YC.js";import{n as m}from"./recharts-6XUQYgRA.js";import{N as d,aS as x,O as o,aT as p}from"./index-CPdqYR4z.js";function h({label:e,icon:s,status:i,detail:n}){return t.jsxs("div",{className:m("flex items-center gap-3 py-3 px-4 rounded-xl transition-all duration-300","active"===i&&"bg-accent-primary/10","complete"===i&&"bg-accent-primary/10 ring-2 ring-inset ring-accent-primary","pending"===i&&"opacity-40"),children:[t.jsx("div",{className:m("w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 transition-all duration-300","active"===i&&"bg-accent-primary/20","complete"===i&&"bg-accent-primary/20","pending"===i&&"bg-subtle-fill"),children:"complete"===i?t.jsx(a,{className:"w-4 h-4 text-accent-primary"}):"active"===i?t.jsx(r,{className:"w-4 h-4 animate-spin text-accent-primary"}):t.jsx("span",{className:"text-text-muted",children:s})}),t.jsxs("div",{className:"flex-1 min-w-0",children:[t.jsx("div",{className:m("text-sm font-medium transition-colors","active"===i&&"text-accent-primary","complete"===i&&"text-accent-primary","pending"===i&&"text-text-muted"),children:e}),n&&"pending"!==i&&t.jsx("div",{className:"text-xs text-text-muted mt-0.5 truncate",children:n})]})]})}const g=e.memo(function({isOpen:e,currentStep:r,packetCount:m,onClose:g}){const j="complete"===r,u=e=>{const t=["fetching","analyzing","building","discovering","complete"],s=t.indexOf(r),a=t.indexOf(e);return a<s?"complete":a===s?"active":"pending"},y=g??(()=>{});return t.jsx(d,{open:e,onClose:y,size:"sm",bottomSheet:!1,children:t.jsx(x,{isLoading:!j,borderRadius:16,children:t.jsx(o,{className:"p-6",children:j?t.jsxs("div",{className:"flex flex-col items-center py-6",children:[t.jsx(s.div,{variants:p,initial:"hidden",animate:"visible",className:"w-16 h-16 rounded-full flex items-center justify-center mb-4 bg-accent-primary/20",children:t.jsx(a,{className:"w-8 h-8 text-accent-primary"})}),t.jsx("h3",{className:"text-lg font-semibold text-accent-primary",children:"Ready!"})]}):t.jsxs(t.Fragment,{children:[t.jsxs("div",{className:"flex items-center gap-3 mb-5",children:[t.jsx("div",{className:"w-10 h-10 rounded-xl flex items-center justify-center bg-accent-primary/15",children:t.jsx(i,{className:"w-5 h-5 text-accent-primary"})}),t.jsxs("div",{children:[t.jsx("h3",{className:"text-base font-semibold text-text-primary",children:"Deep Analysis"}),t.jsx("p",{className:"text-xs text-text-muted",children:"Building mesh topology"})]})]}),t.jsxs("div",{className:"space-y-2",children:[t.jsx(h,{label:"Fetching Packets",icon:t.jsx(n,{className:"w-4 h-4"}),status:u("fetching"),detail:m>0?`${m.toLocaleString()} packets`:"Loading database..."}),t.jsx(h,{label:"Analyzing Database",icon:t.jsx(c,{className:"w-4 h-4"}),status:u("analyzing"),detail:"Processing packet paths"}),t.jsx(h,{label:"Building Topology",icon:t.jsx(i,{className:"w-4 h-4"}),status:u("building"),detail:"Computing mesh edges"}),t.jsx(h,{label:"Discovering Nodes",icon:t.jsx(l,{className:"w-4 h-4"}),status:u("discovering"),detail:"Viterbi HMM ghost detection"})]}),t.jsx("p",{className:"text-xs text-text-muted text-center mt-5",children:"This may take a few seconds..."})]})})})})});export{g as D};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{r as o,j as e}from"./vendor-react-LAbPDfrQ.js";import{c as t}from"./recharts-D38YBQhj.js";const l={hero:{mobile:12},"hero-tall":{mobile:12},"hero-auto":{mobile:12},panel:{mobile:12,md:6},feature:{mobile:12,md:6,lg:4},standard:{mobile:12,sm:6,lg:4,xl:3},compact:{mobile:6,lg:3},widget:{mobile:6,sm:4,md:3,lg:2},auto:{mobile:12}},a={hero:"bento-row-hero","hero-tall":"bento-row-hero-tall","hero-auto":"bento-row-hero-auto",panel:"bento-row-panel",feature:"bento-row-feature",standard:"bento-row-standard",compact:"bento-row-compact",widget:"bento-row-widget",auto:"bento-row-auto"};function n({template:n,children:r,className:s,gap:c}){const i=l[n],b=a[n],d="none"===c?"gap-0":"sm"===c?"bento-gap-sm":"lg"===c?"bento-gap-lg":"bento-gap",p=o.Children.map(r,t=>o.isValidElement(t)?t.type===m?t:e.jsx(m,{span:i.mobile,sm:i.sm,md:i.md,lg:i.lg,xl:i.xl,children:t}):t);return e.jsx("div",{className:t("bento-row",b,d,s),children:p})}function r(o,e=""){const t=e?`${e}:`:"";return"full"===o?`${t}col-span-full`:"auto"===o?`${t}col-auto`:1.5===o?`${t}bento-col-1-5`:`${t}bento-col-${o}`}function m({children:o,span:l,sm:a,md:n,lg:m,xl:s,className:c}){const i=t("bento-cell",r(l),a&&r(a,"sm"),n&&r(n,"md"),m&&r(m,"lg"),s&&r(s,"xl"),c);return e.jsx("div",{className:i,children:o})}export{m as C,n as R};
|
||||
import{r as o,j as e}from"./vendor-react-C341c8YC.js";import{n as t}from"./recharts-6XUQYgRA.js";const l={hero:{mobile:12},"hero-tall":{mobile:12},"hero-auto":{mobile:12},panel:{mobile:12,md:6},feature:{mobile:12,md:6,lg:4},standard:{mobile:12,sm:6,lg:4,xl:3},compact:{mobile:6,lg:3},widget:{mobile:6,sm:4,md:3,lg:2},auto:{mobile:12}},a={hero:"bento-row-hero","hero-tall":"bento-row-hero-tall","hero-auto":"bento-row-hero-auto",panel:"bento-row-panel",feature:"bento-row-feature",standard:"bento-row-standard",compact:"bento-row-compact",widget:"bento-row-widget",auto:"bento-row-auto"};function n({template:n,children:r,className:s,gap:c}){const i=l[n],b=a[n],d="none"===c?"gap-0":"sm"===c?"bento-gap-sm":"lg"===c?"bento-gap-lg":"bento-gap",p=o.Children.map(r,t=>o.isValidElement(t)?t.type===m?t:e.jsx(m,{span:i.mobile,sm:i.sm,md:i.md,lg:i.lg,xl:i.xl,children:t}):t);return e.jsx("div",{className:t("bento-row",b,d,s),children:p})}function r(o,e=""){const t=e?`${e}:`:"";return"full"===o?`${t}col-span-full`:"auto"===o?`${t}col-auto`:1.5===o?`${t}bento-col-1-5`:`${t}bento-col-${o}`}function m({children:o,span:l,sm:a,md:n,lg:m,xl:s,className:c}){const i=t("bento-cell",r(l),a&&r(a,"sm"),n&&r(n,"md"),m&&r(m,"lg"),s&&r(s,"xl"),c);return e.jsx("div",{className:i,children:o})}export{m as C,n as R};
|
||||
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{r as s,j as e,F as a,bl as t,bm as l}from"./vendor-react-LAbPDfrQ.js";import{c as r}from"./recharts-D38YBQhj.js";import{ao as i,ap as o,b as n,aq as c,r as m,am as x,ar as d}from"./index-UmM6aLcb.js";import{u as p}from"./usePolling-Dc-LnIv7.js";import{P as h,b as j,a as u,L as g}from"./PageLayout-COD3p9tO.js";import{C as f}from"./Card-xXPckJMj.js";import"./vendor-core-WoOfkQwm.js";import"./deckgl-DTsmDcfs.js";const b=s.memo(function({log:s}){return e.jsx("div",{className:"p-3 rounded-2xl bg-subtle-fill hover:bg-subtle-fill-strong transition-colors",children:e.jsxs("div",{className:"flex items-baseline gap-3",children:[e.jsx("span",{className:r("type-data-sm w-14 shrink-0",d(s.level)),children:s.level}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"type-data-sm text-text-primary break-words whitespace-pre-wrap",children:s.message}),e.jsx("p",{className:"type-data-xs text-text-muted mt-1",children:new Date(s.timestamp).toLocaleString()})]})]})})});function v({showDebug:s,onToggle:a}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:r("type-data-sm",s?"text-accent-tertiary":"text-accent-primary"),children:s?"DEBUG":"INFO"}),e.jsx("button",{onClick:a,className:r("relative w-10 h-5 rounded-full transition-colors duration-200",s?"bg-accent-tertiary":"bg-accent-primary"),role:"switch","aria-checked":s,children:e.jsx("span",{className:r("absolute top-[2px] left-[2px] w-4 h-4 bg-white rounded-full shadow-sm transition-transform duration-200",s?"translate-x-5":"translate-x-0")})})]})}function N(){const d=i(),N=o(),w=n(),y=c(),k=m(),[C,D]=s.useState(!1),L=s.useCallback(()=>{D(s=>!s)},[]),P=C?d:d.filter(s=>"DEBUG"!==s.level);return p(y,x.logs,w),e.jsxs(h,{children:[e.jsx(j,{title:"System Logs",icon:e.jsx(a,{}),controls:e.jsx(v,{showDebug:C,onToggle:L})}),e.jsxs(u,{noPadding:!0,children:[e.jsx(f,{listHeader:!0,icon:e.jsx(a,{className:"icon-sm"}),title:"Log Entries",actions:e.jsx("button",{onClick:()=>k(!w),className:r("transition-colors",w?"text-signal-critical hover:text-signal-critical/80":"text-accent-primary hover:text-accent-primary/80 animate-pulse-slow"),title:w?"Pause":"Resume",children:w?e.jsx(t,{className:"w-5 h-5"}):e.jsx(l,{className:"w-5 h-5"})})}),e.jsx("div",{className:"space-y-2 max-h-[calc(100vh-300px)] sm:max-h-[calc(100vh-250px)] overflow-y-auto p-4",children:N&&0===d.length?e.jsx(g,{count:10}):0===P.length?e.jsx("div",{className:"text-center py-12 text-text-muted",children:0===d.length?"No logs available":"No logs match selected filters"}):P.map((s,a)=>e.jsx(b,{log:s},`${s.timestamp}-${a}`))})]})]})}export{N as default};
|
||||
import{r as s,j as e,F as a,bA as t,bB as l}from"./vendor-react-C341c8YC.js";import{n as r}from"./recharts-6XUQYgRA.js";import{au as i,av as n,d as o,aw as c,v as m,as as x,ax as d}from"./index-CPdqYR4z.js";import{u as p}from"./usePolling-CtRLadGa.js";import{P as h,b as j,a as u,L as g}from"./PageLayout-CcoYWyzO.js";import{C as f}from"./Card-BeZKc0xw.js";import"./vendor-core-WoOfkQwm.js";import"./deckgl-DTsmDcfs.js";const v=s.memo(function({log:s}){return e.jsx("div",{className:"p-3 rounded-2xl bg-subtle-fill hover:bg-subtle-fill-strong transition-colors",children:e.jsxs("div",{className:"flex items-baseline gap-3",children:[e.jsx("span",{className:r("type-data-sm w-14 shrink-0",d(s.level)),children:s.level}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"type-data-sm text-text-primary break-words whitespace-pre-wrap",children:s.message}),e.jsx("p",{className:"type-data-xs text-text-muted mt-1",children:new Date(s.timestamp).toLocaleString()})]})]})})});function b({showDebug:s,onToggle:a}){return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:r("type-data-sm",s?"text-accent-tertiary":"text-accent-primary"),children:s?"DEBUG":"INFO"}),e.jsx("button",{onClick:a,className:r("relative w-10 h-5 rounded-full transition-colors duration-200",s?"bg-accent-tertiary":"bg-accent-primary"),role:"switch","aria-checked":s,children:e.jsx("span",{className:r("absolute top-[2px] left-[2px] w-4 h-4 bg-white rounded-full shadow-sm transition-transform duration-200",s?"translate-x-5":"translate-x-0")})})]})}function N(){const d=i(),N=n(),w=o(),y=c(),k=m(),[C,D]=s.useState(!1),L=s.useCallback(()=>{D(s=>!s)},[]),P=C?d:d.filter(s=>"DEBUG"!==s.level);return p(y,x.logs,w),e.jsxs(h,{children:[e.jsx(j,{title:"System Logs",icon:e.jsx(a,{}),controls:e.jsx(b,{showDebug:C,onToggle:L})}),e.jsxs(u,{noPadding:!0,children:[e.jsx(f,{listHeader:!0,icon:e.jsx(a,{className:"icon-sm"}),title:"Log Entries",actions:e.jsx("button",{onClick:()=>k(!w),className:r("transition-colors",w?"text-signal-critical hover:text-signal-critical/80":"text-accent-primary hover:text-accent-primary/80 animate-pulse-slow"),title:w?"Pause":"Resume",children:w?e.jsx(t,{className:"w-5 h-5"}):e.jsx(l,{className:"w-5 h-5"})})}),e.jsx("div",{className:"space-y-2 max-h-[calc(100vh-300px)] sm:max-h-[calc(100vh-250px)] overflow-y-auto p-4",children:N&&0===d.length?e.jsx(g,{count:10}):0===P.length?e.jsx("div",{className:"text-center py-12 text-text-muted",children:0===d.length?"No logs available":"No logs match selected filters"}):P.map((s,a)=>e.jsx(v,{log:s},`${s.timestamp}-${a}`))})]})]})}export{N as default};
|
||||
+1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{j as e,E as s}from"./vendor-react-LAbPDfrQ.js";import{a as t}from"./PageLayout-COD3p9tO.js";import{D as a}from"./DataBox-ChCyaBc1.js";import{aE as r}from"./index-UmM6aLcb.js";import{C as l}from"./Card-xXPckJMj.js";function c({nodeName:c,repeaterVersion:m,coreVersion:i,localHash:n,publicKey:d}){return e.jsxs(t,{children:[e.jsx(l,{icon:e.jsx(s,{}),title:"Node Information",largeTitle:!0}),e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4",children:[e.jsxs("div",{className:"min-w-0 col-span-2 sm:col-span-1",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Node Name"}),e.jsx("p",{className:"type-body text-text-primary mt-0.5 sm:mt-1 truncate",title:c,children:c})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Repeater"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${m}`,children:["v",m]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Core"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${i}`,children:["v",i]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Console"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${r}`,children:["v",r]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Local Hash"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:n?e.jsx(a,{copy:!0,size:"compact",children:n}):e.jsx("span",{className:"type-data-sm text-text-secondary",children:"N/A"})})]})]}),d&&e.jsxs("div",{className:"mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-border-subtle",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Public Key"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:e.jsx(a,{copy:!0,size:"responsive",children:d})})]})]})}export{c as N};
|
||||
import{j as e,E as s}from"./vendor-react-C341c8YC.js";import{a as t}from"./PageLayout-CcoYWyzO.js";import{D as a}from"./DataBox-CRX76VsB.js";import{ay as r}from"./index-CPdqYR4z.js";import{C as l}from"./Card-BeZKc0xw.js";function c({nodeName:c,repeaterVersion:m,coreVersion:i,localHash:n,publicKey:d}){return e.jsxs(t,{children:[e.jsx(l,{icon:e.jsx(s,{}),title:"Node Information",largeTitle:!0}),e.jsxs("div",{className:"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-3 sm:gap-4",children:[e.jsxs("div",{className:"min-w-0 col-span-2 sm:col-span-1",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Node Name"}),e.jsx("p",{className:"type-body text-text-primary mt-0.5 sm:mt-1 truncate",title:c,children:c})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Repeater"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${m}`,children:["v",m]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Core"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${i}`,children:["v",i]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Console"}),e.jsxs("p",{className:"type-data text-text-primary mt-0.5 sm:mt-1 truncate",title:`v${r}`,children:["v",r]})]}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Local Hash"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:n?e.jsx(a,{copy:!0,size:"compact",children:n}):e.jsx("span",{className:"type-data-sm text-text-secondary",children:"N/A"})})]})]}),d&&e.jsxs("div",{className:"mt-3 sm:mt-4 pt-3 sm:pt-4 border-t border-border-subtle",children:[e.jsx("span",{className:"type-label text-text-secondary",children:"Public Key"}),e.jsx("div",{className:"mt-0.5 sm:mt-1",children:e.jsx(a,{copy:!0,size:"responsive",children:d})})]})]})}export{c as N};
|
||||
-2
File diff suppressed because one or more lines are too long
+2
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{j as s}from"./vendor-react-LAbPDfrQ.js";import{c as e}from"./recharts-D38YBQhj.js";import"./index-UmM6aLcb.js";const a=[45,72,33,58,80,42,65,28,55,75,38,62];function l({className:a,style:l}){return s.jsx("div",{className:e("animate-pulse bg-white/[0.06] rounded",a),style:l})}function c(){return s.jsx("div",{className:"p-3 rounded-lg border border-border-subtle bg-bg-subtle",children:s.jsxs("div",{className:"flex items-start gap-3",children:[s.jsx(l,{className:"w-14 h-6 rounded shrink-0"}),s.jsxs("div",{className:"flex-1 min-w-0 space-y-2",children:[s.jsx(l,{className:"h-4 w-full"}),s.jsx(l,{className:"h-4 w-3/4"}),s.jsx(l,{className:"h-3 w-32 mt-1"})]})]})})}function r({count:e=8}){return s.jsx("div",{className:"space-y-2",children:Array.from({length:e}).map((e,a)=>s.jsx(c,{},a))})}function i(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx(l,{className:"h-8 w-20"}),s.jsxs("div",{className:"flex-1 flex flex-col justify-end gap-2",children:[s.jsx(l,{className:"h-3 w-full"}),s.jsx(l,{className:"h-3 w-3/4"})]})]})}function n(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx("div",{className:"flex-1 flex items-end gap-1",children:a.slice(0,8).map((e,a)=>s.jsx(l,{className:"flex-1",style:{height:`${e}%`}},a))})]})}function t({rows:e=5}){return s.jsxs("div",{className:"flex flex-col h-full","aria-hidden":"true",children:[s.jsx("div",{className:"pb-3 border-b border-border-subtle",children:s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]})}),s.jsx("div",{className:"flex-1 pt-3 flex flex-col gap-3",children:Array.from({length:e}).map((e,a)=>s.jsx(l,{className:"h-6 w-full"},a))})]})}function d({children:a,className:l}){return s.jsx("div",{className:e("section-gap",l),children:a})}function x({title:e,icon:a,controls:l,subtitle:c}){return s.jsxs("div",{className:"flex flex-col gap-2",children:[s.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-3",children:[s.jsxs("h1",{className:"type-title text-text-primary flex items-center gap-2 sm:gap-3 h-9 min-w-0",children:[a&&s.jsx("span",{className:"w-5 h-5 sm:w-6 sm:h-6 text-icon-page-title flex-shrink-0",children:a}),s.jsx("span",{className:"truncate",children:e})]}),l&&s.jsx("div",{className:"flex items-center gap-2 sm:gap-3 h-9 flex-shrink-0",children:l})]}),c&&s.jsx("div",{children:c})]})}const m={sm:"card-sm",md:"card-md",lg:"card-lg",hero:"card-hero",auto:"card-auto"};function h({children:a,size:l,compact:c,noPadding:r,className:d,style:x,onClick:h,isLoaded:o=!0,skeletonType:f="card"}){return s.jsxs("div",{className:e("glass-card h-full flex flex-col relative",!r&&(c?"card-padding-sm":"card-padding"),l&&m[l],d),style:x,onClick:h,children:[a,!o&&(()=>{switch(f){case"chart":return s.jsx(n,{});case"list":return s.jsx(t,{});default:return s.jsx(i,{})}})()]})}export{i as C,r as L,d as P,l as S,h as a,x as b};
|
||||
import{j as s}from"./vendor-react-C341c8YC.js";import{n as e}from"./recharts-6XUQYgRA.js";import"./index-CPdqYR4z.js";const a=[45,72,33,58,80,42,65,28,55,75,38,62];function l({className:a,style:l}){return s.jsx("div",{className:e("animate-pulse bg-white/[0.06] rounded",a),style:l})}function c(){return s.jsx("div",{className:"p-3 rounded-lg border border-border-subtle bg-bg-subtle",children:s.jsxs("div",{className:"flex items-start gap-3",children:[s.jsx(l,{className:"w-14 h-6 rounded shrink-0"}),s.jsxs("div",{className:"flex-1 min-w-0 space-y-2",children:[s.jsx(l,{className:"h-4 w-full"}),s.jsx(l,{className:"h-4 w-3/4"}),s.jsx(l,{className:"h-3 w-32 mt-1"})]})]})})}function r({count:e=8}){return s.jsx("div",{className:"space-y-2",children:Array.from({length:e}).map((e,a)=>s.jsx(c,{},a))})}function i(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx(l,{className:"h-8 w-20"}),s.jsxs("div",{className:"flex-1 flex flex-col justify-end gap-2",children:[s.jsx(l,{className:"h-3 w-full"}),s.jsx(l,{className:"h-3 w-3/4"})]})]})}function n(){return s.jsxs("div",{className:"flex flex-col gap-3 h-full","aria-hidden":"true",children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]}),s.jsx("div",{className:"flex-1 flex items-end gap-1",children:a.slice(0,8).map((e,a)=>s.jsx(l,{className:"flex-1",style:{height:`${e}%`}},a))})]})}function t({rows:e=5}){return s.jsxs("div",{className:"flex flex-col h-full","aria-hidden":"true",children:[s.jsx("div",{className:"pb-3 border-b border-border-subtle",children:s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx(l,{className:"w-5 h-5"}),s.jsx(l,{className:"h-4 w-24"})]})}),s.jsx("div",{className:"flex-1 pt-3 flex flex-col gap-3",children:Array.from({length:e}).map((e,a)=>s.jsx(l,{className:"h-6 w-full"},a))})]})}function d({children:a,className:l}){return s.jsx("div",{className:e("section-gap",l),children:a})}function x({title:e,icon:a,controls:l,subtitle:c}){return s.jsxs("div",{className:"flex flex-col gap-2",children:[s.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between sm:gap-3",children:[s.jsxs("h1",{className:"type-title text-text-primary flex items-center gap-2 sm:gap-3 h-9 min-w-0",children:[a&&s.jsx("span",{className:"w-5 h-5 sm:w-6 sm:h-6 text-icon-page-title flex-shrink-0",children:a}),s.jsx("span",{className:"truncate",children:e})]}),l&&s.jsx("div",{className:"flex items-center gap-2 sm:gap-3 h-9 flex-shrink-0",children:l})]}),c&&s.jsx("div",{children:c})]})}const m={sm:"card-sm",md:"card-md",lg:"card-lg",hero:"card-hero",auto:"card-auto"};function h({children:a,size:l,compact:c,noPadding:r,className:d,style:x,onClick:h,isLoaded:o=!0,skeletonType:f="card"}){return s.jsxs("div",{className:e("glass-card h-full flex flex-col relative",!r&&(c?"card-padding-sm":"card-padding"),l&&m[l],d),style:x,onClick:h,children:[a,!o&&(()=>{switch(f){case"chart":return s.jsx(n,{});case"list":return s.jsx(t,{});default:return s.jsx(i,{})}})()]})}export{i as C,r as L,d as P,l as S,h as a,x as b};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{r as e,j as o}from"./vendor-react-LAbPDfrQ.js";const t=e.memo(function({ranges:e,selectedIndex:t,onSelect:a,isPending:l}){return o.jsx("div",{className:"toggle-group flex-shrink-0 overflow-x-auto "+(l?"opacity-70":""),children:e.map((e,l)=>o.jsx("button",{onClick:()=>a(l),className:"toggle-group-item "+(t===l?"active":""),children:e.label},e.label))})});export{t as T};
|
||||
import{r as e,j as o}from"./vendor-react-C341c8YC.js";const t=e.memo(function({ranges:e,selectedIndex:t,onSelect:a,isPending:l}){return o.jsx("div",{className:"toggle-group flex-shrink-0 overflow-x-auto "+(l?"opacity-70":""),children:e.map((e,l)=>o.jsx("button",{onClick:()=>a(l),className:"toggle-group-item "+(t===l?"active":""),children:e.label},e.label))})});export{t as T};
|
||||
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
+1
File diff suppressed because one or more lines are too long
+2
File diff suppressed because one or more lines are too long
-2
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
|
||||
import{n as t,aP as e}from"./index-CPdqYR4z.js";function n(t){if(Array.isArray(t))return t;if("string"==typeof t&&t.startsWith("["))try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}return[]}function o(o,r,s){const a=new Map;for(const e of r){const n=t(e);a.has(n)||a.set(n,e)}const c=new Map,i=new Map;for(const t of o){const o=t.route??t.route_type;if(!e(o))continue;const r=n(t.original_path);if(0===r.length)continue;const f=r.map(t=>t.toUpperCase());if(!t.transmitted&&f.length>=2){const t=f[f.length-2];if(t){const e=a.get(t);e&&i.set(e,(i.get(e)??0)+1)}}if(f.includes(s))for(const t of f){if(t===s)continue;const e=a.get(t);e&&c.set(e,(c.get(e)??0)+1)}}let f=0,u=0;for(const t of r)f=Math.max(f,c.get(t)??0),u=Math.max(u,i.get(t)??0);const h=new Map;let g=0,l=0,p=0;for(const t of r){const e=c.get(t)??0,n=i.get(t)??0,o=f>0?Math.round(e/f*100):0,r=u>0?Math.round(n/u*100):0,s=o+r;h.set(t,{hash:t,listenerCount:e,loudCount:n,listenerScore:o,loudScore:r,blendedScore:s}),g=Math.max(g,o),l=Math.max(l,r),p=Math.max(p,s)}return{scores:h,maxListenerScore:g,maxLoudScore:l,maxBlendedScore:p}}const r={YELLOW:"#FFB224",GREEN:"#46A758",RED:"#E5484D",GRAY:"#505050"};export{r as L,o as c};
|
||||
@@ -1 +0,0 @@
|
||||
import{k as t,aL as e}from"./index-UmM6aLcb.js";function o(t){if(Array.isArray(t))return t;if("string"==typeof t&&t.startsWith("["))try{const e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}return[]}function n(n,r,s){const a=new Map;for(const e of r){const o=t(e);a.has(o)||a.set(o,e)}const c=new Map,i=new Map;for(const t of n){const n=t.route??t.route_type;if(!e(n))continue;const r=o(t.original_path);if(0===r.length)continue;const f=r.map(t=>t.toUpperCase());if(!t.transmitted&&f.length>=2){const t=f[f.length-2];if(t){const e=a.get(t);e&&i.set(e,(i.get(e)??0)+1)}}if(f.includes(s))for(const t of f){if(t===s)continue;const e=a.get(t);e&&c.set(e,(c.get(e)??0)+1)}}let f=0,u=0;for(const t of r)f=Math.max(f,c.get(t)??0),u=Math.max(u,i.get(t)??0);const h=new Map;let g=0,l=0,p=0;for(const t of r){const e=c.get(t)??0,o=i.get(t)??0,n=f>0?Math.round(e/f*100):0,r=u>0?Math.round(o/u*100):0,s=n+r;h.set(t,{hash:t,listenerCount:e,loudCount:o,listenerScore:n,loudScore:r,blendedScore:s}),g=Math.max(g,n),l=Math.max(l,r),p=Math.max(p,s)}return{scores:h,maxListenerScore:g,maxLoudScore:l,maxBlendedScore:p}}const r={YELLOW:"#FFB224",GREEN:"#46A758",RED:"#E5484D",GRAY:"#505050"};export{r as L,n as c};
|
||||
+1
-1
@@ -1 +1 @@
|
||||
import{ay as t}from"./index-UmM6aLcb.js";async function e(e,r=10){return t("/api/ping_neighbor",{method:"POST",body:JSON.stringify({target_id:e,timeout:r})})}const r=["Chat Node","Repeater","Room Server","Hybrid Node","Unknown"];async function s(s,o=10){if(o<1||o>60)return{success:!1,error:"Timeout must be 1-60 seconds"};let n;const a=s.match(/^(0x)?([0-9a-fA-F]{1,2})$/);if(a)n=`0x${a[2].padStart(2,"0")}`;else{const e=await async function(e){const s=e.toLowerCase();for(const o of r)try{const e=await t(`/api/adverts_by_contact_type?contact_type=${encodeURIComponent(o)}&hours=168`),r=e.success&&e.data?e.data:e,n=(Array.isArray(r)?r:[]).find(t=>t.node_name&&t.node_name.toLowerCase()===s);if(n&&n.pubkey)return`0x${n.pubkey.substring(0,2)}`}catch{continue}return null}(s);if(!e)return{success:!1,error:`Node '${s}' not found`};n=e}const c=await e(n,o);if(!c.success||!c.data)return{success:!1,error:c.error||"Ping failed"};const i=(u=c.data).rtt_ms>500||u.rssi<-120?"Poor":u.rtt_ms>250||u.rssi<-100?"Fair":u.rtt_ms>100||u.rssi<-80?"Good":"Excellent";var u;return{success:!0,data:{...c.data,quality:i}}}export{s as a,e as p};
|
||||
import{aF as t}from"./index-CPdqYR4z.js";async function e(e,r=10){return t("/api/ping_neighbor",{method:"POST",body:JSON.stringify({target_id:e,timeout:r})})}const r=["Chat Node","Repeater","Room Server","Hybrid Node","Unknown"];async function s(s,o=10){if(o<1||o>60)return{success:!1,error:"Timeout must be 1-60 seconds"};let n;const a=s.match(/^(0x)?([0-9a-fA-F]{1,2})$/);if(a)n=`0x${a[2].padStart(2,"0")}`;else{const e=await async function(e){const s=e.toLowerCase();for(const o of r)try{const e=await t(`/api/adverts_by_contact_type?contact_type=${encodeURIComponent(o)}&hours=168`),r=e.success&&e.data?e.data:e,n=(Array.isArray(r)?r:[]).find(t=>t.node_name&&t.node_name.toLowerCase()===s);if(n&&n.pubkey)return`0x${n.pubkey.substring(0,2)}`}catch{continue}return null}(s);if(!e)return{success:!1,error:`Node '${s}' not found`};n=e}const c=await e(n,o);if(!c.success||!c.data)return{success:!1,error:c.error||"Ping failed"};const i=(u=c.data).rtt_ms>500||u.rssi<-120?"Poor":u.rtt_ms>250||u.rssi<-100?"Fair":u.rtt_ms>100||u.rssi<-80?"Good":"Excellent";var u;return{success:!0,data:{...c.data,quality:i}}}export{s as a,e as p};
|
||||
+1
File diff suppressed because one or more lines are too long
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
import{r}from"./vendor-react-LAbPDfrQ.js";function e(e,t,n=!0,c=!1){const u=r.useRef(e);r.useEffect(()=>{u.current=e},[e]),r.useEffect(()=>{if(!n)return;c||u.current();const r=setInterval(()=>{u.current()},t);return()=>clearInterval(r)},[t,n,c])}export{e as u};
|
||||
import{r}from"./vendor-react-C341c8YC.js";function e(e,t,n=!0,c=!1){const u=r.useRef(e);r.useEffect(()=>{u.current=e},[e]),r.useEffect(()=>{if(!n)return;c||u.current();const r=setInterval(()=>{u.current()},t);return()=>clearInterval(r)},[t,n,c])}export{e as u};
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+3
-3
@@ -39,10 +39,10 @@
|
||||
--font-data: 'JetBrains Mono', 'SF Mono', Monaco, monospace;
|
||||
}
|
||||
</style>
|
||||
<script type="module" crossorigin src="/assets/index-UmM6aLcb.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-CPdqYR4z.js"></script>
|
||||
<link rel="modulepreload" crossorigin href="/assets/vendor-core-WoOfkQwm.js">
|
||||
<link rel="modulepreload" crossorigin href="/assets/vendor-react-LAbPDfrQ.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-BbajDJDJ.css">
|
||||
<link rel="modulepreload" crossorigin href="/assets/vendor-react-C341c8YC.js">
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-CIefRaAd.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pymc_console",
|
||||
"version": "0.9.193",
|
||||
"version": "0.9.194",
|
||||
"description": "Vite + React Dashboard for pyMC_Repeater",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
@@ -14,6 +14,7 @@
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@cosmograph/react": "^2.0.1",
|
||||
"@deck.gl/aggregation-layers": "^9.2.5",
|
||||
"@deck.gl/core": "^9.2.5",
|
||||
"@deck.gl/geo-layers": "^9.2.5",
|
||||
@@ -30,14 +31,12 @@
|
||||
"@fontsource/rubik-mono-one": "^5.2.8",
|
||||
"@fontsource/source-code-pro": "^5.2.7",
|
||||
"@headlessui/react": "^2.2.9",
|
||||
"@types/leaflet": "^1.9.21",
|
||||
"@types/three": "^0.182.0",
|
||||
"axios": "^1.13.2",
|
||||
"clsx": "^2.1.1",
|
||||
"d3-contour": "^4.0.2",
|
||||
"d3-geo": "^3.1.1",
|
||||
"h3-js": "^4.4.0",
|
||||
"leaflet": "^1.9.4",
|
||||
"lucide-react": "^0.559.0",
|
||||
"maplibre-gl": "^5.15.0",
|
||||
"motion": "^12.29.0",
|
||||
@@ -45,7 +44,6 @@
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-is": "^19.2.3",
|
||||
"react-leaflet": "^4.2.1",
|
||||
"react-map-gl": "^8.1.0",
|
||||
"react-router-dom": "^7.1.1",
|
||||
"recharts": "^3.5.1",
|
||||
|
||||
Reference in New Issue
Block a user