semiotic 3.7.1 → 3.7.3

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.
@@ -1,6 +1,7 @@
1
1
  import { ParticlePool } from "./ParticlePool";
2
2
  import type { ActiveTransition } from "./pipelineTransitionUtils";
3
- import type { NetworkPipelineConfig, NetworkSceneNode, NetworkSceneEdge, NetworkLabel, RealtimeNode, RealtimeEdge, EdgePush } from "./networkTypes";
3
+ import { type Quadtree } from "d3-quadtree";
4
+ import type { NetworkPipelineConfig, NetworkSceneNode, NetworkSceneEdge, NetworkCircleNode, NetworkLabel, RealtimeNode, RealtimeEdge, EdgePush } from "./networkTypes";
4
5
  import type { Datum } from "../charts/shared/datumTypes";
5
6
  /**
6
7
  * NetworkPipelineStore — stateful store for the StreamNetworkFrame.
@@ -15,12 +16,28 @@ export declare class NetworkPipelineStore {
15
16
  nodes: Map<string, RealtimeNode>;
16
17
  edges: Map<string, RealtimeEdge>;
17
18
  tension: number;
19
+ /**
20
+ * Monotonic scene/layout-rebuild counter — Network's equivalent of the
21
+ * `version` field on the XY/Ordinal/Geo stores. Shared cross-store
22
+ * convention: bumps on every layout rebuild and on clear(); never resets to
23
+ * a prior value, so a consumer comparing against a last-seen value can
24
+ * always detect "something changed."
25
+ */
18
26
  layoutVersion: number;
19
27
  sceneNodes: NetworkSceneNode[];
20
28
  sceneEdges: NetworkSceneEdge[];
21
29
  labels: NetworkLabel[];
22
30
  /** Overlays returned from customNetworkLayout (consumed by StreamNetworkFrame). */
23
31
  customLayoutOverlays: import("react").ReactNode;
32
+ private _nodeQuadtree;
33
+ private _maxNodeRadius;
34
+ /** Bumped whenever sceneNodes is rebuilt; keys the quadtree cache. */
35
+ private _sceneNodesRevision;
36
+ private _nodeQuadtreeRevision;
37
+ private static readonly QUADTREE_THRESHOLD;
38
+ private _nodesArrCache;
39
+ private _edgesArrCache;
40
+ private _arrCacheVersion;
24
41
  particlePool: ParticlePool | null;
25
42
  private config;
26
43
  private tensionConfig;
@@ -35,6 +52,8 @@ export declare class NetworkPipelineStore {
35
52
  private edgeTimestamps;
36
53
  /** Cached sorted node-timestamp entries for applyDecay(); null = needs rebuild */
37
54
  private _decaySortedNodes;
55
+ /** id→age-index map derived from _decaySortedNodes; rebuilt with it, not per frame. */
56
+ private _decayAgeMap;
38
57
  /** Node IDs added in the most recent layout */
39
58
  addedNodes: Set<string>;
40
59
  /** Node IDs removed in the most recent layout */
@@ -90,6 +109,32 @@ export declare class NetworkPipelineStore {
90
109
  * Build the scene graph from current layout positions.
91
110
  */
92
111
  buildScene(size: [number, number]): void;
112
+ /**
113
+ * Lazily (re)build the circle-node spatial index. Only built when the scene
114
+ * holds more than QUADTREE_THRESHOLD circle nodes (force/orbit graphs); for
115
+ * rect (sankey/treemap) and arc (chord) scenes — which carry far fewer marks
116
+ * and need area/angular hit logic — it stays null and the hit tester scans
117
+ * linearly. Always tracks `_maxNodeRadius` so the hit query can widen its
118
+ * search to cover the largest node.
119
+ */
120
+ private rebuildNodeQuadtree;
121
+ /**
122
+ * Circle-node spatial index for hit testing, or null when the scene is small
123
+ * or not circle-based. Rebuilt on demand only after the scene changed, so a
124
+ * settled graph indexes once and animation frames without a hover pay nothing.
125
+ */
126
+ get nodeQuadtree(): Quadtree<NetworkCircleNode> | null;
127
+ /** Largest circle-node radius in the current scene (widens the hit query). */
128
+ get maxNodeRadius(): number;
129
+ /**
130
+ * Per-frame-stable node/edge arrays (see field docs). Rebuilt only when
131
+ * layoutVersion changes — i.e. on a Map mutation, never on an animation tick.
132
+ */
133
+ private _ensureArrays;
134
+ /** Cached node array — safe only for read / position-mutate consumers. */
135
+ get nodesArray(): RealtimeNode[];
136
+ /** Cached edge array — safe only for read / position-mutate consumers. */
137
+ get edgesArray(): RealtimeEdge[];
93
138
  /** Whether the current layout plugin drives continuous animation (respects orbitAnimated config) */
94
139
  get isAnimating(): boolean;
95
140
  /**
@@ -174,6 +174,12 @@ export declare class PipelineStore {
174
174
  lastIngestTime: number;
175
175
  /** Unified color map cache keyed by sorted category set — shared across point, swarm, etc. */
176
176
  private _colorMapCache;
177
+ /** groupData() result cache. The line/area/stacked-area builders all re-bucket
178
+ * the same buffer by group on every scene build (twice per frame for stacked
179
+ * area); cache keyed on (_ingestVersion, group accessor, data ref) so a
180
+ * streaming push re-buckets once rather than per builder. Mirrors the
181
+ * resolveColorMap cache. Buckets are read-only downstream, so sharing is safe. */
182
+ private _groupDataCache;
177
183
  /** Separate group→color map for resolveGroupColor (insertion-order based, never invalidates _colorMapCache).
178
184
  * FIFO-bounded to `GROUP_COLOR_MAP_CAP` entries — in long-running streams with unique group IDs (e.g. UUIDs
179
185
  * as `lineBy` keys) this would otherwise grow unboundedly. Evicted groups that re-appear get a new palette
@@ -0,0 +1,19 @@
1
+ import type { StalenessConfig } from "./types";
2
+ interface StalenessBadgeProps {
3
+ isStale: boolean;
4
+ position?: StalenessConfig["badgePosition"];
5
+ }
6
+ /**
7
+ * Live/stale indicator chip shown in a corner of a streaming chart when
8
+ * `staleness.showBadge` is set.
9
+ *
10
+ * Shared by all four Stream Frames (XY / ordinal / network / geo) so the badge
11
+ * is pixel-identical across families. Previously each frame inlined its own
12
+ * copy and they had drifted — the network frame used a smaller, heavier variant
13
+ * (10px/700, tighter padding, letterSpacing). This is the canonical style: the
14
+ * more legible 11px/600 the other three shared, plus `zIndex`/`pointerEvents`
15
+ * hardening so the badge always sits above the canvas and never intercepts
16
+ * pointer events.
17
+ */
18
+ export declare function StalenessBadge({ isStale, position }: StalenessBadgeProps): import("react").JSX.Element;
19
+ export {};
@@ -13,10 +13,16 @@ export interface QuadtreeHit<T> {
13
13
  * much larger visual radius can still be a valid hit that `find()` would
14
14
  * hide.
15
15
  *
16
- * `T` must expose `x`, `y`, and `r` the standard `PointSceneNode` shape.
16
+ * For the standard `{ x, y, r }` node shape (e.g. `PointSceneNode`) call it
17
+ * without accessors. For nodes that store their center under different field
18
+ * names (e.g. network circle nodes use `cx`/`cy`) pass `getX`/`getY`/`getR` —
19
+ * the typed overload requires them, so an incompatible shape is a compile
20
+ * error rather than a runtime NaN. The quadtree itself must be built with
21
+ * matching `.x()`/`.y()` accessors.
17
22
  */
18
23
  export declare function findHitPointInQuadtree<T extends {
19
24
  x: number;
20
25
  y: number;
21
26
  r: number;
22
27
  }>(qt: Quadtree<T>, px: number, py: number, maxDistance: number, maxPointRadius: number): QuadtreeHit<T> | null;
28
+ export declare function findHitPointInQuadtree<T>(qt: Quadtree<T>, px: number, py: number, maxDistance: number, maxPointRadius: number, getX: (n: T) => number, getY: (n: T) => number, getR: (n: T) => number): QuadtreeHit<T> | null;