@aceshooting/lyra-ui 28.1.6 → 29.0.0
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/CHANGELOG.md +10 -180
- package/README.md +10 -2
- package/dist/components/charts/chart/chart.class.js +2 -2
- package/dist/components/data/data-grid/data-grid.class.js +1 -1
- package/dist/components/data/table/table.class.js +2 -2
- package/dist/components/forms/combobox/option.class.js +1 -1
- package/dist/components/forms/select/select.class.js +1 -1
- package/dist/components/media/map/map-loader.d.ts +9 -1
- package/dist/components/media/map/map-loader.js +1 -1
- package/dist/components/media/map/map.class.d.ts +20 -11
- package/dist/components/media/map/map.class.js +4 -4
- package/dist/components/retrieval/graph/graph-model.d.ts +10 -1
- package/dist/components/retrieval/graph/graph-spatial-controller.js +30 -0
- package/dist/components/retrieval/graph/graph-spatial.js +1 -0
- package/dist/components/retrieval/graph/graph.class.d.ts +45 -6
- package/dist/components/retrieval/graph/graph.class.js +2 -2
- package/dist/components/retrieval/graph/graph.styles.js +1 -1
- package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.d.ts +22 -5
- package/dist/components/retrieval/knowledge-graph-explorer/knowledge-graph-explorer.class.js +6 -2
- package/dist/events.d.ts +10 -5
- package/dist/framework-types.d.ts +1 -1
- package/dist/internal/accessible-text-controller.js +1 -1
- package/dist/internal/autoloader-manifest.js +1 -1
- package/dist/internal/collection-source-tracker.js +1 -0
- package/dist/internal/default-strings/media.generated.js +1 -1
- package/dist/internal/default-strings/retrieval.generated.js +1 -1
- package/dist/internal/localization-types.d.ts +1 -1
- package/dist/internal/localization.js +1 -1
- package/dist/internal/package-metadata.js +1 -1
- package/dist/internal/positioner.js +1 -1
- package/dist/lyra.d.ts +1 -1
- package/llms/components/lr-geojson-viewer.md +1 -1
- package/llms/components/lr-graph.md +78 -8
- package/llms/components/lr-knowledge-graph-explorer.md +15 -2
- package/llms/components/lr-map.md +60 -25
- package/llms/index.md +1 -1
- package/llms/peers.md +4 -3
- package/llms/shared/ai-and-peers.md +4 -3
- package/llms/shared/imports-and-registration.md +1 -1
- package/llms/shared.md +5 -4
- package/locales.json +138 -138
- package/package.json +12 -6
- package/registrations.json +1 -1
- package/skills/lyra-ui/SKILL.md +8 -3
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type{LyraEventDetailSnapshot}from'../../../internal/lyra-element.js';import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraNodeTypeStyle}from'../../../internal/node-type-style.js';export type{LyraNodeTypeStyle}from'../../../internal/node-type-style.js';import{type LyraGraphCommunity,type LyraGraphEdge,type LyraGraphNode}from'./graph-model.js';export type{LyraGraphCommunity,LyraGraphEdge,LyraGraphNode,}from'./graph-model.js';import'../../overlays/skeleton/skeleton.class.js';export type LyraGraphLayout='force'|'layered';export type LyraGraphRenderer='svg'|'canvas';export type LyraGraphSelectionMode='none'|'single'|'multiple';export type LyraGraphPickKind='node'|'link';
|
|
1
|
+
import type{LyraEventDetailSnapshot}from'../../../internal/lyra-element.js';import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraNodeTypeStyle}from'../../../internal/node-type-style.js';export type{LyraNodeTypeStyle}from'../../../internal/node-type-style.js';import{type LyraGraphCamera,type LyraGraphPosition,type LyraGraphView,type LyraGraphCommunity,type LyraGraphEdge,type LyraGraphNode}from'./graph-model.js';export type{LyraGraphCamera,LyraGraphPosition,LyraGraphView,LyraGraphCommunity,LyraGraphEdge,LyraGraphNode,}from'./graph-model.js';import'../../overlays/skeleton/skeleton.class.js';export type LyraGraphLayout='force'|'layered';export type LyraGraphRenderer='svg'|'canvas';export type LyraGraphSelectionMode='none'|'single'|'multiple';export type LyraGraphPickKind='node'|'link';
|
|
2
2
|
/** See `nodeLabels`'s own doc for the per-renderer default when unset. */
|
|
3
3
|
export type LyraGraphNodeLabelsMode='always'|'zoom'|'none';
|
|
4
4
|
/** See `fitTo`'s own doc. `'none'` keeps the numeric `width`/`height` as the drawing space;
|
|
5
5
|
* `'container'` measures the host's own content box instead. */
|
|
6
|
-
export type LyraGraphFit='none'|'container';export type{LyraScoreThresholds}from'../../../internal/score-tiers.js';export interface LyraGraphEventMap{'lr-node-activate':CustomEvent<{nodeId:string;x:number;y:number;}>;'lr-edge-activate':CustomEvent<{sourceNodeId:string;targetNodeId:string;edgeId?:string;}>;'lr-node-enter':CustomEvent<{nodeId:string;}>;'lr-node-leave':CustomEvent<{nodeId:string;}>;
|
|
6
|
+
export type LyraGraphFit='none'|'container';export type{LyraScoreThresholds}from'../../../internal/score-tiers.js';export interface LyraGraphEventMap{'lr-node-activate':CustomEvent<{nodeId:string;x:number;y:number;z?:number;}>;'lr-camera-change':CustomEvent<{camera:LyraGraphCamera;}>;'lr-view-change':CustomEvent<{view:LyraGraphView;}>;'lr-edge-activate':CustomEvent<{sourceNodeId:string;targetNodeId:string;edgeId?:string;}>;'lr-node-enter':CustomEvent<{nodeId:string;}>;'lr-node-leave':CustomEvent<{nodeId:string;}>;
|
|
7
7
|
/** An edge was hovered. */
|
|
8
8
|
'lr-edge-enter':CustomEvent<{sourceNodeId:string;targetNodeId:string;edgeId?:string;}>;
|
|
9
9
|
/** The hover from `lr-edge-enter` ended. */
|
|
@@ -15,7 +15,19 @@ export type LyraGraphFit='none'|'container';export type{LyraScoreThresholds}from
|
|
|
15
15
|
/**
|
|
16
16
|
* `<lr-graph>` — a force-directed node-link diagram with pan/zoom/drag.
|
|
17
17
|
* Requires the optional peer deps `d3-force`/`d3-drag`/`d3-zoom`/`d3-selection`
|
|
18
|
-
* (lazy-loaded
|
|
18
|
+
* (lazy-loaded only for the default `view="2d"`).
|
|
19
|
+
*
|
|
20
|
+
* `view="3d"` projects real `node.position` x/y/z coordinates through an orbit camera onto a
|
|
21
|
+
* canvas, with near clipping, depth-ordered links/nodes and frontmost picking. Missing positions
|
|
22
|
+
* receive deterministic spherical placement. No simulation, automatic rotation or animation runs
|
|
23
|
+
* in this view. `renderer`, `layout`, `seed`, `chargeStrength` and `edgeDistance` apply only to 2D.
|
|
24
|
+
* Community hull painting is 2D-only; community activation remains available in `view="list"`.
|
|
25
|
+
* `view="list"` provides visible paginated buttons for every node, link and community. Both views
|
|
26
|
+
* work without d3. The spatial toolbar switches between 3D and list and provides camera controls.
|
|
27
|
+
* Drag to orbit, Shift-drag to pan; wheel over the focused canvas to zoom. On the canvas, arrows
|
|
28
|
+
* orbit, Shift-arrows pan, +/- zoom and Home fits. Horizontal keys respect inherited direction.
|
|
29
|
+
* `fit()` and `focusNode()` update the spatial camera immediately, including under reduced motion.
|
|
30
|
+
* Per-node/edge SVG parts are unavailable in 3D, just as in the 2D canvas renderer.
|
|
19
31
|
*
|
|
20
32
|
* Set `seed` for a deterministic layout: node initial positions become
|
|
21
33
|
* reproducible (keyed by node id) and the settle happens synchronously
|
|
@@ -61,6 +73,11 @@ export type LyraGraphFit='none'|'container';export type{LyraScoreThresholds}from
|
|
|
61
73
|
*
|
|
62
74
|
* @event lr-node-activate - Pointer or keyboard node activation with `{ nodeId, x, y }` detail;
|
|
63
75
|
* `x` and `y` are the node's current coordinates in the graph's local drawing space.
|
|
76
|
+
* Spatial/list activation returns world x/y and adds `z`; these are never screen pixels.
|
|
77
|
+
* @event lr-camera-change - Spatial camera changed by a gesture, fit or focus, with `{ camera }`.
|
|
78
|
+
* Coalesced to one event per animation frame. Property assignments are silent.
|
|
79
|
+
* @event lr-view-change - User switched the spatial toolbar view, with `{ view }`.
|
|
80
|
+
* Programmatic `view` assignments are silent.
|
|
64
81
|
* @event lr-edge-activate - Pointer or keyboard edge activation with
|
|
65
82
|
* `{ sourceNodeId, targetNodeId, edgeId? }` detail.
|
|
66
83
|
* @event lr-node-enter - A node was hovered. `detail: { nodeId }`. Suppressed while dragging or
|
|
@@ -109,6 +126,14 @@ export type LyraGraphFit='none'|'container';export type{LyraScoreThresholds}from
|
|
|
109
126
|
* @csspart limit - Localized source/retained notice when the public node or link snapshot truncates.
|
|
110
127
|
* @csspart error - Static visible error shown instead of the graph when the optional `d3` peer
|
|
111
128
|
* dependency is not installed; its transition is announced through a shared light-DOM alert.
|
|
129
|
+
* @csspart spatial-toolbar - View switch and spatial camera controls.
|
|
130
|
+
* @csspart spatial-control - A view, camera or pagination button.
|
|
131
|
+
* @csspart spatial-canvas - Perspective drawing surface in view="3d".
|
|
132
|
+
* @csspart spatial-instructions - Visible keyboard and pointer camera instructions.
|
|
133
|
+
* @csspart spatial-list - Scrollable visible data list in view="list" or when canvas is unavailable.
|
|
134
|
+
* @csspart spatial-list-item - A graph item activation button in the visible list.
|
|
135
|
+
* @csspart spatial-page-count - Visible page and item count.
|
|
136
|
+
* @csspart spatial-pagination - Previous and next list page controls.
|
|
112
137
|
* @csspart canvas - The single canvas surface (`renderer="canvas"` only).
|
|
113
138
|
* @csspart tooltip - The hover tooltip (`renderer="canvas"` only; the SVG `<title>` replacement).
|
|
114
139
|
* @csspart cursor-items - The semantic list containing the active virtual cursor (`renderer="canvas"` only).
|
|
@@ -163,7 +188,14 @@ nodeTypes:readonly LyraNodeTypeStyle[];
|
|
|
163
188
|
hiddenTypes:readonly string[];
|
|
164
189
|
/** Renders one translucent hull per entry, behind links/nodes. Membership is the union of
|
|
165
190
|
* `memberIds` and every node whose `communityId` matches this entry's `id`. */
|
|
166
|
-
communities:readonly LyraGraphCommunity[];private normalizedGraphModel?;private normalizedGraphSources?;private get graphModel();private
|
|
191
|
+
communities:readonly LyraGraphCommunity[];private normalizedGraphModel?;private normalizedGraphSources?;private get graphModel();private _view;
|
|
192
|
+
/** Default '2d' preserves existing SVG/canvas layouts. '3d' uses perspective and true x/y/z
|
|
193
|
+
* positions; 'list' provides visible paginated activation. The latter two need no optional peer. */
|
|
194
|
+
get view():LyraGraphView;set view(value:LyraGraphView);private _camera?;
|
|
195
|
+
/** Optional spatial camera input, defensively copied. Angles are radians; distance and target
|
|
196
|
+
* use graph units. Gestures update internal state and emit lr-camera-change, not this input.
|
|
197
|
+
* Omission fits the initial spatial scene. Invalid numeric fields use a safe default. */
|
|
198
|
+
get camera():LyraGraphCamera|undefined;set camera(value:LyraGraphCamera|undefined);private _layout;
|
|
167
199
|
/** `'force'` (default) runs the existing d3-force simulation, untouched. `'layered'` computes a
|
|
168
200
|
* deterministic Sugiyama-lite layout (`src/internal/layered-layout.ts`, a shared,
|
|
169
201
|
* dependency-free util suitable for any future layered-diagram consumer) instead -- no settle
|
|
@@ -261,7 +293,7 @@ selectedEdgeIds:readonly string[];
|
|
|
261
293
|
dimmedNodeIds:readonly string[];
|
|
262
294
|
/** Same contract as `dimmedNodeIds`, for edges. An edge's dimming key is the same `linkKey()`
|
|
263
295
|
* value (`LyraGraphEdge.id`, else `` `${source}->${target}` ``) `selectedEdgeIds` already uses. */
|
|
264
|
-
dimmedEdgeIds:readonly string[];private readonly arrowMarkerId;private loading;private loadFailed;private loadLibrary;private loadGeneration;private containerSize;private simNodes;private simLinks;private simNodeById;private danglingLinks;private lastPositionById;private lastHiddenNodeCount;private activeGraphItem;private graphLiveText;private readonly announcements;private graphAnnouncementsReady;private pendingGraphItemFocus;private isMounting;private authorRole;private syncingGraphHostRole;private simulation?;private chargeForce?;private linkForce?;private d3?;private detachedGraphChanges;private zoomedEl?;private gEl?;private zoomBehavior?;private boundNodeEls;private nodeEls;private nodeHitEls;private nodeLabelEls;private expandIndicatorEls;private lastKeyActivateIndex;private lastKeyActivateTime;private lastActivation?;private lastAppliedFocusNodeId;private focusHaloEl?;private communityHullEls;private communityHullHitEls;private communityLabelEls;private canvasEl?;private canvasCtx?;private pickCanvas?;private pickCtx?;private hostResizeObserver?;private hostResizeObserverDocument?;private canvasDprQuery?;private canvasDrawRafId?;private canvasDrawRafOwner?;private visible;private intersectionObserver?;private canvasDrawPending;private pickDirty;private canvasCamera;private canvasTooltipEl?;private pickItems;private canvasDragNode?;private canvasPointerId?;private canvasPointerDownAt?;private canvasPointerDownId?;private pendingHover?;private canvasHover?;private hoverRafId?;private hoverRafOwner?;private svgHoverNodeId?;private canvasScene?;private canvasSceneHasEdgeLabels;private cameraTweenId?;private cameraTweenFrameOwner?;private cameraTweenResolve?;private isCameraTweening;private viewportChangeRafId?;private viewportChangeRafOwner?;private linkEls;private linkHitEls;private linkLabelEls;private linkLabelHiddenByLength;private edgeLabelWidthCache;private danglingLinkEls;private edgeLabelMeasureCanvas?;private edgeLabelMeasureCtx?;private linkPaintProbe?;private readonly linkPaintVisibilityCache;private readonly resolvedCssColorCache;private reducedMotion;constructor();attributeChangedCallback(name:string,oldValue:string|null,value:string|null):void;private hostOwnsGraphSemantics;private syncGraphHostRole;private get ownerWindow();private computedStyle;connectedCallback():void;disconnectedCallback():void;adoptedCallback():void;private scheduleViewportChange;private nodeRadius;private safeLinkWidth;private isInteractiveLink;private navigableLinksCache?;private navigableLinks;private lengthInPixels;private get requestedWidth();private get requestedHeight();private get safeWidth();private get safeHeight();private recordContainerSize;private measureHostBox;private syncRequestedHeightVar;private get safeMinZoom();private get safeMaxZoom();private get effectiveZoomBounds();private get safeEdgeLabelMinZoom();private get resolvedNodeLabelsMode();private canvasNodeLabelsVisible;private get safeSeed();private get safeChargeStrength();private get safeLinkDistance();private nodeTypeIndex?;private nodeTypeEntry;private resolveNodeType;private nodeShape;private labeledNodeTypes;private nodeFill;private visibleNodes;private resolveLinksAgainst;private communityMembers;private visibleCommunitiesCache?;private visibleCommunities;private communityHull;private onCommunityClick;private cameraTransitionMs;private cancelCameraTween;private isApplyingZoomTransform;private applyZoomTransform;private tweenCamera;
|
|
296
|
+
dimmedEdgeIds:readonly string[];private readonly arrowMarkerId;private loading;private loadFailed;private loadLibrary;private loadGeneration;private containerSize;private simNodes;private simLinks;private simNodeById;private danglingLinks;private lastPositionById;private lastHiddenNodeCount;private activeGraphItem;private graphLiveText;private readonly announcements;private graphAnnouncementsReady;private pendingGraphItemFocus;private isMounting;private authorRole;private syncingGraphHostRole;private simulation?;private chargeForce?;private linkForce?;private d3?;private detachedGraphChanges;private zoomedEl?;private gEl?;private zoomBehavior?;private boundNodeEls;private nodeEls;private nodeHitEls;private nodeLabelEls;private expandIndicatorEls;private lastKeyActivateIndex;private lastKeyActivateTime;private lastActivation?;private lastAppliedFocusNodeId;private focusHaloEl?;private communityHullEls;private communityHullHitEls;private communityLabelEls;private canvasEl?;private canvasCtx?;private pickCanvas?;private pickCtx?;private hostResizeObserver?;private hostResizeObserverDocument?;private canvasDprQuery?;private canvasDrawRafId?;private canvasDrawRafOwner?;private visible;private intersectionObserver?;private canvasDrawPending;private pickDirty;private canvasCamera;private canvasTooltipEl?;private pickItems;private canvasDragNode?;private canvasPointerId?;private canvasPointerDownAt?;private canvasPointerDownId?;private pendingHover?;private canvasHover?;private hoverRafId?;private hoverRafOwner?;private svgHoverNodeId?;private canvasScene?;private canvasSceneHasEdgeLabels;private cameraTweenId?;private cameraTweenFrameOwner?;private cameraTweenResolve?;private isCameraTweening;private viewportChangeRafId?;private viewportChangeRafOwner?;private linkEls;private linkHitEls;private linkLabelEls;private linkLabelHiddenByLength;private edgeLabelWidthCache;private danglingLinkEls;private edgeLabelMeasureCanvas?;private edgeLabelMeasureCtx?;private linkPaintProbe?;private readonly linkPaintVisibilityCache;private readonly resolvedCssColorCache;private reducedMotion;private readonly spatial;private spatialMessages;constructor();attributeChangedCallback(name:string,oldValue:string|null,value:string|null):void;private hostOwnsGraphSemantics;private syncGraphHostRole;private get ownerWindow();private computedStyle;connectedCallback():void;private connect2d;disconnectedCallback():void;adoptedCallback():void;private scheduleViewportChange;private nodeRadius;private safeLinkWidth;private isInteractiveLink;private navigableLinksCache?;private navigableLinks;private lengthInPixels;private get requestedWidth();private get requestedHeight();private get safeWidth();private get safeHeight();private recordContainerSize;private measureHostBox;private syncRequestedHeightVar;private get safeMinZoom();private get safeMaxZoom();private get effectiveZoomBounds();private get safeEdgeLabelMinZoom();private get resolvedNodeLabelsMode();private canvasNodeLabelsVisible;private get safeSeed();private get safeChargeStrength();private get safeLinkDistance();private nodeTypeIndex?;private nodeTypeEntry;private resolveNodeType;private nodeShape;private labeledNodeTypes;private nodeFill;private visibleNodes;private resolveLinksAgainst;private communityMembers;private visibleCommunitiesCache?;private visibleCommunities;private communityHull;private onCommunityClick;private cameraTransitionMs;private cancelCameraTween;private isApplyingZoomTransform;private applyZoomTransform;private tweenCamera;
|
|
265
297
|
/** Animates the camera so `id` centers in the viewport (the `width` x `height` viewBox), at
|
|
266
298
|
* `options.zoom` (clamped to `[minZoom, maxZoom]`) or the current scale when omitted. Resolves
|
|
267
299
|
* `true` on arrival; `false` for an id with no matching entry in `simNodes` -- there's nothing
|
|
@@ -274,4 +306,11 @@ focusNode(id:string,options?:{zoom?:number;}):Promise<boolean>;
|
|
|
274
306
|
* changed, so no announcement. A no-op with no visible nodes. */
|
|
275
307
|
fit(options?:{padding?:number;}):void;private updateFocusHalo;private setUpCanvasSurface;private ensureCanvasOwnerRealm;private syncHostResizeObserver;private watchHostResize;private watchCanvasDpr;private onCanvasDprChange;private markCanvasDirty;private markCanvasCameraDirty;private scheduleCanvasDraw;private resolveCssColorWithProbe;private createCanvasColorProbe;private withCanvasColorResolver;private buildCanvasScene;private updateCanvasFocus;private drawCanvas;private rebuildPickItems;private redrawPickCanvas;private hitTest;private bindCanvasZoom;private bindCanvasPointer;private onCanvasPointerDown;private onCanvasPointerMove;private simulationIsTicking;private onCanvasPointerUp;private finishCanvasNodeDrag;private takeCanvasPointerDown;private onCanvasPointerCancel;private onCanvasLostPointerCapture;private onCanvasPointerLeave;private canvasHoverSuppressed;private updateCanvasHover;private onCanvasDblClick;private nodeAtCanvasPoint;private updateCanvasTooltip;private isSelected;private paintedCurrent;private isDimmed;private linkKey;private emitSelectionIntent;private clearSelection;protected willUpdate(changed:PropertyValues):void;protected updated(changed:PropertyValues):void;private isDragging;private isPanning;private applyInteractions;private updateHitAreaZoomScale;private applyCanvasInteractions;private onTick;private rebuildSimulation;private announceHiddenNodeCount;private rebuildLayeredLayout;private onNodeClick;
|
|
276
308
|
/** Returns a node's current position in the graph's local drawing space. */
|
|
277
|
-
getNodePosition(id:string):{x:number;y:number;}|undefined;
|
|
309
|
+
getNodePosition(id:string):{x:number;y:number;}|undefined;
|
|
310
|
+
/** World x/y/z in spatial/list view, or undefined for a missing/hidden node or view="2d".
|
|
311
|
+
* The returned point is an immutable copy and never a projected screen position. */
|
|
312
|
+
getNodePosition3d(id:string):LyraGraphPosition|undefined;
|
|
313
|
+
/** Projected CSS pixels relative to this element's border-box top-left. Undefined for list
|
|
314
|
+
* view, missing/hidden nodes or a spatial point behind the near plane. Add the host's viewport
|
|
315
|
+
* rect left/top to anchor a viewport-positioned overlay. This method does not move the camera. */
|
|
316
|
+
getNodeScreenPosition(id:string):{x:number;y:number;}|undefined;private onLinkClick;private onNodeEnter;private onNodeLeave;private onNodeDblClick;private onLinkEnter;private linkHoverDetail;private onLinkLeave;private emitEdgeHover;private nodeAccessibleText;private boundedGraphText;private nodeTooltipText;private linkAccessibleText;private linkTooltipText;private linkCoordinates;private edgeLabelPosition;private edgeLabelFontPx;private edgeLabelContext;private edgeLabelWidth;private updateEdgeLabelZoomGate;private updateNodeLabelZoomGate;private linkIndexBase;private communityIndexBase;private graphItemCount;private normalizedGraphItem;private graphItemIdentity;private graphItemIndex;private communityText;private graphItemText;private graphItemAnnouncement;private onGraphItemFocus;private focusGraphItem;private focusGraphItemElement;private onGraphKeyDown;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-graph':LyraGraph;}}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{__decorate}from"tslib";import{collectionSupport,publicCollectionTruncation}from"../../../internal/collection-snapshot.js";import{html,nothing,svg}from"lit";import{property,state,query}from"lit/decorators.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{fitTransform}from"../../../internal/fit-transform.js";import{specialistTokens}from"../../../internal/specialist-host-tokens.styles.js";import{nextId,srOnly}from"../../../internal/a11y.js";import{prefersReducedMotion}from"../../../internal/motion.js";import{isRtl}from"../../../internal/rtl.js";import{literalSetConverter}from"../../../internal/converters.js";import{resolveCssTokenLength}from"../../../internal/css-token-length.js";import{styles}from"./graph.styles.js";import{loadD3}from"./graph-loader.js";import{convexHull,hullPathD,hullCentroidX,hullTopY}from"./graph-hull.js";import{EXPAND_BADGE_OFFSET,EXPAND_BADGE_R,drawGraphScene,drawPickingScene,pickColorToIndex,shapeHalfSide}from"./graph-canvas.js";import{layeredLayout}from"../../../internal/layered-layout.js";import{finiteNumber,finiteRange,finiteInteger,extent}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{sanitizeCssColor}from"../../../internal/safe-css.js";import{getOwnDataDescriptor,MISSING_OWN_DATA_DESCRIPTOR,UNSAFE_OWN_DATA_DESCRIPTOR}from"../../../internal/data-descriptors.js";import{shadowFocusTarget}from"../../../internal/active-element.js";import{ThemeWatcher}from"../../../internal/theme-watcher.js";import{devWarnOnce}from"../../../internal/dev-warning.js";import{copyGraphLinkIdentity,graphLengthConverter,graphLinkIdentity,normalizeGraphModel}from"./graph-model.js";import{canonicalIdentityList}from"../retrieval-identity.js";import{AnnouncementSinkController}from"../../../internal/announcer.js";import"../../overlays/skeleton/skeleton.class.js";import{LYRA_DEFAULT_graphCommunity,LYRA_DEFAULT_graphDataList,LYRA_DEFAULT_graphDataListLimit,LYRA_DEFAULT_graphDiagram,LYRA_DEFAULT_graphEdgeLimit,LYRA_DEFAULT_graphExpandableItem,LYRA_DEFAULT_graphItemAnnouncement,LYRA_DEFAULT_graphLink,LYRA_DEFAULT_graphMissingLibrary,LYRA_DEFAULT_graphNode,LYRA_DEFAULT_graphNodeFocused,LYRA_DEFAULT_graphNodeLimit,LYRA_DEFAULT_graphNodesHidden,LYRA_DEFAULT_graphSelectionCount,LYRA_DEFAULT_graphTypedNode}from"../../../internal/default-strings/retrieval.generated.js";import{LYRA_DEFAULT_loading,LYRA_DEFAULT_noData}from"../../../internal/default-strings/shared.generated.js";const GRAPH_LAYOUT=literalSetConverter(["force","layered"],"force"),STUB_OFFSET_PX=14,EDGE_LABEL_OFFSET_PX=4,DEFAULT_EDGE_LABEL_FONT_PX=10,EDGE_LABEL_LENGTH_GATE_RATIO=.85,EDGE_LABEL_WIDTH_CACHE_MAX=512,EXPAND_KEY_INTERVAL_MS=500,FOCUS_HALO_PADDING=6,HULL_PADDING=24,NODE_LABEL_MIN_ZOOM=.5,NODE_HIT_SEGMENT_HALF=.5;function ownGraphText(value,property2){const descriptor=getOwnDataDescriptor(value,property2);return descriptor===MISSING_OWN_DATA_DESCRIPTOR||descriptor===UNSAFE_OWN_DATA_DESCRIPTOR||typeof descriptor.value!="string"?void 0:descriptor.value}function ownGraphValue(value,property2){const descriptor=getOwnDataDescriptor(value,property2);return descriptor===MISSING_OWN_DATA_DESCRIPTOR||descriptor===UNSAFE_OWN_DATA_DESCRIPTOR?void 0:descriptor.value}function mulberry32(seed){let a=seed>>>0;return()=>{a=a+1831565813|0;let t=Math.imul(a^a>>>15,a|1);return t=t+Math.imul(t^t>>>7,t|61)^t,((t^t>>>14)>>>0)/4294967296}}function hashNodeSeed(seed,id){let h=seed>>>0;for(let i=0;i<id.length;i++)h=Math.imul(h^id.charCodeAt(i),2654435761),h^=h>>>15;return h>>>0}const MIN_RADIUS=6,MAX_RADIUS=24;function sanitizeNodeColor(color){return sanitizeCssColor(color)}function normalizeLinkDash(dash){if(!(!dash?.length||dash.some(value=>!Number.isFinite(value)||value<0)))return dash.join(" ")}function categoricalPaletteColor(index){return`var(--lr-graph-cat-${index%8+1})`}function squarePath(r){const s=shapeHalfSide(r);return`M ${-s} ${-s} L ${s} ${-s} L ${s} ${s} L ${-s} ${s} Z`}function diamondPath(r){const d=shapeHalfSide(r)*Math.SQRT2;return`M 0 ${-d} L ${d} 0 L 0 ${d} L ${-d} 0 Z`}function sameIds(a,b){return a===b?!0:!a||!b||a.length!==b.length?!1:a.every((id,index)=>id===b[index])}const identitySets=new WeakMap;function identitySet(values){const ids=canonicalIdentityList(values);let set=identitySets.get(ids);return set||identitySets.set(ids,set=new Set(ids)),set}class LyraGraph extends LyraElement{static{this.defaultStrings={...super.defaultStrings,graphCommunity:LYRA_DEFAULT_graphCommunity,graphDataList:LYRA_DEFAULT_graphDataList,graphDataListLimit:LYRA_DEFAULT_graphDataListLimit,graphDiagram:LYRA_DEFAULT_graphDiagram,graphEdgeLimit:LYRA_DEFAULT_graphEdgeLimit,graphExpandableItem:LYRA_DEFAULT_graphExpandableItem,graphItemAnnouncement:LYRA_DEFAULT_graphItemAnnouncement,graphLink:LYRA_DEFAULT_graphLink,graphMissingLibrary:LYRA_DEFAULT_graphMissingLibrary,graphNode:LYRA_DEFAULT_graphNode,graphNodeFocused:LYRA_DEFAULT_graphNodeFocused,graphNodeLimit:LYRA_DEFAULT_graphNodeLimit,graphNodesHidden:LYRA_DEFAULT_graphNodesHidden,graphSelectionCount:LYRA_DEFAULT_graphSelectionCount,graphTypedNode:LYRA_DEFAULT_graphTypedNode,loading:LYRA_DEFAULT_loading,noData:LYRA_DEFAULT_noData}}static{this.collectionSupport=collectionSupport}static{this.ownedCollectionProperties=Object.freeze(["nodes","edges","nodeTypes","hiddenTypes","communities","selectedNodeIds","selectedEdgeIds","dimmedNodeIds","dimmedEdgeIds"])}static get observedAttributes(){return[...new Set([...super.observedAttributes,"role"])]}static{this.styles=[LyraElement.styles,specialistTokens,styles,srOnly]}static{this.immutableEventDetails=Object.freeze(["lr-selection-change"])}get graphModel(){const sources=this.normalizedGraphSources;return(!sources||sources[0]!==this.nodes||sources[1]!==this.edges||sources[2]!==this.nodeTypes||sources[3]!==this.communities)&&(this.normalizedGraphSources=[this.nodes,this.edges,this.nodeTypes,this.communities],this.normalizedGraphModel=normalizeGraphModel(this.nodes,this.edges,this.nodeTypes,this.communities)),this.normalizedGraphModel}get layout(){return this._layout}set layout(next){const normalized=GRAPH_LAYOUT.normalize(next),old=this._layout;old!==normalized&&(this._layout=normalized,this.requestUpdate("layout",old))}constructor(){super(),this.nodes=[],this.edges=[],this.nodeTypes=[],this.hiddenTypes=[],this.communities=[],this._layout="force",this.renderer="svg",this.fitTo="none",this.width=800,this.height=600,this.chargeStrength=-300,this.edgeDistance=100,this.minZoom=.1,this.maxZoom=8,this.label=null,this.accessibleLabel=null,this.withEdgeLabels=!1,this.edgeLabelMinZoom=.6,this.focusNodeId=null,this.selectionMode="none",this.selectedNodeIds=[],this.selectedEdgeIds=[],this.dimmedNodeIds=[],this.dimmedEdgeIds=[],this.arrowMarkerId=nextId("graph-arrow"),this.loading=!0,this.loadFailed=!1,this.loadLibrary=loadD3,this.loadGeneration=0,this.containerSize=null,this.simNodes=[],this.simLinks=[],this.simNodeById=new Map,this.danglingLinks=[],this.lastPositionById=new Map,this.lastHiddenNodeCount=0,this.activeGraphItem=0,this.graphLiveText="",this.announcements=new AnnouncementSinkController(this,{eager:["polite","assertive"]}),this.graphAnnouncementsReady=!1,this.isMounting=!0,this.authorRole=null,this.syncingGraphHostRole=!1,this.detachedGraphChanges=new Map,this.boundNodeEls=new WeakSet,this.nodeEls=[],this.nodeHitEls=[],this.nodeLabelEls=[],this.expandIndicatorEls=[],this.lastKeyActivateIndex=null,this.lastKeyActivateTime=0,this.lastAppliedFocusNodeId=null,this.communityHullEls=[],this.communityHullHitEls=[],this.communityLabelEls=[],this.visible=!0,this.canvasDrawPending=!1,this.pickDirty=!0,this.canvasCamera={k:1,x:0,y:0},this.pickItems=[],this.canvasSceneHasEdgeLabels=!1,this.isCameraTweening=!1,this.linkEls=[],this.linkHitEls=[],this.linkLabelEls=[],this.linkLabelHiddenByLength=[],this.edgeLabelWidthCache=new Map,this.danglingLinkEls=[],this.linkPaintVisibilityCache=new Map,this.resolvedCssColorCache=new Map,this.reducedMotion=!1,this.isApplyingZoomTransform=!1,this.onCanvasDprChange=()=>{this.watchCanvasDpr(),this.markCanvasDirty()},this.onCanvasPointerDown=e=>{if(e.button!==0||(this.canvasPointerDownAt={x:e.clientX,y:e.clientY},this.canvasPointerDownId=e.pointerId,this.layout==="layered"))return;const hit=this.hitTest(e.clientX,e.clientY);if(hit?.kind==="node"){this.canvasDragNode=hit.node,this.canvasPointerId=e.pointerId;try{this.canvasEl.setPointerCapture(e.pointerId)}catch{}hit.node.fx=hit.node.x,hit.node.fy=hit.node.y,this.simulation?.alphaTarget(.3).restart()}},this.onCanvasPointerMove=e=>{if(this.canvasDragNode&&this.canvasPointerId===e.pointerId){const node=this.simNodeById.get(this.canvasDragNode.id);if(node){const rect=this.canvasEl.getBoundingClientRect();node.fx=(e.clientX-rect.left-this.canvasCamera.x)/this.canvasCamera.k,node.fy=(e.clientY-rect.top-this.canvasCamera.y)/this.canvasCamera.k,this.markCanvasDirty()}return}if(this.pendingHover={x:e.clientX,y:e.clientY},this.hoverRafId!=null)return;const frameOwner=this.ownerWindow;frameOwner&&(this.hoverRafOwner=frameOwner,this.hoverRafId=frameOwner.requestAnimationFrame(()=>{if(this.hoverRafId=void 0,this.hoverRafOwner=void 0,!this.isConnected||this.ownerWindow!==frameOwner)return;const pending=this.pendingHover;if(this.pendingHover=void 0,!pending||this.canvasHoverSuppressed()||this.pickDirty&&this.simulationIsTicking())return;const hit=this.hitTest(pending.x,pending.y);this.updateCanvasTooltip(hit,pending.x,pending.y),this.updateCanvasHover(hit)}))},this.onCanvasPointerUp=e=>{this.finishCanvasNodeDrag(e.pointerId);const down=this.takeCanvasPointerDown(e.pointerId);if(!down||Math.hypot(e.clientX-down.x,e.clientY-down.y)>5)return;const hit=this.hitTest(e.clientX,e.clientY);if(!hit){this.clearSelection();return}hit.kind==="node"?this.onNodeClick(hit.node,e):hit.kind==="link"?this.onLinkClick(hit.link,e):this.onCommunityClick(hit.entry.community)},this.onCanvasPointerCancel=e=>{this.finishCanvasNodeDrag(e.pointerId),this.takeCanvasPointerDown(e.pointerId)},this.onCanvasLostPointerCapture=e=>{this.finishCanvasNodeDrag(e.pointerId,!1),this.takeCanvasPointerDown(e.pointerId)},this.onCanvasPointerLeave=()=>{this.pendingHover=void 0,this.hoverRafId!=null&&(this.hoverRafOwner?.cancelAnimationFrame(this.hoverRafId),this.hoverRafId=void 0,this.hoverRafOwner=void 0),this.updateCanvasTooltip(void 0,0,0),this.canvasHoverSuppressed()?this.canvasHover=void 0:this.updateCanvasHover(void 0)},this.onCanvasDblClick=e=>{const hit=this.hitTest(e.clientX,e.clientY),node=hit?.kind==="node"?hit.node:this.nodeAtCanvasPoint(e.clientX,e.clientY);node&&(e.stopImmediatePropagation(),this.emit("lr-node-expand",{nodeId:node.id}))},this.isDragging=!1,this.isPanning=!1,new ThemeWatcher(this,()=>{const reduced=prefersReducedMotion(this);reduced!==this.reducedMotion&&(this.reducedMotion=reduced,reduced?this.simulation?.stop():this.safeSeed==null&&this.simulation?.restart()),this.linkPaintVisibilityCache.clear(),this.resolvedCssColorCache.clear(),this.renderer==="canvas"&&this.markCanvasDirty()},["(prefers-reduced-motion: reduce)"])}attributeChangedCallback(name,oldValue,value){super.attributeChangedCallback(name,oldValue,value),name==="role"&&oldValue!==value&&!this.syncingGraphHostRole&&(this.authorRole=value)}hostOwnsGraphSemantics(){return this.hasAttribute("aria-label")}syncGraphHostRole(){if(this.authorRole===null){this.syncingGraphHostRole=!0;try{this.hostOwnsGraphSemantics()?this.setAttribute("role","group"):this.removeAttribute("role")}finally{this.syncingGraphHostRole=!1}}}get ownerWindow(){return this.ownerDocument.defaultView??void 0}computedStyle(element=this){const view=this.ownerWindow;return view?view.getComputedStyle(element):"style"in element?element.style:this.style}connectedCallback(){if(super.connectedCallback(),this.detachedGraphChanges.size){for(const[key,previous]of this.detachedGraphChanges)this.requestUpdate(key,previous);this.detachedGraphChanges.clear(),this.requestUpdate()}this.reducedMotion=prefersReducedMotion(this);const IntersectionObserverCtor=this.ownerWindow?.IntersectionObserver;if(IntersectionObserverCtor&&(this.intersectionObserver=new IntersectionObserverCtor(entries=>{const wasVisible=this.visible;this.visible=entries[0]?.isIntersecting??!0,this.visible&&!wasVisible&&this.canvasDrawPending&&(this.canvasDrawPending=!1,this.scheduleCanvasDraw())}),this.intersectionObserver.observe(this)),this.fitTo==="container"&&(this.syncHostResizeObserver(),this.measureHostBox()),this.d3){!this.reducedMotion&&this.safeSeed==null&&this.simulation?.restart(),this.renderer==="canvas"&&this.canvasEl&&this.canvasEl===this.zoomedEl&&(this.ensureCanvasOwnerRealm(),this.syncHostResizeObserver(),this.watchCanvasDpr(),this.markCanvasDirty());return}const generation=++this.loadGeneration;this.loadLibrary().then(async mods=>{try{await this.updateComplete}catch{return}if(await new Promise(resolve=>this.updateBrowserDerivedState(resolve)),!(generation!==this.loadGeneration||!this.isConnected)){if(this.loading=!1,!mods){this.loadFailed=!0;return}this.loadFailed=!1,this.d3=mods,this.rebuildSimulation()}})}disconnectedCallback(){super.disconnectedCallback(),this.loadGeneration+=1,this.simulation?.stop(),this.finishCanvasNodeDrag(void 0,!0,!1),this.takeCanvasPointerDown(),this.cancelCameraTween(),this.intersectionObserver?.disconnect(),this.intersectionObserver=void 0,this.hostResizeObserver?.disconnect(),this.hostResizeObserver=void 0,this.hostResizeObserverDocument=void 0,this.canvasDprQuery?.removeEventListener("change",this.onCanvasDprChange),this.canvasDprQuery=void 0,this.canvasDrawRafId!=null&&(this.canvasDrawRafOwner?.cancelAnimationFrame(this.canvasDrawRafId),this.canvasDrawRafId=void 0,this.canvasDrawRafOwner=void 0),this.hoverRafId!=null&&(this.hoverRafOwner?.cancelAnimationFrame(this.hoverRafId),this.hoverRafId=void 0,this.hoverRafOwner=void 0),this.pendingHover=void 0,this.canvasHover=void 0,this.canvasTooltipEl?.setAttribute("hidden",""),this.pendingGraphItemFocus=void 0,this.viewportChangeRafId!=null&&(this.viewportChangeRafOwner?.cancelAnimationFrame(this.viewportChangeRafId),this.viewportChangeRafId=void 0,this.viewportChangeRafOwner=void 0)}adoptedCallback(){super.adoptedCallback(),this.announcements.adopted(),this.ensureCanvasOwnerRealm()}scheduleViewportChange(){if(this.viewportChangeRafId!=null)return;const frameOwner=this.ownerWindow;frameOwner&&(this.viewportChangeRafOwner=frameOwner,this.viewportChangeRafId=frameOwner.requestAnimationFrame(()=>{if(this.viewportChangeRafId=void 0,this.viewportChangeRafOwner=void 0,!this.isConnected||this.ownerWindow!==frameOwner)return;const transform=this.renderer==="canvas"||!this.d3||!this.zoomedEl?this.canvasCamera:this.d3.zoomTransform(this.zoomedEl);this.emit("lr-viewport-change",{zoom:transform.k,x:transform.x,y:transform.y,k:transform.k})}))}nodeRadius(n){const r=n.radius??(MIN_RADIUS+MAX_RADIUS)/2;return Number.isFinite(r)?Math.min(MAX_RADIUS,Math.max(MIN_RADIUS,r)):(MIN_RADIUS+MAX_RADIUS)/2}safeLinkWidth(link){return finiteRange(link.width??1.5,1.5,0)}isInteractiveLink(link,resolveColor,defaultPaint){if(this.safeLinkWidth(link)<=0)return!1;const effectivePaint=sanitizeNodeColor(link.color)??defaultPaint,color=effectivePaint?resolveColor(effectivePaint).trim().toLowerCase():void 0;if(!color)return!0;if(color==="transparent"||/^#[\da-f]{4}$/.test(color)&&color.endsWith("0")||/^#[\da-f]{8}$/.test(color)&&color.endsWith("00")||/\/\s*0(?:\.0+)?%?\s*\)$/.test(color)||/^(?:rgba|hsla)\(/.test(color)&&/,\s*0(?:\.0+)?\s*\)$/.test(color))return!1;const cached=this.linkPaintVisibilityCache.get(color);if(cached!==void 0)return cached;this.linkPaintProbe??=this.ownerDocument.createElement("canvas"),this.linkPaintProbe.width=1,this.linkPaintProbe.height=1;const context=this.linkPaintProbe.getContext("2d",{willReadFrequently:!0});if(!context)return!0;let visible=!0;try{context.clearRect(0,0,1,1),context.fillStyle="rgb(1 2 3)",context.fillStyle=color,context.fillRect(0,0,1,1),visible=context.getImageData(0,0,1,1).data[3]!==0}catch{visible=!0}return this.linkPaintVisibilityCache.set(color,visible),visible}navigableLinks(){return this.navigableLinksCache||(this.navigableLinksCache=this.simLinks.length?this.withCanvasColorResolver(resolveColor=>{const computed=this.computedStyle(),defaultPaint=computed.getPropertyValue("--lr-graph-edge-color").trim()||computed.getPropertyValue("--lr-color-border").trim();return this.simLinks.filter(link=>this.isInteractiveLink(link,resolveColor,defaultPaint))}):[]),this.navigableLinksCache}lengthInPixels(value){return typeof value=="string"?resolveCssTokenLength(value,{host:this})??Number.NaN:value}get requestedWidth(){return finiteRange(this.lengthInPixels(this.width),800,1)}get requestedHeight(){return finiteRange(this.lengthInPixels(this.height),600,1)}get safeWidth(){const requested=this.requestedWidth,measured=this.fitTo==="container"&&this.containerSize;return measured?finiteRange(measured.width,requested,1):requested}get safeHeight(){const requested=this.requestedHeight,measured=this.fitTo==="container"&&this.containerSize;return measured?finiteRange(measured.height,requested,1):requested}recordContainerSize(width,height){const w=Math.round(finiteRange(width,0,0)),h=Math.round(finiteRange(height,0,0));return w<=0||h<=0||this.containerSize?.width===w&&this.containerSize?.height===h?!1:(this.containerSize={width:w,height:h},!0)}measureHostBox(){return this.isConnected?(this.syncRequestedHeightVar(),this.recordContainerSize(this.clientWidth,this.clientHeight)):!1}syncRequestedHeightVar(){this.style.setProperty("--_lr-graph-requested-height",`${this.requestedHeight}px`)}get safeMinZoom(){return finiteRange(this.minZoom,.1,.001,1e3)}get safeMaxZoom(){return finiteRange(this.maxZoom,8,.001,1e3)}get effectiveZoomBounds(){const min=this.safeMinZoom,max=this.safeMaxZoom;return Object.freeze({min:Math.min(min,max),max:Math.max(min,max)})}get safeEdgeLabelMinZoom(){return finiteRange(this.edgeLabelMinZoom,.6,.001,1e3)}get resolvedNodeLabelsMode(){return this.nodeLabels??(this.renderer==="canvas"?"zoom":"always")}canvasNodeLabelsVisible(){const mode=this.resolvedNodeLabelsMode;return mode==="none"?!1:mode==="zoom"?this.canvasCamera.k>=NODE_LABEL_MIN_ZOOM:!0}get safeSeed(){return this.seed==null?void 0:finiteInteger(this.seed,0)}get safeChargeStrength(){return finiteNumber(this.chargeStrength,-300)}get safeLinkDistance(){return finiteRange(this.edgeDistance,100,0)}nodeTypeEntry(node){const types=this.graphModel.nodeTypes;if(this.nodeTypeIndex?.[0]!==types){const labeled=this.labeledNodeTypes();this.nodeTypeIndex=[types,new Map(types.map((type,index)=>{const slot=labeled.indexOf(type);return[type.id,[type,slot<0?index:slot]]}))]}return node.type==null?void 0:this.nodeTypeIndex[1].get(node.type)}resolveNodeType(node){return this.nodeTypeEntry(node)?.[0]}nodeShape(node){return this.resolveNodeType(node)?.shape??"circle"}labeledNodeTypes(){return this.graphModel.nodeTypes.filter(candidate=>typeof candidate?.label=="string"&&candidate.label.trim().length>0)}nodeFill(node){const ownColor=sanitizeNodeColor(node.color);if(ownColor)return ownColor;const entry=this.nodeTypeEntry(node);if(entry)return sanitizeNodeColor(entry[0].color)||categoricalPaletteColor(entry[1])}visibleNodes(){const hiddenTypes=canonicalIdentityList(this.hiddenTypes);if(!hiddenTypes.length)return this.graphModel.nodes;const hidden=new Set(hiddenTypes);return this.graphModel.nodes.filter(n=>n.type==null||!hidden.has(n.type))}resolveLinksAgainst(byId){const nodeExists=new Set(this.graphModel.nodes.map(n=>n.id)),resolved=[],dangling=[];for(const l of this.graphModel.links){const source=byId.get(l.source);if(!source)continue;const target=byId.get(l.target);target?resolved.push(copyGraphLinkIdentity(l,{...l,source,target})):nodeExists.has(l.target)||dangling.push(copyGraphLinkIdentity(l,{...l,source,target:{id:l.target,x:source.x,y:source.y},dangling:!0}))}return{resolved,dangling}}communityMembers(community){const idSet=new Set(community.memberIds);return this.simNodes.filter(n=>idSet.has(n.id)||n.communityId===community.id)}visibleCommunities(){return this.visibleCommunitiesCache||(this.visibleCommunitiesCache=this.graphModel.communities.map(community=>({community,members:this.communityMembers(community)})).filter(entry=>entry.members.length>0)),this.visibleCommunitiesCache}communityHull(members){return convexHull(members.map(n=>({x:n.x??0,y:n.y??0})))}onCommunityClick(community){this.emit("lr-community-activate",{communityId:community.id})}cameraTransitionMs(){const parsed=parseFloat(this.computedStyle().getPropertyValue("--lr-transition-base"));return Number.isFinite(parsed)?parsed:180}cancelCameraTween(){this.cameraTweenId!=null&&(this.cameraTweenFrameOwner?.cancelAnimationFrame(this.cameraTweenId),this.cameraTweenId=void 0,this.cameraTweenFrameOwner=void 0),this.isCameraTweening=!1;const resolve=this.cameraTweenResolve;resolve&&(this.cameraTweenResolve=void 0,resolve(!1))}applyZoomTransform(transform){if(!(!this.d3||!this.zoomedEl||!this.zoomBehavior)){this.isApplyingZoomTransform=!0;try{this.zoomBehavior.transform(this.d3.select(this.zoomedEl),transform)}finally{this.isApplyingZoomTransform=!1}}}tweenCamera(computeTarget){return new Promise(resolve=>{if(!this.d3||!this.zoomedEl||!this.zoomBehavior){resolve(!1);return}this.cancelCameraTween(),this.cameraTweenResolve=resolve,this.isCameraTweening=!0;const frameOwner=this.ownerWindow;if(!frameOwner){this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!1);return}if(prefersReducedMotion(this)){this.applyZoomTransform(computeTarget()),this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!0);return}const current=this.d3.zoomTransform(this.zoomedEl),duration=this.cameraTransitionMs(),start=frameOwner.performance.now(),startK=current.k,startX=current.x,startY=current.y,step=now=>{if(this.cameraTweenResolve!==resolve)return;if(!this.isConnected||this.ownerWindow!==frameOwner){this.cameraTweenId=void 0,this.cameraTweenFrameOwner=void 0,this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!1);return}const t=!prefersReducedMotion(this)&&duration>0?Math.min(1,(now-start)/duration):1,target=computeTarget(),targetK=target.k,targetX=target.x,targetY=target.y;this.applyZoomTransform(this.d3.zoomIdentity.translate(startX+(targetX-startX)*t,startY+(targetY-startY)*t).scale(startK+(targetK-startK)*t)),t<1?(this.cameraTweenFrameOwner=frameOwner,this.cameraTweenId=frameOwner.requestAnimationFrame(step)):(this.cameraTweenId=void 0,this.cameraTweenFrameOwner=void 0,this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!0))};this.cameraTweenFrameOwner=frameOwner,this.cameraTweenId=frameOwner.requestAnimationFrame(step)})}async focusNode(id,options){const node=this.simNodes.find(n=>n.id===id);if(!node||!this.d3||!this.zoomedEl||!this.zoomBehavior)return!1;const current=this.d3.zoomTransform(this.zoomedEl),bounds=this.effectiveZoomBounds,k=finiteRange(options?.zoom??current.k,current.k,bounds.min,bounds.max),arrived=await this.tweenCamera(()=>this.d3.zoomIdentity.translate(this.safeWidth/2-k*(node.x??0),this.safeHeight/2-k*(node.y??0)).scale(k));return arrived&&(this.graphLiveText=this.localize("graphNodeFocused",void 0,{label:this.nodeAccessibleText(node)})),arrived}fit(options){if(!this.d3||!this.zoomedEl||!this.zoomBehavior||!this.simNodes.length)return;const padding=finiteRange(options?.padding??24,24,0);this.tweenCamera(()=>{const fitPoints=[];for(const n of this.simNodes){const r=this.nodeRadius(n);fitPoints.push({x:(n.x??0)-r,y:(n.y??0)-r}),fitPoints.push({x:(n.x??0)+r,y:(n.y??0)+r})}for(const entry of this.visibleCommunities())for(const p of this.communityHull(entry.members))fitPoints.push({x:p.x-HULL_PADDING,y:p.y-HULL_PADDING}),fitPoints.push({x:p.x+HULL_PADDING,y:p.y+HULL_PADDING});const{minX,maxX,minY,maxY}=extent(fitPoints,point=>point.x,point=>point.y),bounds=this.effectiveZoomBounds,transform=fitTransform({minX,minY,maxX,maxY},{width:this.safeWidth,height:this.safeHeight},padding,bounds);return this.d3.zoomIdentity.translate(transform.x,transform.y).scale(transform.zoom)})}updateFocusHalo(){if(!this.focusHaloEl)return;const node=this.focusNodeId!=null?this.simNodes.find(n=>n.id===this.focusNodeId):void 0;node?(this.focusHaloEl.setAttribute("cx",String(node.x??0)),this.focusHaloEl.setAttribute("cy",String(node.y??0)),this.focusHaloEl.setAttribute("r",String(this.nodeRadius(node)+FOCUS_HALO_PADDING)),this.focusHaloEl.removeAttribute("hidden")):this.focusHaloEl.setAttribute("hidden","")}setUpCanvasSurface(){this.canvasCtx=this.canvasEl.getContext("2d")??void 0,this.ensureCanvasOwnerRealm(),this.syncHostResizeObserver(),this.watchCanvasDpr(),this.canvasTooltipEl=this.renderRoot.querySelector('[part="tooltip"]')??void 0,this.bindCanvasPointer(),this.bindCanvasZoom()}ensureCanvasOwnerRealm(){const ownerDocument=this.ownerDocument;this.edgeLabelMeasureCanvas?.ownerDocument!==ownerDocument&&(this.edgeLabelMeasureCanvas=void 0,this.edgeLabelMeasureCtx=void 0,this.edgeLabelWidthCache.clear()),!(!this.pickCanvas&&this.renderer!=="canvas")&&this.pickCanvas?.ownerDocument!==ownerDocument&&(this.pickCanvas=ownerDocument.createElement("canvas"),this.pickCtx=this.pickCanvas.getContext("2d",{willReadFrequently:!0}),this.pickDirty=!0)}syncHostResizeObserver(){if(this.renderer!=="canvas"&&this.fitTo!=="container"){this.hostResizeObserver?.disconnect(),this.hostResizeObserver=void 0,this.hostResizeObserverDocument=void 0;return}this.hostResizeObserver&&this.hostResizeObserverDocument===this.ownerDocument||this.watchHostResize()}watchHostResize(){this.hostResizeObserver?.disconnect();const ResizeObserverCtor=this.ownerWindow?.ResizeObserver;if(!ResizeObserverCtor){this.hostResizeObserver=void 0,this.hostResizeObserverDocument=void 0;return}this.hostResizeObserver=new ResizeObserverCtor(entries=>{const box=entries[entries.length-1]?.contentRect;this.fitTo==="container"&&box&&this.recordContainerSize(box.width,box.height),this.renderer==="canvas"&&this.canvasEl&&this.markCanvasDirty()}),this.hostResizeObserverDocument=this.ownerDocument,this.hostResizeObserver.observe(this)}watchCanvasDpr(){this.canvasDprQuery?.removeEventListener("change",this.onCanvasDprChange);const view=this.ownerWindow;if(!view?.matchMedia){this.canvasDprQuery=void 0;return}this.canvasDprQuery=view.matchMedia(`(resolution: ${view.devicePixelRatio}dppx)`),this.canvasDprQuery.addEventListener("change",this.onCanvasDprChange)}markCanvasDirty(){this.canvasScene=void 0,this.pickDirty=!0,this.scheduleCanvasDraw()}markCanvasCameraDirty(){this.pickDirty=!0,this.scheduleCanvasDraw()}scheduleCanvasDraw(){if(!this.visible){this.canvasDrawPending=!0;return}if(this.canvasDrawRafId!=null)return;const frameOwner=this.ownerWindow;frameOwner&&(this.canvasDrawRafOwner=frameOwner,this.canvasDrawRafId=frameOwner.requestAnimationFrame(()=>{this.canvasDrawRafId=void 0,this.canvasDrawRafOwner=void 0,!(!this.isConnected||this.ownerWindow!==frameOwner)&&this.drawCanvas()}))}resolveCssColorWithProbe(value,probe){const cached=this.resolvedCssColorCache.get(value);if(cached!==void 0)return cached;probe.style.color="",probe.style.color=value;const result=getComputedStyle(probe).color.trim()||getComputedStyle(this).color||"transparent";return this.resolvedCssColorCache.set(value,result),result}createCanvasColorProbe(){const probe=this.ownerDocument.createElement("span");return probe.setAttribute("aria-hidden","true"),probe.style.position="absolute",probe.style.inlineSize="0",probe.style.blockSize="0",probe.style.overflow="hidden",probe.style.visibility="hidden",probe.style.pointerEvents="none",this.renderRoot.append(probe),probe}withCanvasColorResolver(callback){let probe;try{return callback(value=>{const cached=this.resolvedCssColorCache.get(value);return cached!==void 0?cached:(probe??=this.createCanvasColorProbe(),this.resolveCssColorWithProbe(value,probe))})}finally{probe?.remove()}}buildCanvasScene(cs){return this.withCanvasColorResolver(resolveColor=>{const hullFillDefault=cs.getPropertyValue("--lr-graph-hull-fill").trim()||cs.getPropertyValue("--lr-color-brand").trim(),hulls=this.visibleCommunities().map(entry=>({d:hullPathD(this.communityHull(entry.members)),fill:resolveColor(sanitizeNodeColor(entry.community.color)??hullFillDefault)})),linkColorDefault=cs.getPropertyValue("--lr-graph-edge-color").trim()||cs.getPropertyValue("--lr-color-border").trim(),links=this.simLinks.map(l=>{const coords=this.linkCoordinates(l),own=sanitizeNodeColor(l.color);return{x1:coords.x1,y1:coords.y1,x2:coords.x2,y2:coords.y2,color:resolveColor(own??linkColorDefault),width:this.safeLinkWidth(l),dash:l.dash,directed:l.directed,selected:this.isSelected("link",this.linkKey(l)),dimmed:this.isDimmed("link",this.linkKey(l))}}),edgeLabels=this.withEdgeLabels&&this.canvasCamera.k>=this.safeEdgeLabelMinZoom?this.simLinks.flatMap(l=>{const label=ownGraphText(l,"label");if(!label)return[];const pos=this.edgeLabelPosition(l),coords=this.linkCoordinates(l),edgeLength=Math.hypot(coords.x2-coords.x1,coords.y2-coords.y1);return this.edgeLabelWidth(label)>edgeLength*EDGE_LABEL_LENGTH_GATE_RATIO?[]:[{x:pos.x,y:pos.y,text:label}]}):[],nodeFillDefault=cs.getPropertyValue("--lr-graph-node-fill").trim()||cs.getPropertyValue("--lr-color-brand").trim(),nodes=this.simNodes.map(n=>{const fill=this.nodeFill(n);return{x:n.x??0,y:n.y??0,r:this.nodeRadius(n),shape:this.nodeShape(n),fill:resolveColor(fill??nodeFillDefault),selected:this.isSelected("node",n.id),dimmed:this.isDimmed("node",n.id)}}),nodeLabels=this.simNodes.flatMap(n=>{const label=ownGraphText(n,"label");return label?[{x:(n.x??0)+this.nodeRadius(n)+2,y:n.y??0,text:label}]:[]}),expandIndicators=this.simNodes.filter(n=>n.expandable).map(n=>({x:n.x??0,y:n.y??0,r:this.nodeRadius(n)})),focusNode=this.focusNodeId!=null?this.simNodes.find(n=>n.id===this.focusNodeId):void 0,scene={hulls,links,edgeLabels,nodes,nodeLabels,expandIndicators,focusHalo:focusNode?{x:focusNode.x??0,y:focusNode.y??0,r:this.nodeRadius(focusNode)+FOCUS_HALO_PADDING}:void 0,showNodeLabels:this.canvasNodeLabelsVisible(),haloColor:resolveColor(this.ownerWindow?.matchMedia?.("(forced-colors: active)").matches?"CanvasText":cs.getPropertyValue("--lr-graph-focus-halo-color").trim()||cs.getPropertyValue("--lr-color-brand").trim()),selectedColor:resolveColor(cs.getPropertyValue("--lr-graph-selected-color").trim()||cs.getPropertyValue("--lr-color-success").trim()),dimmedOpacity:(()=>{const value=Number(cs.getPropertyValue("--lr-graph-dimmed-opacity").trim());return Number.isFinite(value)?Math.min(1,Math.max(0,value)):.35})(),hullOpacity:(()=>{const value=Number(cs.getPropertyValue("--lr-graph-hull-opacity").trim());return Number.isFinite(value)?Math.min(1,Math.max(0,value)):.12})(),labelColor:resolveColor(cs.getPropertyValue("--lr-color-text").trim()),labelHaloColor:resolveColor(cs.getPropertyValue("--lr-graph-edge-label-halo").trim()||cs.getPropertyValue("--lr-color-surface").trim()),expandBadgeFill:resolveColor(cs.getPropertyValue("--lr-color-surface").trim()),expandBadgeStroke:resolveColor(cs.getPropertyValue("--lr-color-border-strong").trim()),font:`${this.edgeLabelFontPx()}px ${cs.getPropertyValue("--lr-font").trim()||"sans-serif"}`,borderWidths:["thin","medium","thick"].map((size,index)=>resolveCssTokenLength(cs.getPropertyValue(`--lr-border-width-${size}`).trim(),{host:this})??index+1)};return this.updateCanvasFocus(scene),scene})}updateCanvasFocus(scene){const index=shadowFocusTarget(this)?.getAttribute("part")==="cursor-item"?this.normalizedGraphItem():-1,node=index>=0&&index<this.linkIndexBase()?this.simNodes[index]:void 0,link=index>=this.linkIndexBase()&&index<this.communityIndexBase()?this.navigableLinks()[index-this.linkIndexBase()]:void 0,community=index>=this.communityIndexBase()?this.visibleCommunities()[index-this.communityIndexBase()]:void 0;scene.keyboardFocusRing=node?{x:node.x??0,y:node.y??0,r:this.nodeRadius(node)+4}:void 0,scene.keyboardFocusLink=link?{...this.linkCoordinates(link),width:this.safeLinkWidth(link)}:void 0,scene.keyboardFocusHull=community?{d:hullPathD(this.communityHull(community.members))}:void 0}drawCanvas(){if(!this.canvasEl||!this.canvasCtx)return;const dpr=this.ownerWindow?.devicePixelRatio||1,w=this.canvasEl.clientWidth||this.safeWidth,h=this.canvasEl.clientHeight||this.safeHeight,backingW=Math.round(w*dpr),backingH=Math.round(h*dpr);(this.canvasEl.width!==backingW||this.canvasEl.height!==backingH)&&(this.canvasEl.width=backingW,this.canvasEl.height=backingH);const ctx=this.canvasCtx;ctx.setTransform(dpr,0,0,dpr,0,0),ctx.clearRect(0,0,w,h);const edgeLabelsVisible=this.withEdgeLabels&&this.canvasCamera.k>=this.safeEdgeLabelMinZoom,nodeLabelsVisible=this.canvasNodeLabelsVisible();(!this.canvasScene||this.canvasScene.showNodeLabels!==nodeLabelsVisible||this.canvasSceneHasEdgeLabels!==edgeLabelsVisible)&&(this.canvasScene=this.buildCanvasScene(this.computedStyle()),this.canvasSceneHasEdgeLabels=edgeLabelsVisible),this.updateCanvasFocus(this.canvasScene),drawGraphScene(ctx,this.canvasCamera,this.canvasScene)}rebuildPickItems(){this.pickItems=[...this.visibleCommunities().map(entry=>({kind:"hull",entry})),...this.navigableLinks().map(link=>({kind:"link",link})),...this.simNodes.map(node=>({kind:"node",node}))]}redrawPickCanvas(){if(!this.pickCtx||!this.canvasEl||!this.pickCanvas)return;(this.pickCanvas.width!==this.canvasEl.width||this.pickCanvas.height!==this.canvasEl.height)&&(this.pickCanvas.width=this.canvasEl.width,this.pickCanvas.height=this.canvasEl.height),this.rebuildPickItems();const dpr=this.ownerWindow?.devicePixelRatio||1;this.pickCtx.setTransform(dpr,0,0,dpr,0,0),drawPickingScene(this.pickCtx,this.canvasCamera,{hulls:this.pickItems.filter(i=>i.kind==="hull").map(i=>({d:hullPathD(this.communityHull(i.entry.members))})),links:this.pickItems.filter(i=>i.kind==="link").map(i=>{const c=this.linkCoordinates(i.link);return{x1:c.x1,y1:c.y1,x2:c.x2,y2:c.y2,width:this.safeLinkWidth(i.link)}}),nodes:this.pickItems.filter(i=>i.kind==="node").map(i=>({x:i.node.x??0,y:i.node.y??0,r:this.nodeRadius(i.node)+2,shape:this.nodeShape(i.node)}))}),this.pickDirty=!1}hitTest(clientX,clientY){if(!this.canvasEl||!this.pickCtx)return;this.pickDirty&&this.redrawPickCanvas();const rect=this.canvasEl.getBoundingClientRect(),dpr=this.ownerWindow?.devicePixelRatio||1,px=Math.round((clientX-rect.left)*dpr),py=Math.round((clientY-rect.top)*dpr);if(px<0||py<0||px>=this.pickCtx.canvas.width||py>=this.pickCtx.canvas.height)return;const data=this.pickCtx.getImageData(px,py,1,1).data,index=pickColorToIndex(data[0],data[1],data[2]);return index>=0?this.pickItems[index]:void 0}bindCanvasZoom(){if(!this.d3||!this.canvasEl)return;const bounds=this.effectiveZoomBounds,zoomBehavior=this.d3.zoom().scaleExtent([bounds.min,bounds.max]).on("start",()=>{this.isApplyingZoomTransform||(this.isPanning=!0,this.cancelCameraTween())}).on("zoom",event=>{this.canvasCamera={k:event.transform.k,x:event.transform.x,y:event.transform.y},this.markCanvasCameraDirty(),this.scheduleViewportChange()}).on("end",()=>{this.isPanning=!1});this.zoomBehavior=zoomBehavior,this.d3.select(this.canvasEl).call(zoomBehavior)}bindCanvasPointer(){const canvas=this.canvasEl;canvas.addEventListener("pointerdown",this.onCanvasPointerDown),canvas.addEventListener("pointermove",this.onCanvasPointerMove),canvas.addEventListener("pointerup",this.onCanvasPointerUp),canvas.addEventListener("pointercancel",this.onCanvasPointerCancel),canvas.addEventListener("lostpointercapture",this.onCanvasLostPointerCapture),canvas.addEventListener("pointerleave",this.onCanvasPointerLeave),canvas.addEventListener("dblclick",this.onCanvasDblClick)}simulationIsTicking(){return this.simulation!=null&&this.simulation.alpha()>this.simulation.alphaMin()}finishCanvasNodeDrag(pointerId,releaseCapture=!0,redraw=!0){const activePointerId=this.canvasPointerId;if(activePointerId==null||pointerId!=null&&pointerId!==activePointerId)return;const node=this.canvasDragNode&&this.simNodeById.get(this.canvasDragNode.id);if(this.canvasDragNode=void 0,this.canvasPointerId=void 0,this.simulation?.alphaTarget(0),node&&(node.fx=null,node.fy=null),releaseCapture&&this.canvasEl)try{this.canvasEl.releasePointerCapture(activePointerId)}catch{}redraw?this.markCanvasDirty():(this.canvasScene=void 0,this.pickDirty=!0)}takeCanvasPointerDown(pointerId){if(pointerId!=null&&this.canvasPointerDownId!==pointerId)return;const down=this.canvasPointerDownAt;return this.canvasPointerDownAt=void 0,this.canvasPointerDownId=void 0,down}canvasHoverSuppressed(){return!!this.canvasDragNode||this.isDragging||this.isPanning||this.isCameraTweening}updateCanvasHover(hit){const next=hit?.kind==="node"?{kind:"node",id:hit.node.id}:hit?.kind==="link"?{kind:"link",id:this.linkKey(hit.link),detail:this.linkHoverDetail(hit.link)}:void 0,previous=this.canvasHover;previous?.kind===next?.kind&&previous?.id===next?.id||(this.canvasHover=next,previous?.kind==="node"?this.emit("lr-node-leave",{nodeId:previous.id}):previous?.kind==="link"&&this.emitEdgeHover("leave",previous.detail),!(!this.isConnected||this.renderer!=="canvas"||this.canvasHover!==next)&&(next?.kind==="node"?this.emit("lr-node-enter",{nodeId:next.id}):next?.kind==="link"&&this.emitEdgeHover("enter",next.detail)))}nodeAtCanvasPoint(clientX,clientY){if(!this.canvasEl)return;const rect=this.canvasEl.getBoundingClientRect(),worldX=(clientX-rect.left-this.canvasCamera.x)/this.canvasCamera.k,worldY=(clientY-rect.top-this.canvasCamera.y)/this.canvasCamera.k;let closest,closestDistance=1/0;for(const node of this.simNodes){const distance=Math.hypot((node.x??0)-worldX,(node.y??0)-worldY);distance<=this.nodeRadius(node)+2/this.canvasCamera.k&&distance<closestDistance&&(closest=node,closestDistance=distance)}return closest}updateCanvasTooltip(hit,clientX,clientY){if(!this.canvasTooltipEl)return;if(!hit||hit.kind==="hull"){this.canvasTooltipEl.setAttribute("hidden","");return}const rect=this.canvasEl.getBoundingClientRect();this.canvasTooltipEl.textContent=hit.kind==="node"?this.nodeTooltipText(hit.node):this.linkTooltipText(hit.link);let left=clientX-rect.left,top=clientY-rect.top;this.canvasTooltipEl.style.left=`${left}px`,this.canvasTooltipEl.style.top=`${top}px`,this.canvasTooltipEl.removeAttribute("hidden");const tooltipRect=this.canvasTooltipEl.getBoundingClientRect(),view=this.ownerWindow;if(!view)return;const minLeft=Math.max(0,rect.left),maxRight=Math.min(view.innerWidth,rect.right),minTop=Math.max(0,rect.top),maxBottom=Math.min(view.innerHeight,rect.bottom);tooltipRect.right>maxRight&&(left-=tooltipRect.right-maxRight),tooltipRect.left<minLeft&&(left+=minLeft-tooltipRect.left),tooltipRect.bottom>maxBottom&&(top-=tooltipRect.bottom-maxBottom),tooltipRect.top<minTop&&(top+=minTop-tooltipRect.top),this.canvasTooltipEl.style.left=`${left}px`,this.canvasTooltipEl.style.top=`${top}px`}isSelected(kind,id){return identitySet(kind==="node"?this.selectedNodeIds:this.selectedEdgeIds).has(id)}paintedCurrent(kind,id){return this.selectionMode==="none"&&this.isSelected(kind,id)?"true":nothing}isDimmed(kind,id){return identitySet(kind==="node"?this.dimmedNodeIds:this.dimmedEdgeIds).has(id)}linkKey(link){return graphLinkIdentity(link)}emitSelectionIntent(kind,id,toggle){if(this.selectionMode==="none")return;const selected=this.isSelected(kind,id),time=this.ownerWindow?.performance.now()??0,repeat=this.lastActivation?.id===id&&time-this.lastActivation.time<=EXPAND_KEY_INTERVAL_MS;if(this.lastActivation={id,time},this.selectionMode==="single"||!toggle){if(this.selectionMode==="single"&&selected){repeat||this.emit("lr-selection-change",{selectedNodeIds:[],selectedEdgeIds:[]});return}this.emit("lr-selection-change",kind==="node"?{selectedNodeIds:[id],selectedEdgeIds:[]}:{selectedNodeIds:[],selectedEdgeIds:[id]});return}const selectedNodeIds=canonicalIdentityList(this.selectedNodeIds),selectedLinkIds=canonicalIdentityList(this.selectedEdgeIds),nodeIds=kind==="node"?selected?selectedNodeIds.filter(x=>x!==id):[...selectedNodeIds,id]:selectedNodeIds,linkIds=kind==="link"?selected?selectedLinkIds.filter(x=>x!==id):[...selectedLinkIds,id]:selectedLinkIds;this.emit("lr-selection-change",{selectedNodeIds:nodeIds,selectedEdgeIds:linkIds})}clearSelection(){this.selectionMode!=="none"&&(!canonicalIdentityList(this.selectedNodeIds).length&&!canonicalIdentityList(this.selectedEdgeIds).length||this.emit("lr-selection-change",{selectedNodeIds:[],selectedEdgeIds:[]}))}willUpdate(changed){super.willUpdate(changed),changed.has("height")&&this.syncRequestedHeightVar(),changed.has("fitTo")&&this.fitTo!=="container"&&(this.containerSize=null),this.fitTo==="container"&&!this.containerSize&&this.measureHostBox();const cursorOnly=changed.size>0&&[...changed.keys()].every(key=>key==="activeGraphItem"||key==="graphLiveText");cursorOnly||this.resolvedCssColorCache.clear(),cursorOnly||(this.navigableLinksCache=void 0),this.syncGraphHostRole();const wasMounting=this.isMounting;this.isMounting=!1;const hiddenTypesChanged=changed.has("hiddenTypes")&&!sameIds(canonicalIdentityList(changed.get("hiddenTypes")??[]),canonicalIdentityList(this.hiddenTypes)),structureChanged=this.d3&&(changed.has("nodes")||changed.has("edges")||hiddenTypesChanged||changed.has("layout")||this.layout==="layered"&&changed.has("edgeDistance")),graphItemsChanged=!!(structureChanged||changed.has("simNodes")||changed.has("communities")),activePart=shadowFocusTarget(this)?.getAttribute("part")??"",hadGraphItemFocus=graphItemsChanged&&["node","link","hull","cursor-item"].includes(activePart),previousIndex=this.normalizedGraphItem(),previousIdentity=graphItemsChanged?this.graphItemIdentity(previousIndex):void 0;if(structureChanged&&this.isConnected){this.rebuildSimulation(),this.renderer==="svg"&&this.simNodes.length+this.simLinks.length>1e3&&devWarnOnce("lr-graph-svg-scale",'<lr-graph>: renderer="svg" draws every node and link as DOM; use renderer="canvas" above about 1,000 of them.');const hovered=this.svgHoverNodeId;hovered!=null&&!this.simNodeById.has(hovered)&&(this.svgHoverNodeId=void 0,this.emit("lr-node-leave",{nodeId:hovered})),this.canvasHover?.kind==="node"&&!this.simNodeById.has(this.canvasHover.id)&&this.updateCanvasHover(void 0),this.navigableLinksCache=void 0}if(graphItemsChanged){this.visibleCommunitiesCache=void 0;const retainedIndex=previousIdentity?this.graphItemIndex(previousIdentity):-1,nextIndex=retainedIndex>=0?retainedIndex:this.normalizedGraphItem(previousIndex);this.activeGraphItem=nextIndex>=0?nextIndex:0,hadGraphItemFocus&&(this.pendingGraphItemFocus=nextIndex>=0?nextIndex:"base",nextIndex>=0&&(this.graphLiveText=this.graphItemAnnouncement(nextIndex)))}const selectedNodeIdsChanged=changed.has("selectedNodeIds")&&!sameIds(changed.get("selectedNodeIds"),this.selectedNodeIds),selectedLinkIdsChanged=changed.has("selectedEdgeIds")&&!sameIds(changed.get("selectedEdgeIds"),this.selectedEdgeIds);(selectedNodeIdsChanged||selectedLinkIdsChanged)&&!wasMounting&&(this.graphLiveText=this.localize("graphSelectionCount",void 0,{count:getNumberFormat(this.effectiveLocale).format(canonicalIdentityList(this.selectedNodeIds).length+canonicalIdentityList(this.selectedEdgeIds).length)}))}updated(changed){if(super.updated(changed),!this.isConnected){for(const[key,previous]of changed)this.detachedGraphChanges.has(key)||this.detachedGraphChanges.set(key,previous);return}this.setAttribute("aria-busy",String(this.loading));const announceGraphText=this.graphAnnouncementsReady&&changed.has("graphLiveText")&&this.graphLiveText!=="";if(!this.loading&&!this.loadFailed&&(this.graphAnnouncementsReady=!0),announceGraphText&&this.announcements.announcePolite(this.graphLiveText),changed.has("loadFailed")&&changed.get("loadFailed")!==void 0&&this.loadFailed&&this.announcements.announceAssertive(this.localize("graphMissingLibrary")),(changed.has("fitTo")||changed.has("renderer"))&&this.syncHostResizeObserver(),!this.d3)return;!changed.has("nodes")&&!changed.has("edges")&&!changed.has("hiddenTypes")&&((changed.has("width")||changed.has("height")||changed.has("containerSize")||changed.has("fitTo"))&&(this.simulation?.force("center",this.d3.forceCenter(this.safeWidth/2,this.safeHeight/2)),this.simulation?.alpha(.1).restart()),(changed.has("chargeStrength")||changed.has("edgeDistance"))&&(changed.has("chargeStrength")&&this.chargeForce?.strength(this.safeChargeStrength),changed.has("edgeDistance")&&this.linkForce?.distance(this.safeLinkDistance),this.simulation?.alpha(.3).restart())),this.applyInteractions(changed);const cursorOnly=changed.size>0&&[...changed.keys()].every(key=>key==="activeGraphItem"||key==="graphLiveText");this.renderer==="canvas"&&cursorOnly?this.scheduleCanvasDraw():this.applyCanvasInteractions(),this.focusNodeId==null?this.lastAppliedFocusNodeId=null:this.focusNodeId!==this.lastAppliedFocusNodeId&&this.simNodes.some(n=>n.id===this.focusNodeId)&&(this.lastAppliedFocusNodeId=this.focusNodeId,this.focusNode(this.focusNodeId)),this.updateFocusHalo();const pendingFocus=this.pendingGraphItemFocus;pendingFocus!==void 0&&(this.pendingGraphItemFocus=void 0,pendingFocus==="base"?this.renderRoot.querySelector('[part="canvas"], [part="svg"]')?.focus():this.focusGraphItemElement(pendingFocus))}applyInteractions(changed){if(!this.d3||this.renderer!=="svg")return;const svgEl=this.renderRoot.querySelector("svg"),reboundSurface=svgEl&&svgEl!==this.zoomedEl;if(svgEl&&reboundSurface){this.syncHostResizeObserver(),this.canvasHover=void 0,this.zoomedEl=svgEl,this.gEl=this.renderRoot.querySelector("g"),this.focusHaloEl=this.renderRoot.querySelector('[part="focus-halo"]');const bounds=this.effectiveZoomBounds,zoomBehavior=this.d3.zoom().scaleExtent([bounds.min,bounds.max]).on("start",()=>{this.isApplyingZoomTransform||(this.isPanning=!0,this.cancelCameraTween())}).on("zoom",event=>{this.gEl?.setAttribute("transform",event.transform.toString()),this.updateHitAreaZoomScale(event.transform.k),this.updateEdgeLabelZoomGate(event.transform.k),this.updateNodeLabelZoomGate(event.transform.k),this.scheduleViewportChange()}).on("end",()=>{this.isPanning=!1});this.zoomBehavior=zoomBehavior,this.d3.select(svgEl).call(zoomBehavior),this.updateHitAreaZoomScale(1),this.updateEdgeLabelZoomGate(1),this.updateNodeLabelZoomGate(1)}else if(this.zoomBehavior&&(changed.has("minZoom")||changed.has("maxZoom"))){const bounds=this.effectiveZoomBounds;this.zoomBehavior.scaleExtent([bounds.min,bounds.max])}if(changed.has("nodeLabels")&&this.zoomedEl&&this.updateNodeLabelZoomGate(this.d3.zoomTransform(this.zoomedEl).k),!(reboundSurface||changed.has("simNodes")||changed.has("simLinks")||changed.has("nodeTypes")||changed.has("withEdgeLabels")||changed.has("nodeLabels")||changed.has("communities")))return;const nodeEls=Array.from(this.renderRoot.querySelectorAll('[part="node"]'));this.nodeEls=nodeEls,this.nodeHitEls=Array.from(this.renderRoot.querySelectorAll('[data-hit-area="node"]')),this.nodeLabelEls=nodeEls.map(el=>el.parentElement?.querySelector('[part="label"]')??null),this.expandIndicatorEls=nodeEls.map(el=>el.parentElement?.querySelector('[part="expand-indicator"]')??null),this.linkEls=Array.from(this.renderRoot.querySelectorAll('[part="link"]:not([data-dangling])')),this.linkHitEls=Array.from(this.renderRoot.querySelectorAll('[data-hit-area="link"]')),this.linkLabelEls=this.linkEls.map(el=>el.parentElement?.querySelector('[part="link-label"]')??null),this.linkLabelHiddenByLength=[],this.danglingLinkEls=Array.from(this.renderRoot.querySelectorAll('[part="link"][data-dangling]')),this.communityHullEls=Array.from(this.renderRoot.querySelectorAll('[part="hull"]')),this.communityHullHitEls=Array.from(this.renderRoot.querySelectorAll('[data-hit-area="hull"]')),this.communityLabelEls=Array.from(this.renderRoot.querySelectorAll('[part="community-label"]')),this.layout!=="layered"&&nodeEls.forEach((el,i)=>{const id=this.simNodes[i]?.id;if(id!=null)for(const dragTarget of[el,this.nodeHitEls[i]])!dragTarget||this.boundNodeEls.has(dragTarget)||(this.boundNodeEls.add(dragTarget),this.d3.select(dragTarget).call(this.d3.drag().on("start",event=>{this.isDragging=!0,event.sourceEvent?.stopPropagation(),event.active||this.simulation?.alphaTarget(.3).restart();const n=this.simNodeById.get(id);n&&(n.fx=n.x,n.fy=n.y)}).on("drag",event=>{const n=this.simNodeById.get(id);n&&(n.fx=event.x,n.fy=event.y)}).on("end",event=>{this.isDragging=!1,event.active||this.simulation?.alphaTarget(0);const n=this.simNodeById.get(id);n&&(n.fx=null,n.fy=null)})))})}updateHitAreaZoomScale(zoom){const safeZoom=finiteRange(zoom,1,Number.EPSILON);this.gEl?.style.setProperty("--_lr-graph-hit-area-scale",String(1/safeZoom))}applyCanvasInteractions(){if(this.renderer!=="canvas"||!this.canvasEl)return;this.canvasEl!==this.zoomedEl&&(this.zoomedEl=this.canvasEl,this.setUpCanvasSurface());const bounds=this.effectiveZoomBounds;this.zoomBehavior?.scaleExtent([bounds.min,bounds.max]),this.markCanvasDirty()}onTick(){for(const l of this.danglingLinks){const source=l.source,target=l.target;target.x=(source.x??0)+STUB_OFFSET_PX,target.y=(source.y??0)+STUB_OFFSET_PX}for(const n of this.simNodes)n.x!=null&&n.y!=null&&this.lastPositionById.set(n.id,{x:n.x,y:n.y});this.simNodes.forEach((n,i)=>{const el=this.nodeEls[i];el&&(el.tagName==="circle"?(el.setAttribute("cx",String(n.x??0)),el.setAttribute("cy",String(n.y??0))):el.setAttribute("transform",`translate(${n.x??0},${n.y??0})`));const hit=this.nodeHitEls[i];hit&&(hit.setAttribute("x1",String((n.x??0)-NODE_HIT_SEGMENT_HALF)),hit.setAttribute("y1",String(n.y??0)),hit.setAttribute("x2",String((n.x??0)+NODE_HIT_SEGMENT_HALF)),hit.setAttribute("y2",String(n.y??0)));const label=this.nodeLabelEls[i];label&&(label.setAttribute("x",String((n.x??0)+this.nodeRadius(n)+2)),label.setAttribute("y",String(n.y??0)))}),this.simLinks.forEach((l,i)=>{const line=this.linkEls[i],coordinates=this.linkCoordinates(l);for(const target of[line,this.linkHitEls[i]])target&&(target.setAttribute("x1",String(coordinates.x1)),target.setAttribute("y1",String(coordinates.y1)),target.setAttribute("x2",String(coordinates.x2)),target.setAttribute("y2",String(coordinates.y2)))}),this.withEdgeLabels&&this.simLinks.forEach((l,i)=>{const labelEl=this.linkLabelEls[i];if(!labelEl)return;const label=ownGraphText(l,"label"),pos=this.edgeLabelPosition(l);labelEl.setAttribute("x",String(pos.x)),labelEl.setAttribute("y",String(pos.y));const{x1,y1,x2,y2}=this.linkCoordinates(l),edgeLength=Math.hypot(x2-x1,y2-y1),tooLong=this.edgeLabelWidth(label??"")>edgeLength*EDGE_LABEL_LENGTH_GATE_RATIO;this.linkLabelHiddenByLength[i]!==tooLong&&(this.linkLabelHiddenByLength[i]=tooLong,labelEl.setAttribute("visibility",tooLong?"hidden":"visible"))}),this.simNodes.forEach((n,i)=>{const indicator=this.expandIndicatorEls[i];indicator&&indicator.setAttribute("transform",`translate(${n.x??0},${n.y??0})`)}),this.danglingLinks.forEach((l,i)=>{const line=this.danglingLinkEls[i];if(!line)return;const coordinates=this.linkCoordinates(l);line.setAttribute("x1",String(coordinates.x1)),line.setAttribute("y1",String(coordinates.y1)),line.setAttribute("x2",String(coordinates.x2)),line.setAttribute("y2",String(coordinates.y2))}),this.updateFocusHalo(),this.visibleCommunities().forEach((entry,i)=>{const hullEl=this.communityHullEls[i],hullHitEl=this.communityHullHitEls[i],labelEl=this.communityLabelEls[i];if(!hullEl&&!hullHitEl&&!labelEl)return;const hull=this.communityHull(entry.members);hullEl&&hullEl.setAttribute("d",hullPathD(hull)),hullHitEl&&hullHitEl.setAttribute("d",hullPathD(hull)),labelEl&&(labelEl.setAttribute("x",String(hullCentroidX(hull))),labelEl.setAttribute("y",String(hullTopY(hull)-HULL_PADDING)))}),this.renderer==="canvas"&&this.markCanvasDirty(),this.scheduleViewportChange()}rebuildSimulation(){if(!this.d3)return;this.simulation?.stop(),this.boundNodeEls=new WeakSet;const liveIds=new Set(this.graphModel.nodes.map(n=>n.id));for(const id of this.lastPositionById.keys())liveIds.has(id)||this.lastPositionById.delete(id);const visible=this.visibleNodes();if(this.layout==="layered"){this.rebuildLayeredLayout(visible);return}const prevById=new Map(this.simNodes.map(n=>[n.id,n])),nodes=visible.map(n=>{const prev=prevById.get(n.id);if(prev)return{...prev,...n};const remembered=this.lastPositionById.get(n.id);return remembered?{...n,x:remembered.x,y:remembered.y}:{...n}}),byId=new Map(nodes.map(n=>[n.id,n])),{resolved:resolvedLinks,dangling:danglingLinks}=this.resolveLinksAgainst(byId),links=resolvedLinks;this.danglingLinks=danglingLinks;const seedForSpawn=this.safeSeed,incidentLinks=new Map;if(nodes.some(n=>n.x!=null))for(const l of resolvedLinks)for(const id of new Set([l.source.id,l.target.id])){const incident=incidentLinks.get(id);incident?incident.push(l):incidentLinks.set(id,[l])}for(const n of nodes){if(n.x!=null&&n.y!=null)continue;const neighborLink=incidentLinks.get(n.id)?.find(l=>{const source2=l.source,target2=l.target;return source2.id===n.id&&target2.x!=null||target2.id===n.id&&source2.x!=null});if(!neighborLink)continue;const source=neighborLink.source,target=neighborLink.target,neighbor=source.id===n.id?target:source,jitterRadius=this.safeLinkDistance/2,angle=seedForSpawn!=null?hashNodeSeed(seedForSpawn,n.id)/4294967296*Math.PI*2:Math.random()*Math.PI*2;n.x=(neighbor.x??0)+Math.cos(angle)*jitterRadius,n.y=(neighbor.y??0)+Math.sin(angle)*jitterRadius}if(seedForSpawn!=null)for(const n of nodes){if(n.x!=null&&n.y!=null)continue;const rng=mulberry32(hashNodeSeed(seedForSpawn,n.id));n.x=rng()*this.safeWidth,n.y=rng()*this.safeHeight}this.linkForce=this.d3.forceLink(links).distance(this.safeLinkDistance),this.chargeForce=this.d3.forceManyBody().strength(this.safeChargeStrength);const simulation=this.d3.forceSimulation(nodes).force("link",this.linkForce).force("charge",this.chargeForce).force("center",this.d3.forceCenter(this.safeWidth/2,this.safeHeight/2)).force("collide",this.d3.forceCollide().radius(n=>this.nodeRadius(n)+10)).on("tick",()=>this.onTick());if(this.simulation=simulation,prefersReducedMotion(this)||this.safeSeed!=null){const pinnedForSettle=new Set;for(const n of nodes)(prevById.has(n.id)||this.lastPositionById.has(n.id))&&n.x!=null&&n.y!=null&&n.fx==null&&n.fy==null&&(n.fx=n.x,n.fy=n.y,pinnedForSettle.add(n.id));for(simulation.stop();simulation.alpha()>simulation.alphaMin();)simulation.tick();for(const n of nodes)pinnedForSettle.has(n.id)&&(n.fx=null,n.fy=null)}this.simNodes=nodes,this.simNodeById=byId,this.simLinks=links;for(const n of nodes)n.x!=null&&n.y!=null&&this.lastPositionById.set(n.id,{x:n.x,y:n.y});this.announceHiddenNodeCount(nodes.length)}announceHiddenNodeCount(visibleNodeCount){const totalNodeCount=this.graphModel.nodes.length,hiddenNodeCount=totalNodeCount-visibleNodeCount;totalNodeCount>0&&(hiddenNodeCount>0||this.lastHiddenNodeCount>0)&&(this.graphLiveText=this.localize("graphNodesHidden",void 0,{hidden:getNumberFormat(this.effectiveLocale).format(hiddenNodeCount),total:getNumberFormat(this.effectiveLocale).format(totalNodeCount)})),this.lastHiddenNodeCount=hiddenNodeCount}rebuildLayeredLayout(visible){const boxes=visible.map(n=>{const r=this.nodeRadius(n);return{id:n.id,width:r*2,height:r*2}}),visibleIds=new Set(visible.map(n=>n.id)),edges=this.graphModel.links.filter(l=>visibleIds.has(l.source)&&visibleIds.has(l.target)).map(l=>({source:l.source,target:l.target})),{positions:raw}=layeredLayout({nodes:boxes,edges,options:{gapX:12,gapY:this.safeLinkDistance}}),bounds=extent(raw.values(),point=>point.x,point=>point.y),offsetX=raw.size?this.safeWidth/2-(bounds.minX+(bounds.maxX-bounds.minX)/2):this.safeWidth/2,offsetY=raw.size?this.safeHeight/2-(bounds.minY+(bounds.maxY-bounds.minY)/2):this.safeHeight/2,nodes=visible.map(n=>{const p=raw.get(n.id);return{...n,x:p.x+offsetX,y:p.y+offsetY}}),byId=new Map(nodes.map(n=>[n.id,n])),{resolved,dangling}=this.resolveLinksAgainst(byId);this.danglingLinks=dangling,this.simulation=void 0,this.simNodes=nodes,this.simNodeById=byId,this.simLinks=resolved;for(const n of nodes)n.x!=null&&n.y!=null&&this.lastPositionById.set(n.id,{x:n.x,y:n.y});this.announceHiddenNodeCount(nodes.length)}onNodeClick(node,e){const detail={nodeId:node.id,x:node.x??0,y:node.y??0};this.emit("lr-node-activate",{...detail}),this.emitSelectionIntent("node",node.id,!!(e?.ctrlKey||e?.metaKey))}getNodePosition(id){const node=this.simNodes.find(candidate=>candidate.id===id);if(!(!node||!Number.isFinite(node.x)||!Number.isFinite(node.y)))return{x:node.x,y:node.y}}onLinkClick(link,e){const source=typeof link.source=="object"?link.source.id:String(link.source),target=typeof link.target=="object"?link.target.id:String(link.target);this.emit("lr-edge-activate",{sourceNodeId:source,targetNodeId:target,...link.id?{edgeId:link.id}:{}}),this.emitSelectionIntent("link",this.linkKey(link),!!(e?.ctrlKey||e?.metaKey))}onNodeEnter(node,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.setAttribute("data-hovered",""),this.svgHoverNodeId=node.id,this.emit("lr-node-enter",{nodeId:node.id}))}onNodeLeave(node,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.removeAttribute("data-hovered"),this.svgHoverNodeId=void 0,this.emit("lr-node-leave",{nodeId:node.id}))}onNodeDblClick(node,e){e.stopPropagation(),this.emit("lr-node-expand",{nodeId:node.id})}onLinkEnter(link,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.setAttribute("data-hovered",""),this.emitEdgeHover("enter",this.linkHoverDetail(link)))}linkHoverDetail(link){const source=typeof link.source=="object"?link.source.id:String(link.source),target=typeof link.target=="object"?link.target.id:String(link.target);return{sourceNodeId:source,targetNodeId:target,...link.id?{edgeId:link.id}:{}}}onLinkLeave(link,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.removeAttribute("data-hovered"),this.emitEdgeHover("leave",this.linkHoverDetail(link)))}emitEdgeHover(phase,detail){this.emit(phase==="enter"?"lr-edge-enter":"lr-edge-leave",{...detail})}nodeAccessibleText(node){let text=ownGraphText(node,"accessibleLabel")||ownGraphText(node,"label")||node.id;const type=this.resolveNodeType(node),typeLabel=type?ownGraphText(type,"label"):void 0;return typeLabel!==void 0&&(text=this.localize("graphTypedNode",void 0,{label:text,type:typeLabel})),node.expandable&&(text=this.localize("graphExpandableItem",void 0,{item:text})),text}boundedGraphText(value){if(typeof value!="string")return"";const normalized=value.replace(/\s+/g," ").trim();return normalized.length>512?`${normalized.slice(0,512)}…`:normalized}nodeTooltipText(node){return this.boundedGraphText(ownGraphText(node,"description")||ownGraphText(node,"label")||ownGraphText(node,"accessibleLabel")||node.id)}linkAccessibleText(link){const accessibleLabel=ownGraphText(link,"accessibleLabel");if(accessibleLabel)return accessibleLabel;const sourceValue=ownGraphValue(link,"source"),targetValue=ownGraphValue(link,"target"),source=sourceValue!==null&&typeof sourceValue=="object"?this.nodeAccessibleText(sourceValue):typeof sourceValue=="string"?sourceValue:"",target=targetValue!==null&&typeof targetValue=="object"?this.nodeAccessibleText(targetValue):typeof targetValue=="string"?targetValue:"";return ownGraphText(link,"label")||this.localize("graphLink",void 0,{source,target})}linkTooltipText(link){return this.boundedGraphText(ownGraphText(link,"description")||ownGraphText(link,"label")||ownGraphText(link,"accessibleLabel")||this.linkAccessibleText(link))}linkCoordinates(link){const source=link.source,target=link.target,x1=source.x??0,y1=source.y??0,targetX=target.x??0,targetY=target.y??0;if(!link.directed||link.dangling)return{x1,y1,x2:targetX,y2:targetY};const dx=targetX-x1,dy=targetY-y1,distance=Math.hypot(dx,dy);if(distance===0)return{x1,y1,x2:targetX,y2:targetY};const inset=Math.min(this.nodeRadius(target),distance);return{x1,y1,x2:targetX-dx/distance*inset,y2:targetY-dy/distance*inset}}edgeLabelPosition(link){const{x1,y1,x2,y2}=this.linkCoordinates(link),dx=x2-x1,dy=y2-y1,len=Math.hypot(dx,dy),mx=(x1+x2)/2,my=(y1+y2)/2;return len===0?{x:mx,y:my}:{x:mx+-dy/len*EDGE_LABEL_OFFSET_PX,y:my+dx/len*EDGE_LABEL_OFFSET_PX}}edgeLabelFontPx(){const raw=this.computedStyle().getPropertyValue("--lr-font-size-2xs").trim();return resolveCssTokenLength(raw,{host:this})??DEFAULT_EDGE_LABEL_FONT_PX}edgeLabelContext(){return this.edgeLabelMeasureCanvas?.ownerDocument!==this.ownerDocument&&(this.edgeLabelMeasureCanvas=this.ownerDocument.createElement("canvas"),this.edgeLabelMeasureCtx=this.edgeLabelMeasureCanvas.getContext("2d")),this.edgeLabelMeasureCtx??null}edgeLabelWidth(text){const cached=this.edgeLabelWidthCache.get(text);if(cached!=null)return cached;const ctx=this.edgeLabelContext();let width;if(ctx){const fontFamily=this.computedStyle().getPropertyValue("--lr-font").trim()||"sans-serif";ctx.font=`${this.edgeLabelFontPx()}px ${fontFamily}`,width=ctx.measureText(text).width}else width=text.length*this.edgeLabelFontPx()*.6;if(this.edgeLabelWidthCache.size>=EDGE_LABEL_WIDTH_CACHE_MAX){const oldest=this.edgeLabelWidthCache.keys().next().value;oldest!==void 0&&this.edgeLabelWidthCache.delete(oldest)}return this.edgeLabelWidthCache.set(text,width),width}updateEdgeLabelZoomGate(k){this.gEl&&(k<this.safeEdgeLabelMinZoom?this.gEl.setAttribute("data-edge-labels-hidden",""):this.gEl.removeAttribute("data-edge-labels-hidden"))}updateNodeLabelZoomGate(k){this.gEl&&(this.resolvedNodeLabelsMode==="zoom"&&k<NODE_LABEL_MIN_ZOOM?this.gEl.setAttribute("data-node-labels-hidden",""):this.gEl.removeAttribute("data-node-labels-hidden"))}linkIndexBase(){return this.simNodes.length}communityIndexBase(){return this.linkIndexBase()+this.navigableLinks().length}graphItemCount(){return this.communityIndexBase()+this.visibleCommunities().length}normalizedGraphItem(index=this.activeGraphItem){const count=this.graphItemCount();return count?Math.min(Math.max(index,0),count-1):-1}graphItemIdentity(index){if(index<0)return;if(index<this.linkIndexBase()){const node=this.simNodes[index];return node?{kind:"node",id:node.id}:void 0}if(index<this.communityIndexBase()){const link=this.navigableLinks()[index-this.linkIndexBase()];return link?{kind:"link",id:this.linkKey(link)}:void 0}const community=this.visibleCommunities()[index-this.communityIndexBase()]?.community;return community?{kind:"community",id:community.id}:void 0}graphItemIndex(identity){if(identity.kind==="node")return this.simNodes.findIndex(node=>node.id===identity.id);if(identity.kind==="link"){const index2=this.navigableLinks().findIndex(link=>this.linkKey(link)===identity.id);return index2<0?-1:this.linkIndexBase()+index2}const index=this.visibleCommunities().findIndex(entry=>entry.community.id===identity.id);return index<0?-1:this.communityIndexBase()+index}communityText(community){return ownGraphText(community,"label")??community.id}graphItemText(index){if(index<this.linkIndexBase()){const node=this.simNodes[index];return node?this.localize("graphNode",void 0,{label:this.nodeTooltipText(node)}):""}if(index<this.communityIndexBase()){const link=this.navigableLinks()[index-this.linkIndexBase()];return link?this.linkTooltipText(link):""}const entry=this.visibleCommunities()[index-this.communityIndexBase()];return entry?this.localize("graphCommunity",void 0,{label:this.communityText(entry.community),count:getNumberFormat(this.effectiveLocale).format(entry.members.length)}):""}graphItemAnnouncement(index){return this.localize("graphItemAnnouncement",void 0,{item:this.graphItemText(index),index:getNumberFormat(this.effectiveLocale).format(index+1),total:getNumberFormat(this.effectiveLocale).format(this.graphItemCount())})}onGraphItemFocus(index){this.normalizedGraphItem(index)<0||(this.activeGraphItem=index,this.graphLiveText=this.graphItemAnnouncement(index))}focusGraphItem(index){const normalized=this.normalizedGraphItem(index);normalized<0||(this.activeGraphItem=normalized,this.graphLiveText=this.graphItemAnnouncement(normalized),this.updateComplete.then(()=>this.focusGraphItemElement(normalized)))}focusGraphItemElement(index){if(this.renderer==="canvas"){this.renderRoot.querySelector('[part="cursor-item"]')?.focus(),this.scheduleCanvasDraw();return}[...this.renderRoot.querySelectorAll('[part="node"]'),...this.renderRoot.querySelectorAll('[part="link"][tabindex]'),...this.renderRoot.querySelectorAll('[part="hull"]')][index]?.focus()}onGraphKeyDown(e,index,activate){if(e.key==="Enter"||e.key===" "){if(e.preventDefault(),e.repeat)return;if(this.onGraphItemFocus(index),activate(e),index<this.simNodes.length){const now=this.ownerWindow?.performance.now()??0;if(this.lastKeyActivateIndex===index&&now-this.lastKeyActivateTime<=EXPAND_KEY_INTERVAL_MS){const node=this.simNodes[index];node&&this.emit("lr-node-expand",{nodeId:node.id}),this.lastKeyActivateIndex=null}else this.lastKeyActivateIndex=index,this.lastKeyActivateTime=now}return}const count=this.graphItemCount();if(!count)return;const rtl=isRtl(this),forwardKey=rtl?"ArrowLeft":"ArrowRight",backwardKey=rtl?"ArrowRight":"ArrowLeft";let next=index;if(e.key===forwardKey||e.key==="ArrowDown")next=Math.min(count-1,index+1);else if(e.key===backwardKey||e.key==="ArrowUp")next=Math.max(0,index-1);else if(e.key==="Home")next=0;else if(e.key==="End")next=count-1;else return;e.preventDefault(),this.focusGraphItem(next)}render(){const nodeLimit=publicCollectionTruncation(this,"nodes"),edgeLimit=publicCollectionTruncation(this,"edges"),limitNotices=html`${nodeLimit?html`<p part="limit" role="note">${this.localize("graphNodeLimit",void 0,{shown:getNumberFormat(this.effectiveLocale).format(nodeLimit.retained),total:getNumberFormat(this.effectiveLocale).format(nodeLimit.source)})}</p>`:nothing}${edgeLimit?html`<p part="limit" role="note">${this.localize("graphEdgeLimit",void 0,{shown:getNumberFormat(this.effectiveLocale).format(edgeLimit.retained),total:getNumberFormat(this.effectiveLocale).format(edgeLimit.source)})}</p>`:nothing}`;if(this.loading)return html`
|
|
1
|
+
import{__decorate}from"tslib";import{collectionSupport,publicCollectionTruncation}from"../../../internal/collection-snapshot.js";import{html,nothing,svg}from"lit";import{property,state,query}from"lit/decorators.js";import{styleMap}from"lit/directives/style-map.js";import{LyraElement}from"../../../internal/lyra-element.js";import{fitTransform}from"../../../internal/fit-transform.js";import{specialistTokens}from"../../../internal/specialist-host-tokens.styles.js";import{nextId,srOnly}from"../../../internal/a11y.js";import{prefersReducedMotion}from"../../../internal/motion.js";import{isRtl}from"../../../internal/rtl.js";import{literalSetConverter}from"../../../internal/converters.js";import{resolveCssTokenLength}from"../../../internal/css-token-length.js";import{styles}from"./graph.styles.js";import{loadD3}from"./graph-loader.js";import{convexHull,hullPathD,hullCentroidX,hullTopY}from"./graph-hull.js";import{EXPAND_BADGE_OFFSET,EXPAND_BADGE_R,drawGraphScene,drawPickingScene,pickColorToIndex,shapeHalfSide}from"./graph-canvas.js";import{GraphSpatialController}from"./graph-spatial-controller.js";import{normalizeGraphCamera}from"./graph-spatial.js";import{layeredLayout}from"../../../internal/layered-layout.js";import{finiteNumber,finiteRange,finiteInteger,extent}from"../../../internal/numbers.js";import{getNumberFormat}from"../../../internal/intl-cache.js";import{sanitizeCssColor}from"../../../internal/safe-css.js";import{getOwnDataDescriptor,MISSING_OWN_DATA_DESCRIPTOR,UNSAFE_OWN_DATA_DESCRIPTOR}from"../../../internal/data-descriptors.js";import{shadowFocusTarget}from"../../../internal/active-element.js";import{ThemeWatcher}from"../../../internal/theme-watcher.js";import{devWarnOnce}from"../../../internal/dev-warning.js";import{copyGraphLinkIdentity,graphLengthConverter,graphLinkIdentity,normalizeGraphModel}from"./graph-model.js";import{canonicalIdentityList}from"../retrieval-identity.js";import{AnnouncementSinkController}from"../../../internal/announcer.js";import"../../overlays/skeleton/skeleton.class.js";import{LYRA_DEFAULT_graphCommunity,LYRA_DEFAULT_graphDataList,LYRA_DEFAULT_graphDataListLimit,LYRA_DEFAULT_graphDiagram,LYRA_DEFAULT_graphEdgeLimit,LYRA_DEFAULT_graphExpandableItem,LYRA_DEFAULT_graphFit,LYRA_DEFAULT_graphItemAnnouncement,LYRA_DEFAULT_graphLink,LYRA_DEFAULT_graphMissingLibrary,LYRA_DEFAULT_graphNode,LYRA_DEFAULT_graphNodeFocused,LYRA_DEFAULT_graphNodeLimit,LYRA_DEFAULT_graphNodesHidden,LYRA_DEFAULT_graphOrbitDown,LYRA_DEFAULT_graphOrbitLeft,LYRA_DEFAULT_graphOrbitRight,LYRA_DEFAULT_graphOrbitUp,LYRA_DEFAULT_graphSelectionCount,LYRA_DEFAULT_graphSpatialControls,LYRA_DEFAULT_graphSpatialInstructions,LYRA_DEFAULT_graphSpatialPage,LYRA_DEFAULT_graphSpatialUnavailable,LYRA_DEFAULT_graphTypedNode,LYRA_DEFAULT_graphView3d,LYRA_DEFAULT_graphViewList}from"../../../internal/default-strings/retrieval.generated.js";import{LYRA_DEFAULT_loading,LYRA_DEFAULT_next,LYRA_DEFAULT_noData,LYRA_DEFAULT_previous,LYRA_DEFAULT_zoomIn,LYRA_DEFAULT_zoomOut}from"../../../internal/default-strings/shared.generated.js";const GRAPH_LAYOUT=literalSetConverter(["force","layered"],"force"),GRAPH_VIEW=literalSetConverter(["2d","3d","list"],"2d"),STUB_OFFSET_PX=14,EDGE_LABEL_OFFSET_PX=4,DEFAULT_EDGE_LABEL_FONT_PX=10,EDGE_LABEL_LENGTH_GATE_RATIO=.85,EDGE_LABEL_WIDTH_CACHE_MAX=512,EXPAND_KEY_INTERVAL_MS=500,FOCUS_HALO_PADDING=6,HULL_PADDING=24,NODE_LABEL_MIN_ZOOM=.5,NODE_HIT_SEGMENT_HALF=.5;function ownGraphText(value,property2){const descriptor=getOwnDataDescriptor(value,property2);return descriptor===MISSING_OWN_DATA_DESCRIPTOR||descriptor===UNSAFE_OWN_DATA_DESCRIPTOR||typeof descriptor.value!="string"?void 0:descriptor.value}function ownGraphValue(value,property2){const descriptor=getOwnDataDescriptor(value,property2);return descriptor===MISSING_OWN_DATA_DESCRIPTOR||descriptor===UNSAFE_OWN_DATA_DESCRIPTOR?void 0:descriptor.value}function mulberry32(seed){let a=seed>>>0;return()=>{a=a+1831565813|0;let t=Math.imul(a^a>>>15,a|1);return t=t+Math.imul(t^t>>>7,t|61)^t,((t^t>>>14)>>>0)/4294967296}}function hashNodeSeed(seed,id){let h=seed>>>0;for(let i=0;i<id.length;i++)h=Math.imul(h^id.charCodeAt(i),2654435761),h^=h>>>15;return h>>>0}const MIN_RADIUS=6,MAX_RADIUS=24;function sanitizeNodeColor(color){return sanitizeCssColor(color)}function normalizeLinkDash(dash){if(!(!dash?.length||dash.some(value=>!Number.isFinite(value)||value<0)))return dash.join(" ")}function categoricalPaletteColor(index){return`var(--lr-graph-cat-${index%8+1})`}function squarePath(r){const s=shapeHalfSide(r);return`M ${-s} ${-s} L ${s} ${-s} L ${s} ${s} L ${-s} ${s} Z`}function diamondPath(r){const d=shapeHalfSide(r)*Math.SQRT2;return`M 0 ${-d} L ${d} 0 L 0 ${d} L ${-d} 0 Z`}function sameIds(a,b){return a===b?!0:!a||!b||a.length!==b.length?!1:a.every((id,index)=>id===b[index])}const identitySets=new WeakMap;function identitySet(values){const ids=canonicalIdentityList(values);let set=identitySets.get(ids);return set||identitySets.set(ids,set=new Set(ids)),set}class LyraGraph extends LyraElement{static{this.defaultStrings={...super.defaultStrings,graphCommunity:LYRA_DEFAULT_graphCommunity,graphDataList:LYRA_DEFAULT_graphDataList,graphDataListLimit:LYRA_DEFAULT_graphDataListLimit,graphDiagram:LYRA_DEFAULT_graphDiagram,graphEdgeLimit:LYRA_DEFAULT_graphEdgeLimit,graphExpandableItem:LYRA_DEFAULT_graphExpandableItem,graphFit:LYRA_DEFAULT_graphFit,graphItemAnnouncement:LYRA_DEFAULT_graphItemAnnouncement,graphLink:LYRA_DEFAULT_graphLink,graphMissingLibrary:LYRA_DEFAULT_graphMissingLibrary,graphNode:LYRA_DEFAULT_graphNode,graphNodeFocused:LYRA_DEFAULT_graphNodeFocused,graphNodeLimit:LYRA_DEFAULT_graphNodeLimit,graphNodesHidden:LYRA_DEFAULT_graphNodesHidden,graphOrbitDown:LYRA_DEFAULT_graphOrbitDown,graphOrbitLeft:LYRA_DEFAULT_graphOrbitLeft,graphOrbitRight:LYRA_DEFAULT_graphOrbitRight,graphOrbitUp:LYRA_DEFAULT_graphOrbitUp,graphSelectionCount:LYRA_DEFAULT_graphSelectionCount,graphSpatialControls:LYRA_DEFAULT_graphSpatialControls,graphSpatialInstructions:LYRA_DEFAULT_graphSpatialInstructions,graphSpatialPage:LYRA_DEFAULT_graphSpatialPage,graphSpatialUnavailable:LYRA_DEFAULT_graphSpatialUnavailable,graphTypedNode:LYRA_DEFAULT_graphTypedNode,graphView3d:LYRA_DEFAULT_graphView3d,graphViewList:LYRA_DEFAULT_graphViewList,loading:LYRA_DEFAULT_loading,next:LYRA_DEFAULT_next,noData:LYRA_DEFAULT_noData,previous:LYRA_DEFAULT_previous,zoomIn:LYRA_DEFAULT_zoomIn,zoomOut:LYRA_DEFAULT_zoomOut}}static{this.collectionSupport=collectionSupport}static{this.ownedCollectionProperties=Object.freeze(["nodes","edges","nodeTypes","hiddenTypes","communities","selectedNodeIds","selectedEdgeIds","dimmedNodeIds","dimmedEdgeIds"])}static get observedAttributes(){return[...new Set([...super.observedAttributes,"role"])]}static{this.styles=[LyraElement.styles,specialistTokens,styles,srOnly]}static{this.immutableEventDetails=Object.freeze(["lr-selection-change"])}get graphModel(){const sources=this.normalizedGraphSources;return(!sources||sources[0]!==this.nodes||sources[1]!==this.edges||sources[2]!==this.nodeTypes||sources[3]!==this.communities)&&(this.normalizedGraphSources=[this.nodes,this.edges,this.nodeTypes,this.communities],this.normalizedGraphModel=normalizeGraphModel(this.nodes,this.edges,this.nodeTypes,this.communities)),this.normalizedGraphModel}get view(){return this._view}set view(value){const next=GRAPH_VIEW.normalize(value),old=this._view;next!==old&&(this._view=next,this.requestUpdate("view",old))}get camera(){return this._camera}set camera(value){const old=this._camera;this._camera=value==null?void 0:normalizeGraphCamera(value,{yaw:0,pitch:0,distance:500,target:{x:0,y:0,z:0}}),this.requestUpdate("camera",old)}get layout(){return this._layout}set layout(next){const normalized=GRAPH_LAYOUT.normalize(next),old=this._layout;old!==normalized&&(this._layout=normalized,this.requestUpdate("layout",old))}spatialMessages(){return{controls:this.localize("graphSpatialControls"),view3d:this.localize("graphView3d"),viewList:this.localize("graphViewList"),fit:this.localize("graphFit"),left:this.localize("graphOrbitLeft"),right:this.localize("graphOrbitRight"),up:this.localize("graphOrbitUp"),down:this.localize("graphOrbitDown"),instructions:this.localize("graphSpatialInstructions"),unavailable:this.localize("graphSpatialUnavailable"),zoomIn:this.localize("zoomIn"),zoomOut:this.localize("zoomOut"),previous:this.localize("previous"),next:this.localize("next"),dataList:this.localize("graphDataList"),noData:this.localize("noData")}}constructor(){super(),this.nodes=[],this.edges=[],this.nodeTypes=[],this.hiddenTypes=[],this.communities=[],this._view="2d",this._layout="force",this.renderer="svg",this.fitTo="none",this.width=800,this.height=600,this.chargeStrength=-300,this.edgeDistance=100,this.minZoom=.1,this.maxZoom=8,this.label=null,this.accessibleLabel=null,this.withEdgeLabels=!1,this.edgeLabelMinZoom=.6,this.focusNodeId=null,this.selectionMode="none",this.selectedNodeIds=[],this.selectedEdgeIds=[],this.dimmedNodeIds=[],this.dimmedEdgeIds=[],this.arrowMarkerId=nextId("graph-arrow"),this.loading=!0,this.loadFailed=!1,this.loadLibrary=loadD3,this.loadGeneration=0,this.containerSize=null,this.simNodes=[],this.simLinks=[],this.simNodeById=new Map,this.danglingLinks=[],this.lastPositionById=new Map,this.lastHiddenNodeCount=0,this.activeGraphItem=0,this.graphLiveText="",this.announcements=new AnnouncementSinkController(this,{eager:["polite","assertive"]}),this.graphAnnouncementsReady=!1,this.isMounting=!0,this.authorRole=null,this.syncingGraphHostRole=!1,this.detachedGraphChanges=new Map,this.boundNodeEls=new WeakSet,this.nodeEls=[],this.nodeHitEls=[],this.nodeLabelEls=[],this.expandIndicatorEls=[],this.lastKeyActivateIndex=null,this.lastKeyActivateTime=0,this.lastAppliedFocusNodeId=null,this.communityHullEls=[],this.communityHullHitEls=[],this.communityLabelEls=[],this.visible=!0,this.canvasDrawPending=!1,this.pickDirty=!0,this.canvasCamera={k:1,x:0,y:0},this.pickItems=[],this.canvasSceneHasEdgeLabels=!1,this.isCameraTweening=!1,this.linkEls=[],this.linkHitEls=[],this.linkLabelEls=[],this.linkLabelHiddenByLength=[],this.edgeLabelWidthCache=new Map,this.danglingLinkEls=[],this.linkPaintVisibilityCache=new Map,this.resolvedCssColorCache=new Map,this.reducedMotion=!1,this.spatial=new GraphSpatialController(this,{model:()=>this.graphModel,locale:()=>this.effectiveLocale,direction:()=>this.effectiveDirection,pageText:values=>this.localize("graphSpatialPage",void 0,values),viewport:()=>({width:this.safeWidth,height:this.safeHeight}),messages:()=>this.spatialMessages(),communityText:values=>this.localize("graphCommunity",void 0,values),nodeText:node=>this.nodeAccessibleText(node),edgeText:edge=>this.linkAccessibleText(edge),nodeTooltip:node=>this.nodeTooltipText(node),edgeTooltip:edge=>this.linkTooltipText(edge),nodeShape:node=>this.nodeShape(node),paint:(nodes,edges)=>this.withCanvasColorResolver(resolve=>{const css=this.computedStyle(),nodeDefault=css.getPropertyValue("--lr-graph-node-fill").trim()||css.getPropertyValue("--lr-color-brand").trim(),edgeDefault=css.getPropertyValue("--lr-graph-edge-color").trim()||css.getPropertyValue("--lr-color-border").trim();return{nodes:new Map(nodes.map(({node})=>[node.id,resolve(this.nodeFill(node)??nodeDefault)])),edges:new Map(edges.map(edge=>[graphLinkIdentity(edge),resolve(sanitizeNodeColor(edge.color)??edgeDefault)])),visibleEdges:new Set(edges.filter(edge=>this.isInteractiveLink(edge,resolve,edgeDefault)).map(graphLinkIdentity)),text:resolve(css.getPropertyValue("--lr-color-text").trim()),selected:resolve(css.getPropertyValue("--lr-graph-selected-color").trim()||css.getPropertyValue("--lr-color-success").trim()),font:css.getPropertyValue("--lr-font").trim()||css.fontFamily,fontSize:this.edgeLabelFontPx(),dimmedOpacity:finiteRange(Number(css.getPropertyValue("--lr-graph-dimmed-opacity").trim()||.35),.35,0,1)}}),activate:(hit,event)=>{if(hit.kind==="node"){const position=this.spatial.position(hit.id);if(!position)return;this.emit("lr-node-activate",{nodeId:hit.id,...position}),this.emitSelectionIntent("node",hit.id,event.ctrlKey||event.metaKey)}else this.onLinkClick(hit.edge,event)},expand:nodeId=>this.emit("lr-node-expand",{nodeId}),hover:(previous,next)=>{previous?.kind==="node"?this.emit("lr-node-leave",{nodeId:previous.id}):previous?.kind==="link"&&this.emitEdgeHover("leave",this.linkHoverDetail(previous.edge)),next?.kind==="node"?this.emit("lr-node-enter",{nodeId:next.id}):next?.kind==="link"&&this.emitEdgeHover("enter",this.linkHoverDetail(next.edge))},community:community=>this.onCommunityClick(community),cameraChanged:camera=>this.emit("lr-camera-change",{camera}),viewChanged:()=>this.emit("lr-view-change",{view:this.view}),unavailable:()=>this.announcements.announceAssertive(this.localize("graphSpatialUnavailable")),clearSelection:()=>this.clearSelection(),afterUpdate:(callback,key)=>this.scheduleAfterUpdate(callback,key)}),this.isApplyingZoomTransform=!1,this.onCanvasDprChange=()=>{this.watchCanvasDpr(),this.markCanvasDirty()},this.onCanvasPointerDown=e=>{if(e.button!==0||(this.canvasPointerDownAt={x:e.clientX,y:e.clientY},this.canvasPointerDownId=e.pointerId,this.layout==="layered"))return;const hit=this.hitTest(e.clientX,e.clientY);if(hit?.kind==="node"){this.canvasDragNode=hit.node,this.canvasPointerId=e.pointerId;try{this.canvasEl.setPointerCapture(e.pointerId)}catch{}hit.node.fx=hit.node.x,hit.node.fy=hit.node.y,this.simulation?.alphaTarget(.3).restart()}},this.onCanvasPointerMove=e=>{if(this.canvasDragNode&&this.canvasPointerId===e.pointerId){const node=this.simNodeById.get(this.canvasDragNode.id);if(node){const rect=this.canvasEl.getBoundingClientRect();node.fx=(e.clientX-rect.left-this.canvasCamera.x)/this.canvasCamera.k,node.fy=(e.clientY-rect.top-this.canvasCamera.y)/this.canvasCamera.k,this.markCanvasDirty()}return}if(this.pendingHover={x:e.clientX,y:e.clientY},this.hoverRafId!=null)return;const frameOwner=this.ownerWindow;frameOwner&&(this.hoverRafOwner=frameOwner,this.hoverRafId=frameOwner.requestAnimationFrame(()=>{if(this.hoverRafId=void 0,this.hoverRafOwner=void 0,!this.isConnected||this.ownerWindow!==frameOwner)return;const pending=this.pendingHover;if(this.pendingHover=void 0,!pending||this.canvasHoverSuppressed()||this.pickDirty&&this.simulationIsTicking())return;const hit=this.hitTest(pending.x,pending.y);this.updateCanvasTooltip(hit,pending.x,pending.y),this.updateCanvasHover(hit)}))},this.onCanvasPointerUp=e=>{this.finishCanvasNodeDrag(e.pointerId);const down=this.takeCanvasPointerDown(e.pointerId);if(!down||Math.hypot(e.clientX-down.x,e.clientY-down.y)>5)return;const hit=this.hitTest(e.clientX,e.clientY);if(!hit){this.clearSelection();return}hit.kind==="node"?this.onNodeClick(hit.node,e):hit.kind==="link"?this.onLinkClick(hit.link,e):this.onCommunityClick(hit.entry.community)},this.onCanvasPointerCancel=e=>{this.finishCanvasNodeDrag(e.pointerId),this.takeCanvasPointerDown(e.pointerId)},this.onCanvasLostPointerCapture=e=>{this.finishCanvasNodeDrag(e.pointerId,!1),this.takeCanvasPointerDown(e.pointerId)},this.onCanvasPointerLeave=()=>{this.pendingHover=void 0,this.hoverRafId!=null&&(this.hoverRafOwner?.cancelAnimationFrame(this.hoverRafId),this.hoverRafId=void 0,this.hoverRafOwner=void 0),this.updateCanvasTooltip(void 0,0,0),this.canvasHoverSuppressed()?this.canvasHover=void 0:this.updateCanvasHover(void 0)},this.onCanvasDblClick=e=>{const hit=this.hitTest(e.clientX,e.clientY),node=hit?.kind==="node"?hit.node:this.nodeAtCanvasPoint(e.clientX,e.clientY);node&&(e.stopImmediatePropagation(),this.emit("lr-node-expand",{nodeId:node.id}))},this.isDragging=!1,this.isPanning=!1,new ThemeWatcher(this,()=>{const reduced=prefersReducedMotion(this);reduced!==this.reducedMotion&&(this.reducedMotion=reduced,reduced?this.simulation?.stop():this.view==="2d"&&this.safeSeed==null&&this.simulation?.restart()),this.linkPaintVisibilityCache.clear(),this.resolvedCssColorCache.clear(),this.view!=="2d"?this.spatial.invalidate():this.renderer==="canvas"&&this.markCanvasDirty()},["(prefers-reduced-motion: reduce)"])}attributeChangedCallback(name,oldValue,value){super.attributeChangedCallback(name,oldValue,value),name==="role"&&oldValue!==value&&!this.syncingGraphHostRole&&(this.authorRole=value)}hostOwnsGraphSemantics(){return this.hasAttribute("aria-label")}syncGraphHostRole(){if(this.authorRole===null){this.syncingGraphHostRole=!0;try{this.hostOwnsGraphSemantics()?this.setAttribute("role","group"):this.removeAttribute("role")}finally{this.syncingGraphHostRole=!1}}}get ownerWindow(){return this.ownerDocument.defaultView??void 0}computedStyle(element=this){const view=this.ownerWindow;return view?view.getComputedStyle(element):"style"in element?element.style:this.style}connectedCallback(){if(super.connectedCallback(),this.detachedGraphChanges.size){for(const[key,previous]of this.detachedGraphChanges)this.requestUpdate(key,previous);this.detachedGraphChanges.clear(),this.requestUpdate()}this.reducedMotion=prefersReducedMotion(this);const IntersectionObserverCtor=this.ownerWindow?.IntersectionObserver;this.view==="2d"&&IntersectionObserverCtor&&(this.intersectionObserver=new IntersectionObserverCtor(entries=>{const wasVisible=this.visible;this.visible=entries[0]?.isIntersecting??!0,this.visible&&!wasVisible&&this.canvasDrawPending&&(this.canvasDrawPending=!1,this.scheduleCanvasDraw())}),this.intersectionObserver.observe(this)),this.fitTo==="container"&&(this.syncHostResizeObserver(),this.measureHostBox()),this.view==="2d"?this.connect2d():(this.loading=!1,this.requestUpdate())}connect2d(){const Observer=this.ownerWindow?.IntersectionObserver;if(!this.intersectionObserver&&Observer&&(this.intersectionObserver=new Observer(entries=>{const wasVisible=this.visible;this.visible=entries[0]?.isIntersecting??!0,this.visible&&!wasVisible&&this.canvasDrawPending&&(this.canvasDrawPending=!1,this.scheduleCanvasDraw())}),this.intersectionObserver.observe(this)),this.d3){!this.reducedMotion&&this.safeSeed==null&&this.simulation?.restart(),this.renderer==="canvas"&&this.canvasEl&&this.canvasEl===this.zoomedEl&&(this.ensureCanvasOwnerRealm(),this.syncHostResizeObserver(),this.watchCanvasDpr(),this.markCanvasDirty());return}const generation=++this.loadGeneration;this.loadLibrary().then(async mods=>{try{await this.updateComplete}catch{return}if(await new Promise(resolve=>this.updateBrowserDerivedState(resolve)),!(generation!==this.loadGeneration||!this.isConnected)){if(this.loading=!1,!mods){this.loadFailed=!0;return}this.loadFailed=!1,this.d3=mods,this.rebuildSimulation()}})}disconnectedCallback(){super.disconnectedCallback(),this.spatial.disconnect(),this.loadGeneration+=1,this.simulation?.stop(),this.finishCanvasNodeDrag(void 0,!0,!1),this.takeCanvasPointerDown(),this.cancelCameraTween(),this.intersectionObserver?.disconnect(),this.intersectionObserver=void 0,this.hostResizeObserver?.disconnect(),this.hostResizeObserver=void 0,this.hostResizeObserverDocument=void 0,this.canvasDprQuery?.removeEventListener("change",this.onCanvasDprChange),this.canvasDprQuery=void 0,this.canvasDrawRafId!=null&&(this.canvasDrawRafOwner?.cancelAnimationFrame(this.canvasDrawRafId),this.canvasDrawRafId=void 0,this.canvasDrawRafOwner=void 0),this.hoverRafId!=null&&(this.hoverRafOwner?.cancelAnimationFrame(this.hoverRafId),this.hoverRafId=void 0,this.hoverRafOwner=void 0),this.pendingHover=void 0,this.canvasHover=void 0,this.canvasTooltipEl?.setAttribute("hidden",""),this.pendingGraphItemFocus=void 0,this.viewportChangeRafId!=null&&(this.viewportChangeRafOwner?.cancelAnimationFrame(this.viewportChangeRafId),this.viewportChangeRafId=void 0,this.viewportChangeRafOwner=void 0)}adoptedCallback(){super.adoptedCallback(),this.announcements.adopted(),this.ensureCanvasOwnerRealm()}scheduleViewportChange(){if(this.view!=="2d"||this.viewportChangeRafId!=null)return;const frameOwner=this.ownerWindow;frameOwner&&(this.viewportChangeRafOwner=frameOwner,this.viewportChangeRafId=frameOwner.requestAnimationFrame(()=>{if(this.viewportChangeRafId=void 0,this.viewportChangeRafOwner=void 0,!this.isConnected||this.ownerWindow!==frameOwner)return;const transform=this.renderer==="canvas"||!this.d3||!this.zoomedEl?this.canvasCamera:this.d3.zoomTransform(this.zoomedEl);this.emit("lr-viewport-change",{zoom:transform.k,x:transform.x,y:transform.y,k:transform.k})}))}nodeRadius(n){const r=n.radius??(MIN_RADIUS+MAX_RADIUS)/2;return Number.isFinite(r)?Math.min(MAX_RADIUS,Math.max(MIN_RADIUS,r)):(MIN_RADIUS+MAX_RADIUS)/2}safeLinkWidth(link){return finiteRange(link.width??1.5,1.5,0)}isInteractiveLink(link,resolveColor,defaultPaint){if(this.safeLinkWidth(link)<=0)return!1;const effectivePaint=sanitizeNodeColor(link.color)??defaultPaint,color=effectivePaint?resolveColor(effectivePaint).trim().toLowerCase():void 0;if(!color)return!0;if(color==="transparent"||/^#[\da-f]{4}$/.test(color)&&color.endsWith("0")||/^#[\da-f]{8}$/.test(color)&&color.endsWith("00")||/\/\s*0(?:\.0+)?%?\s*\)$/.test(color)||/^(?:rgba|hsla)\(/.test(color)&&/,\s*0(?:\.0+)?\s*\)$/.test(color))return!1;const cached=this.linkPaintVisibilityCache.get(color);if(cached!==void 0)return cached;this.linkPaintProbe??=this.ownerDocument.createElement("canvas"),this.linkPaintProbe.width=1,this.linkPaintProbe.height=1;const context=this.linkPaintProbe.getContext("2d",{willReadFrequently:!0});if(!context)return!0;let visible=!0;try{context.clearRect(0,0,1,1),context.fillStyle="rgb(1 2 3)",context.fillStyle=color,context.fillRect(0,0,1,1),visible=context.getImageData(0,0,1,1).data[3]!==0}catch{visible=!0}return this.linkPaintVisibilityCache.set(color,visible),visible}navigableLinks(){return this.navigableLinksCache||(this.navigableLinksCache=this.simLinks.length?this.withCanvasColorResolver(resolveColor=>{const computed=this.computedStyle(),defaultPaint=computed.getPropertyValue("--lr-graph-edge-color").trim()||computed.getPropertyValue("--lr-color-border").trim();return this.simLinks.filter(link=>this.isInteractiveLink(link,resolveColor,defaultPaint))}):[]),this.navigableLinksCache}lengthInPixels(value){return typeof value=="string"?resolveCssTokenLength(value,{host:this})??Number.NaN:value}get requestedWidth(){return finiteRange(this.lengthInPixels(this.width),800,1)}get requestedHeight(){return finiteRange(this.lengthInPixels(this.height),600,1)}get safeWidth(){const requested=this.requestedWidth,measured=this.fitTo==="container"&&this.containerSize;return measured?finiteRange(measured.width,requested,1):requested}get safeHeight(){const requested=this.requestedHeight,measured=this.fitTo==="container"&&this.containerSize;return measured?finiteRange(measured.height,requested,1):requested}recordContainerSize(width,height){const w=Math.round(finiteRange(width,0,0)),h=Math.round(finiteRange(height,0,0));return w<=0||h<=0||this.containerSize?.width===w&&this.containerSize?.height===h?!1:(this.containerSize={width:w,height:h},!0)}measureHostBox(){return this.isConnected?(this.syncRequestedHeightVar(),this.recordContainerSize(this.clientWidth,this.clientHeight)):!1}syncRequestedHeightVar(){this.style.setProperty("--_lr-graph-requested-height",`${this.requestedHeight}px`)}get safeMinZoom(){return finiteRange(this.minZoom,.1,.001,1e3)}get safeMaxZoom(){return finiteRange(this.maxZoom,8,.001,1e3)}get effectiveZoomBounds(){const min=this.safeMinZoom,max=this.safeMaxZoom;return Object.freeze({min:Math.min(min,max),max:Math.max(min,max)})}get safeEdgeLabelMinZoom(){return finiteRange(this.edgeLabelMinZoom,.6,.001,1e3)}get resolvedNodeLabelsMode(){return this.nodeLabels??(this.renderer==="canvas"?"zoom":"always")}canvasNodeLabelsVisible(){const mode=this.resolvedNodeLabelsMode;return mode==="none"?!1:mode==="zoom"?this.canvasCamera.k>=NODE_LABEL_MIN_ZOOM:!0}get safeSeed(){return this.seed==null?void 0:finiteInteger(this.seed,0)}get safeChargeStrength(){return finiteNumber(this.chargeStrength,-300)}get safeLinkDistance(){return finiteRange(this.edgeDistance,100,0)}nodeTypeEntry(node){const types=this.graphModel.nodeTypes;if(this.nodeTypeIndex?.[0]!==types){const labeled=this.labeledNodeTypes();this.nodeTypeIndex=[types,new Map(types.map((type,index)=>{const slot=labeled.indexOf(type);return[type.id,[type,slot<0?index:slot]]}))]}return node.type==null?void 0:this.nodeTypeIndex[1].get(node.type)}resolveNodeType(node){return this.nodeTypeEntry(node)?.[0]}nodeShape(node){return this.resolveNodeType(node)?.shape??"circle"}labeledNodeTypes(){return this.graphModel.nodeTypes.filter(candidate=>typeof candidate?.label=="string"&&candidate.label.trim().length>0)}nodeFill(node){const ownColor=sanitizeNodeColor(node.color);if(ownColor)return ownColor;const entry=this.nodeTypeEntry(node);if(entry)return sanitizeNodeColor(entry[0].color)||categoricalPaletteColor(entry[1])}visibleNodes(){const hiddenTypes=canonicalIdentityList(this.hiddenTypes);if(!hiddenTypes.length)return this.graphModel.nodes;const hidden=new Set(hiddenTypes);return this.graphModel.nodes.filter(n=>n.type==null||!hidden.has(n.type))}resolveLinksAgainst(byId){const nodeExists=new Set(this.graphModel.nodes.map(n=>n.id)),resolved=[],dangling=[];for(const l of this.graphModel.links){const source=byId.get(l.source);if(!source)continue;const target=byId.get(l.target);target?resolved.push(copyGraphLinkIdentity(l,{...l,source,target})):nodeExists.has(l.target)||dangling.push(copyGraphLinkIdentity(l,{...l,source,target:{id:l.target,x:source.x,y:source.y},dangling:!0}))}return{resolved,dangling}}communityMembers(community){const idSet=new Set(community.memberIds);return this.simNodes.filter(n=>idSet.has(n.id)||n.communityId===community.id)}visibleCommunities(){return this.visibleCommunitiesCache||(this.visibleCommunitiesCache=this.graphModel.communities.map(community=>({community,members:this.communityMembers(community)})).filter(entry=>entry.members.length>0)),this.visibleCommunitiesCache}communityHull(members){return convexHull(members.map(n=>({x:n.x??0,y:n.y??0})))}onCommunityClick(community){this.emit("lr-community-activate",{communityId:community.id})}cameraTransitionMs(){const parsed=parseFloat(this.computedStyle().getPropertyValue("--lr-transition-base"));return Number.isFinite(parsed)?parsed:180}cancelCameraTween(){this.cameraTweenId!=null&&(this.cameraTweenFrameOwner?.cancelAnimationFrame(this.cameraTweenId),this.cameraTweenId=void 0,this.cameraTweenFrameOwner=void 0),this.isCameraTweening=!1;const resolve=this.cameraTweenResolve;resolve&&(this.cameraTweenResolve=void 0,resolve(!1))}applyZoomTransform(transform){if(!(!this.d3||!this.zoomedEl||!this.zoomBehavior)){this.isApplyingZoomTransform=!0;try{this.zoomBehavior.transform(this.d3.select(this.zoomedEl),transform)}finally{this.isApplyingZoomTransform=!1}}}tweenCamera(computeTarget){return new Promise(resolve=>{if(!this.d3||!this.zoomedEl||!this.zoomBehavior){resolve(!1);return}this.cancelCameraTween(),this.cameraTweenResolve=resolve,this.isCameraTweening=!0;const frameOwner=this.ownerWindow;if(!frameOwner){this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!1);return}if(prefersReducedMotion(this)){this.applyZoomTransform(computeTarget()),this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!0);return}const current=this.d3.zoomTransform(this.zoomedEl),duration=this.cameraTransitionMs(),start=frameOwner.performance.now(),startK=current.k,startX=current.x,startY=current.y,step=now=>{if(this.cameraTweenResolve!==resolve)return;if(!this.isConnected||this.ownerWindow!==frameOwner){this.cameraTweenId=void 0,this.cameraTweenFrameOwner=void 0,this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!1);return}const t=!prefersReducedMotion(this)&&duration>0?Math.min(1,(now-start)/duration):1,target=computeTarget(),targetK=target.k,targetX=target.x,targetY=target.y;this.applyZoomTransform(this.d3.zoomIdentity.translate(startX+(targetX-startX)*t,startY+(targetY-startY)*t).scale(startK+(targetK-startK)*t)),t<1?(this.cameraTweenFrameOwner=frameOwner,this.cameraTweenId=frameOwner.requestAnimationFrame(step)):(this.cameraTweenId=void 0,this.cameraTweenFrameOwner=void 0,this.isCameraTweening=!1,this.cameraTweenResolve=void 0,resolve(!0))};this.cameraTweenFrameOwner=frameOwner,this.cameraTweenId=frameOwner.requestAnimationFrame(step)})}async focusNode(id,options){if(this.view!=="2d"){if(!this.isConnected)return!1;const focused=this.spatial.focusNode(id,options?.zoom);if(focused){const node2=this.graphModel.nodes.find(candidate=>candidate.id===id);node2&&this.announcements.announcePolite(this.localize("graphNodeFocused",void 0,{label:this.nodeAccessibleText(node2)}))}return focused}const node=this.simNodes.find(n=>n.id===id);if(!node||!this.d3||!this.zoomedEl||!this.zoomBehavior)return!1;const current=this.d3.zoomTransform(this.zoomedEl),bounds=this.effectiveZoomBounds,k=finiteRange(options?.zoom??current.k,current.k,bounds.min,bounds.max),arrived=await this.tweenCamera(()=>this.d3.zoomIdentity.translate(this.safeWidth/2-k*(node.x??0),this.safeHeight/2-k*(node.y??0)).scale(k));return arrived&&(this.graphLiveText=this.localize("graphNodeFocused",void 0,{label:this.nodeAccessibleText(node)})),arrived}fit(options){if(this.view!=="2d"){this.isConnected&&this.spatial.fit(options?.padding);return}if(!this.d3||!this.zoomedEl||!this.zoomBehavior||!this.simNodes.length)return;const padding=finiteRange(options?.padding??24,24,0);this.tweenCamera(()=>{const fitPoints=[];for(const n of this.simNodes){const r=this.nodeRadius(n);fitPoints.push({x:(n.x??0)-r,y:(n.y??0)-r}),fitPoints.push({x:(n.x??0)+r,y:(n.y??0)+r})}for(const entry of this.visibleCommunities())for(const p of this.communityHull(entry.members))fitPoints.push({x:p.x-HULL_PADDING,y:p.y-HULL_PADDING}),fitPoints.push({x:p.x+HULL_PADDING,y:p.y+HULL_PADDING});const{minX,maxX,minY,maxY}=extent(fitPoints,point=>point.x,point=>point.y),bounds=this.effectiveZoomBounds,transform=fitTransform({minX,minY,maxX,maxY},{width:this.safeWidth,height:this.safeHeight},padding,bounds);return this.d3.zoomIdentity.translate(transform.x,transform.y).scale(transform.zoom)})}updateFocusHalo(){if(!this.focusHaloEl)return;const node=this.focusNodeId!=null?this.simNodes.find(n=>n.id===this.focusNodeId):void 0;node?(this.focusHaloEl.setAttribute("cx",String(node.x??0)),this.focusHaloEl.setAttribute("cy",String(node.y??0)),this.focusHaloEl.setAttribute("r",String(this.nodeRadius(node)+FOCUS_HALO_PADDING)),this.focusHaloEl.removeAttribute("hidden")):this.focusHaloEl.setAttribute("hidden","")}setUpCanvasSurface(){this.canvasCtx=this.canvasEl.getContext("2d")??void 0,this.ensureCanvasOwnerRealm(),this.syncHostResizeObserver(),this.watchCanvasDpr(),this.canvasTooltipEl=this.renderRoot.querySelector('[part="tooltip"]')??void 0,this.bindCanvasPointer(),this.bindCanvasZoom()}ensureCanvasOwnerRealm(){const ownerDocument=this.ownerDocument;this.edgeLabelMeasureCanvas?.ownerDocument!==ownerDocument&&(this.edgeLabelMeasureCanvas=void 0,this.edgeLabelMeasureCtx=void 0,this.edgeLabelWidthCache.clear()),!(!this.pickCanvas&&this.renderer!=="canvas")&&this.pickCanvas?.ownerDocument!==ownerDocument&&(this.pickCanvas=ownerDocument.createElement("canvas"),this.pickCtx=this.pickCanvas.getContext("2d",{willReadFrequently:!0}),this.pickDirty=!0)}syncHostResizeObserver(){if(this.view!=="2d"||this.renderer!=="canvas"&&this.fitTo!=="container"){this.hostResizeObserver?.disconnect(),this.hostResizeObserver=void 0,this.hostResizeObserverDocument=void 0;return}this.hostResizeObserver&&this.hostResizeObserverDocument===this.ownerDocument||this.watchHostResize()}watchHostResize(){this.hostResizeObserver?.disconnect();const ResizeObserverCtor=this.ownerWindow?.ResizeObserver;if(!ResizeObserverCtor){this.hostResizeObserver=void 0,this.hostResizeObserverDocument=void 0;return}this.hostResizeObserver=new ResizeObserverCtor(entries=>{const box=entries[entries.length-1]?.contentRect;this.fitTo==="container"&&box&&this.recordContainerSize(box.width,box.height),this.renderer==="canvas"&&this.canvasEl&&this.markCanvasDirty()}),this.hostResizeObserverDocument=this.ownerDocument,this.hostResizeObserver.observe(this)}watchCanvasDpr(){this.canvasDprQuery?.removeEventListener("change",this.onCanvasDprChange);const view=this.ownerWindow;if(!view?.matchMedia){this.canvasDprQuery=void 0;return}this.canvasDprQuery=view.matchMedia(`(resolution: ${view.devicePixelRatio}dppx)`),this.canvasDprQuery.addEventListener("change",this.onCanvasDprChange)}markCanvasDirty(){this.canvasScene=void 0,this.pickDirty=!0,this.scheduleCanvasDraw()}markCanvasCameraDirty(){this.pickDirty=!0,this.scheduleCanvasDraw()}scheduleCanvasDraw(){if(this.view!=="2d")return;if(!this.visible){this.canvasDrawPending=!0;return}if(this.canvasDrawRafId!=null)return;const frameOwner=this.ownerWindow;frameOwner&&(this.canvasDrawRafOwner=frameOwner,this.canvasDrawRafId=frameOwner.requestAnimationFrame(()=>{this.canvasDrawRafId=void 0,this.canvasDrawRafOwner=void 0,!(!this.isConnected||this.ownerWindow!==frameOwner)&&this.drawCanvas()}))}resolveCssColorWithProbe(value,probe){const cached=this.resolvedCssColorCache.get(value);if(cached!==void 0)return cached;probe.style.color="",probe.style.color=value;const result=getComputedStyle(probe).color.trim()||getComputedStyle(this).color||"transparent";return this.resolvedCssColorCache.set(value,result),result}createCanvasColorProbe(){const probe=this.ownerDocument.createElement("span");return probe.setAttribute("aria-hidden","true"),probe.style.position="absolute",probe.style.inlineSize="0",probe.style.blockSize="0",probe.style.overflow="hidden",probe.style.visibility="hidden",probe.style.pointerEvents="none",this.renderRoot.append(probe),probe}withCanvasColorResolver(callback){let probe;try{return callback(value=>{const cached=this.resolvedCssColorCache.get(value);return cached!==void 0?cached:(probe??=this.createCanvasColorProbe(),this.resolveCssColorWithProbe(value,probe))})}finally{probe?.remove()}}buildCanvasScene(cs){return this.withCanvasColorResolver(resolveColor=>{const hullFillDefault=cs.getPropertyValue("--lr-graph-hull-fill").trim()||cs.getPropertyValue("--lr-color-brand").trim(),hulls=this.visibleCommunities().map(entry=>({d:hullPathD(this.communityHull(entry.members)),fill:resolveColor(sanitizeNodeColor(entry.community.color)??hullFillDefault)})),linkColorDefault=cs.getPropertyValue("--lr-graph-edge-color").trim()||cs.getPropertyValue("--lr-color-border").trim(),links=this.simLinks.map(l=>{const coords=this.linkCoordinates(l),own=sanitizeNodeColor(l.color);return{x1:coords.x1,y1:coords.y1,x2:coords.x2,y2:coords.y2,color:resolveColor(own??linkColorDefault),width:this.safeLinkWidth(l),dash:l.dash,directed:l.directed,selected:this.isSelected("link",this.linkKey(l)),dimmed:this.isDimmed("link",this.linkKey(l))}}),edgeLabels=this.withEdgeLabels&&this.canvasCamera.k>=this.safeEdgeLabelMinZoom?this.simLinks.flatMap(l=>{const label=ownGraphText(l,"label");if(!label)return[];const pos=this.edgeLabelPosition(l),coords=this.linkCoordinates(l),edgeLength=Math.hypot(coords.x2-coords.x1,coords.y2-coords.y1);return this.edgeLabelWidth(label)>edgeLength*EDGE_LABEL_LENGTH_GATE_RATIO?[]:[{x:pos.x,y:pos.y,text:label}]}):[],nodeFillDefault=cs.getPropertyValue("--lr-graph-node-fill").trim()||cs.getPropertyValue("--lr-color-brand").trim(),nodes=this.simNodes.map(n=>{const fill=this.nodeFill(n);return{x:n.x??0,y:n.y??0,r:this.nodeRadius(n),shape:this.nodeShape(n),fill:resolveColor(fill??nodeFillDefault),selected:this.isSelected("node",n.id),dimmed:this.isDimmed("node",n.id)}}),nodeLabels=this.simNodes.flatMap(n=>{const label=ownGraphText(n,"label");return label?[{x:(n.x??0)+this.nodeRadius(n)+2,y:n.y??0,text:label}]:[]}),expandIndicators=this.simNodes.filter(n=>n.expandable).map(n=>({x:n.x??0,y:n.y??0,r:this.nodeRadius(n)})),focusNode=this.focusNodeId!=null?this.simNodes.find(n=>n.id===this.focusNodeId):void 0,scene={hulls,links,edgeLabels,nodes,nodeLabels,expandIndicators,focusHalo:focusNode?{x:focusNode.x??0,y:focusNode.y??0,r:this.nodeRadius(focusNode)+FOCUS_HALO_PADDING}:void 0,showNodeLabels:this.canvasNodeLabelsVisible(),haloColor:resolveColor(this.ownerWindow?.matchMedia?.("(forced-colors: active)").matches?"CanvasText":cs.getPropertyValue("--lr-graph-focus-halo-color").trim()||cs.getPropertyValue("--lr-color-brand").trim()),selectedColor:resolveColor(cs.getPropertyValue("--lr-graph-selected-color").trim()||cs.getPropertyValue("--lr-color-success").trim()),dimmedOpacity:(()=>{const value=Number(cs.getPropertyValue("--lr-graph-dimmed-opacity").trim());return Number.isFinite(value)?Math.min(1,Math.max(0,value)):.35})(),hullOpacity:(()=>{const value=Number(cs.getPropertyValue("--lr-graph-hull-opacity").trim());return Number.isFinite(value)?Math.min(1,Math.max(0,value)):.12})(),labelColor:resolveColor(cs.getPropertyValue("--lr-color-text").trim()),labelHaloColor:resolveColor(cs.getPropertyValue("--lr-graph-edge-label-halo").trim()||cs.getPropertyValue("--lr-color-surface").trim()),expandBadgeFill:resolveColor(cs.getPropertyValue("--lr-color-surface").trim()),expandBadgeStroke:resolveColor(cs.getPropertyValue("--lr-color-border-strong").trim()),font:`${this.edgeLabelFontPx()}px ${cs.getPropertyValue("--lr-font").trim()||"sans-serif"}`,borderWidths:["thin","medium","thick"].map((size,index)=>resolveCssTokenLength(cs.getPropertyValue(`--lr-border-width-${size}`).trim(),{host:this})??index+1)};return this.updateCanvasFocus(scene),scene})}updateCanvasFocus(scene){const index=shadowFocusTarget(this)?.getAttribute("part")==="cursor-item"?this.normalizedGraphItem():-1,node=index>=0&&index<this.linkIndexBase()?this.simNodes[index]:void 0,link=index>=this.linkIndexBase()&&index<this.communityIndexBase()?this.navigableLinks()[index-this.linkIndexBase()]:void 0,community=index>=this.communityIndexBase()?this.visibleCommunities()[index-this.communityIndexBase()]:void 0;scene.keyboardFocusRing=node?{x:node.x??0,y:node.y??0,r:this.nodeRadius(node)+4}:void 0,scene.keyboardFocusLink=link?{...this.linkCoordinates(link),width:this.safeLinkWidth(link)}:void 0,scene.keyboardFocusHull=community?{d:hullPathD(this.communityHull(community.members))}:void 0}drawCanvas(){if(!this.canvasEl||!this.canvasCtx)return;const dpr=this.ownerWindow?.devicePixelRatio||1,w=this.canvasEl.clientWidth||this.safeWidth,h=this.canvasEl.clientHeight||this.safeHeight,backingW=Math.round(w*dpr),backingH=Math.round(h*dpr);(this.canvasEl.width!==backingW||this.canvasEl.height!==backingH)&&(this.canvasEl.width=backingW,this.canvasEl.height=backingH);const ctx=this.canvasCtx;ctx.setTransform(dpr,0,0,dpr,0,0),ctx.clearRect(0,0,w,h);const edgeLabelsVisible=this.withEdgeLabels&&this.canvasCamera.k>=this.safeEdgeLabelMinZoom,nodeLabelsVisible=this.canvasNodeLabelsVisible();(!this.canvasScene||this.canvasScene.showNodeLabels!==nodeLabelsVisible||this.canvasSceneHasEdgeLabels!==edgeLabelsVisible)&&(this.canvasScene=this.buildCanvasScene(this.computedStyle()),this.canvasSceneHasEdgeLabels=edgeLabelsVisible),this.updateCanvasFocus(this.canvasScene),drawGraphScene(ctx,this.canvasCamera,this.canvasScene)}rebuildPickItems(){this.pickItems=[...this.visibleCommunities().map(entry=>({kind:"hull",entry})),...this.navigableLinks().map(link=>({kind:"link",link})),...this.simNodes.map(node=>({kind:"node",node}))]}redrawPickCanvas(){if(!this.pickCtx||!this.canvasEl||!this.pickCanvas)return;(this.pickCanvas.width!==this.canvasEl.width||this.pickCanvas.height!==this.canvasEl.height)&&(this.pickCanvas.width=this.canvasEl.width,this.pickCanvas.height=this.canvasEl.height),this.rebuildPickItems();const dpr=this.ownerWindow?.devicePixelRatio||1;this.pickCtx.setTransform(dpr,0,0,dpr,0,0),drawPickingScene(this.pickCtx,this.canvasCamera,{hulls:this.pickItems.filter(i=>i.kind==="hull").map(i=>({d:hullPathD(this.communityHull(i.entry.members))})),links:this.pickItems.filter(i=>i.kind==="link").map(i=>{const c=this.linkCoordinates(i.link);return{x1:c.x1,y1:c.y1,x2:c.x2,y2:c.y2,width:this.safeLinkWidth(i.link)}}),nodes:this.pickItems.filter(i=>i.kind==="node").map(i=>({x:i.node.x??0,y:i.node.y??0,r:this.nodeRadius(i.node)+2,shape:this.nodeShape(i.node)}))}),this.pickDirty=!1}hitTest(clientX,clientY){if(!this.canvasEl||!this.pickCtx)return;this.pickDirty&&this.redrawPickCanvas();const rect=this.canvasEl.getBoundingClientRect(),dpr=this.ownerWindow?.devicePixelRatio||1,px=Math.round((clientX-rect.left)*dpr),py=Math.round((clientY-rect.top)*dpr);if(px<0||py<0||px>=this.pickCtx.canvas.width||py>=this.pickCtx.canvas.height)return;const data=this.pickCtx.getImageData(px,py,1,1).data,index=pickColorToIndex(data[0],data[1],data[2]);return index>=0?this.pickItems[index]:void 0}bindCanvasZoom(){if(!this.d3||!this.canvasEl)return;const bounds=this.effectiveZoomBounds,zoomBehavior=this.d3.zoom().scaleExtent([bounds.min,bounds.max]).on("start",()=>{this.isApplyingZoomTransform||(this.isPanning=!0,this.cancelCameraTween())}).on("zoom",event=>{this.canvasCamera={k:event.transform.k,x:event.transform.x,y:event.transform.y},this.markCanvasCameraDirty(),this.scheduleViewportChange()}).on("end",()=>{this.isPanning=!1});this.zoomBehavior=zoomBehavior,this.d3.select(this.canvasEl).call(zoomBehavior)}bindCanvasPointer(){const canvas=this.canvasEl;canvas.addEventListener("pointerdown",this.onCanvasPointerDown),canvas.addEventListener("pointermove",this.onCanvasPointerMove),canvas.addEventListener("pointerup",this.onCanvasPointerUp),canvas.addEventListener("pointercancel",this.onCanvasPointerCancel),canvas.addEventListener("lostpointercapture",this.onCanvasLostPointerCapture),canvas.addEventListener("pointerleave",this.onCanvasPointerLeave),canvas.addEventListener("dblclick",this.onCanvasDblClick)}simulationIsTicking(){return this.simulation!=null&&this.simulation.alpha()>this.simulation.alphaMin()}finishCanvasNodeDrag(pointerId,releaseCapture=!0,redraw=!0){const activePointerId=this.canvasPointerId;if(activePointerId==null||pointerId!=null&&pointerId!==activePointerId)return;const node=this.canvasDragNode&&this.simNodeById.get(this.canvasDragNode.id);if(this.canvasDragNode=void 0,this.canvasPointerId=void 0,this.simulation?.alphaTarget(0),node&&(node.fx=null,node.fy=null),releaseCapture&&this.canvasEl)try{this.canvasEl.releasePointerCapture(activePointerId)}catch{}redraw?this.markCanvasDirty():(this.canvasScene=void 0,this.pickDirty=!0)}takeCanvasPointerDown(pointerId){if(pointerId!=null&&this.canvasPointerDownId!==pointerId)return;const down=this.canvasPointerDownAt;return this.canvasPointerDownAt=void 0,this.canvasPointerDownId=void 0,down}canvasHoverSuppressed(){return!!this.canvasDragNode||this.isDragging||this.isPanning||this.isCameraTweening}updateCanvasHover(hit){const next=hit?.kind==="node"?{kind:"node",id:hit.node.id}:hit?.kind==="link"?{kind:"link",id:this.linkKey(hit.link),detail:this.linkHoverDetail(hit.link)}:void 0,previous=this.canvasHover;previous?.kind===next?.kind&&previous?.id===next?.id||(this.canvasHover=next,previous?.kind==="node"?this.emit("lr-node-leave",{nodeId:previous.id}):previous?.kind==="link"&&this.emitEdgeHover("leave",previous.detail),!(!this.isConnected||this.renderer!=="canvas"||this.canvasHover!==next)&&(next?.kind==="node"?this.emit("lr-node-enter",{nodeId:next.id}):next?.kind==="link"&&this.emitEdgeHover("enter",next.detail)))}nodeAtCanvasPoint(clientX,clientY){if(!this.canvasEl)return;const rect=this.canvasEl.getBoundingClientRect(),worldX=(clientX-rect.left-this.canvasCamera.x)/this.canvasCamera.k,worldY=(clientY-rect.top-this.canvasCamera.y)/this.canvasCamera.k;let closest,closestDistance=1/0;for(const node of this.simNodes){const distance=Math.hypot((node.x??0)-worldX,(node.y??0)-worldY);distance<=this.nodeRadius(node)+2/this.canvasCamera.k&&distance<closestDistance&&(closest=node,closestDistance=distance)}return closest}updateCanvasTooltip(hit,clientX,clientY){if(!this.canvasTooltipEl)return;if(!hit||hit.kind==="hull"){this.canvasTooltipEl.setAttribute("hidden","");return}const rect=this.canvasEl.getBoundingClientRect();this.canvasTooltipEl.textContent=hit.kind==="node"?this.nodeTooltipText(hit.node):this.linkTooltipText(hit.link);let left=clientX-rect.left,top=clientY-rect.top;this.canvasTooltipEl.style.left=`${left}px`,this.canvasTooltipEl.style.top=`${top}px`,this.canvasTooltipEl.removeAttribute("hidden");const tooltipRect=this.canvasTooltipEl.getBoundingClientRect(),view=this.ownerWindow;if(!view)return;const minLeft=Math.max(0,rect.left),maxRight=Math.min(view.innerWidth,rect.right),minTop=Math.max(0,rect.top),maxBottom=Math.min(view.innerHeight,rect.bottom);tooltipRect.right>maxRight&&(left-=tooltipRect.right-maxRight),tooltipRect.left<minLeft&&(left+=minLeft-tooltipRect.left),tooltipRect.bottom>maxBottom&&(top-=tooltipRect.bottom-maxBottom),tooltipRect.top<minTop&&(top+=minTop-tooltipRect.top),this.canvasTooltipEl.style.left=`${left}px`,this.canvasTooltipEl.style.top=`${top}px`}isSelected(kind,id){return identitySet(kind==="node"?this.selectedNodeIds:this.selectedEdgeIds).has(id)}paintedCurrent(kind,id){return this.selectionMode==="none"&&this.isSelected(kind,id)?"true":nothing}isDimmed(kind,id){return identitySet(kind==="node"?this.dimmedNodeIds:this.dimmedEdgeIds).has(id)}linkKey(link){return graphLinkIdentity(link)}emitSelectionIntent(kind,id,toggle){if(this.selectionMode==="none")return;const selected=this.isSelected(kind,id),time=this.ownerWindow?.performance.now()??0,repeat=this.lastActivation?.id===id&&time-this.lastActivation.time<=EXPAND_KEY_INTERVAL_MS;if(this.lastActivation={id,time},this.selectionMode==="single"||!toggle){if(this.selectionMode==="single"&&selected){repeat||this.emit("lr-selection-change",{selectedNodeIds:[],selectedEdgeIds:[]});return}this.emit("lr-selection-change",kind==="node"?{selectedNodeIds:[id],selectedEdgeIds:[]}:{selectedNodeIds:[],selectedEdgeIds:[id]});return}const selectedNodeIds=canonicalIdentityList(this.selectedNodeIds),selectedLinkIds=canonicalIdentityList(this.selectedEdgeIds),nodeIds=kind==="node"?selected?selectedNodeIds.filter(x=>x!==id):[...selectedNodeIds,id]:selectedNodeIds,linkIds=kind==="link"?selected?selectedLinkIds.filter(x=>x!==id):[...selectedLinkIds,id]:selectedLinkIds;this.emit("lr-selection-change",{selectedNodeIds:nodeIds,selectedEdgeIds:linkIds})}clearSelection(){this.selectionMode!=="none"&&(!canonicalIdentityList(this.selectedNodeIds).length&&!canonicalIdentityList(this.selectedEdgeIds).length||this.emit("lr-selection-change",{selectedNodeIds:[],selectedEdgeIds:[]}))}willUpdate(changed){super.willUpdate(changed),changed.has("view")&&this.isConnected&&(this.view!=="2d"?(this.loadGeneration+=1,this.simulation?.stop(),this.cancelCameraTween(),this.finishCanvasNodeDrag(void 0,!0,!1),this.takeCanvasPointerDown(),this.canvasDrawRafId!=null&&this.canvasDrawRafOwner?.cancelAnimationFrame(this.canvasDrawRafId),this.canvasDrawRafId=void 0,this.canvasDrawRafOwner=void 0,this.hoverRafId!=null&&this.hoverRafOwner?.cancelAnimationFrame(this.hoverRafId),this.hoverRafId=void 0,this.hoverRafOwner=void 0,this.pendingHover=void 0,this.viewportChangeRafId!=null&&this.viewportChangeRafOwner?.cancelAnimationFrame(this.viewportChangeRafId),this.viewportChangeRafId=void 0,this.viewportChangeRafOwner=void 0,this.canvasDprQuery?.removeEventListener("change",this.onCanvasDprChange),this.canvasDprQuery=void 0,this.intersectionObserver?.disconnect(),this.intersectionObserver=void 0,this.loading=!1,this.loadFailed=!1,this.zoomedEl=void 0,this.gEl=void 0,this.boundNodeEls=new WeakSet,this.syncHostResizeObserver()):changed.get("view")!==void 0&&(this.spatial.disconnect(),this.loading=!this.d3,this.connect2d(),this.d3&&this.rebuildSimulation())),changed.has("height")&&this.syncRequestedHeightVar(),changed.has("fitTo")&&this.fitTo!=="container"&&(this.containerSize=null),this.fitTo==="container"&&!this.containerSize&&this.measureHostBox();const cursorOnly=changed.size>0&&[...changed.keys()].every(key=>key==="activeGraphItem"||key==="graphLiveText");if(cursorOnly||this.resolvedCssColorCache.clear(),cursorOnly||(this.navigableLinksCache=void 0),this.syncGraphHostRole(),this.view!=="2d"){this.spatial.prepare(),this.focusNodeId==null?this.lastAppliedFocusNodeId=null:this.focusNodeId!==this.lastAppliedFocusNodeId&&this.spatial.focusNode(this.focusNodeId)&&(this.lastAppliedFocusNodeId=this.focusNodeId),this.isMounting=!1;return}const wasMounting=this.isMounting;this.isMounting=!1;const hiddenTypesChanged=changed.has("hiddenTypes")&&!sameIds(canonicalIdentityList(changed.get("hiddenTypes")??[]),canonicalIdentityList(this.hiddenTypes)),structureChanged=this.d3&&(changed.has("nodes")||changed.has("edges")||hiddenTypesChanged||changed.has("layout")||this.layout==="layered"&&changed.has("edgeDistance")),graphItemsChanged=!!(structureChanged||changed.has("simNodes")||changed.has("communities")),activePart=shadowFocusTarget(this)?.getAttribute("part")??"",hadGraphItemFocus=graphItemsChanged&&["node","link","hull","cursor-item"].includes(activePart),previousIndex=this.normalizedGraphItem(),previousIdentity=graphItemsChanged?this.graphItemIdentity(previousIndex):void 0;if(structureChanged&&this.isConnected){this.rebuildSimulation(),this.renderer==="svg"&&this.simNodes.length+this.simLinks.length>1e3&&devWarnOnce("lr-graph-svg-scale",'<lr-graph>: renderer="svg" draws every node and link as DOM; use renderer="canvas" above about 1,000 of them.');const hovered=this.svgHoverNodeId;hovered!=null&&!this.simNodeById.has(hovered)&&(this.svgHoverNodeId=void 0,this.emit("lr-node-leave",{nodeId:hovered})),this.canvasHover?.kind==="node"&&!this.simNodeById.has(this.canvasHover.id)&&this.updateCanvasHover(void 0),this.navigableLinksCache=void 0}if(graphItemsChanged){this.visibleCommunitiesCache=void 0;const retainedIndex=previousIdentity?this.graphItemIndex(previousIdentity):-1,nextIndex=retainedIndex>=0?retainedIndex:this.normalizedGraphItem(previousIndex);this.activeGraphItem=nextIndex>=0?nextIndex:0,hadGraphItemFocus&&(this.pendingGraphItemFocus=nextIndex>=0?nextIndex:"base",nextIndex>=0&&(this.graphLiveText=this.graphItemAnnouncement(nextIndex)))}const selectedNodeIdsChanged=changed.has("selectedNodeIds")&&!sameIds(changed.get("selectedNodeIds"),this.selectedNodeIds),selectedLinkIdsChanged=changed.has("selectedEdgeIds")&&!sameIds(changed.get("selectedEdgeIds"),this.selectedEdgeIds);(selectedNodeIdsChanged||selectedLinkIdsChanged)&&!wasMounting&&(this.graphLiveText=this.localize("graphSelectionCount",void 0,{count:getNumberFormat(this.effectiveLocale).format(canonicalIdentityList(this.selectedNodeIds).length+canonicalIdentityList(this.selectedEdgeIds).length)}))}updated(changed){if(super.updated(changed),!this.isConnected){for(const[key,previous]of changed)this.detachedGraphChanges.has(key)||this.detachedGraphChanges.set(key,previous);return}if(this.view!=="2d"){this.setAttribute("aria-busy","false"),this.spatial.update();return}this.setAttribute("aria-busy",String(this.loading));const announceGraphText=this.graphAnnouncementsReady&&changed.has("graphLiveText")&&this.graphLiveText!=="";if(!this.loading&&!this.loadFailed&&(this.graphAnnouncementsReady=!0),announceGraphText&&this.announcements.announcePolite(this.graphLiveText),changed.has("loadFailed")&&changed.get("loadFailed")!==void 0&&this.loadFailed&&this.announcements.announceAssertive(this.localize("graphMissingLibrary")),(changed.has("fitTo")||changed.has("renderer"))&&this.syncHostResizeObserver(),!this.d3)return;!changed.has("nodes")&&!changed.has("edges")&&!changed.has("hiddenTypes")&&((changed.has("width")||changed.has("height")||changed.has("containerSize")||changed.has("fitTo"))&&(this.simulation?.force("center",this.d3.forceCenter(this.safeWidth/2,this.safeHeight/2)),this.simulation?.alpha(.1).restart()),(changed.has("chargeStrength")||changed.has("edgeDistance"))&&(changed.has("chargeStrength")&&this.chargeForce?.strength(this.safeChargeStrength),changed.has("edgeDistance")&&this.linkForce?.distance(this.safeLinkDistance),this.simulation?.alpha(.3).restart())),this.applyInteractions(changed);const cursorOnly=changed.size>0&&[...changed.keys()].every(key=>key==="activeGraphItem"||key==="graphLiveText");this.renderer==="canvas"&&cursorOnly?this.scheduleCanvasDraw():this.applyCanvasInteractions(),this.focusNodeId==null?this.lastAppliedFocusNodeId=null:this.focusNodeId!==this.lastAppliedFocusNodeId&&this.simNodes.some(n=>n.id===this.focusNodeId)&&(this.lastAppliedFocusNodeId=this.focusNodeId,this.focusNode(this.focusNodeId)),this.updateFocusHalo();const pendingFocus=this.pendingGraphItemFocus;pendingFocus!==void 0&&(this.pendingGraphItemFocus=void 0,pendingFocus==="base"?this.renderRoot.querySelector('[part="canvas"], [part="svg"]')?.focus():this.focusGraphItemElement(pendingFocus))}applyInteractions(changed){if(!this.d3||this.renderer!=="svg")return;const svgEl=this.renderRoot.querySelector("svg"),reboundSurface=svgEl&&svgEl!==this.zoomedEl;if(svgEl&&reboundSurface){this.syncHostResizeObserver(),this.canvasHover=void 0,this.zoomedEl=svgEl,this.gEl=this.renderRoot.querySelector("g"),this.focusHaloEl=this.renderRoot.querySelector('[part="focus-halo"]');const bounds=this.effectiveZoomBounds,zoomBehavior=this.d3.zoom().scaleExtent([bounds.min,bounds.max]).on("start",()=>{this.isApplyingZoomTransform||(this.isPanning=!0,this.cancelCameraTween())}).on("zoom",event=>{this.gEl?.setAttribute("transform",event.transform.toString()),this.updateHitAreaZoomScale(event.transform.k),this.updateEdgeLabelZoomGate(event.transform.k),this.updateNodeLabelZoomGate(event.transform.k),this.scheduleViewportChange()}).on("end",()=>{this.isPanning=!1});this.zoomBehavior=zoomBehavior,this.d3.select(svgEl).call(zoomBehavior),this.updateHitAreaZoomScale(1),this.updateEdgeLabelZoomGate(1),this.updateNodeLabelZoomGate(1)}else if(this.zoomBehavior&&(changed.has("minZoom")||changed.has("maxZoom"))){const bounds=this.effectiveZoomBounds;this.zoomBehavior.scaleExtent([bounds.min,bounds.max])}if(changed.has("nodeLabels")&&this.zoomedEl&&this.updateNodeLabelZoomGate(this.d3.zoomTransform(this.zoomedEl).k),!(reboundSurface||changed.has("simNodes")||changed.has("simLinks")||changed.has("nodeTypes")||changed.has("withEdgeLabels")||changed.has("nodeLabels")||changed.has("communities")))return;const nodeEls=Array.from(this.renderRoot.querySelectorAll('[part="node"]'));this.nodeEls=nodeEls,this.nodeHitEls=Array.from(this.renderRoot.querySelectorAll('[data-hit-area="node"]')),this.nodeLabelEls=nodeEls.map(el=>el.parentElement?.querySelector('[part="label"]')??null),this.expandIndicatorEls=nodeEls.map(el=>el.parentElement?.querySelector('[part="expand-indicator"]')??null),this.linkEls=Array.from(this.renderRoot.querySelectorAll('[part="link"]:not([data-dangling])')),this.linkHitEls=Array.from(this.renderRoot.querySelectorAll('[data-hit-area="link"]')),this.linkLabelEls=this.linkEls.map(el=>el.parentElement?.querySelector('[part="link-label"]')??null),this.linkLabelHiddenByLength=[],this.danglingLinkEls=Array.from(this.renderRoot.querySelectorAll('[part="link"][data-dangling]')),this.communityHullEls=Array.from(this.renderRoot.querySelectorAll('[part="hull"]')),this.communityHullHitEls=Array.from(this.renderRoot.querySelectorAll('[data-hit-area="hull"]')),this.communityLabelEls=Array.from(this.renderRoot.querySelectorAll('[part="community-label"]')),this.layout!=="layered"&&nodeEls.forEach((el,i)=>{const id=this.simNodes[i]?.id;if(id!=null)for(const dragTarget of[el,this.nodeHitEls[i]])!dragTarget||this.boundNodeEls.has(dragTarget)||(this.boundNodeEls.add(dragTarget),this.d3.select(dragTarget).call(this.d3.drag().on("start",event=>{this.isDragging=!0,event.sourceEvent?.stopPropagation(),event.active||this.simulation?.alphaTarget(.3).restart();const n=this.simNodeById.get(id);n&&(n.fx=n.x,n.fy=n.y)}).on("drag",event=>{const n=this.simNodeById.get(id);n&&(n.fx=event.x,n.fy=event.y)}).on("end",event=>{this.isDragging=!1,event.active||this.simulation?.alphaTarget(0);const n=this.simNodeById.get(id);n&&(n.fx=null,n.fy=null)})))})}updateHitAreaZoomScale(zoom){const safeZoom=finiteRange(zoom,1,Number.EPSILON);this.gEl?.style.setProperty("--_lr-graph-hit-area-scale",String(1/safeZoom))}applyCanvasInteractions(){if(this.renderer!=="canvas"||!this.canvasEl)return;this.canvasEl!==this.zoomedEl&&(this.zoomedEl=this.canvasEl,this.setUpCanvasSurface());const bounds=this.effectiveZoomBounds;this.zoomBehavior?.scaleExtent([bounds.min,bounds.max]),this.markCanvasDirty()}onTick(){for(const l of this.danglingLinks){const source=l.source,target=l.target;target.x=(source.x??0)+STUB_OFFSET_PX,target.y=(source.y??0)+STUB_OFFSET_PX}for(const n of this.simNodes)n.x!=null&&n.y!=null&&this.lastPositionById.set(n.id,{x:n.x,y:n.y});this.simNodes.forEach((n,i)=>{const el=this.nodeEls[i];el&&(el.tagName==="circle"?(el.setAttribute("cx",String(n.x??0)),el.setAttribute("cy",String(n.y??0))):el.setAttribute("transform",`translate(${n.x??0},${n.y??0})`));const hit=this.nodeHitEls[i];hit&&(hit.setAttribute("x1",String((n.x??0)-NODE_HIT_SEGMENT_HALF)),hit.setAttribute("y1",String(n.y??0)),hit.setAttribute("x2",String((n.x??0)+NODE_HIT_SEGMENT_HALF)),hit.setAttribute("y2",String(n.y??0)));const label=this.nodeLabelEls[i];label&&(label.setAttribute("x",String((n.x??0)+this.nodeRadius(n)+2)),label.setAttribute("y",String(n.y??0)))}),this.simLinks.forEach((l,i)=>{const line=this.linkEls[i],coordinates=this.linkCoordinates(l);for(const target of[line,this.linkHitEls[i]])target&&(target.setAttribute("x1",String(coordinates.x1)),target.setAttribute("y1",String(coordinates.y1)),target.setAttribute("x2",String(coordinates.x2)),target.setAttribute("y2",String(coordinates.y2)))}),this.withEdgeLabels&&this.simLinks.forEach((l,i)=>{const labelEl=this.linkLabelEls[i];if(!labelEl)return;const label=ownGraphText(l,"label"),pos=this.edgeLabelPosition(l);labelEl.setAttribute("x",String(pos.x)),labelEl.setAttribute("y",String(pos.y));const{x1,y1,x2,y2}=this.linkCoordinates(l),edgeLength=Math.hypot(x2-x1,y2-y1),tooLong=this.edgeLabelWidth(label??"")>edgeLength*EDGE_LABEL_LENGTH_GATE_RATIO;this.linkLabelHiddenByLength[i]!==tooLong&&(this.linkLabelHiddenByLength[i]=tooLong,labelEl.setAttribute("visibility",tooLong?"hidden":"visible"))}),this.simNodes.forEach((n,i)=>{const indicator=this.expandIndicatorEls[i];indicator&&indicator.setAttribute("transform",`translate(${n.x??0},${n.y??0})`)}),this.danglingLinks.forEach((l,i)=>{const line=this.danglingLinkEls[i];if(!line)return;const coordinates=this.linkCoordinates(l);line.setAttribute("x1",String(coordinates.x1)),line.setAttribute("y1",String(coordinates.y1)),line.setAttribute("x2",String(coordinates.x2)),line.setAttribute("y2",String(coordinates.y2))}),this.updateFocusHalo(),this.visibleCommunities().forEach((entry,i)=>{const hullEl=this.communityHullEls[i],hullHitEl=this.communityHullHitEls[i],labelEl=this.communityLabelEls[i];if(!hullEl&&!hullHitEl&&!labelEl)return;const hull=this.communityHull(entry.members);hullEl&&hullEl.setAttribute("d",hullPathD(hull)),hullHitEl&&hullHitEl.setAttribute("d",hullPathD(hull)),labelEl&&(labelEl.setAttribute("x",String(hullCentroidX(hull))),labelEl.setAttribute("y",String(hullTopY(hull)-HULL_PADDING)))}),this.renderer==="canvas"&&this.markCanvasDirty(),this.scheduleViewportChange()}rebuildSimulation(){if(this.view!=="2d"||!this.d3)return;this.simulation?.stop(),this.boundNodeEls=new WeakSet;const liveIds=new Set(this.graphModel.nodes.map(n=>n.id));for(const id of this.lastPositionById.keys())liveIds.has(id)||this.lastPositionById.delete(id);const visible=this.visibleNodes();if(this.layout==="layered"){this.rebuildLayeredLayout(visible);return}const prevById=new Map(this.simNodes.map(n=>[n.id,n])),nodes=visible.map(n=>{const prev=prevById.get(n.id);if(prev)return{...prev,...n};const remembered=this.lastPositionById.get(n.id);return remembered?{...n,x:remembered.x,y:remembered.y}:{...n}}),byId=new Map(nodes.map(n=>[n.id,n])),{resolved:resolvedLinks,dangling:danglingLinks}=this.resolveLinksAgainst(byId),links=resolvedLinks;this.danglingLinks=danglingLinks;const seedForSpawn=this.safeSeed,incidentLinks=new Map;if(nodes.some(n=>n.x!=null))for(const l of resolvedLinks)for(const id of new Set([l.source.id,l.target.id])){const incident=incidentLinks.get(id);incident?incident.push(l):incidentLinks.set(id,[l])}for(const n of nodes){if(n.x!=null&&n.y!=null)continue;const neighborLink=incidentLinks.get(n.id)?.find(l=>{const source2=l.source,target2=l.target;return source2.id===n.id&&target2.x!=null||target2.id===n.id&&source2.x!=null});if(!neighborLink)continue;const source=neighborLink.source,target=neighborLink.target,neighbor=source.id===n.id?target:source,jitterRadius=this.safeLinkDistance/2,angle=seedForSpawn!=null?hashNodeSeed(seedForSpawn,n.id)/4294967296*Math.PI*2:Math.random()*Math.PI*2;n.x=(neighbor.x??0)+Math.cos(angle)*jitterRadius,n.y=(neighbor.y??0)+Math.sin(angle)*jitterRadius}if(seedForSpawn!=null)for(const n of nodes){if(n.x!=null&&n.y!=null)continue;const rng=mulberry32(hashNodeSeed(seedForSpawn,n.id));n.x=rng()*this.safeWidth,n.y=rng()*this.safeHeight}this.linkForce=this.d3.forceLink(links).distance(this.safeLinkDistance),this.chargeForce=this.d3.forceManyBody().strength(this.safeChargeStrength);const simulation=this.d3.forceSimulation(nodes).force("link",this.linkForce).force("charge",this.chargeForce).force("center",this.d3.forceCenter(this.safeWidth/2,this.safeHeight/2)).force("collide",this.d3.forceCollide().radius(n=>this.nodeRadius(n)+10)).on("tick",()=>this.onTick());if(this.simulation=simulation,prefersReducedMotion(this)||this.safeSeed!=null){const pinnedForSettle=new Set;for(const n of nodes)(prevById.has(n.id)||this.lastPositionById.has(n.id))&&n.x!=null&&n.y!=null&&n.fx==null&&n.fy==null&&(n.fx=n.x,n.fy=n.y,pinnedForSettle.add(n.id));for(simulation.stop();simulation.alpha()>simulation.alphaMin();)simulation.tick();for(const n of nodes)pinnedForSettle.has(n.id)&&(n.fx=null,n.fy=null)}this.simNodes=nodes,this.simNodeById=byId,this.simLinks=links;for(const n of nodes)n.x!=null&&n.y!=null&&this.lastPositionById.set(n.id,{x:n.x,y:n.y});this.announceHiddenNodeCount(nodes.length)}announceHiddenNodeCount(visibleNodeCount){const totalNodeCount=this.graphModel.nodes.length,hiddenNodeCount=totalNodeCount-visibleNodeCount;totalNodeCount>0&&(hiddenNodeCount>0||this.lastHiddenNodeCount>0)&&(this.graphLiveText=this.localize("graphNodesHidden",void 0,{hidden:getNumberFormat(this.effectiveLocale).format(hiddenNodeCount),total:getNumberFormat(this.effectiveLocale).format(totalNodeCount)})),this.lastHiddenNodeCount=hiddenNodeCount}rebuildLayeredLayout(visible){const boxes=visible.map(n=>{const r=this.nodeRadius(n);return{id:n.id,width:r*2,height:r*2}}),visibleIds=new Set(visible.map(n=>n.id)),edges=this.graphModel.links.filter(l=>visibleIds.has(l.source)&&visibleIds.has(l.target)).map(l=>({source:l.source,target:l.target})),{positions:raw}=layeredLayout({nodes:boxes,edges,options:{gapX:12,gapY:this.safeLinkDistance}}),bounds=extent(raw.values(),point=>point.x,point=>point.y),offsetX=raw.size?this.safeWidth/2-(bounds.minX+(bounds.maxX-bounds.minX)/2):this.safeWidth/2,offsetY=raw.size?this.safeHeight/2-(bounds.minY+(bounds.maxY-bounds.minY)/2):this.safeHeight/2,nodes=visible.map(n=>{const p=raw.get(n.id);return{...n,x:p.x+offsetX,y:p.y+offsetY}}),byId=new Map(nodes.map(n=>[n.id,n])),{resolved,dangling}=this.resolveLinksAgainst(byId);this.danglingLinks=dangling,this.simulation=void 0,this.simNodes=nodes,this.simNodeById=byId,this.simLinks=resolved;for(const n of nodes)n.x!=null&&n.y!=null&&this.lastPositionById.set(n.id,{x:n.x,y:n.y});this.announceHiddenNodeCount(nodes.length)}onNodeClick(node,e){const detail={nodeId:node.id,x:node.x??0,y:node.y??0};this.emit("lr-node-activate",{...detail}),this.emitSelectionIntent("node",node.id,!!(e?.ctrlKey||e?.metaKey))}getNodePosition(id){if(this.view!=="2d"){const position=this.spatial.position(id);return position?{x:position.x,y:position.y}:void 0}const node=this.simNodes.find(candidate=>candidate.id===id);if(!(!node||!Number.isFinite(node.x)||!Number.isFinite(node.y)))return{x:node.x,y:node.y}}getNodePosition3d(id){return this.view==="2d"?void 0:this.spatial.position(id)}getNodeScreenPosition(id){if(this.view!=="2d")return this.spatial.screenPosition(id);const position=this.getNodePosition(id);if(!position||!this.zoomedEl||!this.d3)return;const hostRect=this.getBoundingClientRect(),rect=this.zoomedEl.getBoundingClientRect(),camera=this.d3.zoomTransform(this.zoomedEl),x=position.x*camera.k+camera.x,y=position.y*camera.k+camera.y;if("getScreenCTM"in this.zoomedEl){const matrix=this.zoomedEl.getScreenCTM();return matrix?{x:matrix.a*x+matrix.c*y+matrix.e-hostRect.left,y:matrix.b*x+matrix.d*y+matrix.f-hostRect.top}:void 0}return{x:rect.left-hostRect.left+x,y:rect.top-hostRect.top+y}}onLinkClick(link,e){const source=typeof link.source=="object"?link.source.id:String(link.source),target=typeof link.target=="object"?link.target.id:String(link.target);this.emit("lr-edge-activate",{sourceNodeId:source,targetNodeId:target,...link.id?{edgeId:link.id}:{}}),this.emitSelectionIntent("link",this.linkKey(link),!!(e?.ctrlKey||e?.metaKey))}onNodeEnter(node,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.setAttribute("data-hovered",""),this.svgHoverNodeId=node.id,this.emit("lr-node-enter",{nodeId:node.id}))}onNodeLeave(node,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.removeAttribute("data-hovered"),this.svgHoverNodeId=void 0,this.emit("lr-node-leave",{nodeId:node.id}))}onNodeDblClick(node,e){e.stopPropagation(),this.emit("lr-node-expand",{nodeId:node.id})}onLinkEnter(link,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.setAttribute("data-hovered",""),this.emitEdgeHover("enter",this.linkHoverDetail(link)))}linkHoverDetail(link){const source=typeof link.source=="object"?link.source.id:String(link.source),target=typeof link.target=="object"?link.target.id:String(link.target);return{sourceNodeId:source,targetNodeId:target,...link.id?{edgeId:link.id}:{}}}onLinkLeave(link,e){this.isDragging||this.isPanning||this.isCameraTweening||(e.currentTarget.removeAttribute("data-hovered"),this.emitEdgeHover("leave",this.linkHoverDetail(link)))}emitEdgeHover(phase,detail){this.emit(phase==="enter"?"lr-edge-enter":"lr-edge-leave",{...detail})}nodeAccessibleText(node){let text=ownGraphText(node,"accessibleLabel")||ownGraphText(node,"label")||node.id;const type=this.resolveNodeType(node),typeLabel=type?ownGraphText(type,"label"):void 0;return typeLabel!==void 0&&(text=this.localize("graphTypedNode",void 0,{label:text,type:typeLabel})),node.expandable&&(text=this.localize("graphExpandableItem",void 0,{item:text})),text}boundedGraphText(value){if(typeof value!="string")return"";const normalized=value.replace(/\s+/g," ").trim();return normalized.length>512?`${normalized.slice(0,512)}…`:normalized}nodeTooltipText(node){return this.boundedGraphText(ownGraphText(node,"description")||ownGraphText(node,"label")||ownGraphText(node,"accessibleLabel")||node.id)}linkAccessibleText(link){const accessibleLabel=ownGraphText(link,"accessibleLabel");if(accessibleLabel)return accessibleLabel;const sourceValue=ownGraphValue(link,"source"),targetValue=ownGraphValue(link,"target"),source=sourceValue!==null&&typeof sourceValue=="object"?this.nodeAccessibleText(sourceValue):typeof sourceValue=="string"?sourceValue:"",target=targetValue!==null&&typeof targetValue=="object"?this.nodeAccessibleText(targetValue):typeof targetValue=="string"?targetValue:"";return ownGraphText(link,"label")||this.localize("graphLink",void 0,{source,target})}linkTooltipText(link){return this.boundedGraphText(ownGraphText(link,"description")||ownGraphText(link,"label")||ownGraphText(link,"accessibleLabel")||this.linkAccessibleText(link))}linkCoordinates(link){const source=link.source,target=link.target,x1=source.x??0,y1=source.y??0,targetX=target.x??0,targetY=target.y??0;if(!link.directed||link.dangling)return{x1,y1,x2:targetX,y2:targetY};const dx=targetX-x1,dy=targetY-y1,distance=Math.hypot(dx,dy);if(distance===0)return{x1,y1,x2:targetX,y2:targetY};const inset=Math.min(this.nodeRadius(target),distance);return{x1,y1,x2:targetX-dx/distance*inset,y2:targetY-dy/distance*inset}}edgeLabelPosition(link){const{x1,y1,x2,y2}=this.linkCoordinates(link),dx=x2-x1,dy=y2-y1,len=Math.hypot(dx,dy),mx=(x1+x2)/2,my=(y1+y2)/2;return len===0?{x:mx,y:my}:{x:mx+-dy/len*EDGE_LABEL_OFFSET_PX,y:my+dx/len*EDGE_LABEL_OFFSET_PX}}edgeLabelFontPx(){const raw=this.computedStyle().getPropertyValue("--lr-font-size-2xs").trim();return resolveCssTokenLength(raw,{host:this})??DEFAULT_EDGE_LABEL_FONT_PX}edgeLabelContext(){return this.edgeLabelMeasureCanvas?.ownerDocument!==this.ownerDocument&&(this.edgeLabelMeasureCanvas=this.ownerDocument.createElement("canvas"),this.edgeLabelMeasureCtx=this.edgeLabelMeasureCanvas.getContext("2d")),this.edgeLabelMeasureCtx??null}edgeLabelWidth(text){const cached=this.edgeLabelWidthCache.get(text);if(cached!=null)return cached;const ctx=this.edgeLabelContext();let width;if(ctx){const fontFamily=this.computedStyle().getPropertyValue("--lr-font").trim()||"sans-serif";ctx.font=`${this.edgeLabelFontPx()}px ${fontFamily}`,width=ctx.measureText(text).width}else width=text.length*this.edgeLabelFontPx()*.6;if(this.edgeLabelWidthCache.size>=EDGE_LABEL_WIDTH_CACHE_MAX){const oldest=this.edgeLabelWidthCache.keys().next().value;oldest!==void 0&&this.edgeLabelWidthCache.delete(oldest)}return this.edgeLabelWidthCache.set(text,width),width}updateEdgeLabelZoomGate(k){this.gEl&&(k<this.safeEdgeLabelMinZoom?this.gEl.setAttribute("data-edge-labels-hidden",""):this.gEl.removeAttribute("data-edge-labels-hidden"))}updateNodeLabelZoomGate(k){this.gEl&&(this.resolvedNodeLabelsMode==="zoom"&&k<NODE_LABEL_MIN_ZOOM?this.gEl.setAttribute("data-node-labels-hidden",""):this.gEl.removeAttribute("data-node-labels-hidden"))}linkIndexBase(){return this.simNodes.length}communityIndexBase(){return this.linkIndexBase()+this.navigableLinks().length}graphItemCount(){return this.communityIndexBase()+this.visibleCommunities().length}normalizedGraphItem(index=this.activeGraphItem){const count=this.graphItemCount();return count?Math.min(Math.max(index,0),count-1):-1}graphItemIdentity(index){if(index<0)return;if(index<this.linkIndexBase()){const node=this.simNodes[index];return node?{kind:"node",id:node.id}:void 0}if(index<this.communityIndexBase()){const link=this.navigableLinks()[index-this.linkIndexBase()];return link?{kind:"link",id:this.linkKey(link)}:void 0}const community=this.visibleCommunities()[index-this.communityIndexBase()]?.community;return community?{kind:"community",id:community.id}:void 0}graphItemIndex(identity){if(identity.kind==="node")return this.simNodes.findIndex(node=>node.id===identity.id);if(identity.kind==="link"){const index2=this.navigableLinks().findIndex(link=>this.linkKey(link)===identity.id);return index2<0?-1:this.linkIndexBase()+index2}const index=this.visibleCommunities().findIndex(entry=>entry.community.id===identity.id);return index<0?-1:this.communityIndexBase()+index}communityText(community){return ownGraphText(community,"label")??community.id}graphItemText(index){if(index<this.linkIndexBase()){const node=this.simNodes[index];return node?this.localize("graphNode",void 0,{label:this.nodeTooltipText(node)}):""}if(index<this.communityIndexBase()){const link=this.navigableLinks()[index-this.linkIndexBase()];return link?this.linkTooltipText(link):""}const entry=this.visibleCommunities()[index-this.communityIndexBase()];return entry?this.localize("graphCommunity",void 0,{label:this.communityText(entry.community),count:getNumberFormat(this.effectiveLocale).format(entry.members.length)}):""}graphItemAnnouncement(index){return this.localize("graphItemAnnouncement",void 0,{item:this.graphItemText(index),index:getNumberFormat(this.effectiveLocale).format(index+1),total:getNumberFormat(this.effectiveLocale).format(this.graphItemCount())})}onGraphItemFocus(index){this.normalizedGraphItem(index)<0||(this.activeGraphItem=index,this.graphLiveText=this.graphItemAnnouncement(index))}focusGraphItem(index){const normalized=this.normalizedGraphItem(index);normalized<0||(this.activeGraphItem=normalized,this.graphLiveText=this.graphItemAnnouncement(normalized),this.updateComplete.then(()=>this.focusGraphItemElement(normalized)))}focusGraphItemElement(index){if(this.renderer==="canvas"){this.renderRoot.querySelector('[part="cursor-item"]')?.focus(),this.scheduleCanvasDraw();return}[...this.renderRoot.querySelectorAll('[part="node"]'),...this.renderRoot.querySelectorAll('[part="link"][tabindex]'),...this.renderRoot.querySelectorAll('[part="hull"]')][index]?.focus()}onGraphKeyDown(e,index,activate){if(e.key==="Enter"||e.key===" "){if(e.preventDefault(),e.repeat)return;if(this.onGraphItemFocus(index),activate(e),index<this.simNodes.length){const now=this.ownerWindow?.performance.now()??0;if(this.lastKeyActivateIndex===index&&now-this.lastKeyActivateTime<=EXPAND_KEY_INTERVAL_MS){const node=this.simNodes[index];node&&this.emit("lr-node-expand",{nodeId:node.id}),this.lastKeyActivateIndex=null}else this.lastKeyActivateIndex=index,this.lastKeyActivateTime=now}return}const count=this.graphItemCount();if(!count)return;const rtl=isRtl(this),forwardKey=rtl?"ArrowLeft":"ArrowRight",backwardKey=rtl?"ArrowRight":"ArrowLeft";let next=index;if(e.key===forwardKey||e.key==="ArrowDown")next=Math.min(count-1,index+1);else if(e.key===backwardKey||e.key==="ArrowUp")next=Math.max(0,index-1);else if(e.key==="Home")next=0;else if(e.key==="End")next=count-1;else return;e.preventDefault(),this.focusGraphItem(next)}render(){const nodeLimit=publicCollectionTruncation(this,"nodes"),edgeLimit=publicCollectionTruncation(this,"edges"),limitNotices=html`${nodeLimit?html`<p part="limit" role="note">${this.localize("graphNodeLimit",void 0,{shown:getNumberFormat(this.effectiveLocale).format(nodeLimit.retained),total:getNumberFormat(this.effectiveLocale).format(nodeLimit.source)})}</p>`:nothing}${edgeLimit?html`<p part="limit" role="note">${this.localize("graphEdgeLimit",void 0,{shown:getNumberFormat(this.effectiveLocale).format(edgeLimit.retained),total:getNumberFormat(this.effectiveLocale).format(edgeLimit.source)})}</p>`:nothing}`;if(this.view!=="2d")return this.spatial.render(limitNotices);if(this.loading)return html`
|
|
2
2
|
<div part="base">
|
|
3
3
|
<lr-skeleton
|
|
4
4
|
shape="rect"
|
|
@@ -231,4 +231,4 @@ import{__decorate}from"tslib";import{collectionSupport,publicCollectionTruncatio
|
|
|
231
231
|
</ul>
|
|
232
232
|
${limitNotices}
|
|
233
233
|
</div>
|
|
234
|
-
`}}__decorate([property({attribute:!1})],LyraGraph.prototype,"nodes",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"edges",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"nodeTypes",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"hiddenTypes",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"communities",void 0),__decorate([property({converter:GRAPH_LAYOUT})],LyraGraph.prototype,"layout",null),__decorate([property()],LyraGraph.prototype,"renderer",void 0),__decorate([property({attribute:"fit-to"})],LyraGraph.prototype,"fitTo",void 0),__decorate([property({converter:graphLengthConverter})],LyraGraph.prototype,"width",void 0),__decorate([property({converter:graphLengthConverter})],LyraGraph.prototype,"height",void 0),__decorate([property({type:Number,attribute:"charge-strength"})],LyraGraph.prototype,"chargeStrength",void 0),__decorate([property({type:Number,attribute:"edge-distance"})],LyraGraph.prototype,"edgeDistance",void 0),__decorate([property({type:Number,attribute:"min-zoom"})],LyraGraph.prototype,"minZoom",void 0),__decorate([property({type:Number,attribute:"max-zoom"})],LyraGraph.prototype,"maxZoom",void 0),__decorate([property()],LyraGraph.prototype,"label",void 0),__decorate([property({attribute:"aria-label"})],LyraGraph.prototype,"accessibleLabel",void 0),__decorate([property({type:Number})],LyraGraph.prototype,"seed",void 0),__decorate([property({type:Boolean,attribute:"with-edge-labels"})],LyraGraph.prototype,"withEdgeLabels",void 0),__decorate([property({type:Number,attribute:"edge-label-min-zoom"})],LyraGraph.prototype,"edgeLabelMinZoom",void 0),__decorate([property({attribute:"node-labels"})],LyraGraph.prototype,"nodeLabels",void 0),__decorate([property({attribute:"focus-node-id"})],LyraGraph.prototype,"focusNodeId",void 0),__decorate([property({attribute:"selection-mode"})],LyraGraph.prototype,"selectionMode",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"selectedNodeIds",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"selectedEdgeIds",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"dimmedNodeIds",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"dimmedEdgeIds",void 0),__decorate([state()],LyraGraph.prototype,"loading",void 0),__decorate([state()],LyraGraph.prototype,"loadFailed",void 0),__decorate([state()],LyraGraph.prototype,"containerSize",void 0),__decorate([state()],LyraGraph.prototype,"simNodes",void 0),__decorate([state()],LyraGraph.prototype,"simLinks",void 0),__decorate([state()],LyraGraph.prototype,"activeGraphItem",void 0),__decorate([state()],LyraGraph.prototype,"graphLiveText",void 0),__decorate([query("canvas")],LyraGraph.prototype,"canvasEl",void 0);export{LyraGraph};
|
|
234
|
+
`}}__decorate([property({attribute:!1})],LyraGraph.prototype,"nodes",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"edges",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"nodeTypes",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"hiddenTypes",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"communities",void 0),__decorate([property({converter:GRAPH_VIEW})],LyraGraph.prototype,"view",null),__decorate([property({attribute:!1})],LyraGraph.prototype,"camera",null),__decorate([property({converter:GRAPH_LAYOUT})],LyraGraph.prototype,"layout",null),__decorate([property()],LyraGraph.prototype,"renderer",void 0),__decorate([property({attribute:"fit-to"})],LyraGraph.prototype,"fitTo",void 0),__decorate([property({converter:graphLengthConverter})],LyraGraph.prototype,"width",void 0),__decorate([property({converter:graphLengthConverter})],LyraGraph.prototype,"height",void 0),__decorate([property({type:Number,attribute:"charge-strength"})],LyraGraph.prototype,"chargeStrength",void 0),__decorate([property({type:Number,attribute:"edge-distance"})],LyraGraph.prototype,"edgeDistance",void 0),__decorate([property({type:Number,attribute:"min-zoom"})],LyraGraph.prototype,"minZoom",void 0),__decorate([property({type:Number,attribute:"max-zoom"})],LyraGraph.prototype,"maxZoom",void 0),__decorate([property()],LyraGraph.prototype,"label",void 0),__decorate([property({attribute:"aria-label"})],LyraGraph.prototype,"accessibleLabel",void 0),__decorate([property({type:Number})],LyraGraph.prototype,"seed",void 0),__decorate([property({type:Boolean,attribute:"with-edge-labels"})],LyraGraph.prototype,"withEdgeLabels",void 0),__decorate([property({type:Number,attribute:"edge-label-min-zoom"})],LyraGraph.prototype,"edgeLabelMinZoom",void 0),__decorate([property({attribute:"node-labels"})],LyraGraph.prototype,"nodeLabels",void 0),__decorate([property({attribute:"focus-node-id"})],LyraGraph.prototype,"focusNodeId",void 0),__decorate([property({attribute:"selection-mode"})],LyraGraph.prototype,"selectionMode",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"selectedNodeIds",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"selectedEdgeIds",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"dimmedNodeIds",void 0),__decorate([property({attribute:!1})],LyraGraph.prototype,"dimmedEdgeIds",void 0),__decorate([state()],LyraGraph.prototype,"loading",void 0),__decorate([state()],LyraGraph.prototype,"loadFailed",void 0),__decorate([state()],LyraGraph.prototype,"containerSize",void 0),__decorate([state()],LyraGraph.prototype,"simNodes",void 0),__decorate([state()],LyraGraph.prototype,"simLinks",void 0),__decorate([state()],LyraGraph.prototype,"activeGraphItem",void 0),__decorate([state()],LyraGraph.prototype,"graphLiveText",void 0),__decorate([query('[part="canvas"]')],LyraGraph.prototype,"canvasEl",void 0);export{LyraGraph};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{focusRing}from"../../../internal/interactive-control.styles.js";import{css}from"lit";const styles=css` :host { display: block; block-size: var( --lr-canvas-reserved-height, var(--_lr-graph-requested-height, var(--lr-size-24rem)) ); } [part="base"] { position: relative; inline-size: 100%; block-size: 100%; } svg { display: block; inline-size: 100%; block-size: 100%; } [part="canvas"] { display: block; inline-size: 100%; block-size: 100%; touch-action: none; transition: background-color var(--lr-transition-fast); } [part="canvas"]:focus-visible { ${focusRing} } [part="canvas"]:hover { background: color-mix( in oklab, transparent, var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="tooltip"] { position: absolute; left: 0; top: 0; pointer-events: none; background: var(--lr-color-surface); color: var(--lr-color-text); font-size: var(--lr-font-size-2xs); font-family: var(--lr-font); padding-block: var(--lr-size-2px); padding-inline: var(--lr-size-6px); border-radius: var(--lr-radius-xs); border: var(--lr-border-width-thin) solid var(--lr-color-border-subtle); z-index: var(--lr-layer-content); transform: translate(var(--lr-size-6px), calc(-100% - var(--lr-size-6px))); max-inline-size: min( calc(100% - var(--lr-size-0-75rem)), calc(100vw - var(--lr-size-0-75rem)) ); overflow-wrap: anywhere; white-space: normal; } [part="tooltip"][hidden] { display: none; } [part="link"] { stroke: var(--lr-graph-edge-color, var(--lr-color-border)); fill: none; cursor: pointer; } [data-hit-area] { fill: none; stroke: var(--lr-color-text); stroke-opacity: 0.001; stroke-width: calc( var(--lr-size-24px) * var(--_lr-graph-hit-area-scale, 1) ); cursor: pointer; } [data-hit-area="node"], [data-hit-area="link"] { stroke-linecap: round; pointer-events: stroke; } [data-hit-area="hull"] { fill: transparent; stroke-linecap: round; stroke-linejoin: round; pointer-events: all; } [part="link"]:hover { stroke: color-mix( in oklab, var(--lr-graph-edge-color, var(--lr-color-border)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="link"]:active { stroke: color-mix( in oklab, var(--lr-graph-edge-color, var(--lr-color-border)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); } [part="arrowhead"] { fill: context-stroke; } [part="link"]:focus-visible { ${focusRing} } [part="link"][data-dangling] { stroke-dasharray: var(--lr-size-2px) var(--lr-size-2px); opacity: var(--lr-opacity-disabled); } [part="node"] { fill: var(--lr-graph-node-fill, var(--lr-color-brand)); cursor: pointer; } [part="node"]:hover { fill: color-mix( in oklab, var(--lr-graph-node-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="node"]:active { fill: color-mix( in oklab, var(--lr-graph-node-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); } [part="node"]:focus-visible { ${focusRing} } [part="label"] { font-size: var(--lr-font-size-2xs); fill: var(--lr-color-text); font-family: var(--lr-font); pointer-events: none; } [part="link-label"] { font-size: var(--lr-font-size-2xs); fill: var(--lr-color-text); font-family: var(--lr-font); pointer-events: none; paint-order: stroke; stroke: var(--lr-graph-edge-label-halo, var(--lr-color-surface)); stroke-width: var(--lr-border-width-thick); } g[data-edge-labels-hidden] [part="link-label"], g[data-edge-labels-hidden] [part="community-label"] { display: none; } g[data-node-labels-hidden] [part="label"] { display: none; } [part="empty"] { color: var(--lr-color-text-quiet); font-size: var(--lr-font-size-md-sm); } [part="error"] { margin: 0; padding: var(--lr-space-l); color: var(--lr-color-danger); font-size: var(--lr-font-size-md-sm); text-align: center; } [part="expand-indicator"] circle { fill: var(--lr-color-surface); stroke: var(--lr-color-border-strong); stroke-width: var(--lr-border-width-thin); } [part="expand-indicator"] path { stroke: var(--lr-color-text); stroke-width: var(--lr-border-width-thin); fill: none; } [part="focus-halo"] { fill: none; stroke: var(--lr-graph-focus-halo-color, var(--lr-color-brand)); stroke-width: var(--lr-border-width-medium); pointer-events: none; } [part="node"][data-selected] { stroke: var(--lr-graph-selected-color, var(--lr-color-success)); stroke-width: var(--lr-border-width-medium); } [part="link"][data-selected] { stroke: var(--lr-graph-selected-color, var(--lr-color-success)) !important; stroke-width: var(--lr-border-width-thick); } [part="link"][data-selected]:hover { stroke: color-mix( in oklab, var(--lr-graph-selected-color, var(--lr-color-success)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ) !important; } [part="link"][data-selected]:active { stroke: color-mix( in oklab, var(--lr-graph-selected-color, var(--lr-color-success)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ) !important; } [part="node"][data-dimmed] { opacity: var(--lr-graph-dimmed-opacity, 0.35); } [part="link"][data-dimmed] { opacity: var(--lr-graph-dimmed-opacity, 0.35); } [data-hit-area="link"][data-inert] { pointer-events: none; } [part="hull"] { fill: var(--lr-graph-hull-fill, var(--lr-color-brand)); stroke: var(--lr-graph-hull-fill, var(--lr-color-brand)); stroke-width: calc(var(--lr-size-24px) * 2); stroke-linejoin: round; stroke-linecap: round; opacity: var(--lr-graph-hull-opacity, 0.12); cursor: pointer; } [part="hull"]:hover { fill: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); stroke: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="hull"]:active { fill: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); stroke: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); } [part="hull"]:focus-visible { ${focusRing} } [part="community-label"] { font-size: var(--lr-font-size-2xs); fill: var(--lr-color-text); font-family: var(--lr-font); text-anchor: middle; pointer-events: none; paint-order: stroke; stroke: var(--lr-graph-edge-label-halo, var(--lr-color-surface)); stroke-width: var(--lr-border-width-thick); } `;export{styles};
|
|
1
|
+
import{focusRing}from"../../../internal/interactive-control.styles.js";import{css}from"lit";const styles=css` :host { display: block; block-size: var( --lr-canvas-reserved-height, var(--_lr-graph-requested-height, var(--lr-size-24rem)) ); } [part="base"] { position: relative; inline-size: 100%; block-size: 100%; } .spatial-base { display: flex; flex-direction: column; min-inline-size: 0; overflow: hidden; } [part="spatial-toolbar"], [part="spatial-pagination"] { display: flex; flex-wrap: wrap; gap: var(--lr-space-s); padding: var(--lr-space-s); } [part="spatial-control"], [part="spatial-list-item"] { --_lr-spatial-fill: var(--lr-color-neutral-fill-quiet); min-inline-size: var(--lr-icon-button-size); min-block-size: var(--lr-icon-button-size); padding: var(--lr-space-s) var(--lr-space-m); border: var(--lr-border-width-thin) solid var(--lr-color-border); border-radius: var(--lr-radius-xs); background: var(--_lr-spatial-fill); color: var(--lr-color-text); font: inherit; cursor: pointer; transition: var(--lr-transition-interactive); overflow-wrap: anywhere; } [part="spatial-control"]:where([aria-pressed="true"]), [part="spatial-list-item"]:where([aria-pressed="true"], [aria-current="true"]) { --_lr-spatial-fill: var(--lr-color-brand-fill-quiet); } [part="spatial-control"]:hover:where(:not(:disabled)), [part="spatial-list-item"]:hover { background: color-mix(in oklab, var(--_lr-spatial-fill), var(--lr-color-mix-partner) var(--lr-color-mix-hover)); } [part="spatial-control"]:active:where(:not(:disabled)), [part="spatial-list-item"]:active { background: color-mix(in oklab, var(--_lr-spatial-fill), var(--lr-color-mix-partner) var(--lr-color-mix-active)); } [part="spatial-control"]:focus-visible, [part="spatial-list-item"]:focus-visible, [part="spatial-canvas"]:focus-visible { ${focusRing} } [part="spatial-control"]:disabled { cursor: default; opacity: var(--lr-opacity-disabled); } [part="spatial-instructions"], [part="spatial-page-count"] { margin: 0; padding: var(--lr-space-s); font-size: var(--lr-font-size-sm); overflow-wrap: anywhere; } [part="spatial-canvas"] { min-inline-size: var(--lr-icon-button-size); display: block; flex: 1 1 auto; inline-size: 100%; block-size: 0; min-block-size: var(--lr-icon-button-size); touch-action: none; transition: var(--lr-transition-interactive); } [part="spatial-list"] { min-block-size: 0; overflow: auto; padding: var(--lr-space-s); } [part="spatial-list"] ul { list-style: none; margin: 0; padding: 0; } [part="spatial-list-item"] { inline-size: 100%; text-align: start; margin-block-end: var(--lr-space-xs); } svg { display: block; inline-size: 100%; block-size: 100%; } [part="canvas"] { display: block; inline-size: 100%; block-size: 100%; touch-action: none; transition: background-color var(--lr-transition-fast); } [part="canvas"]:focus-visible { ${focusRing} } [part="canvas"]:hover, [part="spatial-canvas"]:hover { background: color-mix( in oklab, transparent, var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="tooltip"] { position: absolute; left: 0; top: 0; pointer-events: none; background: var(--lr-color-surface); color: var(--lr-color-text); font-size: var(--lr-font-size-2xs); font-family: var(--lr-font); padding-block: var(--lr-size-2px); padding-inline: var(--lr-size-6px); border-radius: var(--lr-radius-xs); border: var(--lr-border-width-thin) solid var(--lr-color-border-subtle); z-index: var(--lr-layer-content); transform: translate(var(--lr-size-6px), calc(-100% - var(--lr-size-6px))); max-inline-size: min( calc(100% - var(--lr-size-0-75rem)), calc(100vw - var(--lr-size-0-75rem)) ); overflow-wrap: anywhere; white-space: normal; } [part="tooltip"][hidden] { display: none; } [part="link"] { stroke: var(--lr-graph-edge-color, var(--lr-color-border)); fill: none; cursor: pointer; } [data-hit-area] { fill: none; stroke: var(--lr-color-text); stroke-opacity: 0.001; stroke-width: calc( var(--lr-size-24px) * var(--_lr-graph-hit-area-scale, 1) ); cursor: pointer; } [data-hit-area="node"], [data-hit-area="link"] { stroke-linecap: round; pointer-events: stroke; } [data-hit-area="hull"] { fill: transparent; stroke-linecap: round; stroke-linejoin: round; pointer-events: all; } [part="link"]:hover { stroke: color-mix( in oklab, var(--lr-graph-edge-color, var(--lr-color-border)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="link"]:active { stroke: color-mix( in oklab, var(--lr-graph-edge-color, var(--lr-color-border)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); } [part="arrowhead"] { fill: context-stroke; } [part="link"]:focus-visible { ${focusRing} } [part="link"][data-dangling] { stroke-dasharray: var(--lr-size-2px) var(--lr-size-2px); opacity: var(--lr-opacity-disabled); } [part="node"] { fill: var(--lr-graph-node-fill, var(--lr-color-brand)); cursor: pointer; } [part="node"]:hover { fill: color-mix( in oklab, var(--lr-graph-node-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="node"]:active { fill: color-mix( in oklab, var(--lr-graph-node-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); } [part="node"]:focus-visible { ${focusRing} } [part="label"] { font-size: var(--lr-font-size-2xs); fill: var(--lr-color-text); font-family: var(--lr-font); pointer-events: none; } [part="link-label"] { font-size: var(--lr-font-size-2xs); fill: var(--lr-color-text); font-family: var(--lr-font); pointer-events: none; paint-order: stroke; stroke: var(--lr-graph-edge-label-halo, var(--lr-color-surface)); stroke-width: var(--lr-border-width-thick); } g[data-edge-labels-hidden] [part="link-label"], g[data-edge-labels-hidden] [part="community-label"] { display: none; } g[data-node-labels-hidden] [part="label"] { display: none; } [part="empty"] { color: var(--lr-color-text-quiet); font-size: var(--lr-font-size-md-sm); } [part="error"] { margin: 0; padding: var(--lr-space-l); color: var(--lr-color-danger); font-size: var(--lr-font-size-md-sm); text-align: center; } [part="expand-indicator"] circle { fill: var(--lr-color-surface); stroke: var(--lr-color-border-strong); stroke-width: var(--lr-border-width-thin); } [part="expand-indicator"] path { stroke: var(--lr-color-text); stroke-width: var(--lr-border-width-thin); fill: none; } [part="focus-halo"] { fill: none; stroke: var(--lr-graph-focus-halo-color, var(--lr-color-brand)); stroke-width: var(--lr-border-width-medium); pointer-events: none; } [part="node"][data-selected] { stroke: var(--lr-graph-selected-color, var(--lr-color-success)); stroke-width: var(--lr-border-width-medium); } [part="link"][data-selected] { stroke: var(--lr-graph-selected-color, var(--lr-color-success)) !important; stroke-width: var(--lr-border-width-thick); } [part="link"][data-selected]:hover { stroke: color-mix( in oklab, var(--lr-graph-selected-color, var(--lr-color-success)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ) !important; } [part="link"][data-selected]:active { stroke: color-mix( in oklab, var(--lr-graph-selected-color, var(--lr-color-success)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ) !important; } [part="node"][data-dimmed] { opacity: var(--lr-graph-dimmed-opacity, 0.35); } [part="link"][data-dimmed] { opacity: var(--lr-graph-dimmed-opacity, 0.35); } [data-hit-area="link"][data-inert] { pointer-events: none; } [part="hull"] { fill: var(--lr-graph-hull-fill, var(--lr-color-brand)); stroke: var(--lr-graph-hull-fill, var(--lr-color-brand)); stroke-width: calc(var(--lr-size-24px) * 2); stroke-linejoin: round; stroke-linecap: round; opacity: var(--lr-graph-hull-opacity, 0.12); cursor: pointer; } [part="hull"]:hover { fill: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); stroke: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-hover) ); } [part="hull"]:active { fill: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); stroke: color-mix( in oklab, var(--lr-graph-hull-fill, var(--lr-color-brand)), var(--lr-color-mix-partner) var(--lr-color-mix-active) ); } [part="hull"]:focus-visible { ${focusRing} } [part="community-label"] { font-size: var(--lr-font-size-2xs); fill: var(--lr-color-text); font-family: var(--lr-font); text-anchor: middle; pointer-events: none; paint-order: stroke; stroke: var(--lr-graph-edge-label-halo, var(--lr-color-surface)); stroke-width: var(--lr-border-width-thick); } `;export{styles};
|