semiotic 3.8.2 → 3.8.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +9 -9
- package/README.md +42 -40
- package/ai/examples.md +1 -1
- package/ai/schema.json +2726 -300
- package/ai/surface-manifest.json +1 -1
- package/ai/system-prompt.md +1 -1
- package/dist/chunk-chunk-2JGJ5GUG.module.min.js +0 -1
- package/dist/chunk-chunk-3ILKBVVQ.module.min.js +1 -0
- package/dist/{chunk-chunk-NO4MCQVD.module.min.js → chunk-chunk-5RKXZQ2P.module.min.js} +1 -1
- package/dist/{chunk-chunk-CYIML3AV.module.min.js → chunk-chunk-6TPGFL7M.module.min.js} +1 -1
- package/dist/{chunk-chunk-VVCA3DB7.module.min.js → chunk-chunk-7ALTGHK6.module.min.js} +1 -1
- package/dist/chunk-chunk-7KZJUTKP.module.min.js +2 -0
- package/dist/chunk-chunk-7RYBCTK5.module.min.js +1 -0
- package/dist/chunk-chunk-ACLDBMRH.module.min.js +2 -0
- package/dist/chunk-chunk-ANYDWOZF.module.min.js +1 -0
- package/dist/{chunk-chunk-ZLKRTF5N.module.min.js → chunk-chunk-AQPQN2HH.module.min.js} +1 -1
- package/dist/chunk-chunk-ASKSE5F5.module.min.js +1 -0
- package/dist/chunk-chunk-AVBI6GDT.module.min.js +1 -0
- package/dist/chunk-chunk-B3DRZPBK.module.min.js +2 -0
- package/dist/chunk-chunk-BFHUYEOS.module.min.js +2 -0
- package/dist/chunk-chunk-C4YA6TDR.module.min.js +1 -0
- package/dist/chunk-chunk-C57LR3YG.module.min.js +1 -0
- package/dist/chunk-chunk-EMO5NUGE.module.min.js +1 -0
- package/dist/chunk-chunk-F5V4UIE6.module.min.js +2 -0
- package/dist/chunk-chunk-F7WFPD4O.module.min.js +2 -0
- package/dist/chunk-chunk-FBGHXL72.module.min.js +2 -0
- package/dist/chunk-chunk-FP44FHFO.module.min.js +2 -0
- package/dist/chunk-chunk-HKXUAEPJ.module.min.js +2 -0
- package/dist/chunk-chunk-ICEXPNDC.module.min.js +2 -0
- package/dist/chunk-chunk-IY7RYD4S.module.min.js +1 -0
- package/dist/{chunk-chunk-7LHMKRKE.module.min.js → chunk-chunk-JDXT6ORT.module.min.js} +1 -1
- package/dist/chunk-chunk-JMVEIZXP.module.min.js +1 -0
- package/dist/chunk-chunk-KHCOJMGK.module.min.js +1 -0
- package/dist/chunk-chunk-KQ546MKE.module.min.js +2 -0
- package/dist/chunk-chunk-LQBSXO7K.module.min.js +2 -0
- package/dist/chunk-chunk-LRIFN2HK.module.min.js +1 -0
- package/dist/chunk-chunk-MFHF4J2Z.module.min.js +1 -0
- package/dist/chunk-chunk-N6VKKF3A.module.min.js +2 -0
- package/dist/chunk-chunk-NEVE562N.module.min.js +1 -0
- package/dist/chunk-chunk-NKZ75IM5.module.min.js +2 -0
- package/dist/chunk-chunk-PLIDPQNG.module.min.js +2 -0
- package/dist/{chunk-chunk-FYY2ACNJ.module.min.js → chunk-chunk-PRDGLMJT.module.min.js} +1 -1
- package/dist/chunk-chunk-QGZGZI4X.module.min.js +1 -0
- package/dist/chunk-chunk-RP7WTID5.module.min.js +1 -0
- package/dist/chunk-chunk-S7KLNUO6.module.min.js +1 -0
- package/dist/chunk-chunk-SR4ZXOWR.module.min.js +2 -0
- package/dist/chunk-chunk-ZOAQDIJO.module.min.js +1 -0
- package/dist/chunk-minimapBrushOverlay-JU57U7NM.module.min.js +2 -0
- package/dist/chunk-scatterplotMatrixBrushOverlay-SDIZSN66.module.min.js +2 -0
- package/dist/chunk-statisticalOverlays-QGDLRUHX.module.min.js +1 -0
- package/dist/chunk-statisticalOverlays-T77OKLDY.module.min.js +1 -0
- package/dist/components/ChartContainer.d.ts +2 -2
- package/dist/components/ai/chartCapabilityTypes.d.ts +5 -0
- package/dist/components/charts/custom/XYCustomChart.d.ts +3 -0
- package/dist/components/charts/geo/ChoroplethMap.d.ts +2 -0
- package/dist/components/charts/geo/DistanceCartogram.d.ts +7 -3
- package/dist/components/charts/geo/FlowMap.d.ts +4 -0
- package/dist/components/charts/geo/ProportionalSymbolMap.d.ts +3 -1
- package/dist/components/charts/physics/CollisionSwarmChart.d.ts +6 -1
- package/dist/components/charts/physics/GaltonBoardChart.d.ts +6 -1
- package/dist/components/charts/physics/gauntletChartProps.d.ts +7 -1
- package/dist/components/charts/physics/gauntletChrome.d.ts +2 -1
- package/dist/components/charts/physics/gauntletPhysics.d.ts +19 -4
- package/dist/components/charts/physics/gauntletRuntime.d.ts +3 -0
- package/dist/components/charts/physics/physicsHocUtils.d.ts +12 -0
- package/dist/components/charts/realtime/RealtimeHistogram.d.ts +5 -6
- package/dist/components/charts/realtime/temporalHistogramConfig.d.ts +11 -0
- package/dist/components/charts/shared/areaSeriesData.d.ts +15 -0
- package/dist/components/charts/shared/chartMode.d.ts +75 -0
- package/dist/components/charts/shared/chartSpecCore.d.ts +2 -2
- package/dist/components/charts/shared/colorUtils.d.ts +8 -0
- package/dist/components/charts/shared/geoStyleDefaults.d.ts +3 -0
- package/dist/components/charts/shared/hatchPattern.d.ts +8 -3
- package/dist/components/charts/shared/hooks.d.ts +13 -80
- package/dist/components/charts/shared/lineSeriesSsr.d.ts +55 -0
- package/dist/components/charts/shared/types.d.ts +2 -2
- package/dist/components/charts/shared/useChartSetup.d.ts +3 -0
- package/dist/components/charts/shared/useCustomChartSetup.d.ts +3 -0
- package/dist/components/charts/shared/useXYLineStyle.d.ts +3 -2
- package/dist/components/charts/shared/validateProps.d.ts +1 -1
- package/dist/components/charts/shared/xyLineStyle.d.ts +21 -0
- package/dist/components/charts/xy/AreaChart.d.ts +10 -0
- package/dist/components/charts/xy/LineChart.d.ts +3 -0
- package/dist/components/charts/xy/minimapBrushOverlay.d.ts +17 -0
- package/dist/components/charts/xy/minimapBrushOverlayLazy.d.ts +4 -0
- package/dist/components/charts/xy/scatterplotMatrixBrushOverlay.d.ts +8 -0
- package/dist/components/charts/xy/scatterplotMatrixBrushOverlayLazy.d.ts +3 -0
- package/dist/components/legendLayout.d.ts +31 -0
- package/dist/components/realtime/types.d.ts +5 -0
- package/dist/components/recipes/gridObservatory.d.ts +176 -0
- package/dist/components/recipes/recipeChrome.d.ts +24 -0
- package/dist/components/recipes/sequenceLayout.d.ts +139 -0
- package/dist/components/semiotic-recipes-core.d.ts +6 -2
- package/dist/components/server/serverChartConfigShared.d.ts +29 -0
- package/dist/components/server/serverChartConfigs.d.ts +2 -13
- package/dist/components/server/serverChartConfigsXY.d.ts +3 -0
- package/dist/components/server/serverGaugeOverlay.d.ts +28 -0
- package/dist/components/server/staticAnnotations.d.ts +3 -1
- package/dist/components/server/staticLegend.d.ts +7 -1
- package/dist/components/server/staticSVGChrome.d.ts +57 -0
- package/dist/components/stream/GeoPipelineStore.d.ts +2 -0
- package/dist/components/stream/GeoSVGOverlay.d.ts +2 -0
- package/dist/components/stream/SceneToSVG.d.ts +10 -8
- package/dist/components/stream/SceneToSVGGeo.d.ts +10 -0
- package/dist/components/stream/SceneToSVGNetwork.d.ts +12 -0
- package/dist/components/stream/SceneToSVGOrdinal.d.ts +12 -0
- package/dist/components/stream/canvasBackground.d.ts +7 -0
- package/dist/components/stream/networkFramePaint.d.ts +2 -0
- package/dist/components/stream/networkTypes.d.ts +2 -4
- package/dist/components/stream/physics/PhysicsPipelineStore.d.ts +18 -2
- package/dist/components/stream/physics/physicsBodyCanvas.d.ts +7 -0
- package/dist/components/stream/physics/physicsPipelineEviction.d.ts +15 -0
- package/dist/components/stream/physics/physicsPipelineObservations.d.ts +1 -1
- package/dist/components/stream/physics/physicsPipelineQuiescence.d.ts +20 -0
- package/dist/components/stream/renderBackend.d.ts +14 -0
- package/dist/components/stream/sceneToSVGShared.d.ts +80 -0
- package/dist/components/stream/types.d.ts +4 -0
- package/dist/components/stream/useHydration.d.ts +7 -1
- package/dist/components/stream/xySceneBuilders/candlestickScene.d.ts +1 -1
- package/dist/components/types/legendTypes.d.ts +16 -3
- package/dist/forceLayoutWorker.js +1 -1
- package/dist/geo.min.js +1 -1
- package/dist/geo.module.min.js +1 -1
- package/dist/network.min.js +1 -1
- package/dist/network.module.min.js +1 -1
- package/dist/ordinal.min.js +1 -1
- package/dist/ordinal.module.min.js +1 -1
- package/dist/physics.min.js +1 -1
- package/dist/physics.module.min.js +1 -1
- package/dist/physicsWorker.js +1 -1
- package/dist/realtime.min.js +1 -1
- package/dist/realtime.module.min.js +1 -1
- package/dist/rough.min.js +1 -1
- package/dist/rough.module.min.js +1 -1
- package/dist/semiotic-ai-core.min.js +1 -1
- package/dist/semiotic-ai-core.module.min.js +1 -1
- package/dist/semiotic-ai.min.js +1 -1
- package/dist/semiotic-ai.module.min.js +1 -1
- package/dist/semiotic-experimental.min.js +1 -1
- package/dist/semiotic-experimental.module.min.js +1 -1
- package/dist/semiotic-realtime-core.min.js +1 -1
- package/dist/semiotic-realtime-core.module.min.js +1 -1
- package/dist/semiotic-recipes-core.d.ts +6 -2
- package/dist/semiotic-recipes-core.min.js +1 -1
- package/dist/semiotic-recipes-core.module.min.js +1 -1
- package/dist/semiotic-recipes.min.js +1 -1
- package/dist/semiotic-recipes.module.min.js +1 -1
- package/dist/semiotic-server-edge.min.js +1 -1
- package/dist/semiotic-server-edge.module.min.js +1 -1
- package/dist/semiotic-server-node.min.js +1 -1
- package/dist/semiotic-server-node.module.min.js +1 -1
- package/dist/semiotic-utils-core.min.js +1 -1
- package/dist/semiotic-utils-core.module.min.js +1 -1
- package/dist/semiotic-utils.min.js +1 -1
- package/dist/semiotic-utils.module.min.js +1 -1
- package/dist/semiotic-value.module.min.js +1 -1
- package/dist/semiotic.min.js +1 -1
- package/dist/semiotic.module.min.js +1 -1
- package/dist/server.min.js +1 -1
- package/dist/server.module.min.js +1 -1
- package/dist/xy.min.js +1 -1
- package/dist/xy.module.min.js +1 -1
- package/package.json +3 -2
- package/dist/chunk-chunk-255KDHW5.module.min.js +0 -1
- package/dist/chunk-chunk-27HVVXS6.module.min.js +0 -1
- package/dist/chunk-chunk-2UN3ANRN.module.min.js +0 -2
- package/dist/chunk-chunk-2VUEY5TH.module.min.js +0 -1
- package/dist/chunk-chunk-2WVCH4PL.module.min.js +0 -1
- package/dist/chunk-chunk-5WEFWNUW.module.min.js +0 -2
- package/dist/chunk-chunk-6F6GEAQU.module.min.js +0 -1
- package/dist/chunk-chunk-BHYTYMY2.module.min.js +0 -2
- package/dist/chunk-chunk-C6EJ4IOD.module.min.js +0 -2
- package/dist/chunk-chunk-CP3EN6KZ.module.min.js +0 -1
- package/dist/chunk-chunk-DNY43POY.module.min.js +0 -1
- package/dist/chunk-chunk-E7MIQX7D.module.min.js +0 -2
- package/dist/chunk-chunk-ES4DCG3L.module.min.js +0 -1
- package/dist/chunk-chunk-FAKO3RGQ.module.min.js +0 -2
- package/dist/chunk-chunk-H4PPRW6N.module.min.js +0 -1
- package/dist/chunk-chunk-IFYPMWKY.module.min.js +0 -1
- package/dist/chunk-chunk-J3ELI22J.module.min.js +0 -1
- package/dist/chunk-chunk-L6D3I3V7.module.min.js +0 -2
- package/dist/chunk-chunk-M337NY6L.module.min.js +0 -1
- package/dist/chunk-chunk-ODUZEEBH.module.min.js +0 -2
- package/dist/chunk-chunk-P6UBCMSQ.module.min.js +0 -2
- package/dist/chunk-chunk-QRIBHZYW.module.min.js +0 -1
- package/dist/chunk-chunk-RH5TSQPH.module.min.js +0 -1
- package/dist/chunk-chunk-STZFFTAN.module.min.js +0 -2
- package/dist/chunk-chunk-T27ZEV6A.module.min.js +0 -1
- package/dist/chunk-chunk-U3AGQ5EF.module.min.js +0 -2
- package/dist/chunk-chunk-W3DB2MN4.module.min.js +0 -2
- package/dist/chunk-chunk-WDIN4LRC.module.min.js +0 -1
- package/dist/chunk-chunk-XOYX77KF.module.min.js +0 -2
- package/dist/chunk-chunk-Z5KXAVQD.module.min.js +0 -2
- package/dist/chunk-chunk-ZCNBUZPL.module.min.js +0 -2
- package/dist/chunk-chunk-ZTNVDWAK.module.min.js +0 -2
|
@@ -39,7 +39,32 @@ export interface ThemeAwareProps {
|
|
|
39
39
|
legendLayout?: LegendLayout;
|
|
40
40
|
/** Prefix for SVG element IDs — used by renderDashboard to avoid collisions */
|
|
41
41
|
_idPrefix?: string;
|
|
42
|
+
/** Internal HOC-level legend/margin contract metadata. */
|
|
43
|
+
__explicitMargin?: unknown;
|
|
44
|
+
__autoLegendMargin?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The supplied legend already contains the chart HOC's inferred groups.
|
|
47
|
+
* Specialized charts use this when their semantic categories cannot be
|
|
48
|
+
* reconstructed from the lower-level frame data (for example Likert's
|
|
49
|
+
* split neutral buckets). Caller legend groups may still be composed into
|
|
50
|
+
* that complete value by the chart config.
|
|
51
|
+
*/
|
|
52
|
+
__legendIncludesAutomatic?: boolean;
|
|
42
53
|
}
|
|
54
|
+
type LegendPosition = "right" | "left" | "top" | "bottom";
|
|
55
|
+
type StaticLegendHostProps = ThemeAwareProps & {
|
|
56
|
+
legend?: unknown;
|
|
57
|
+
colorScheme?: string | string[] | Record<string, string>;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* The client HOCs reserve a stable legend gutter before layout. The static
|
|
61
|
+
* frame API still uses content measurement by default, but renderChart()
|
|
62
|
+
* marks HOC requests so both paths share that contract. An explicitly set
|
|
63
|
+
* side remains fully caller-controlled.
|
|
64
|
+
*/
|
|
65
|
+
export declare function hocLegendMarginMinimum(props: ThemeAwareProps, position: LegendPosition): number | undefined;
|
|
66
|
+
/** Whether the caller, rather than the HOC default, owns a legend side. */
|
|
67
|
+
export declare function hasExplicitLegendMargin(props: ThemeAwareProps, position: LegendPosition): boolean;
|
|
43
68
|
export declare function reserveStaticLegendMargin(margin: {
|
|
44
69
|
top: number;
|
|
45
70
|
right: number;
|
|
@@ -53,6 +78,8 @@ export declare function reserveStaticLegendMargin(margin: {
|
|
|
53
78
|
size: [number, number];
|
|
54
79
|
hasTitle?: boolean;
|
|
55
80
|
legendLayout?: LegendLayout;
|
|
81
|
+
minimumMargin?: number;
|
|
82
|
+
preserveExplicitMargin?: boolean;
|
|
56
83
|
}): void;
|
|
57
84
|
export declare function reserveLegendConfigMargin(margin: {
|
|
58
85
|
top: number;
|
|
@@ -66,6 +93,8 @@ export declare function reserveLegendConfigMargin(margin: {
|
|
|
66
93
|
size: [number, number];
|
|
67
94
|
hasTitle?: boolean;
|
|
68
95
|
legendLayout?: LegendLayout;
|
|
96
|
+
minimumMargin?: number;
|
|
97
|
+
preserveExplicitMargin?: boolean;
|
|
69
98
|
}): void;
|
|
70
99
|
export declare function renderLegendConfig(legend: unknown, options: {
|
|
71
100
|
theme: ReturnType<typeof resolveTheme>;
|
|
@@ -80,6 +109,34 @@ export declare function renderLegendConfig(legend: unknown, options: {
|
|
|
80
109
|
hasTitle?: boolean;
|
|
81
110
|
legendLayout?: LegendLayout;
|
|
82
111
|
idPrefix?: string;
|
|
112
|
+
reservedWidth?: number;
|
|
113
|
+
}): React.ReactNode;
|
|
114
|
+
/** Reserve the plot gutter for either a supplied legend config or categories. */
|
|
115
|
+
export declare function reserveFrameLegendMargin(margin: {
|
|
116
|
+
top: number;
|
|
117
|
+
right: number;
|
|
118
|
+
bottom: number;
|
|
119
|
+
left: number;
|
|
120
|
+
}, options: {
|
|
121
|
+
props: StaticLegendHostProps;
|
|
122
|
+
categories: string[];
|
|
123
|
+
theme: ReturnType<typeof resolveTheme>;
|
|
124
|
+
size: [number, number];
|
|
125
|
+
hasTitle?: boolean;
|
|
126
|
+
}): LegendPosition;
|
|
127
|
+
/** Render caller-supplied or automatic categorical legends with one contract. */
|
|
128
|
+
export declare function renderFrameLegend(options: {
|
|
129
|
+
props: StaticLegendHostProps;
|
|
130
|
+
categories: string[];
|
|
131
|
+
theme: ReturnType<typeof resolveTheme>;
|
|
132
|
+
size: [number, number];
|
|
133
|
+
margin: {
|
|
134
|
+
top: number;
|
|
135
|
+
right: number;
|
|
136
|
+
bottom: number;
|
|
137
|
+
left: number;
|
|
138
|
+
};
|
|
139
|
+
hasTitle?: boolean;
|
|
83
140
|
}): React.ReactNode;
|
|
84
141
|
export declare function defaultTickFormat(v: number): string;
|
|
85
142
|
/** Render grid lines for XY charts */
|
|
@@ -154,6 +154,8 @@ export declare class GeoPipelineStore implements UpdateResultStore {
|
|
|
154
154
|
* (e.g., applyZoomScale), to avoid redundant scene builds.
|
|
155
155
|
*/
|
|
156
156
|
setRotation(rotation: [number, number, number]): void;
|
|
157
|
+
/** Whether a projection has been resolved by at least one scene compute. */
|
|
158
|
+
hasProjection(): boolean;
|
|
157
159
|
/** Get current rotation (for external tracking) */
|
|
158
160
|
getRotation(): [number, number, number];
|
|
159
161
|
/** Get the current base projection state (for zoom reset) */
|
|
@@ -51,6 +51,8 @@ interface GeoSVGOverlayProps {
|
|
|
51
51
|
y: number;
|
|
52
52
|
r: number;
|
|
53
53
|
}[];
|
|
54
|
+
/** Project geographic `[longitude, latitude]` annotation coordinates. */
|
|
55
|
+
geoProjection?: (longitude: number, latitude: number) => [number, number] | null;
|
|
54
56
|
}
|
|
55
57
|
/**
|
|
56
58
|
* The SVG chrome used by StreamGeoFrame.
|
|
@@ -3,18 +3,20 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Shared module used by Stream Frames for SSR rendering and
|
|
5
5
|
* by semiotic/server for static SVG export.
|
|
6
|
+
*
|
|
7
|
+
* Network, geo, and ordinal serializers live in sibling modules
|
|
8
|
+
* (SceneToSVGNetwork.tsx / SceneToSVGGeo.tsx / SceneToSVGOrdinal.tsx) and are
|
|
9
|
+
* re-exported below to keep this file under the file-size ratchet ceiling;
|
|
10
|
+
* low-level helpers shared across them (svgFill, safeSvgId, glyphNodeToSVG,
|
|
11
|
+
* buildRectSVGGradient, perCornerSvgPath, symbolSceneNodeToSVG, ARC_NOOP)
|
|
12
|
+
* live in sceneToSVGShared.tsx.
|
|
6
13
|
*/
|
|
7
14
|
import * as React from "react";
|
|
8
15
|
import type { SceneNode } from "./types";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
export { networkSceneNodeToSVG, networkSceneEdgeToSVG, networkLabelToSVG } from "./SceneToSVGNetwork";
|
|
17
|
+
export { geoSceneNodeToSVG } from "./SceneToSVGGeo";
|
|
18
|
+
export { ordinalSceneNodeToSVG } from "./SceneToSVGOrdinal";
|
|
12
19
|
export declare function xySceneNodeToSVG(node: SceneNode, i: number, idPrefix?: string): React.ReactNode;
|
|
13
|
-
export declare function networkSceneNodeToSVG(node: NetworkSceneNode, i: number): React.ReactNode;
|
|
14
|
-
export declare function networkSceneEdgeToSVG(edge: NetworkSceneEdge, i: number): React.ReactNode;
|
|
15
|
-
export declare function networkLabelToSVG(label: NetworkLabel, i: number): React.ReactNode;
|
|
16
|
-
export declare function ordinalSceneNodeToSVG(node: OrdinalSceneNode, i: number, idPrefix?: string): React.ReactNode;
|
|
17
|
-
export declare function geoSceneNodeToSVG(node: GeoSceneNode, i: number): React.ReactNode;
|
|
18
20
|
/**
|
|
19
21
|
* Returns true when running in a true server/Node.js context where
|
|
20
22
|
* window and document are not available.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scene graph → SVG element converters for the geo family.
|
|
3
|
+
*
|
|
4
|
+
* Split out of SceneToSVG.tsx (see scripts/file-size-policy.json) to keep
|
|
5
|
+
* that module under the file-size ratchet ceiling. Re-exported from
|
|
6
|
+
* SceneToSVG.tsx so existing imports are unaffected.
|
|
7
|
+
*/
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import type { GeoSceneNode } from "./geoTypes";
|
|
10
|
+
export declare function geoSceneNodeToSVG(node: GeoSceneNode, i: number): React.ReactNode;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scene graph → SVG element converters for the network family.
|
|
3
|
+
*
|
|
4
|
+
* Split out of SceneToSVG.tsx (see scripts/file-size-policy.json) to keep
|
|
5
|
+
* that module under the file-size ratchet ceiling. Re-exported from
|
|
6
|
+
* SceneToSVG.tsx so existing imports are unaffected.
|
|
7
|
+
*/
|
|
8
|
+
import * as React from "react";
|
|
9
|
+
import type { NetworkSceneNode, NetworkSceneEdge, NetworkLabel } from "./networkTypes";
|
|
10
|
+
export declare function networkSceneNodeToSVG(node: NetworkSceneNode, i: number): React.ReactNode;
|
|
11
|
+
export declare function networkSceneEdgeToSVG(edge: NetworkSceneEdge, i: number): React.ReactNode;
|
|
12
|
+
export declare function networkLabelToSVG(label: NetworkLabel, i: number): React.ReactNode;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ordinal scene graph → SVG element converter.
|
|
3
|
+
*
|
|
4
|
+
* Split out of SceneToSVG.tsx (which re-exports `ordinalSceneNodeToSVG`) to
|
|
5
|
+
* keep that file under the file-size ratchet ceiling. Shared helpers
|
|
6
|
+
* (svgFill, safeSvgId, glyphNodeToSVG, buildRectSVGGradient,
|
|
7
|
+
* perCornerSvgPath, symbolSceneNodeToSVG, ARC_NOOP) live in
|
|
8
|
+
* sceneToSVGShared.tsx so the XY and ordinal serializers agree on geometry.
|
|
9
|
+
*/
|
|
10
|
+
import * as React from "react";
|
|
11
|
+
import type { OrdinalSceneNode } from "./ordinalTypes";
|
|
12
|
+
export declare function ordinalSceneNodeToSVG(node: OrdinalSceneNode, i: number, idPrefix?: string): React.ReactNode;
|
|
@@ -17,6 +17,13 @@ export interface PaintCanvasBackgroundOptions {
|
|
|
17
17
|
width: number;
|
|
18
18
|
height: number;
|
|
19
19
|
}
|
|
20
|
+
export type CanvasBackgroundOptions = Pick<PaintCanvasBackgroundOptions, "background" | "hasBackgroundGraphics" | "themeBackground">;
|
|
21
|
+
/**
|
|
22
|
+
* Select the background token a canvas will attempt to paint. This is kept
|
|
23
|
+
* separate from the drawing operation so SVG layer composition can use the
|
|
24
|
+
* exact same visibility decision as the canvas renderer.
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveCanvasBackground(options: CanvasBackgroundOptions): string | null;
|
|
20
27
|
/**
|
|
21
28
|
* Paint an opaque chart background when appropriate.
|
|
22
29
|
* Returns true if a fill was applied.
|
|
@@ -44,6 +44,8 @@ export interface NetworkFramePaintContext {
|
|
|
44
44
|
};
|
|
45
45
|
setAnnotationFrame: (updater: (f: number) => number) => void;
|
|
46
46
|
scheduleNextFrame: () => void;
|
|
47
|
+
/** Resync color caches from scene fills after an invalidating rebuild. */
|
|
48
|
+
syncColorMap?: () => void;
|
|
47
49
|
}
|
|
48
50
|
/**
|
|
49
51
|
* Run one paint tick. Returns whether another rAF should be scheduled
|
|
@@ -5,7 +5,7 @@ type NetworkDatumComparator = {
|
|
|
5
5
|
bivarianceHack(a: Datum, b: Datum): number;
|
|
6
6
|
}["bivarianceHack"];
|
|
7
7
|
type NetworkGroupComparator = (a: number, b: number) => number;
|
|
8
|
-
import type {
|
|
8
|
+
import type { LegendLayout, LegendValue } from "../types/legendTypes";
|
|
9
9
|
import type { Style, DecayConfig, PulseConfig, TransitionConfig, StalenessConfig, ThemeSemanticColors, SceneDatum, SceneAccessibilityMetadata, SceneRenderMode } from "./types";
|
|
10
10
|
import type { AnimateProp } from "./pipelineTransitionUtils";
|
|
11
11
|
import type { NetworkSymbolName } from "./symbolPath";
|
|
@@ -616,9 +616,7 @@ export interface StreamNetworkFrameProps<T = Datum> extends StreamNetworkInterac
|
|
|
616
616
|
};
|
|
617
617
|
className?: string;
|
|
618
618
|
background?: string;
|
|
619
|
-
legend?:
|
|
620
|
-
legendGroups: LegendGroup[];
|
|
621
|
-
};
|
|
619
|
+
legend?: LegendValue;
|
|
622
620
|
legendPosition?: "right" | "left" | "top" | "bottom";
|
|
623
621
|
legendLayout?: LegendLayout;
|
|
624
622
|
legendHoverBehavior?: (item: {
|
|
@@ -28,6 +28,7 @@ export declare class PhysicsPipelineStore {
|
|
|
28
28
|
private simulationState;
|
|
29
29
|
private visible;
|
|
30
30
|
private world;
|
|
31
|
+
private quiescence;
|
|
31
32
|
constructor(config?: PhysicsPipelineConfig);
|
|
32
33
|
updateConfig(config: PhysicsPipelineConfig): void;
|
|
33
34
|
/** Additive explicit-result form of {@link updateConfig}. */
|
|
@@ -37,6 +38,15 @@ export declare class PhysicsPipelineStore {
|
|
|
37
38
|
/** Additive explicit-result form of {@link enqueue}. */
|
|
38
39
|
enqueueWithResult(spawn: PhysicsQueuedSpawn | PhysicsQueuedSpawn[], pacing?: PhysicsSpawnPacingOptions): UpdateResult;
|
|
39
40
|
spawnNow(spawn: PhysicsQueuedSpawn): void;
|
|
41
|
+
/**
|
|
42
|
+
* Materialize already-due queued spawns without advancing simulation time.
|
|
43
|
+
*
|
|
44
|
+
* Unlike {@link tick} / {@link settleWithObservations}, this runs while
|
|
45
|
+
* paused or hidden so seed bodies (`initialSpawns` with `spawnAt <= elapsed`)
|
|
46
|
+
* appear on the first paint of a paused snapshot frame. Future-paced queue
|
|
47
|
+
* items stay queued. Does not step the kernel.
|
|
48
|
+
*/
|
|
49
|
+
materializeDueSpawns(): string[];
|
|
40
50
|
clear(): void;
|
|
41
51
|
tick(deltaSeconds: number): PhysicsPipelineTickResult;
|
|
42
52
|
settle(maxSteps?: number): number;
|
|
@@ -49,6 +59,14 @@ export declare class PhysicsPipelineStore {
|
|
|
49
59
|
hitTest(x: number, y: number, radius?: number): PhysicsBodyState | null;
|
|
50
60
|
events(): PhysicsKernelEvent[];
|
|
51
61
|
allSleeping(): boolean;
|
|
62
|
+
/**
|
|
63
|
+
* True when the world is done moving — either every body has formally slept,
|
|
64
|
+
* or the whole system has stayed quiescent long enough that never-sleeping
|
|
65
|
+
* stragglers (mutually-leaning bodies, force-equilibrium tethers) should still
|
|
66
|
+
* count as settled. This is the gate for `shouldContinue` and the "settled"
|
|
67
|
+
* simulation state, so it decides when `rerunMS` re-arms.
|
|
68
|
+
*/
|
|
69
|
+
atRest(): boolean;
|
|
52
70
|
hasPendingWork(): boolean;
|
|
53
71
|
queueSize(): number;
|
|
54
72
|
liveBodyCount(): number;
|
|
@@ -81,6 +99,4 @@ export declare class PhysicsPipelineStore {
|
|
|
81
99
|
private observeBodyBudget;
|
|
82
100
|
private syncSimulationState;
|
|
83
101
|
private evictOverflow;
|
|
84
|
-
private absorbSediment;
|
|
85
|
-
private sleepingFirstEvictionOrder;
|
|
86
102
|
}
|
|
@@ -13,12 +13,19 @@ export interface StreamPhysicsPopOptions {
|
|
|
13
13
|
color?: string;
|
|
14
14
|
durationMs?: number;
|
|
15
15
|
radius?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Uniform multiplier on the whole burst geometry (ring + sparks). Defaults to
|
|
18
|
+
* 1. Shrink it for small charts — a sparkline can't hold a context-scale
|
|
19
|
+
* burst — without changing the removed body's `radius`.
|
|
20
|
+
*/
|
|
21
|
+
scale?: number;
|
|
16
22
|
}
|
|
17
23
|
export interface StreamPhysicsPopAnimation {
|
|
18
24
|
body: PhysicsBodyState;
|
|
19
25
|
color: string;
|
|
20
26
|
durationMs: number;
|
|
21
27
|
radius: number;
|
|
28
|
+
scale: number;
|
|
22
29
|
startedAt: number;
|
|
23
30
|
}
|
|
24
31
|
export declare function resolveBodyMark(body: PhysicsBodyState, style: Style): PhysicsBodyMark;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { PhysicsEngineAdapter } from "./PhysicsEngineAdapter";
|
|
2
|
+
import type { PhysicsSedimentAccumulator } from "./PhysicsSediment";
|
|
3
|
+
import type { PhysicsPipelineConfig } from "./PhysicsPipelineTypes";
|
|
4
|
+
import type { PhysicsPipelineEvictionResult } from "./physicsPipelineHelpers";
|
|
5
|
+
import type { PhysicsObservationContext } from "./physicsPipelineObservations";
|
|
6
|
+
export declare function selectEvictionCandidates(world: PhysicsEngineAdapter, eviction: PhysicsPipelineConfig["eviction"], liveBodyOrder: string[]): string[];
|
|
7
|
+
export declare function absorbPhysicsSediment(world: PhysicsEngineAdapter, sediment: PhysicsSedimentAccumulator, ids: string[], context: PhysicsObservationContext): string[];
|
|
8
|
+
/**
|
|
9
|
+
* Selects and removes overflow bodies past `bodyLimit`, absorbing them into
|
|
10
|
+
* sediment where applicable. Returns the surviving `liveBodyOrder` alongside
|
|
11
|
+
* the eviction result so the caller can commit both atomically.
|
|
12
|
+
*/
|
|
13
|
+
export declare function evictPhysicsOverflow(world: PhysicsEngineAdapter, sediment: PhysicsSedimentAccumulator, eviction: PhysicsPipelineConfig["eviction"], bodyLimit: number, liveBodyOrder: string[], context: PhysicsObservationContext): PhysicsPipelineEvictionResult & {
|
|
14
|
+
liveBodyOrder: string[];
|
|
15
|
+
};
|
|
@@ -10,5 +10,5 @@ export interface PhysicsObservationContext {
|
|
|
10
10
|
export declare function observePhysicsKernelEvents(world: PhysicsEngineAdapter, events: PhysicsKernelEvent[], context: PhysicsObservationContext): void;
|
|
11
11
|
export declare function observePhysicsSensorTransitions(world: PhysicsEngineAdapter, previousPairs: ReadonlySet<string>, context: PhysicsObservationContext): Set<string>;
|
|
12
12
|
export declare function removePhysicsSensorPairsForBodies(pairs: Set<string>, bodyIds: ReadonlySet<string>): void;
|
|
13
|
-
export declare function resolvePhysicsSimulationState(paused: boolean, visible: boolean, hasQueuedBodies: boolean,
|
|
13
|
+
export declare function resolvePhysicsSimulationState(paused: boolean, visible: boolean, hasQueuedBodies: boolean, atRest: boolean): PhysicsSimulationState;
|
|
14
14
|
export declare function emitPhysicsSimulationStateTransition(previous: PhysicsSimulationState, next: PhysicsSimulationState, context: PhysicsObservationContext): void;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PhysicsKernelOptions } from "./PhysicsKernel";
|
|
2
|
+
import type { PhysicsEngineAdapter } from "./PhysicsEngineAdapter";
|
|
3
|
+
/**
|
|
4
|
+
* Tracks sustained-quiescence as an "at rest" fallback for bodies that never
|
|
5
|
+
* formally sleep (see {@link QUIESCENT_AFTER_SECONDS}).
|
|
6
|
+
*/
|
|
7
|
+
export declare class PhysicsQuiescenceTracker {
|
|
8
|
+
private seconds;
|
|
9
|
+
private speed;
|
|
10
|
+
private scratch;
|
|
11
|
+
setKernelOptions(kernel: PhysicsKernelOptions | undefined): void;
|
|
12
|
+
reset(): void;
|
|
13
|
+
isAtRest(): boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Advance (or reset) the sustained-quiescence timer from the bodies' current
|
|
16
|
+
* speeds. A fresh spawn or any body moving faster than the quiescent speed
|
|
17
|
+
* resets it; otherwise it accrues the simulated delta.
|
|
18
|
+
*/
|
|
19
|
+
refresh(world: PhysicsEngineAdapter, deltaSeconds: number, spawnedCount: number): void;
|
|
20
|
+
}
|
|
@@ -23,5 +23,19 @@ export declare function renderSceneWithBackend<Node extends SceneLike>(args: {
|
|
|
23
23
|
renderMode: SceneRenderMode<Node> | undefined;
|
|
24
24
|
fallback: () => React.ReactNode;
|
|
25
25
|
}): React.ReactNode;
|
|
26
|
+
export interface RenderedSceneEntry<Node> {
|
|
27
|
+
node: Node;
|
|
28
|
+
element: React.ReactNode;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Render a scene once and retain only nodes that produced static output.
|
|
32
|
+
* Static evidence and SVG markup consume the same entries, preventing an
|
|
33
|
+
* unpaintable node from being reported as a successful rendered mark.
|
|
34
|
+
*/
|
|
35
|
+
export declare function renderSceneListWithBackend<Node extends SceneLike>(args: {
|
|
36
|
+
nodes: Node[];
|
|
37
|
+
renderMode: SceneRenderMode<Node> | undefined;
|
|
38
|
+
fallback: (node: Node, index: number) => React.ReactNode;
|
|
39
|
+
}): RenderedSceneEntry<Node>[];
|
|
26
40
|
export declare function resetRenderBackendWarningsForTests(): void;
|
|
27
41
|
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Low-level SVG serialization helpers shared across SceneToSVG.tsx,
|
|
3
|
+
* SceneToSVGNetwork.tsx, and SceneToSVGGeo.tsx. Split out so the three
|
|
4
|
+
* scene-family serializers can import a common base without a circular
|
|
5
|
+
* dependency between them.
|
|
6
|
+
*/
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
import type { DefaultArcObject } from "d3-shape";
|
|
9
|
+
import { type HatchFill } from "../charts/shared/hatchFill";
|
|
10
|
+
import type { GlyphDef } from "./glyphDef";
|
|
11
|
+
import type { RectSceneNode, Style, SymbolSceneNode } from "./types";
|
|
12
|
+
/**
|
|
13
|
+
* Sentinel arg for d3-shape arc generators that have all four
|
|
14
|
+
* accessors set to constants. The generator's call signature requires
|
|
15
|
+
* a `DefaultArcObject` even though it never reads the argument when
|
|
16
|
+
* accessors are non-functional. Typing this once avoids local unsafe casts at
|
|
17
|
+
* the arc-emit sites in the network/ordinal serializers.
|
|
18
|
+
*/
|
|
19
|
+
export declare const ARC_NOOP: DefaultArcObject;
|
|
20
|
+
export declare function svgFill(fill: string | HatchFill | CanvasPattern | undefined, fallback?: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Coerce a candidate SVG `id` value to the strict `[A-Za-z0-9_-]` charset.
|
|
23
|
+
* Scene-node keys embed user-provided category/group strings, which can
|
|
24
|
+
* contain spaces, colons, parentheses, or other characters that are either
|
|
25
|
+
* invalid in an SVG id or break a `url(#id)` reference. Non-matching
|
|
26
|
+
* characters are replaced with underscores; an empty/leading-digit result
|
|
27
|
+
* is prefixed so the final id is a legal SVG identifier.
|
|
28
|
+
*/
|
|
29
|
+
export declare function safeSvgId(candidate: string): string;
|
|
30
|
+
/**
|
|
31
|
+
* Shared SVG serializer for glyph nodes across all four pipelines — the
|
|
32
|
+
* composite-pictogram sibling of `symbolSceneNodeToSVG`. Callers pass the
|
|
33
|
+
* node's position explicitly (`x`/`y` for XY/ordinal/geo, `cx`/`cy` for
|
|
34
|
+
* network) so one implementation matches `glyphCanvasRenderer` exactly:
|
|
35
|
+
* anchor + scale transform, role-token paints, optional ghost silhouette,
|
|
36
|
+
* and a deterministic `clipPath` for partial fills.
|
|
37
|
+
*/
|
|
38
|
+
export declare function glyphNodeToSVG(g: {
|
|
39
|
+
size: number;
|
|
40
|
+
glyph: GlyphDef;
|
|
41
|
+
color?: string;
|
|
42
|
+
accent?: string;
|
|
43
|
+
fraction?: number;
|
|
44
|
+
fractionStart?: number;
|
|
45
|
+
fractionDirection?: "horizontal" | "vertical";
|
|
46
|
+
ghostColor?: string;
|
|
47
|
+
rotation?: number;
|
|
48
|
+
style: Style;
|
|
49
|
+
pointId?: string;
|
|
50
|
+
_decayOpacity?: number;
|
|
51
|
+
}, x: number, y: number, key: string): React.ReactNode;
|
|
52
|
+
export declare function colorStopElements(colorStops: Array<{
|
|
53
|
+
offset: number;
|
|
54
|
+
color: string;
|
|
55
|
+
}>): React.ReactElement[] | null;
|
|
56
|
+
/**
|
|
57
|
+
* Build `<defs><linearGradient>` for a bar's fillGradient, mirroring the
|
|
58
|
+
* tip→base direction the canvas renderer uses (inferred from roundedEdge).
|
|
59
|
+
* Returns null when the config can't resolve (e.g. colorStops < 2), so the
|
|
60
|
+
* caller falls back to a solid fill — same parity with the canvas path.
|
|
61
|
+
*
|
|
62
|
+
* Using `gradientUnits="userSpaceOnUse"` with absolute coords keeps each bar's
|
|
63
|
+
* gradient aligned to its own rect independent of the parent viewBox.
|
|
64
|
+
*/
|
|
65
|
+
export declare function buildRectSVGGradient(n: RectSceneNode, id: string): React.ReactElement | null;
|
|
66
|
+
/**
|
|
67
|
+
* Emit an SVG path string for a rect with per-corner radii. Same trace
|
|
68
|
+
* order as the canvas helper (CCW from top-left); shared shape utilities
|
|
69
|
+
* (`hasAnyCornerRadius`, `clampCornerRadii`) live in
|
|
70
|
+
* `./renderers/cornerRadii.ts` so both paint paths agree on geometry.
|
|
71
|
+
*/
|
|
72
|
+
export declare function perCornerSvgPath(n: RectSceneNode): string;
|
|
73
|
+
/**
|
|
74
|
+
* Shared SVG serializer for the XY/ordinal `SymbolSceneNode` (x/y-based) — the
|
|
75
|
+
* sibling of the network symbol case in `networkSceneNodeToSVG` (cx/cy). Both
|
|
76
|
+
* delegate glyph-path generation to `symbolPathString`, matching the canvas
|
|
77
|
+
* renderer exactly (fill only when a fill is set, so stroke-only glyphs stay
|
|
78
|
+
* unfilled in SSR too).
|
|
79
|
+
*/
|
|
80
|
+
export declare function symbolSceneNodeToSVG(n: SymbolSceneNode, i: number, idPrefix?: string): React.ReactNode;
|
|
@@ -457,6 +457,10 @@ export interface CandlestickSceneNode {
|
|
|
457
457
|
isUp: boolean;
|
|
458
458
|
/** Range/dumbbell mode — no body, endpoint dots instead */
|
|
459
459
|
isRange?: boolean;
|
|
460
|
+
/** Endpoint dot radius for range/dumbbell mode. Computed in the scene
|
|
461
|
+
* builder (which owns the layout height) so the canvas and SVG renderers
|
|
462
|
+
* paint identical bulbs. */
|
|
463
|
+
dotRadius?: number;
|
|
460
464
|
datum: SceneDatum;
|
|
461
465
|
accessibleDatum?: SceneAccessibilityMetadata["accessibleDatum"];
|
|
462
466
|
accessibility?: SceneAccessibilityMetadata["accessibility"];
|
|
@@ -60,10 +60,16 @@ export interface HydrationLifecycleOptions {
|
|
|
60
60
|
* `cancelIntroAnimation()`; the hook calls it when the SVG → canvas
|
|
61
61
|
* swap fires after SSR rehydration. (Currently every shipped store
|
|
62
62
|
* implements the method, but the optional shape lets a custom store
|
|
63
|
-
* opt out.)
|
|
63
|
+
* opt out.) `sceneNodes` + `markStylePaintPending()` let the hook
|
|
64
|
+
* repaint an already-built scene instead of forcing a rebuild (see the
|
|
65
|
+
* effect body); both are optional so a minimal custom store still works.
|
|
64
66
|
*/
|
|
65
67
|
storeRef: RefObject<{
|
|
66
68
|
cancelIntroAnimation?: () => void;
|
|
69
|
+
sceneNodes?: {
|
|
70
|
+
length: number;
|
|
71
|
+
};
|
|
72
|
+
markStylePaintPending?: () => void;
|
|
67
73
|
} | null>;
|
|
68
74
|
/**
|
|
69
75
|
* Mutable dirty flag the renderer reads on its next paint. The hook
|
|
@@ -8,4 +8,4 @@ import type { Datum } from "../../charts/shared/datumTypes";
|
|
|
8
8
|
*/
|
|
9
9
|
import type { CandlestickSceneNode, StreamLayout } from "../types";
|
|
10
10
|
import type { XYSceneContext } from "./types";
|
|
11
|
-
export declare function buildCandlestickScene(ctx: XYSceneContext, data: Datum[],
|
|
11
|
+
export declare function buildCandlestickScene(ctx: XYSceneContext, data: Datum[], layout: StreamLayout): CandlestickSceneNode[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CSSProperties, ReactElement } from "react";
|
|
1
|
+
import type { CSSProperties, ReactElement, ReactNode } from "react";
|
|
2
2
|
export type SupportedLegendGlyphs = "fill" | "line";
|
|
3
3
|
export type ItemType = SupportedLegendGlyphs | ((item: LegendItem) => ReactElement);
|
|
4
4
|
export interface LegendItem {
|
|
@@ -23,10 +23,23 @@ export interface GradientLegendConfig {
|
|
|
23
23
|
/** Optional format function for tick labels */
|
|
24
24
|
format?: (v: number) => string;
|
|
25
25
|
}
|
|
26
|
-
|
|
27
|
-
export declare function isLegendConfig(value: unknown): value is {
|
|
26
|
+
export interface CategoricalLegendConfig {
|
|
28
27
|
legendGroups: LegendGroup[];
|
|
28
|
+
}
|
|
29
|
+
/** Public legend slot accepted by stream frames and legend-aware chart HOCs. */
|
|
30
|
+
export type LegendValue = ReactNode | CategoricalLegendConfig | {
|
|
31
|
+
gradient: GradientLegendConfig;
|
|
29
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Compose inferred and caller-supplied legends without discarding either
|
|
35
|
+
* categorical domain. Configured groups are appended in argument order, so
|
|
36
|
+
* the chart's inferred series remain first and caller context follows.
|
|
37
|
+
* Gradient/custom-node legends remain exclusive slots; the last explicit
|
|
38
|
+
* value wins because those forms cannot be laid out as categorical groups.
|
|
39
|
+
*/
|
|
40
|
+
export declare function composeLegendConfigs(...values: Array<LegendValue | null | undefined | false>): LegendValue | undefined;
|
|
41
|
+
/** Type guard: categorical legend config */
|
|
42
|
+
export declare function isLegendConfig(value: unknown): value is CategoricalLegendConfig;
|
|
30
43
|
/** Type guard: gradient legend config */
|
|
31
44
|
export declare function isGradientLegendConfig(value: unknown): value is {
|
|
32
45
|
gradient: GradientLegendConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{forceCenter as e,forceCollide as t,forceLink as o,forceManyBody as n,forceSimulation as r,forceX as a,forceY as f}from"d3-force";function c(c,s,i={}){const d=i.seed??1,u=i.iterations??260,l=i.repulsion??5200,g=i.linkDistance??165,h=i.linkStrength??.045,b=i.centerStrength??.018,y=i.damping??.84,p=i.nodeRadius??12,m=i.nodePadding??3,M=i.inset??.06,x=function(e){let t=e>>>0;return function(){t=t+1831565813|0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}(d),S=new Map;for(const e of c)S.set(e.id,0);for(const e of s)S.set(e.source,(S.get(e.source)??0)+1),S.set(e.target,(S.get(e.target)??0)+1);const k=500,w=c.map(e=>({id:e.id,data:e,x:200+600*x(),y:200+600*x()})),q=new Set(c.map(e=>e.id)),v=s.filter(e=>q.has(e.source)&&q.has(e.target)).map(e=>({source:e.source,target:e.target}));if(u>0){const c=r(w).randomSource(x).alphaDecay(1-Math.pow(.001,1/u)).velocityDecay(Math.max(0,Math.min(1,1-y))).force("charge",n().strength(e=>{const t=S.get(e.id)??0;return 2.5*-Math.sqrt(l)*Math.sqrt(t+1)})).force("collide",t(e=>(e=>"function"==typeof p?p(e.data):p)(e)+m).strength(.9).iterations(2)).force("center",e(k,k).strength(.8)).force("x",a(k).strength(b)).force("y",f(k).strength(b));v.length>0&&c.force("link",o(v).id(e=>e.id).distance(g).strength(e=>{const t="string"==typeof e.source?e.source:e.source.id,o="string"==typeof e.target?e.target:e.target.id,n=Math.max(1,Math.min(S.get(t)??1,S.get(o)??1));return h/.045/n})),c.stop();for(let e=0;e<u;e+=1)c.tick()}let I=1/0,R=1/0,z=-1/0,$=-1/0;for(const e of w){const t=e.x??k,o=e.y??k;t<I&&(I=t),o<R&&(R=o),t>z&&(z=t),o>$&&($=o)}const E=z-I,_=$-R,C={};for(const e of w)C[e.id]={x:0===E?.5:M+((e.x??k)-I)/E*(1-2*M),y:0===_?.5:M+((e.y??k)-R)/_*(1-2*M)};return C}import{forceSimulation as s,forceCenter as i,forceX as d,forceY as u,forceLink as l,forceManyBody as g,forceCollide as h}from"d3-force";import{scaleLinear as b}from"d3-scale";function y(e){return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function p(e,t,o){const n=e=>e.toString(16).padStart(2,"0");return`#${n(e)}${n(t)}${n(o)}`}function m(e){const t=e.map(y),o=t.length-1;return e=>{if(e<=0){const[e,o,n]=t[0];return p(e,o,n)}if(e>=1){const[e,n,r]=t[o];return p(e,n,r)}const n=e*o,r=Math.floor(n),a=n-r,[f,c,s]=t[r],[i,d,u]=t[r+1];return p(Math.round(f+(i-f)*a),Math.round(c+(d-c)*a),Math.round(s+(u-s)*a))}}var M=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"];m(["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"]),m(["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"]),m(["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"]),m(["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"]),m(["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"]),m(["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"]),m(["#440154","#482878","#3e4989","#31688e","#26828e","#1f9e89","#35b779","#6ece58","#b5de2b","#fde725"]),m(["#0d0887","#41049d","#6a00a8","#8f0da4","#b12a90","#cb4679","#e16462","#f1844b","#fca636","#fcce25","#f0f921"]),m(["#000004","#160b39","#420a68","#6a176e","#932667","#bc3754","#dd513a","#f3771a","#fca50a","#f6d746","#fcffa4"]),m(["#000004","#140e36","#3b0f70","#641a80","#8c2981","#b73779","#de4968","#f7705c","#fe9f6d","#fecf92","#fcfdbf"]),m(["#00224e","#123570","#3b496c","#575d6d","#707173","#8a8678","#a59c74","#c3b369","#e1cc55","#fee838","#ffea46"]),m(["#23171b","#4a58dd","#3f9ee9","#46c7af","#7eed5a","#cdf134","#fbb91f","#f56918","#c52f06","#7a0403"]),m(["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"]),m(["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"]),m(["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"]),m(["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"]),m(["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"]),m(["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"]),m(["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"]);var x=new Set,S=new WeakMap;function k(e,t){if(!e||!e.data||"object"!=typeof e.data)return e;let o=S.get(e);if(o){const e=o.get(t);if(e)return e}else o=new Map,S.set(e,o);const n=new Proxy(e,{get(e,o,n){if("string"==typeof o&&!(o in e)&&e.data&&o in e.data){const e=`${t}:${o}`;x.has(e)||(x.add(e),console.warn(`[Semiotic] "${t}" callback accessed "${o}" on the wrapper object, but it only exists on ".data". Use d.data.${o} (or d.data?.${o}) instead. Frame callbacks receive RealtimeNode/RealtimeEdge wrappers, not your raw data.`))}return Reflect.get(e,o,n)}});return o.set(t,n),n}var w={supportsStreaming:!0,hierarchical:!1,computeLayout(e,t,o,n){if(0===e.length)return;const r=o.forceStrength??.1,a=n[0]/2,f=n[1]/2,c=o.__previousPositions;let b=0;const y=[];for(const t of e){const e=null!=t.x&&null!=t.y&&(0!==t.x||0!==t.y),o=c?.get(t.id);e?b++:o?(t.x=o.x,t.y=o.y,b++):y.push(t)}const p=e.length>0?y.length/e.length:1,m=b>0&&p<=.3;if(m){const o=new Map;for(const t of e)o.set(t.id,t);for(const e of y){const n=q(e.id,t,o);if(n.length>0){let t=0,o=0;for(const e of n)t+=e.x,o+=e.y;const r=v(e.id),a=r%360*(Math.PI/180),f=10+r%20;e.x=t/n.length+f*Math.cos(a),e.y=o/n.length+f*Math.sin(a)}else{const t=v(e.id),o=t%360*(Math.PI/180),n=15+t%30;e.x=a+n*Math.cos(o),e.y=f+n*Math.sin(o)}}}else{const t=Math.PI*(3-Math.sqrt(5));for(let o=0;o<e.length;o++){const n=e[o];if(null==n.x||null==n.y||0===n.x&&0===n.y){const e=10*Math.sqrt(o+.5),r=o*t;n.x=a+e*Math.cos(r),n.y=f+e*Math.sin(r)}}}const M=e.length,x=o.iterations??Math.max(50,Math.min(300,Math.floor(300-2*(M-30)))),S=o.__skipForceSimulation||0===o.iterations?0:m?40:x,k=I(o.nodeSize,o.nodeSizeRange,e),w=e=>k(e);if(S>0){const n=new Map,c=new Map;for(const t of e)n.set(t.id,0),c.set(t.id,t);for(const e of t){const t="string"==typeof e.source?e.source:e.source.id,o="string"==typeof e.target?e.target:e.target.id;n.set(t,(n.get(t)??0)+1),n.set(o,(n.get(o)??0)+1)}const b=l().strength(e=>{const t=e.weight,o="string"==typeof e.source?e.source:e.source.id,a="string"==typeof e.target?e.target:e.target.id,f=Math.max(1,Math.min(n.get(o)??1,n.get(a)??1)),c=t&&t>0?Math.sqrt(t):1;return Math.min(2.5,c*r/(.1*f))}).distance(e=>{const t="string"==typeof e.source?c.get(e.source):e.source,o="string"==typeof e.target?c.get(e.target):e.target,n=(t?w(t):0)+(o?w(o):0)+12;return Math.max(40,n)}).id(e=>e.id),y=s();if(void 0===o.random&&void 0===o.seed||y.randomSource(o.random??function(e){let t=e>>>0;return()=>{t+=1831565813;let e=t;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296}}(o.seed)),y.force("charge",g().strength(e=>{const t=n.get(e.id)??0;return-15*w(e)*Math.sqrt(t+1)})).force("collide",h(e=>w(e)+3).strength(.9).iterations(2)).force("center",i(a,f).strength(.8)).force("x",d(a).strength(.06)).force("y",u(f).strength(.06)),y.nodes(e),t.length>0){const e=t.map(e=>({...e,source:"string"==typeof e.source?e.source:e.source.id,target:"string"==typeof e.target?e.target:e.target.id}));b.links(e),y.force("link",b)}m?y.alpha(.3):y.alpha()<.1&&y.alpha(1),y.stop();for(let e=0;e<S;++e)y.tick()}for(const t of e){if(null==t.x||null==t.y)continue;const e=w(t);t.x=Math.max(e,Math.min(n[0]-e,t.x)),t.y=Math.max(e,Math.min(n[1]-e,t.y)),t.x0=0,t.x1=0,t.y0=0,t.y1=0}const R=new Map;for(const t of e)R.set(t.id,t);for(const e of t){if("string"==typeof e.source){const t=R.get(e.source);t&&(e.source=t)}if("string"==typeof e.target){const t=R.get(e.target);t&&(e.target=t)}}},buildScene(e,t,o,n){const r=o.nodeStyle,a=o.edgeStyle,f=I(o.nodeSize,o.nodeSizeRange,e),c=Array.isArray(o.colorScheme)?o.colorScheme:o.themeCategorical&&o.themeCategorical.length>0?o.themeCategorical:M,s=new Map;e.forEach((e,t)=>{s.set(e.id,c[t%c.length])});const i=[],d=[],u=[];for(const t of e){if(null==t.x||null==t.y)continue;const e=f(k(t,"nodeSize")),n=r?r(k(t,"nodeStyle")):{},a={fill:n.fill||s.get(t.id)||o.themeSemantic?.primary||"#007bff",stroke:n.stroke||o.themeSemantic?.surface||"#fff",strokeWidth:n.strokeWidth??2,opacity:n.opacity};i.push({type:"circle",cx:t.x,cy:t.y,r:e,style:a,datum:t,id:t.id,label:t.id})}const l=new Map;for(const t of e)l.set(t.id,t);for(const e of t){const t="object"==typeof e.source?e.source:l.get(e.source),n="object"==typeof e.target?e.target:l.get(e.target);if(!t||!n)continue;if(null==t.x||null==t.y)continue;if(null==n.x||null==n.y)continue;const r=a?a(k(e,"edgeStyle")):{},f={stroke:r.stroke||o.themeSemantic?.border||o.themeSemantic?.secondary||"#999",strokeWidth:r.strokeWidth??1,opacity:r.opacity??.6};d.push({type:"line",x1:t.x,y1:t.y,x2:n.x,y2:n.y,style:f,datum:e})}if(!1!==o.showLabels){const t=(g=o.nodeLabel)?"function"==typeof g?g:e=>e[g]||e.id:null;for(const o of e){if(null==o.x||null==o.y)continue;const e=t?t(o):o.id;if(!e)continue;const n=f(k(o,"nodeSize"));u.push({x:o.x,y:o.y-n-4,text:String(e),anchor:"middle",baseline:"auto",fontSize:11})}}var g;return{sceneNodes:i,sceneEdges:d,labels:u}}};function q(e,t,o){const n=[];for(const r of t){const t="string"==typeof r.source?r.source:r.source.id,a="string"==typeof r.target?r.target:r.target.id;let f=null;if(t===e?f=a:a===e&&(f=t),f){const e=o.get(f);!e||0===e.x&&0===e.y||n.push({x:e.x,y:e.y})}}return n}function v(e){let t=0;for(let o=0;o<e.length;o++)t=(t<<5)-t+e.charCodeAt(o)|0;return Math.abs(t)}function I(e,t,o){if(o.some(e=>null!=e.__forceRadius))return e=>e.__forceRadius??8;if(null==e)return()=>8;if("number"==typeof e)return()=>e;if("function"==typeof e)return t=>e(t)||8;const n=t||[5,20],r=[];for(const t of o){const o=t.data?.[e];"number"==typeof o&&r.push(o)}if(0===r.length)return()=>n[0];const[a,f]=function(e){let t=1/0,o=-1/0;for(const n of e)n<t&&(t=n),n>o&&(o=n);return[t,o]}(r);if(a===f)return()=>(n[0]+n[1])/2;const c=b().domain([a,f]).range(n).clamp(!0);return t=>{const o=t.data?.[e];return null==o||"number"!=typeof o?n[0]:c(o)}}self.onmessage=e=>{const t=e.data,o=t?.requestId,n=t?.request??t;try{if("normalized"===n.kind){const e=n.nodeRadii,t=e?{...n.options,nodeRadius:t=>e[t.id]??12}:n.options;return void self.postMessage({requestId:o,positions:c(n.nodes,n.edges,t)})}const e=n.nodes,t=n.edges;w.computeLayout(e,t,n.config,n.size),self.postMessage({requestId:o,positions:Object.fromEntries(e.map(e=>[e.id,{x:e.x,y:e.y}]))})}catch(e){self.postMessage({requestId:o,error:{message:e instanceof Error?e.message:String(e),name:e instanceof Error?e.name:"Error",stack:e instanceof Error?e.stack:void 0}})}};
|
|
1
|
+
import{forceCenter as e,forceCollide as t,forceLink as o,forceManyBody as n,forceSimulation as r,forceX as a,forceY as f}from"d3-force";function c(c,s,i={}){const d=i.seed??1,u=i.iterations??260,l=i.repulsion??5200,g=i.linkDistance??165,h=i.linkStrength??.045,y=i.centerStrength??.018,b=i.damping??.84,m=i.nodeRadius??12,p=i.nodePadding??3,M=i.inset??.06,x=function(e){let t=e>>>0;return function(){t=t+1831565813|0;let e=Math.imul(t^t>>>15,1|t);return e=e+Math.imul(e^e>>>7,61|e)^e,((e^e>>>14)>>>0)/4294967296}}(d),S=new Map;for(const e of c)S.set(e.id,0);for(const e of s)S.set(e.source,(S.get(e.source)??0)+1),S.set(e.target,(S.get(e.target)??0)+1);const k=500,w=c.map(e=>({id:e.id,data:e,x:200+600*x(),y:200+600*x()})),v=new Set(c.map(e=>e.id)),q=s.filter(e=>v.has(e.source)&&v.has(e.target)).map(e=>({source:e.source,target:e.target}));if(u>0){const c=r(w).randomSource(x).alphaDecay(1-Math.pow(.001,1/u)).velocityDecay(Math.max(0,Math.min(1,1-b))).force("charge",n().strength(e=>{const t=S.get(e.id)??0;return 2.5*-Math.sqrt(l)*Math.sqrt(t+1)})).force("collide",t(e=>(e=>"function"==typeof m?m(e.data):m)(e)+p).strength(.9).iterations(2)).force("center",e(k,k).strength(.8)).force("x",a(k).strength(y)).force("y",f(k).strength(y));q.length>0&&c.force("link",o(q).id(e=>e.id).distance(g).strength(e=>{const t="string"==typeof e.source?e.source:e.source.id,o="string"==typeof e.target?e.target:e.target.id,n=Math.max(1,Math.min(S.get(t)??1,S.get(o)??1));return h/.045/n})),c.stop();for(let e=0;e<u;e+=1)c.tick()}let z=1/0,I=1/0,R=-1/0,$=-1/0;for(const e of w){const t=e.x??k,o=e.y??k;t<z&&(z=t),o<I&&(I=o),t>R&&(R=t),o>$&&($=o)}const E=R-z,_=$-I,C={};for(const e of w)C[e.id]={x:0===E?.5:M+((e.x??k)-z)/E*(1-2*M),y:0===_?.5:M+((e.y??k)-I)/_*(1-2*M)};return C}import{forceSimulation as s,forceCenter as i,forceX as d,forceY as u,forceLink as l,forceManyBody as g,forceCollide as h}from"d3-force";import{scaleLinear as y}from"d3-scale";function b(e){return[parseInt(e.slice(1,3),16),parseInt(e.slice(3,5),16),parseInt(e.slice(5,7),16)]}function m(e,t,o){const n=e=>e.toString(16).padStart(2,"0");return`#${n(e)}${n(t)}${n(o)}`}function p(e){const t=e.map(b),o=t.length-1;return e=>{if(e<=0){const[e,o,n]=t[0];return m(e,o,n)}if(e>=1){const[e,n,r]=t[o];return m(e,n,r)}const n=e*o,r=Math.floor(n),a=n-r,[f,c,s]=t[r],[i,d,u]=t[r+1];return m(Math.round(f+(i-f)*a),Math.round(c+(d-c)*a),Math.round(s+(u-s)*a))}}var M=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"];p(["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"]),p(["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"]),p(["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"]),p(["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"]),p(["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"]),p(["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"]),p(["#440154","#482878","#3e4989","#31688e","#26828e","#1f9e89","#35b779","#6ece58","#b5de2b","#fde725"]),p(["#0d0887","#41049d","#6a00a8","#8f0da4","#b12a90","#cb4679","#e16462","#f1844b","#fca636","#fcce25","#f0f921"]),p(["#000004","#160b39","#420a68","#6a176e","#932667","#bc3754","#dd513a","#f3771a","#fca50a","#f6d746","#fcffa4"]),p(["#000004","#140e36","#3b0f70","#641a80","#8c2981","#b73779","#de4968","#f7705c","#fe9f6d","#fecf92","#fcfdbf"]),p(["#00224e","#123570","#3b496c","#575d6d","#707173","#8a8678","#a59c74","#c3b369","#e1cc55","#fee838","#ffea46"]),p(["#23171b","#4a58dd","#3f9ee9","#46c7af","#7eed5a","#cdf134","#fbb91f","#f56918","#c52f06","#7a0403"]),p(["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"]),p(["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"]),p(["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"]),p(["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"]),p(["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"]),p(["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"]),p(["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"]);var x=new Set,S=new WeakMap;function k(e,t){if(!e||!e.data||"object"!=typeof e.data)return e;let o=S.get(e);if(o){const e=o.get(t);if(e)return e}else o=new Map,S.set(e,o);const n=new Proxy(e,{get(e,o,n){if("string"==typeof o&&!(o in e)&&e.data&&o in e.data){const e=`${t}:${o}`;x.has(e)||(x.add(e),console.warn(`[Semiotic] "${t}" callback accessed "${o}" on the wrapper object, but it only exists on ".data". Use d.data.${o} (or d.data?.${o}) instead. Frame callbacks receive RealtimeNode/RealtimeEdge wrappers, not your raw data.`))}return Reflect.get(e,o,n)}});return o.set(t,n),n}var w={supportsStreaming:!0,hierarchical:!1,computeLayout(e,t,o,n){if(0===e.length)return;const r=o.forceStrength??.1,a=n[0]/2,f=n[1]/2,c=Math.max(.1,Math.min(1,Math.min(n[0],n[1])/200)),y=Math.min(.5,.06+1.8*(1-c)),b=o.__previousPositions;let m=0;const p=[];for(const t of e){const e=null!=t.x&&null!=t.y&&(0!==t.x||0!==t.y),o=b?.get(t.id);e?m++:o?(t.x=o.x,t.y=o.y,m++):p.push(t)}const M=e.length>0?p.length/e.length:1,x=m>0&&M<=.3;if(x){const o=new Map;for(const t of e)o.set(t.id,t);for(const e of p){const n=v(e.id,t,o);if(n.length>0){let t=0,o=0;for(const e of n)t+=e.x,o+=e.y;const r=q(e.id),a=r%360*(Math.PI/180),f=(10+r%20)*c;e.x=t/n.length+f*Math.cos(a),e.y=o/n.length+f*Math.sin(a)}else{const t=q(e.id),o=t%360*(Math.PI/180),n=(15+t%30)*c;e.x=a+n*Math.cos(o),e.y=f+n*Math.sin(o)}}}else{const t=Math.PI*(3-Math.sqrt(5));for(let o=0;o<e.length;o++){const n=e[o];if(null==n.x||null==n.y||0===n.x&&0===n.y){const e=10*Math.sqrt(o+.5)*c,r=o*t;n.x=a+e*Math.cos(r),n.y=f+e*Math.sin(r)}}}const S=e.length,k=o.iterations??Math.max(50,Math.min(300,Math.floor(300-2*(S-30)))),w=o.__skipForceSimulation||0===o.iterations?0:x?40:k,I=z(o.nodeSize,o.nodeSizeRange,e),R=e=>I(e);if(w>0){const b=new Map,m=new Map;for(const t of e)b.set(t.id,0),m.set(t.id,t);for(const e of t){const t="string"==typeof e.source?e.source:e.source.id,o="string"==typeof e.target?e.target:e.target.id;b.set(t,(b.get(t)??0)+1),b.set(o,(b.get(o)??0)+1)}const p=l().strength(e=>{const t=e.weight,o="string"==typeof e.source?e.source:e.source.id,n="string"==typeof e.target?e.target:e.target.id,a=Math.max(1,Math.min(b.get(o)??1,b.get(n)??1)),f=t&&t>0?Math.sqrt(t):1;return Math.min(2.5,f*r/(.1*a))}).distance(e=>{const t="string"==typeof e.source?m.get(e.source):e.source,o="string"==typeof e.target?m.get(e.target):e.target,n=(t?R(t):0)+(o?R(o):0)+Math.max(6,12*c);return Math.max(16,40*c,n)}).id(e=>e.id),M=s();if(void 0===o.random&&void 0===o.seed||M.randomSource(o.random??function(e){let t=e>>>0;return()=>{t+=1831565813;let e=t;return e=Math.imul(e^e>>>15,1|e),e^=e+Math.imul(e^e>>>7,61|e),((e^e>>>14)>>>0)/4294967296}}(o.seed)),M.force("charge",g().strength(e=>{const t=b.get(e.id)??0;return-15*c*R(e)*Math.sqrt(t+1)})).force("collide",h(e=>R(e)+3*c).strength(.9).iterations(2)).force("center",i(a,f).strength(.8)).force("x",d(a).strength(y)).force("y",u(f).strength(y)).force("bounds",function(e,t,o=2,n=.6){let r=[];const a=a=>{const f=n*Math.max(a,.2);for(const n of r){const r=n.x??e[0]/2,a=n.y??e[1]/2,c=n.vx??0,s=n.vy??0,i=t(n)+o,d=Math.min(e[0]/2,i),u=Math.max(e[0]/2,e[0]-i),l=Math.min(e[1]/2,i),g=Math.max(e[1]/2,e[1]-i),h=r+c,y=a+s;h<d?n.vx=c+(d-h)*f:h>u&&(n.vx=c+(u-h)*f),y<l?n.vy=s+(l-y)*f:y>g&&(n.vy=s+(g-y)*f)}};return a.initialize=e=>{r=e},a}(n,R)),M.nodes(e),t.length>0){const e=t.map(e=>({...e,source:"string"==typeof e.source?e.source:e.source.id,target:"string"==typeof e.target?e.target:e.target.id}));p.links(e),M.force("link",p)}x?M.alpha(.3):M.alpha()<.1&&M.alpha(1),M.stop();for(let e=0;e<w;++e)M.tick()}for(const t of e){if(null==t.x||null==t.y)continue;const e=R(t),o=w>0?2:0,r=Math.min(n[0]/2,e+o),a=Math.min(n[1]/2,e+o);t.x=Math.max(r,Math.min(n[0]-r,t.x)),t.y=Math.max(a,Math.min(n[1]-a,t.y)),t.x0=0,t.x1=0,t.y0=0,t.y1=0}const $=new Map;for(const t of e)$.set(t.id,t);for(const e of t){if("string"==typeof e.source){const t=$.get(e.source);t&&(e.source=t)}if("string"==typeof e.target){const t=$.get(e.target);t&&(e.target=t)}}},buildScene(e,t,o,n){const r=o.nodeStyle,a=o.edgeStyle,f=z(o.nodeSize,o.nodeSizeRange,e),c=Array.isArray(o.colorScheme)?o.colorScheme:o.themeCategorical&&o.themeCategorical.length>0?o.themeCategorical:M,s=new Map;e.forEach((e,t)=>{s.set(e.id,c[t%c.length])});const i=[],d=[],u=[];for(const t of e){if(null==t.x||null==t.y)continue;const e=f(k(t,"nodeSize")),n=r?r(k(t,"nodeStyle")):{},a={fill:n.fill||s.get(t.id)||o.themeSemantic?.primary||"#007bff",stroke:n.stroke||o.themeSemantic?.surface||"#fff",strokeWidth:n.strokeWidth??2,opacity:n.opacity};i.push({type:"circle",cx:t.x,cy:t.y,r:e,style:a,datum:t,id:t.id,label:t.id})}const l=new Map;for(const t of e)l.set(t.id,t);for(const e of t){const t="object"==typeof e.source?e.source:l.get(e.source),n="object"==typeof e.target?e.target:l.get(e.target);if(!t||!n)continue;if(null==t.x||null==t.y)continue;if(null==n.x||null==n.y)continue;const r=a?a(k(e,"edgeStyle")):{},f={stroke:r.stroke||o.themeSemantic?.border||o.themeSemantic?.secondary||"#999",strokeWidth:r.strokeWidth??1,opacity:r.opacity??.6};d.push({type:"line",x1:t.x,y1:t.y,x2:n.x,y2:n.y,style:f,datum:e})}if(!1!==o.showLabels){const t=(g=o.nodeLabel)?"function"==typeof g?g:e=>e[g]||e.id:null;for(const o of e){if(null==o.x||null==o.y)continue;const e=t?t(o):o.id;if(!e)continue;const n=f(k(o,"nodeSize"));u.push({x:o.x,y:o.y-n-4,text:String(e),anchor:"middle",baseline:"auto",fontSize:11})}}var g;return{sceneNodes:i,sceneEdges:d,labels:u}}};function v(e,t,o){const n=[];for(const r of t){const t="string"==typeof r.source?r.source:r.source.id,a="string"==typeof r.target?r.target:r.target.id;let f=null;if(t===e?f=a:a===e&&(f=t),f){const e=o.get(f);!e||0===e.x&&0===e.y||n.push({x:e.x,y:e.y})}}return n}function q(e){let t=0;for(let o=0;o<e.length;o++)t=(t<<5)-t+e.charCodeAt(o)|0;return Math.abs(t)}function z(e,t,o){if(o.some(e=>null!=e.__forceRadius))return e=>e.__forceRadius??8;if(null==e)return()=>8;if("number"==typeof e)return()=>e;if("function"==typeof e)return t=>e(t)||8;const n=t||[5,20],r=[];for(const t of o){const o=t.data?.[e];"number"==typeof o&&r.push(o)}if(0===r.length)return()=>n[0];const[a,f]=function(e){let t=1/0,o=-1/0;for(const n of e)n<t&&(t=n),n>o&&(o=n);return[t,o]}(r);if(a===f)return()=>(n[0]+n[1])/2;const c=y().domain([a,f]).range(n).clamp(!0);return t=>{const o=t.data?.[e];return null==o||"number"!=typeof o?n[0]:c(o)}}self.onmessage=e=>{const t=e.data,o=t?.requestId,n=t?.request??t;try{if("normalized"===n.kind){const e=n.nodeRadii,t=e?{...n.options,nodeRadius:t=>e[t.id]??12}:n.options;return void self.postMessage({requestId:o,positions:c(n.nodes,n.edges,t)})}const e=n.nodes,t=n.edges;w.computeLayout(e,t,n.config,n.size),self.postMessage({requestId:o,positions:Object.fromEntries(e.map(e=>[e.id,{x:e.x,y:e.y}]))})}catch(e){self.postMessage({requestId:o,error:{message:e instanceof Error?e.message:String(e),name:e instanceof Error?e.name:"Error",stack:e instanceof Error?e.stack:void 0}})}};
|