@ankhorage/zora 20.2.1 → 20.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 20.2.3
4
+
5
+ ### Patch Changes
6
+
7
+ - e1263fd: Update Ankhorage dependencies: `@ankhorage/contracts`.
8
+
9
+ ## 20.2.2
10
+
11
+ ### Patch Changes
12
+
13
+ - d46bab4: Make the materialized GraphView artifact consumable by Next/Turbopack by hoisting its client directive and bundling the browser-safe ELK adapter.
14
+
3
15
  ## 20.2.1
4
16
 
5
17
  ### Patch Changes
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @ankhorage/zora
5
5
 
6
- ![license: MIT](././paradox/badges/license.svg) ![npm: v20.2.1](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
6
+ ![license: MIT](././paradox/badges/license.svg) ![npm: v20.2.3](././paradox/badges/npm.svg) ![runtime: bun](././paradox/badges/runtime.svg) ![typescript: strict](././paradox/badges/typescript.svg) ![eslint: checked](././paradox/badges/eslint.svg) ![prettier: checked](././paradox/badges/prettier.svg) ![build: checked](././paradox/badges/build.svg) ![tests: checked](././paradox/badges/tests.svg) ![docs: paradox](././paradox/badges/docs.svg)
7
7
 
8
8
  Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.
9
9
 
@@ -1 +1 @@
1
- {"version":3,"file":"GraphNodeOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphNodeOverlay.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACb,0BAA0B,EAC1B,qBAAqB,EACrB,aAAa,EACd,MAAM,aAAa,CAAC;AAErB,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,aAAa,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACzD,QAAQ,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAC5E,QAAQ,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CAChE;AAED,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,qBAgC5D"}
1
+ {"version":3,"file":"GraphNodeOverlay.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphNodeOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,KAAK,EACV,yBAAyB,EACzB,aAAa,EACb,0BAA0B,EAC1B,qBAAqB,EACrB,aAAa,EACd,MAAM,aAAa,CAAC;AAErB,UAAU,qBAAqB;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,aAAa,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACzD,QAAQ,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,KAAK,CAAC,SAAS,CAAC;IAC9E,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,yBAAyB,KAAK,IAAI,CAAC;IAC5E,QAAQ,CAAC,UAAU,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,aAAa,KAAK,IAAI,CAAC;CAChE;AAED,mGAAmG;AACnG,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,qBAgC5D"}
@@ -1,4 +1,3 @@
1
- 'use client';
2
1
  import React from 'react';
3
2
  /*** Render optional React node content above Cytoscape at its authoritative rendered positions. */
4
3
  export function GraphNodeOverlay(props) {
@@ -1 +1 @@
1
- {"version":3,"file":"GraphNodeOverlay.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphNodeOverlay.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport React from 'react';\n\nimport type {\n GraphViewElementEventType,\n GraphViewNode,\n GraphViewNodeRenderContext,\n GraphViewRenderedNode,\n GraphViewSize,\n} from './GraphView';\n\ninterface GraphNodeOverlayProps {\n readonly nodes: readonly GraphViewNode[];\n readonly renderedNodes: readonly GraphViewRenderedNode[];\n readonly renderNode: (context: GraphViewNodeRenderContext) => React.ReactNode;\n readonly onNodeEvent: (id: string, type: GraphViewElementEventType) => void;\n readonly onNodeSize: (id: string, size: GraphViewSize) => void;\n}\n\n/*** Render optional React node content above Cytoscape at its authoritative rendered positions. */\nexport function GraphNodeOverlay(props: GraphNodeOverlayProps) {\n const nodesById = React.useMemo(\n () => new Map(props.nodes.map((node) => [node.id, node] as const)),\n [props.nodes],\n );\n\n return (\n <div\n aria-hidden\n style={{\n inset: 0,\n overflow: 'hidden',\n pointerEvents: 'none',\n position: 'absolute',\n }}\n >\n {props.renderedNodes.map((renderedNode) => {\n const node = nodesById.get(renderedNode.id);\n if (!node) return null;\n return (\n <MeasuredGraphNode\n key={node.id}\n node={node}\n renderedNode={renderedNode}\n renderNode={props.renderNode}\n onNodeEvent={props.onNodeEvent}\n onNodeSize={props.onNodeSize}\n />\n );\n })}\n </div>\n );\n}\n\ninterface MeasuredGraphNodeProps {\n readonly node: GraphViewNode;\n readonly renderedNode: GraphViewRenderedNode;\n readonly renderNode: GraphNodeOverlayProps['renderNode'];\n readonly onNodeEvent: GraphNodeOverlayProps['onNodeEvent'];\n readonly onNodeSize: GraphNodeOverlayProps['onNodeSize'];\n}\n\n/*** Measure one rich node at model scale and translate its DOM interactions into graph events. */\nfunction MeasuredGraphNode(props: MeasuredGraphNodeProps) {\n const elementRef = React.useRef<HTMLDivElement | null>(null);\n const { node, onNodeSize, renderedNode } = props;\n\n React.useLayoutEffect(() => {\n const element = elementRef.current;\n if (element === null) return;\n reportElementSize(element, node.id, onNodeSize);\n\n const Observer = readResizeObserverConstructor();\n if (Observer === null) return;\n const observer = new Observer(() => reportElementSize(element, node.id, onNodeSize));\n observer.observe(element);\n return () => observer.disconnect();\n }, [node.id, onNodeSize]);\n\n return (\n <div\n ref={(element) => {\n elementRef.current = element;\n }}\n style={{\n left: renderedNode.position.x,\n pointerEvents: 'auto',\n position: 'absolute',\n top: renderedNode.position.y,\n transform: `translate(-50%, -50%) scale(${renderedNode.zoom})`,\n transformOrigin: 'center',\n }}\n onClick={() => props.onNodeEvent(node.id, 'press')}\n onDoubleClick={() => props.onNodeEvent(node.id, 'double-press')}\n onMouseEnter={() => props.onNodeEvent(node.id, 'pointer-enter')}\n onMouseLeave={() => props.onNodeEvent(node.id, 'pointer-leave')}\n >\n {props.renderNode({\n hovered: renderedNode.hovered,\n node,\n selected: renderedNode.selected,\n zoom: renderedNode.zoom,\n })}\n </div>\n );\n}\n\n/*** Report unscaled DOM dimensions only when a measurable node has positive size. */\nfunction reportElementSize(\n element: unknown,\n nodeId: string,\n onNodeSize: (id: string, size: GraphViewSize) => void,\n) {\n const measured = element as {\n readonly offsetHeight?: unknown;\n readonly offsetWidth?: unknown;\n };\n if (typeof measured.offsetWidth !== 'number' || typeof measured.offsetHeight !== 'number') return;\n if (measured.offsetWidth <= 0 || measured.offsetHeight <= 0) return;\n onNodeSize(nodeId, {\n width: measured.offsetWidth,\n height: measured.offsetHeight,\n });\n}\n\n/*** Read ResizeObserver without requiring the DOM lib in the package TypeScript target. */\nfunction readResizeObserverConstructor(): ResizeObserverConstructorLike | null {\n const observer = (\n globalThis as unknown as {\n ResizeObserver?: ResizeObserverConstructorLike;\n }\n ).ResizeObserver;\n return observer ?? null;\n}\n\ninterface ResizeObserverLike {\n disconnect(): void;\n observe(target: unknown): void;\n}\n\ntype ResizeObserverConstructorLike = new (callback: () => void) => ResizeObserverLike;\n"]}
1
+ {"version":3,"file":"GraphNodeOverlay.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphNodeOverlay.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from 'react';\n\nimport type {\n GraphViewElementEventType,\n GraphViewNode,\n GraphViewNodeRenderContext,\n GraphViewRenderedNode,\n GraphViewSize,\n} from './GraphView';\n\ninterface GraphNodeOverlayProps {\n readonly nodes: readonly GraphViewNode[];\n readonly renderedNodes: readonly GraphViewRenderedNode[];\n readonly renderNode: (context: GraphViewNodeRenderContext) => React.ReactNode;\n readonly onNodeEvent: (id: string, type: GraphViewElementEventType) => void;\n readonly onNodeSize: (id: string, size: GraphViewSize) => void;\n}\n\n/*** Render optional React node content above Cytoscape at its authoritative rendered positions. */\nexport function GraphNodeOverlay(props: GraphNodeOverlayProps) {\n const nodesById = React.useMemo(\n () => new Map(props.nodes.map((node) => [node.id, node] as const)),\n [props.nodes],\n );\n\n return (\n <div\n aria-hidden\n style={{\n inset: 0,\n overflow: 'hidden',\n pointerEvents: 'none',\n position: 'absolute',\n }}\n >\n {props.renderedNodes.map((renderedNode) => {\n const node = nodesById.get(renderedNode.id);\n if (!node) return null;\n return (\n <MeasuredGraphNode\n key={node.id}\n node={node}\n renderedNode={renderedNode}\n renderNode={props.renderNode}\n onNodeEvent={props.onNodeEvent}\n onNodeSize={props.onNodeSize}\n />\n );\n })}\n </div>\n );\n}\n\ninterface MeasuredGraphNodeProps {\n readonly node: GraphViewNode;\n readonly renderedNode: GraphViewRenderedNode;\n readonly renderNode: GraphNodeOverlayProps['renderNode'];\n readonly onNodeEvent: GraphNodeOverlayProps['onNodeEvent'];\n readonly onNodeSize: GraphNodeOverlayProps['onNodeSize'];\n}\n\n/*** Measure one rich node at model scale and translate its DOM interactions into graph events. */\nfunction MeasuredGraphNode(props: MeasuredGraphNodeProps) {\n const elementRef = React.useRef<HTMLDivElement | null>(null);\n const { node, onNodeSize, renderedNode } = props;\n\n React.useLayoutEffect(() => {\n const element = elementRef.current;\n if (element === null) return;\n reportElementSize(element, node.id, onNodeSize);\n\n const Observer = readResizeObserverConstructor();\n if (Observer === null) return;\n const observer = new Observer(() => reportElementSize(element, node.id, onNodeSize));\n observer.observe(element);\n return () => observer.disconnect();\n }, [node.id, onNodeSize]);\n\n return (\n <div\n ref={(element) => {\n elementRef.current = element;\n }}\n style={{\n left: renderedNode.position.x,\n pointerEvents: 'auto',\n position: 'absolute',\n top: renderedNode.position.y,\n transform: `translate(-50%, -50%) scale(${renderedNode.zoom})`,\n transformOrigin: 'center',\n }}\n onClick={() => props.onNodeEvent(node.id, 'press')}\n onDoubleClick={() => props.onNodeEvent(node.id, 'double-press')}\n onMouseEnter={() => props.onNodeEvent(node.id, 'pointer-enter')}\n onMouseLeave={() => props.onNodeEvent(node.id, 'pointer-leave')}\n >\n {props.renderNode({\n hovered: renderedNode.hovered,\n node,\n selected: renderedNode.selected,\n zoom: renderedNode.zoom,\n })}\n </div>\n );\n}\n\n/*** Report unscaled DOM dimensions only when a measurable node has positive size. */\nfunction reportElementSize(\n element: unknown,\n nodeId: string,\n onNodeSize: (id: string, size: GraphViewSize) => void,\n) {\n const measured = element as {\n readonly offsetHeight?: unknown;\n readonly offsetWidth?: unknown;\n };\n if (typeof measured.offsetWidth !== 'number' || typeof measured.offsetHeight !== 'number') return;\n if (measured.offsetWidth <= 0 || measured.offsetHeight <= 0) return;\n onNodeSize(nodeId, {\n width: measured.offsetWidth,\n height: measured.offsetHeight,\n });\n}\n\n/*** Read ResizeObserver without requiring the DOM lib in the package TypeScript target. */\nfunction readResizeObserverConstructor(): ResizeObserverConstructorLike | null {\n const observer = (\n globalThis as unknown as {\n ResizeObserver?: ResizeObserverConstructorLike;\n }\n ).ResizeObserver;\n return observer ?? null;\n}\n\ninterface ResizeObserverLike {\n disconnect(): void;\n observe(target: unknown): void;\n}\n\ntype ResizeObserverConstructorLike = new (callback: () => void) => ResizeObserverLike;\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"GraphView.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphView.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,CAAC;AAC5F,MAAM,MAAM,yBAAyB,GACnC,OAAO,GAAG,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,eAAe,GAAG,eAAe,CAAC;AAEvF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;CAC1C;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACzC,WAAW,IAAI,iBAAiB,CAAC;IACjC,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACpD,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,KAAK,CAAC,SAAS,CAAC;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,aAAa,GAAG,SAAS,CAAC;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACnE;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,cAAc,EACd,aAAa,GAAG,kBAAkB,GAAG,aAAa,GAAG,SAAS,GAAG,kBAAkB,CACpF,CAAC;AAIF,+FAA+F;AAC/F,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBA6B9C"}
1
+ {"version":3,"file":"GraphView.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG,QAAQ,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,CAAC;AAC5F,MAAM,MAAM,yBAAyB,GACnC,OAAO,GAAG,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,eAAe,GAAG,eAAe,CAAC;AAEvF,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC;IAClC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,yBAAyB,CAAC;CAC1C;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,CAAC,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACzC,WAAW,IAAI,iBAAiB,CAAC;IACjC,MAAM,CAAC,GAAG,EAAE,cAAc,GAAG,IAAI,CAAC;IAClC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,QAAQ,CAAC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,kBAAkB,EAAE,CAAC;IACpD,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,KAAK,CAAC,SAAS,CAAC;IAC/E,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,aAAa,GAAG,SAAS,CAAC;IAC1E,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IAC7D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACtE,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC9D,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC9D,QAAQ,CAAC,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAC;CACnE;AAED,MAAM,MAAM,kBAAkB,GAAG,IAAI,CACnC,cAAc,EACd,aAAa,GAAG,kBAAkB,GAAG,aAAa,GAAG,SAAS,GAAG,kBAAkB,CACpF,CAAC;AAIF,+FAA+F;AAC/F,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,qBA6B9C"}
@@ -1,4 +1,3 @@
1
- 'use client';
2
1
  import React from 'react';
3
2
  import { createGraphRuntime } from './createGraphRuntime';
4
3
  import { GraphNodeOverlay } from './GraphNodeOverlay';
@@ -1 +1 @@
1
- {"version":3,"file":"GraphView.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphView.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport type { CytoscapeOptions } from 'cytoscape';\nimport React from 'react';\n\nimport { createGraphRuntime, type GraphRuntime } from './createGraphRuntime';\nimport { GraphNodeOverlay } from './GraphNodeOverlay';\n\nexport type GraphViewLayoutName = 'breadthfirst' | 'circle' | 'concentric' | 'elk' | 'grid';\nexport type GraphViewElementEventType =\n 'press' | 'double-press' | 'select' | 'unselect' | 'pointer-enter' | 'pointer-leave';\n\nexport interface GraphViewNode {\n readonly id: string;\n readonly label?: string;\n readonly parentId?: string;\n readonly classes?: string;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\nexport interface GraphViewEdge {\n readonly id?: string;\n readonly source: string;\n readonly target: string;\n readonly classes?: string;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\nexport interface GraphViewStyleRule {\n readonly selector: string;\n readonly style: Readonly<Record<string, unknown>>;\n}\n\nexport interface GraphViewPoint {\n readonly x: number;\n readonly y: number;\n}\n\nexport interface GraphViewSize {\n readonly width: number;\n readonly height: number;\n}\n\nexport interface GraphViewNodeRenderContext {\n readonly hovered: boolean;\n readonly node: GraphViewNode;\n readonly selected: boolean;\n readonly zoom: number;\n}\n\nexport interface GraphViewRenderedNode {\n readonly hovered: boolean;\n readonly id: string;\n readonly position: GraphViewPoint;\n readonly selected: boolean;\n readonly zoom: number;\n}\n\nexport interface GraphViewViewport {\n readonly zoom: number;\n readonly pan: GraphViewPoint;\n}\n\nexport interface GraphViewFitOptions {\n readonly nodeIds?: readonly string[];\n readonly padding?: number;\n}\n\nexport interface GraphViewElementEvent {\n readonly id: string;\n readonly type: GraphViewElementEventType;\n}\n\nexport interface GraphViewController {\n fit(options?: GraphViewFitOptions): void;\n getViewport(): GraphViewViewport;\n setPan(pan: GraphViewPoint): void;\n setZoom(zoom: number): void;\n zoomBy(factor: number): void;\n}\n\nexport interface GraphViewProps {\n readonly nodes: readonly GraphViewNode[];\n readonly edges: readonly GraphViewEdge[];\n readonly layout?: GraphViewLayoutName;\n readonly layoutOptions?: Readonly<Record<string, unknown>>;\n readonly spacingFactor?: number;\n readonly styleRules?: readonly GraphViewStyleRule[];\n readonly selectedNodeIds?: readonly string[];\n readonly renderNode?: (context: GraphViewNodeRenderContext) => React.ReactNode;\n readonly getNodeSize?: (node: GraphViewNode) => GraphViewSize | undefined;\n readonly fitPadding?: number;\n readonly minZoom?: number;\n readonly maxZoom?: number;\n readonly className?: string;\n readonly style?: React.CSSProperties;\n readonly ariaLabel?: string;\n readonly onReady?: (controller: GraphViewController) => void;\n readonly onLayoutComplete?: (controller: GraphViewController) => void;\n readonly onNodeEvent?: (event: GraphViewElementEvent) => void;\n readonly onEdgeEvent?: (event: GraphViewElementEvent) => void;\n readonly onViewportChange?: (viewport: GraphViewViewport) => void;\n}\n\nexport type GraphViewCallbacks = Pick<\n GraphViewProps,\n 'onEdgeEvent' | 'onLayoutComplete' | 'onNodeEvent' | 'onReady' | 'onViewportChange'\n>;\n\ntype GraphContainer = NonNullable<CytoscapeOptions['container']>;\n\n/*** Render a browser graph while one runtime owns Cytoscape layout, viewport, and disposal. */\nexport function GraphView(props: GraphViewProps) {\n const { containerRef, renderedNodes, runtimeRef } = useGraphViewRuntime(props);\n\n return (\n <div\n aria-label={props.ariaLabel ?? 'Graph'}\n className={props.className}\n role=\"application\"\n style={{\n height: '100%',\n minHeight: 0,\n minWidth: 0,\n position: 'relative',\n width: '100%',\n ...props.style,\n }}\n >\n <div ref={containerRef} style={{ height: '100%', width: '100%' }} />\n {props.renderNode ? (\n <GraphNodeOverlay\n nodes={props.nodes}\n renderedNodes={renderedNodes}\n renderNode={props.renderNode}\n onNodeEvent={(id, type) => runtimeRef.current?.handleOverlayNodeEvent(id, type)}\n onNodeSize={(id, size) => runtimeRef.current?.setNodeSize(id, size)}\n />\n ) : null}\n </div>\n );\n}\n\n/*** Compose React synchronization around the single imperative graph runtime. */\nfunction useGraphViewRuntime(props: GraphViewProps) {\n const containerRef = React.useRef<GraphContainer | null>(null);\n const runtimeRef = React.useRef<GraphRuntime | null>(null);\n const callbacksRef = useGraphCallbacksRef(props);\n const [renderedNodes, setRenderedNodes] = React.useState<readonly GraphViewRenderedNode[]>([]);\n\n useRuntimeLifecycle(containerRef, runtimeRef, callbacksRef);\n useRuntimeGraphUpdate(runtimeRef, props);\n useRuntimeSelection(runtimeRef, props.selectedNodeIds);\n useRenderedNodeSubscription(runtimeRef, props.renderNode, setRenderedNodes);\n useKnownNodeSizes(runtimeRef, props.nodes, props.getNodeSize);\n\n return { containerRef, renderedNodes, runtimeRef };\n}\n\n/*** Keep the callback ref current without mutating refs during render. */\nfunction useGraphCallbacksRef(props: GraphViewProps) {\n const callbacksRef = React.useRef<GraphViewCallbacks>(readCallbacks(props));\n const { onEdgeEvent, onLayoutComplete, onNodeEvent, onReady, onViewportChange } = props;\n\n React.useEffect(() => {\n callbacksRef.current = {\n onEdgeEvent,\n onLayoutComplete,\n onNodeEvent,\n onReady,\n onViewportChange,\n };\n }, [onEdgeEvent, onLayoutComplete, onNodeEvent, onReady, onViewportChange]);\n\n return callbacksRef;\n}\n\n/*** Create and dispose the runtime only with the underlying browser container lifetime. */\nfunction useRuntimeLifecycle(\n containerRef: { current: GraphContainer | null },\n runtimeRef: { current: GraphRuntime | null },\n callbacksRef: { current: GraphViewCallbacks },\n) {\n React.useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n const runtime = createGraphRuntime(container, callbacksRef);\n runtimeRef.current = runtime;\n return () => {\n runtime.destroy();\n runtimeRef.current = null;\n };\n }, [callbacksRef, containerRef, runtimeRef]);\n}\n\n/*** Synchronize graph data and layout policy without exposing Cytoscape to React. */\nfunction useRuntimeGraphUpdate(\n runtimeRef: { current: GraphRuntime | null },\n props: GraphViewProps,\n) {\n const {\n edges,\n fitPadding,\n layout,\n layoutOptions,\n maxZoom,\n minZoom,\n nodes,\n renderNode,\n spacingFactor,\n styleRules,\n } = props;\n\n React.useEffect(() => {\n runtimeRef.current?.update({\n edges,\n fitPadding,\n layout,\n layoutOptions,\n maxZoom,\n minZoom,\n nodes,\n richNodeRendering: renderNode !== undefined,\n spacingFactor,\n styleRules,\n });\n }, [\n edges,\n fitPadding,\n layout,\n layoutOptions,\n maxZoom,\n minZoom,\n nodes,\n renderNode,\n runtimeRef,\n spacingFactor,\n styleRules,\n ]);\n}\n\n/*** Synchronize optional controlled selection independently from graph layout. */\nfunction useRuntimeSelection(\n runtimeRef: { current: GraphRuntime | null },\n selectedNodeIds: readonly string[] | undefined,\n) {\n React.useEffect(() => {\n runtimeRef.current?.setSelectedNodeIds(selectedNodeIds);\n }, [runtimeRef, selectedNodeIds]);\n}\n\n/*** Subscribe the optional rich-node overlay to rendered runtime positions. */\nfunction useRenderedNodeSubscription(\n runtimeRef: { current: GraphRuntime | null },\n renderNode: GraphViewProps['renderNode'],\n setRenderedNodes: (nodes: readonly GraphViewRenderedNode[]) => void,\n) {\n React.useEffect(() => {\n const runtime = runtimeRef.current;\n if (runtime === null || renderNode === undefined) {\n setRenderedNodes([]);\n return;\n }\n return runtime.subscribeRenderedNodes(setRenderedNodes);\n }, [renderNode, runtimeRef, setRenderedNodes]);\n}\n\n/*** Seed known rich-node dimensions without requiring DOM measurement. */\nfunction useKnownNodeSizes(\n runtimeRef: { current: GraphRuntime | null },\n nodes: readonly GraphViewNode[],\n getNodeSize: GraphViewProps['getNodeSize'],\n) {\n React.useEffect(() => {\n const runtime = runtimeRef.current;\n if (runtime === null || getNodeSize === undefined) return;\n for (const node of nodes) {\n const size = getNodeSize(node);\n if (size) runtime.setNodeSize(node.id, size);\n }\n }, [getNodeSize, nodes, runtimeRef]);\n}\n\n/*** Read callback props for the initial runtime callback-ref value. */\nfunction readCallbacks(props: GraphViewProps): GraphViewCallbacks {\n return {\n onEdgeEvent: props.onEdgeEvent,\n onLayoutComplete: props.onLayoutComplete,\n onNodeEvent: props.onNodeEvent,\n onReady: props.onReady,\n onViewportChange: props.onViewportChange,\n };\n}\n"]}
1
+ {"version":3,"file":"GraphView.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/GraphView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,kBAAkB,EAAqB,MAAM,sBAAsB,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAyGtD,+FAA+F;AAC/F,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAE/E,OAAO,CACL,CAAC,GAAG,CACF,UAAU,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,OAAO,CAAC,CACvC,SAAS,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAC3B,IAAI,CAAC,aAAa,CAClB,KAAK,CAAC,CAAC;YACL,MAAM,EAAE,MAAM;YACd,SAAS,EAAE,CAAC;YACZ,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,MAAM;YACb,GAAG,KAAK,CAAC,KAAK;SACf,CAAC,CAEF;MAAA,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EACjE;MAAA,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAClB,CAAC,gBAAgB,CACf,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CACnB,aAAa,CAAC,CAAC,aAAa,CAAC,CAC7B,UAAU,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAC7B,WAAW,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,sBAAsB,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAChF,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,EACpE,CACH,CAAC,CAAC,CAAC,IAAI,CACV;IAAA,EAAE,GAAG,CAAC,CACP,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,SAAS,mBAAmB,CAAC,KAAqB;IAChD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAwB,IAAI,CAAC,CAAC;IAC/D,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAsB,IAAI,CAAC,CAAC;IAC3D,MAAM,YAAY,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAmC,EAAE,CAAC,CAAC;IAE/F,mBAAmB,CAAC,YAAY,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC;IAC5D,qBAAqB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACzC,mBAAmB,CAAC,UAAU,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;IACvD,2BAA2B,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;IAC5E,iBAAiB,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;IAE9D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,CAAC;AACrD,CAAC;AAED,0EAA0E;AAC1E,SAAS,oBAAoB,CAAC,KAAqB;IACjD,MAAM,YAAY,GAAG,KAAK,CAAC,MAAM,CAAqB,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IAC5E,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,EAAE,GAAG,KAAK,CAAC;IAExF,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,YAAY,CAAC,OAAO,GAAG;YACrB,WAAW;YACX,gBAAgB;YAChB,WAAW;YACX,OAAO;YACP,gBAAgB;SACjB,CAAC;IACJ,CAAC,EAAE,CAAC,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAE5E,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,2FAA2F;AAC3F,SAAS,mBAAmB,CAC1B,YAAgD,EAChD,UAA4C,EAC5C,YAA6C;IAE7C,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC;QACvC,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO;QAC/B,MAAM,OAAO,GAAG,kBAAkB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC5D,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;QAC7B,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,OAAO,EAAE,CAAC;YAClB,UAAU,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,qFAAqF;AACrF,SAAS,qBAAqB,CAC5B,UAA4C,EAC5C,KAAqB;IAErB,MAAM,EACJ,KAAK,EACL,UAAU,EACV,MAAM,EACN,aAAa,EACb,OAAO,EACP,OAAO,EACP,KAAK,EACL,UAAU,EACV,aAAa,EACb,UAAU,GACX,GAAG,KAAK,CAAC;IAEV,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC;YACzB,KAAK;YACL,UAAU;YACV,MAAM;YACN,aAAa;YACb,OAAO;YACP,OAAO;YACP,KAAK;YACL,iBAAiB,EAAE,UAAU,KAAK,SAAS;YAC3C,aAAa;YACb,UAAU;SACX,CAAC,CAAC;IACL,CAAC,EAAE;QACD,KAAK;QACL,UAAU;QACV,MAAM;QACN,aAAa;QACb,OAAO;QACP,OAAO;QACP,KAAK;QACL,UAAU;QACV,UAAU;QACV,aAAa;QACb,UAAU;KACX,CAAC,CAAC;AACL,CAAC;AAED,kFAAkF;AAClF,SAAS,mBAAmB,CAC1B,UAA4C,EAC5C,eAA8C;IAE9C,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,UAAU,CAAC,OAAO,EAAE,kBAAkB,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC,EAAE,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,CAAC;AACpC,CAAC;AAED,+EAA+E;AAC/E,SAAS,2BAA2B,CAClC,UAA4C,EAC5C,UAAwC,EACxC,gBAAmE;IAEnE,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;QACnC,IAAI,OAAO,KAAK,IAAI,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YACjD,gBAAgB,CAAC,EAAE,CAAC,CAAC;YACrB,OAAO;QACT,CAAC;QACD,OAAO,OAAO,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;IAC1D,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,EAAE,gBAAgB,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,0EAA0E;AAC1E,SAAS,iBAAiB,CACxB,UAA4C,EAC5C,KAA+B,EAC/B,WAA0C;IAE1C,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,MAAM,OAAO,GAAG,UAAU,CAAC,OAAO,CAAC;QACnC,IAAI,OAAO,KAAK,IAAI,IAAI,WAAW,KAAK,SAAS;YAAE,OAAO;QAC1D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,IAAI;gBAAE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,uEAAuE;AACvE,SAAS,aAAa,CAAC,KAAqB;IAC1C,OAAO;QACL,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;QACxC,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;KACzC,CAAC;AACJ,CAAC","sourcesContent":["import type { CytoscapeOptions } from 'cytoscape';\nimport React from 'react';\n\nimport { createGraphRuntime, type GraphRuntime } from './createGraphRuntime';\nimport { GraphNodeOverlay } from './GraphNodeOverlay';\n\nexport type GraphViewLayoutName = 'breadthfirst' | 'circle' | 'concentric' | 'elk' | 'grid';\nexport type GraphViewElementEventType =\n 'press' | 'double-press' | 'select' | 'unselect' | 'pointer-enter' | 'pointer-leave';\n\nexport interface GraphViewNode {\n readonly id: string;\n readonly label?: string;\n readonly parentId?: string;\n readonly classes?: string;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\nexport interface GraphViewEdge {\n readonly id?: string;\n readonly source: string;\n readonly target: string;\n readonly classes?: string;\n readonly data?: Readonly<Record<string, unknown>>;\n}\n\nexport interface GraphViewStyleRule {\n readonly selector: string;\n readonly style: Readonly<Record<string, unknown>>;\n}\n\nexport interface GraphViewPoint {\n readonly x: number;\n readonly y: number;\n}\n\nexport interface GraphViewSize {\n readonly width: number;\n readonly height: number;\n}\n\nexport interface GraphViewNodeRenderContext {\n readonly hovered: boolean;\n readonly node: GraphViewNode;\n readonly selected: boolean;\n readonly zoom: number;\n}\n\nexport interface GraphViewRenderedNode {\n readonly hovered: boolean;\n readonly id: string;\n readonly position: GraphViewPoint;\n readonly selected: boolean;\n readonly zoom: number;\n}\n\nexport interface GraphViewViewport {\n readonly zoom: number;\n readonly pan: GraphViewPoint;\n}\n\nexport interface GraphViewFitOptions {\n readonly nodeIds?: readonly string[];\n readonly padding?: number;\n}\n\nexport interface GraphViewElementEvent {\n readonly id: string;\n readonly type: GraphViewElementEventType;\n}\n\nexport interface GraphViewController {\n fit(options?: GraphViewFitOptions): void;\n getViewport(): GraphViewViewport;\n setPan(pan: GraphViewPoint): void;\n setZoom(zoom: number): void;\n zoomBy(factor: number): void;\n}\n\nexport interface GraphViewProps {\n readonly nodes: readonly GraphViewNode[];\n readonly edges: readonly GraphViewEdge[];\n readonly layout?: GraphViewLayoutName;\n readonly layoutOptions?: Readonly<Record<string, unknown>>;\n readonly spacingFactor?: number;\n readonly styleRules?: readonly GraphViewStyleRule[];\n readonly selectedNodeIds?: readonly string[];\n readonly renderNode?: (context: GraphViewNodeRenderContext) => React.ReactNode;\n readonly getNodeSize?: (node: GraphViewNode) => GraphViewSize | undefined;\n readonly fitPadding?: number;\n readonly minZoom?: number;\n readonly maxZoom?: number;\n readonly className?: string;\n readonly style?: React.CSSProperties;\n readonly ariaLabel?: string;\n readonly onReady?: (controller: GraphViewController) => void;\n readonly onLayoutComplete?: (controller: GraphViewController) => void;\n readonly onNodeEvent?: (event: GraphViewElementEvent) => void;\n readonly onEdgeEvent?: (event: GraphViewElementEvent) => void;\n readonly onViewportChange?: (viewport: GraphViewViewport) => void;\n}\n\nexport type GraphViewCallbacks = Pick<\n GraphViewProps,\n 'onEdgeEvent' | 'onLayoutComplete' | 'onNodeEvent' | 'onReady' | 'onViewportChange'\n>;\n\ntype GraphContainer = NonNullable<CytoscapeOptions['container']>;\n\n/*** Render a browser graph while one runtime owns Cytoscape layout, viewport, and disposal. */\nexport function GraphView(props: GraphViewProps) {\n const { containerRef, renderedNodes, runtimeRef } = useGraphViewRuntime(props);\n\n return (\n <div\n aria-label={props.ariaLabel ?? 'Graph'}\n className={props.className}\n role=\"application\"\n style={{\n height: '100%',\n minHeight: 0,\n minWidth: 0,\n position: 'relative',\n width: '100%',\n ...props.style,\n }}\n >\n <div ref={containerRef} style={{ height: '100%', width: '100%' }} />\n {props.renderNode ? (\n <GraphNodeOverlay\n nodes={props.nodes}\n renderedNodes={renderedNodes}\n renderNode={props.renderNode}\n onNodeEvent={(id, type) => runtimeRef.current?.handleOverlayNodeEvent(id, type)}\n onNodeSize={(id, size) => runtimeRef.current?.setNodeSize(id, size)}\n />\n ) : null}\n </div>\n );\n}\n\n/*** Compose React synchronization around the single imperative graph runtime. */\nfunction useGraphViewRuntime(props: GraphViewProps) {\n const containerRef = React.useRef<GraphContainer | null>(null);\n const runtimeRef = React.useRef<GraphRuntime | null>(null);\n const callbacksRef = useGraphCallbacksRef(props);\n const [renderedNodes, setRenderedNodes] = React.useState<readonly GraphViewRenderedNode[]>([]);\n\n useRuntimeLifecycle(containerRef, runtimeRef, callbacksRef);\n useRuntimeGraphUpdate(runtimeRef, props);\n useRuntimeSelection(runtimeRef, props.selectedNodeIds);\n useRenderedNodeSubscription(runtimeRef, props.renderNode, setRenderedNodes);\n useKnownNodeSizes(runtimeRef, props.nodes, props.getNodeSize);\n\n return { containerRef, renderedNodes, runtimeRef };\n}\n\n/*** Keep the callback ref current without mutating refs during render. */\nfunction useGraphCallbacksRef(props: GraphViewProps) {\n const callbacksRef = React.useRef<GraphViewCallbacks>(readCallbacks(props));\n const { onEdgeEvent, onLayoutComplete, onNodeEvent, onReady, onViewportChange } = props;\n\n React.useEffect(() => {\n callbacksRef.current = {\n onEdgeEvent,\n onLayoutComplete,\n onNodeEvent,\n onReady,\n onViewportChange,\n };\n }, [onEdgeEvent, onLayoutComplete, onNodeEvent, onReady, onViewportChange]);\n\n return callbacksRef;\n}\n\n/*** Create and dispose the runtime only with the underlying browser container lifetime. */\nfunction useRuntimeLifecycle(\n containerRef: { current: GraphContainer | null },\n runtimeRef: { current: GraphRuntime | null },\n callbacksRef: { current: GraphViewCallbacks },\n) {\n React.useEffect(() => {\n const container = containerRef.current;\n if (container === null) return;\n const runtime = createGraphRuntime(container, callbacksRef);\n runtimeRef.current = runtime;\n return () => {\n runtime.destroy();\n runtimeRef.current = null;\n };\n }, [callbacksRef, containerRef, runtimeRef]);\n}\n\n/*** Synchronize graph data and layout policy without exposing Cytoscape to React. */\nfunction useRuntimeGraphUpdate(\n runtimeRef: { current: GraphRuntime | null },\n props: GraphViewProps,\n) {\n const {\n edges,\n fitPadding,\n layout,\n layoutOptions,\n maxZoom,\n minZoom,\n nodes,\n renderNode,\n spacingFactor,\n styleRules,\n } = props;\n\n React.useEffect(() => {\n runtimeRef.current?.update({\n edges,\n fitPadding,\n layout,\n layoutOptions,\n maxZoom,\n minZoom,\n nodes,\n richNodeRendering: renderNode !== undefined,\n spacingFactor,\n styleRules,\n });\n }, [\n edges,\n fitPadding,\n layout,\n layoutOptions,\n maxZoom,\n minZoom,\n nodes,\n renderNode,\n runtimeRef,\n spacingFactor,\n styleRules,\n ]);\n}\n\n/*** Synchronize optional controlled selection independently from graph layout. */\nfunction useRuntimeSelection(\n runtimeRef: { current: GraphRuntime | null },\n selectedNodeIds: readonly string[] | undefined,\n) {\n React.useEffect(() => {\n runtimeRef.current?.setSelectedNodeIds(selectedNodeIds);\n }, [runtimeRef, selectedNodeIds]);\n}\n\n/*** Subscribe the optional rich-node overlay to rendered runtime positions. */\nfunction useRenderedNodeSubscription(\n runtimeRef: { current: GraphRuntime | null },\n renderNode: GraphViewProps['renderNode'],\n setRenderedNodes: (nodes: readonly GraphViewRenderedNode[]) => void,\n) {\n React.useEffect(() => {\n const runtime = runtimeRef.current;\n if (runtime === null || renderNode === undefined) {\n setRenderedNodes([]);\n return;\n }\n return runtime.subscribeRenderedNodes(setRenderedNodes);\n }, [renderNode, runtimeRef, setRenderedNodes]);\n}\n\n/*** Seed known rich-node dimensions without requiring DOM measurement. */\nfunction useKnownNodeSizes(\n runtimeRef: { current: GraphRuntime | null },\n nodes: readonly GraphViewNode[],\n getNodeSize: GraphViewProps['getNodeSize'],\n) {\n React.useEffect(() => {\n const runtime = runtimeRef.current;\n if (runtime === null || getNodeSize === undefined) return;\n for (const node of nodes) {\n const size = getNodeSize(node);\n if (size) runtime.setNodeSize(node.id, size);\n }\n }, [getNodeSize, nodes, runtimeRef]);\n}\n\n/*** Read callback props for the initial runtime callback-ref value. */\nfunction readCallbacks(props: GraphViewProps): GraphViewCallbacks {\n return {\n onEdgeEvent: props.onEdgeEvent,\n onLayoutComplete: props.onLayoutComplete,\n onNodeEvent: props.onNodeEvent,\n onReady: props.onReady,\n onViewportChange: props.onViewportChange,\n };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import cytoscape, {} from 'cytoscape';
2
- import elk from 'cytoscape-elk';
2
+ import elk from 'cytoscape-elk/src/index.js';
3
3
  import { bindGraphEvents } from './bindGraphEvents';
4
4
  import { createGraphController } from './createGraphController';
5
5
  import { createGraphResizeObserver } from './createGraphResizeObserver';
@@ -1 +1 @@
1
- {"version":3,"file":"createGraphRuntime.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import cytoscape, { type Core, type CytoscapeOptions } from 'cytoscape';\nimport elk from 'cytoscape-elk';\n\nimport { bindGraphEvents } from './bindGraphEvents';\nimport { createGraphController } from './createGraphController';\nimport { createGraphResizeObserver, type GraphResizeObserver } from './createGraphResizeObserver';\nimport { fitGraphViewport } from './fitGraphViewport';\nimport type {\n GraphViewCallbacks,\n GraphViewEdge,\n GraphViewElementEventType,\n GraphViewLayoutName,\n GraphViewNode,\n GraphViewRenderedNode,\n GraphViewSize,\n GraphViewStyleRule,\n} from './GraphView';\nimport { readGraphRenderedNodes } from './readGraphRenderedNodes';\nimport { runGraphLayout } from './runGraphLayout';\nimport { scheduleGraphFrame } from './scheduleGraphFrame';\nimport { syncGraphElements } from './syncGraphElements';\n\ncytoscape.use(elk as cytoscape.Ext);\n\ntype GraphContainer = NonNullable<CytoscapeOptions['container']>;\ntype RenderedNodeListener = (nodes: readonly GraphViewRenderedNode[]) => void;\n\ninterface GraphRuntimeUpdate {\n readonly edges: readonly GraphViewEdge[];\n readonly fitPadding?: number;\n readonly layout?: GraphViewLayoutName;\n readonly layoutOptions?: Readonly<Record<string, unknown>>;\n readonly maxZoom?: number;\n readonly minZoom?: number;\n readonly nodes: readonly GraphViewNode[];\n readonly richNodeRendering: boolean;\n readonly spacingFactor?: number;\n readonly styleRules?: readonly GraphViewStyleRule[];\n}\n\nexport interface GraphRuntime {\n destroy(): void;\n handleOverlayNodeEvent(id: string, type: GraphViewElementEventType): void;\n setNodeSize(id: string, size: GraphViewSize): void;\n setSelectedNodeIds(nodeIds: readonly string[] | undefined): void;\n subscribeRenderedNodes(listener: RenderedNodeListener): () => void;\n update(input: GraphRuntimeUpdate): void;\n}\n\ninterface GraphRuntimeState {\n readonly callbacksRef: { current: GraphViewCallbacks };\n readonly controller: ReturnType<typeof createGraphController>;\n readonly cy: Core;\n readonly fitPaddingRef: { current: number };\n readonly generationRef: { current: number };\n readonly hoveredNodeIds: Set<string>;\n readonly latestUpdateRef: { current: GraphRuntimeUpdate | null };\n readonly layoutRef: { current: ReturnType<typeof runGraphLayout> | null };\n readonly layoutRunningRef: { current: boolean };\n readonly nodeSizes: Map<string, GraphViewSize>;\n readonly readyRef: { current: boolean };\n readonly relayoutScheduledRef: { current: boolean };\n readonly renderedNodeListeners: Set<RenderedNodeListener>;\n readonly resizeObserver: GraphResizeObserver | null;\n readonly unbindEvents: () => void;\n}\n\n/*** Create one Cytoscape runtime that exclusively owns layout, fit, resize, and disposal. */\nexport function createGraphRuntime(\n container: GraphContainer,\n callbacksRef: { current: GraphViewCallbacks },\n): GraphRuntime {\n const cy = cytoscape({\n container,\n elements: [],\n minZoom: 0.05,\n maxZoom: 2,\n selectionType: 'additive',\n userPanningEnabled: true,\n });\n const state = createRuntimeState(cy, container, callbacksRef);\n\n return {\n destroy: () => destroyRuntime(state),\n handleOverlayNodeEvent: (id, type) => handleOverlayNodeEvent(state, id, type),\n setNodeSize: (id, size) => setNodeSize(state, id, size),\n setSelectedNodeIds: (nodeIds) => setSelectedNodeIds(state, nodeIds),\n subscribeRenderedNodes: (listener) => subscribeRenderedNodes(state, listener),\n update: (input) => updateRuntime(state, input),\n };\n}\n\n/*** Build the mutable state shared by the single graph-runtime owner. */\nfunction createRuntimeState(\n cy: Core,\n container: GraphContainer,\n callbacksRef: { current: GraphViewCallbacks },\n): GraphRuntimeState {\n const fitPaddingRef = { current: 50 };\n const controller = createGraphController(cy, fitPaddingRef);\n const layoutRunningRef = { current: false };\n const readyRef = { current: false };\n const renderedNodeListeners = new Set<RenderedNodeListener>();\n const stateBase = {\n callbacksRef,\n controller,\n cy,\n fitPaddingRef,\n generationRef: { current: 0 },\n hoveredNodeIds: new Set<string>(),\n latestUpdateRef: { current: null as GraphRuntimeUpdate | null },\n layoutRef: { current: null as ReturnType<typeof runGraphLayout> | null },\n layoutRunningRef,\n nodeSizes: new Map<string, GraphViewSize>(),\n readyRef,\n relayoutScheduledRef: { current: false },\n renderedNodeListeners,\n };\n const unbindEvents = bindGraphEvents(cy, callbacksRef, controller, () =>\n emitRenderedNodes(stateBase),\n );\n const resizeObserver = createGraphResizeObserver({\n container,\n cy,\n fitPaddingRef,\n layoutRunningRef,\n onViewportSettled: () => emitRenderedNodes(stateBase),\n readyRef,\n });\n\n return { ...stateBase, resizeObserver, unbindEvents };\n}\n\n/*** Apply one graph update and start exactly one new layout generation. */\nfunction updateRuntime(state: GraphRuntimeState, input: GraphRuntimeUpdate) {\n if (state.cy.destroyed()) return;\n stopCurrentLayout(state);\n state.latestUpdateRef.current = input;\n state.fitPaddingRef.current = input.fitPadding ?? 50;\n state.cy.minZoom(input.minZoom ?? 0.05);\n state.cy.maxZoom(input.maxZoom ?? 2);\n syncGraphElements(state.cy, input.nodes, input.edges);\n applyGraphStyles(state.cy, input.styleRules, input.richNodeRendering);\n applyKnownNodeSizes(state);\n startCurrentLayout(state, input);\n}\n\n/*** Start a generation-safe layout whose completion is the only normal automatic fit trigger. */\nfunction startCurrentLayout(state: GraphRuntimeState, input: GraphRuntimeUpdate) {\n const generation = state.generationRef.current + 1;\n state.generationRef.current = generation;\n state.layoutRunningRef.current = true;\n state.cy.resize();\n state.layoutRef.current = runGraphLayout(\n state.cy,\n {\n layout: input.layout ?? 'concentric',\n layoutOptions: input.layoutOptions,\n spacingFactor: input.spacingFactor ?? 1,\n },\n () => completeCurrentLayout(state, generation),\n );\n}\n\n/*** Settle only the latest layout generation and fit once from node bounds. */\nfunction completeCurrentLayout(state: GraphRuntimeState, generation: number) {\n state.layoutRef.current = null;\n scheduleGraphFrame(() => {\n if (state.cy.destroyed() || generation !== state.generationRef.current) return;\n state.cy.resize();\n state.layoutRunningRef.current = false;\n if (!hasUsableViewport(state.cy)) return;\n fitGraphViewport(state.cy, { padding: state.fitPaddingRef.current });\n emitRenderedNodes(state);\n\n if (!state.readyRef.current) {\n state.readyRef.current = true;\n state.callbacksRef.current.onReady?.(state.controller);\n }\n state.callbacksRef.current.onLayoutComplete?.(state.controller);\n });\n}\n\n/*** Stop the current layout and invalidate every stale completion callback. */\nfunction stopCurrentLayout(state: GraphRuntimeState) {\n state.generationRef.current += 1;\n state.layoutRunningRef.current = false;\n state.layoutRef.current?.stop();\n state.layoutRef.current = null;\n}\n\n/*** Apply consumer styles and hide native node paint only when React rich nodes are active. */\nfunction applyGraphStyles(\n cy: Core,\n rules: readonly GraphViewStyleRule[] | undefined,\n richNodeRendering: boolean,\n) {\n const styles = [...(rules ?? [])];\n if (richNodeRendering) {\n styles.push({\n selector: 'node',\n style: {\n 'background-opacity': 0,\n 'border-width': 0,\n label: '',\n 'overlay-opacity': 0,\n },\n });\n }\n if (styles.length > 0) cy.style(styles).update();\n}\n\n/*** Synchronize controlled selection without rerunning layout. */\nfunction setSelectedNodeIds(state: GraphRuntimeState, nodeIds: readonly string[] | undefined) {\n if (state.cy.destroyed() || nodeIds === undefined) return;\n const selectedIds = new Set(nodeIds);\n state.cy.nodes().forEach((node) => {\n if (selectedIds.has(node.id())) node.select();\n else node.unselect();\n });\n emitRenderedNodes(state);\n}\n\n/*** Persist one rich-node size and schedule at most one relayout for changed geometry. */\nfunction setNodeSize(state: GraphRuntimeState, id: string, size: GraphViewSize) {\n const previous = state.nodeSizes.get(id);\n if (previous?.width === size.width && previous.height === size.height) return;\n state.nodeSizes.set(id, size);\n applyNodeSize(state.cy, id, size);\n scheduleMeasuredNodeRelayout(state);\n}\n\n/*** Apply every known rich-node size after Cytoscape elements are replaced. */\nfunction applyKnownNodeSizes(state: GraphRuntimeState) {\n for (const [id, size] of state.nodeSizes) applyNodeSize(state.cy, id, size);\n}\n\n/*** Apply one measured model-space size as a Cytoscape per-node style bypass. */\nfunction applyNodeSize(cy: Core, id: string, size: GraphViewSize) {\n const node = cy.getElementById(id);\n if (node.empty()) return;\n node.style({ height: size.height, width: size.width });\n}\n\n/*** Coalesce DOM measurements into one follow-up layout generation. */\nfunction scheduleMeasuredNodeRelayout(state: GraphRuntimeState) {\n if (state.relayoutScheduledRef.current) return;\n state.relayoutScheduledRef.current = true;\n scheduleGraphFrame(() => {\n state.relayoutScheduledRef.current = false;\n const input = state.latestUpdateRef.current;\n if (input === null || state.cy.destroyed()) return;\n stopCurrentLayout(state);\n startCurrentLayout(state, input);\n });\n}\n\n/*** Subscribe one React overlay to rendered node state without exposing the Cytoscape core. */\nfunction subscribeRenderedNodes(state: GraphRuntimeState, listener: RenderedNodeListener) {\n state.renderedNodeListeners.add(listener);\n listener(readGraphRenderedNodes(state.cy, state.hoveredNodeIds));\n return () => {\n state.renderedNodeListeners.delete(listener);\n };\n}\n\n/*** Publish current rendered node positions only to active rich-node subscribers. */\nfunction emitRenderedNodes(\n state: Pick<GraphRuntimeState, 'cy' | 'hoveredNodeIds' | 'renderedNodeListeners'>,\n) {\n if (state.renderedNodeListeners.size === 0) return;\n const nodes = readGraphRenderedNodes(state.cy, state.hoveredNodeIds);\n for (const listener of state.renderedNodeListeners) listener(nodes);\n}\n\n/*** Translate one rich-overlay event back into normal graph selection and callbacks. */\nfunction handleOverlayNodeEvent(\n state: GraphRuntimeState,\n id: string,\n type: GraphViewElementEventType,\n) {\n if (type === 'pointer-enter') state.hoveredNodeIds.add(id);\n if (type === 'pointer-leave') state.hoveredNodeIds.delete(id);\n if (type === 'press') state.cy.getElementById(id).select();\n state.callbacksRef.current.onNodeEvent?.({ id, type });\n emitRenderedNodes(state);\n}\n\n/*** Return whether Cytoscape currently has dimensions suitable for fitting. */\nfunction hasUsableViewport(cy: Core): boolean {\n return cy.width() > 0 && cy.height() > 0;\n}\n\n/*** Dispose all runtime resources in the reverse order they were acquired. */\nfunction destroyRuntime(state: GraphRuntimeState) {\n state.resizeObserver?.disconnect();\n stopCurrentLayout(state);\n state.unbindEvents();\n state.renderedNodeListeners.clear();\n if (!state.cy.destroyed()) state.cy.destroy();\n}\n"]}
1
+ {"version":3,"file":"createGraphRuntime.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import cytoscape, { type Core, type CytoscapeOptions } from 'cytoscape';\nimport elk from 'cytoscape-elk/src/index.js';\n\nimport { bindGraphEvents } from './bindGraphEvents';\nimport { createGraphController } from './createGraphController';\nimport { createGraphResizeObserver, type GraphResizeObserver } from './createGraphResizeObserver';\nimport { fitGraphViewport } from './fitGraphViewport';\nimport type {\n GraphViewCallbacks,\n GraphViewEdge,\n GraphViewElementEventType,\n GraphViewLayoutName,\n GraphViewNode,\n GraphViewRenderedNode,\n GraphViewSize,\n GraphViewStyleRule,\n} from './GraphView';\nimport { readGraphRenderedNodes } from './readGraphRenderedNodes';\nimport { runGraphLayout } from './runGraphLayout';\nimport { scheduleGraphFrame } from './scheduleGraphFrame';\nimport { syncGraphElements } from './syncGraphElements';\n\ncytoscape.use(elk as cytoscape.Ext);\n\ntype GraphContainer = NonNullable<CytoscapeOptions['container']>;\ntype RenderedNodeListener = (nodes: readonly GraphViewRenderedNode[]) => void;\n\ninterface GraphRuntimeUpdate {\n readonly edges: readonly GraphViewEdge[];\n readonly fitPadding?: number;\n readonly layout?: GraphViewLayoutName;\n readonly layoutOptions?: Readonly<Record<string, unknown>>;\n readonly maxZoom?: number;\n readonly minZoom?: number;\n readonly nodes: readonly GraphViewNode[];\n readonly richNodeRendering: boolean;\n readonly spacingFactor?: number;\n readonly styleRules?: readonly GraphViewStyleRule[];\n}\n\nexport interface GraphRuntime {\n destroy(): void;\n handleOverlayNodeEvent(id: string, type: GraphViewElementEventType): void;\n setNodeSize(id: string, size: GraphViewSize): void;\n setSelectedNodeIds(nodeIds: readonly string[] | undefined): void;\n subscribeRenderedNodes(listener: RenderedNodeListener): () => void;\n update(input: GraphRuntimeUpdate): void;\n}\n\ninterface GraphRuntimeState {\n readonly callbacksRef: { current: GraphViewCallbacks };\n readonly controller: ReturnType<typeof createGraphController>;\n readonly cy: Core;\n readonly fitPaddingRef: { current: number };\n readonly generationRef: { current: number };\n readonly hoveredNodeIds: Set<string>;\n readonly latestUpdateRef: { current: GraphRuntimeUpdate | null };\n readonly layoutRef: { current: ReturnType<typeof runGraphLayout> | null };\n readonly layoutRunningRef: { current: boolean };\n readonly nodeSizes: Map<string, GraphViewSize>;\n readonly readyRef: { current: boolean };\n readonly relayoutScheduledRef: { current: boolean };\n readonly renderedNodeListeners: Set<RenderedNodeListener>;\n readonly resizeObserver: GraphResizeObserver | null;\n readonly unbindEvents: () => void;\n}\n\n/*** Create one Cytoscape runtime that exclusively owns layout, fit, resize, and disposal. */\nexport function createGraphRuntime(\n container: GraphContainer,\n callbacksRef: { current: GraphViewCallbacks },\n): GraphRuntime {\n const cy = cytoscape({\n container,\n elements: [],\n minZoom: 0.05,\n maxZoom: 2,\n selectionType: 'additive',\n userPanningEnabled: true,\n });\n const state = createRuntimeState(cy, container, callbacksRef);\n\n return {\n destroy: () => destroyRuntime(state),\n handleOverlayNodeEvent: (id, type) => handleOverlayNodeEvent(state, id, type),\n setNodeSize: (id, size) => setNodeSize(state, id, size),\n setSelectedNodeIds: (nodeIds) => setSelectedNodeIds(state, nodeIds),\n subscribeRenderedNodes: (listener) => subscribeRenderedNodes(state, listener),\n update: (input) => updateRuntime(state, input),\n };\n}\n\n/*** Build the mutable state shared by the single graph-runtime owner. */\nfunction createRuntimeState(\n cy: Core,\n container: GraphContainer,\n callbacksRef: { current: GraphViewCallbacks },\n): GraphRuntimeState {\n const fitPaddingRef = { current: 50 };\n const controller = createGraphController(cy, fitPaddingRef);\n const layoutRunningRef = { current: false };\n const readyRef = { current: false };\n const renderedNodeListeners = new Set<RenderedNodeListener>();\n const stateBase = {\n callbacksRef,\n controller,\n cy,\n fitPaddingRef,\n generationRef: { current: 0 },\n hoveredNodeIds: new Set<string>(),\n latestUpdateRef: { current: null as GraphRuntimeUpdate | null },\n layoutRef: { current: null as ReturnType<typeof runGraphLayout> | null },\n layoutRunningRef,\n nodeSizes: new Map<string, GraphViewSize>(),\n readyRef,\n relayoutScheduledRef: { current: false },\n renderedNodeListeners,\n };\n const unbindEvents = bindGraphEvents(cy, callbacksRef, controller, () =>\n emitRenderedNodes(stateBase),\n );\n const resizeObserver = createGraphResizeObserver({\n container,\n cy,\n fitPaddingRef,\n layoutRunningRef,\n onViewportSettled: () => emitRenderedNodes(stateBase),\n readyRef,\n });\n\n return { ...stateBase, resizeObserver, unbindEvents };\n}\n\n/*** Apply one graph update and start exactly one new layout generation. */\nfunction updateRuntime(state: GraphRuntimeState, input: GraphRuntimeUpdate) {\n if (state.cy.destroyed()) return;\n stopCurrentLayout(state);\n state.latestUpdateRef.current = input;\n state.fitPaddingRef.current = input.fitPadding ?? 50;\n state.cy.minZoom(input.minZoom ?? 0.05);\n state.cy.maxZoom(input.maxZoom ?? 2);\n syncGraphElements(state.cy, input.nodes, input.edges);\n applyGraphStyles(state.cy, input.styleRules, input.richNodeRendering);\n applyKnownNodeSizes(state);\n startCurrentLayout(state, input);\n}\n\n/*** Start a generation-safe layout whose completion is the only normal automatic fit trigger. */\nfunction startCurrentLayout(state: GraphRuntimeState, input: GraphRuntimeUpdate) {\n const generation = state.generationRef.current + 1;\n state.generationRef.current = generation;\n state.layoutRunningRef.current = true;\n state.cy.resize();\n state.layoutRef.current = runGraphLayout(\n state.cy,\n {\n layout: input.layout ?? 'concentric',\n layoutOptions: input.layoutOptions,\n spacingFactor: input.spacingFactor ?? 1,\n },\n () => completeCurrentLayout(state, generation),\n );\n}\n\n/*** Settle only the latest layout generation and fit once from node bounds. */\nfunction completeCurrentLayout(state: GraphRuntimeState, generation: number) {\n state.layoutRef.current = null;\n scheduleGraphFrame(() => {\n if (state.cy.destroyed() || generation !== state.generationRef.current) return;\n state.cy.resize();\n state.layoutRunningRef.current = false;\n if (!hasUsableViewport(state.cy)) return;\n fitGraphViewport(state.cy, { padding: state.fitPaddingRef.current });\n emitRenderedNodes(state);\n\n if (!state.readyRef.current) {\n state.readyRef.current = true;\n state.callbacksRef.current.onReady?.(state.controller);\n }\n state.callbacksRef.current.onLayoutComplete?.(state.controller);\n });\n}\n\n/*** Stop the current layout and invalidate every stale completion callback. */\nfunction stopCurrentLayout(state: GraphRuntimeState) {\n state.generationRef.current += 1;\n state.layoutRunningRef.current = false;\n state.layoutRef.current?.stop();\n state.layoutRef.current = null;\n}\n\n/*** Apply consumer styles and hide native node paint only when React rich nodes are active. */\nfunction applyGraphStyles(\n cy: Core,\n rules: readonly GraphViewStyleRule[] | undefined,\n richNodeRendering: boolean,\n) {\n const styles = [...(rules ?? [])];\n if (richNodeRendering) {\n styles.push({\n selector: 'node',\n style: {\n 'background-opacity': 0,\n 'border-width': 0,\n label: '',\n 'overlay-opacity': 0,\n },\n });\n }\n if (styles.length > 0) cy.style(styles).update();\n}\n\n/*** Synchronize controlled selection without rerunning layout. */\nfunction setSelectedNodeIds(state: GraphRuntimeState, nodeIds: readonly string[] | undefined) {\n if (state.cy.destroyed() || nodeIds === undefined) return;\n const selectedIds = new Set(nodeIds);\n state.cy.nodes().forEach((node) => {\n if (selectedIds.has(node.id())) node.select();\n else node.unselect();\n });\n emitRenderedNodes(state);\n}\n\n/*** Persist one rich-node size and schedule at most one relayout for changed geometry. */\nfunction setNodeSize(state: GraphRuntimeState, id: string, size: GraphViewSize) {\n const previous = state.nodeSizes.get(id);\n if (previous?.width === size.width && previous.height === size.height) return;\n state.nodeSizes.set(id, size);\n applyNodeSize(state.cy, id, size);\n scheduleMeasuredNodeRelayout(state);\n}\n\n/*** Apply every known rich-node size after Cytoscape elements are replaced. */\nfunction applyKnownNodeSizes(state: GraphRuntimeState) {\n for (const [id, size] of state.nodeSizes) applyNodeSize(state.cy, id, size);\n}\n\n/*** Apply one measured model-space size as a Cytoscape per-node style bypass. */\nfunction applyNodeSize(cy: Core, id: string, size: GraphViewSize) {\n const node = cy.getElementById(id);\n if (node.empty()) return;\n node.style({ height: size.height, width: size.width });\n}\n\n/*** Coalesce DOM measurements into one follow-up layout generation. */\nfunction scheduleMeasuredNodeRelayout(state: GraphRuntimeState) {\n if (state.relayoutScheduledRef.current) return;\n state.relayoutScheduledRef.current = true;\n scheduleGraphFrame(() => {\n state.relayoutScheduledRef.current = false;\n const input = state.latestUpdateRef.current;\n if (input === null || state.cy.destroyed()) return;\n stopCurrentLayout(state);\n startCurrentLayout(state, input);\n });\n}\n\n/*** Subscribe one React overlay to rendered node state without exposing the Cytoscape core. */\nfunction subscribeRenderedNodes(state: GraphRuntimeState, listener: RenderedNodeListener) {\n state.renderedNodeListeners.add(listener);\n listener(readGraphRenderedNodes(state.cy, state.hoveredNodeIds));\n return () => {\n state.renderedNodeListeners.delete(listener);\n };\n}\n\n/*** Publish current rendered node positions only to active rich-node subscribers. */\nfunction emitRenderedNodes(\n state: Pick<GraphRuntimeState, 'cy' | 'hoveredNodeIds' | 'renderedNodeListeners'>,\n) {\n if (state.renderedNodeListeners.size === 0) return;\n const nodes = readGraphRenderedNodes(state.cy, state.hoveredNodeIds);\n for (const listener of state.renderedNodeListeners) listener(nodes);\n}\n\n/*** Translate one rich-overlay event back into normal graph selection and callbacks. */\nfunction handleOverlayNodeEvent(\n state: GraphRuntimeState,\n id: string,\n type: GraphViewElementEventType,\n) {\n if (type === 'pointer-enter') state.hoveredNodeIds.add(id);\n if (type === 'pointer-leave') state.hoveredNodeIds.delete(id);\n if (type === 'press') state.cy.getElementById(id).select();\n state.callbacksRef.current.onNodeEvent?.({ id, type });\n emitRenderedNodes(state);\n}\n\n/*** Return whether Cytoscape currently has dimensions suitable for fitting. */\nfunction hasUsableViewport(cy: Core): boolean {\n return cy.width() > 0 && cy.height() > 0;\n}\n\n/*** Dispose all runtime resources in the reverse order they were acquired. */\nfunction destroyRuntime(state: GraphRuntimeState) {\n state.resizeObserver?.disconnect();\n stopCurrentLayout(state);\n state.unbindEvents();\n state.renderedNodeListeners.clear();\n if (!state.cy.destroyed()) state.cy.destroy();\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ankhorage/zora",
3
3
  "type": "module",
4
- "version": "20.2.1",
4
+ "version": "20.2.3",
5
5
  "description": "Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.",
6
6
  "homepage": "https://github.com/ankhorage/zora#readme",
7
7
  "bugs": {
@@ -41,7 +41,7 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@ankhorage/color-theory": "^0.3.1",
44
- "@ankhorage/contracts": "^22.1.0",
44
+ "@ankhorage/contracts": "^22.1.1",
45
45
  "@ankhorage/surface": "^9.0.7",
46
46
  "@ankhorage/utility": "^1.4.0",
47
47
  "expo-document-picker": "~57.0.1",
@@ -1,5 +1,3 @@
1
- 'use client';
2
-
3
1
  import React from 'react';
4
2
 
5
3
  import type {
@@ -1,5 +1,3 @@
1
- 'use client';
2
-
3
1
  import type { CytoscapeOptions } from 'cytoscape';
4
2
  import React from 'react';
5
3
 
@@ -1,5 +1,5 @@
1
1
  import cytoscape, { type Core, type CytoscapeOptions } from 'cytoscape';
2
- import elk from 'cytoscape-elk';
2
+ import elk from 'cytoscape-elk/src/index.js';
3
3
 
4
4
  import { bindGraphEvents } from './bindGraphEvents';
5
5
  import { createGraphController } from './createGraphController';
@@ -1,4 +1,4 @@
1
- declare module 'cytoscape-elk' {
1
+ declare module 'cytoscape-elk/src/index.js' {
2
2
  const extension: unknown;
3
3
  export default extension;
4
4
  }
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  var __create = Object.create;
2
3
  var __getProtoOf = Object.getPrototypeOf;
3
4
  var __defProp = Object.defineProperty;
@@ -91989,277 +91990,6 @@ Consider installing the package or pass your own 'workerFactory' to ELK's constr
91989
91990
  });
91990
91991
  });
91991
91992
 
91992
- // node_modules/cytoscape-elk/dist/cytoscape-elk.js
91993
- var require_cytoscape_elk = __commonJS(function(exports, module) {
91994
- (function webpackUniversalModuleDefinition(root, factory) {
91995
- if (typeof exports === "object" && typeof module === "object")
91996
- module.exports = factory(require_elk_bundled());
91997
- else if (typeof define === "function" && define.amd)
91998
- define(["elkjs"], factory);
91999
- else if (typeof exports === "object")
92000
- exports["cytoscapeElk"] = factory(require_elk_bundled());
92001
- else
92002
- root["cytoscapeElk"] = factory(root["ELK"]);
92003
- })(exports, function(__WEBPACK_EXTERNAL_MODULE__632__) {
92004
- return function() {
92005
- var __webpack_modules__ = {
92006
- 632: function(module2) {
92007
- module2.exports = __WEBPACK_EXTERNAL_MODULE__632__;
92008
- }
92009
- };
92010
- var __webpack_module_cache__ = {};
92011
- function __webpack_require__(moduleId) {
92012
- var cachedModule = __webpack_module_cache__[moduleId];
92013
- if (cachedModule !== undefined) {
92014
- return cachedModule.exports;
92015
- }
92016
- var module2 = __webpack_module_cache__[moduleId] = {
92017
- exports: {}
92018
- };
92019
- __webpack_modules__[moduleId](module2, module2.exports, __webpack_require__);
92020
- return module2.exports;
92021
- }
92022
- (function() {
92023
- __webpack_require__.n = function(module2) {
92024
- var getter = module2 && module2.__esModule ? function() {
92025
- return module2["default"];
92026
- } : function() {
92027
- return module2;
92028
- };
92029
- __webpack_require__.d(getter, { a: getter });
92030
- return getter;
92031
- };
92032
- })();
92033
- (function() {
92034
- __webpack_require__.d = function(exports2, definition) {
92035
- for (var key in definition) {
92036
- if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports2, key)) {
92037
- Object.defineProperty(exports2, key, { enumerable: true, get: definition[key] });
92038
- }
92039
- }
92040
- };
92041
- })();
92042
- (function() {
92043
- __webpack_require__.o = function(obj, prop) {
92044
- return Object.prototype.hasOwnProperty.call(obj, prop);
92045
- };
92046
- })();
92047
- var __webpack_exports__ = {};
92048
- (function() {
92049
- __webpack_require__.d(__webpack_exports__, {
92050
- default: function() {
92051
- return src;
92052
- }
92053
- });
92054
- var elk_bundled_js_amd_elkjs_root_ELK_ = __webpack_require__(632);
92055
- var elk_bundled_js_amd_elkjs_root_ELK_default = /* @__PURE__ */ __webpack_require__.n(elk_bundled_js_amd_elkjs_root_ELK_);
92056
- function assign_assign(tgt) {
92057
- for (var _len = arguments.length, srcs = new Array(_len > 1 ? _len - 1 : 0), _key = 1;_key < _len; _key++) {
92058
- srcs[_key - 1] = arguments[_key];
92059
- }
92060
- srcs.forEach(function(src) {
92061
- Object.keys(src).forEach(function(k) {
92062
- return tgt[k] = src[k];
92063
- });
92064
- });
92065
- return tgt;
92066
- }
92067
- var src_assign = Object.assign != null ? Object.assign.bind(Object) : assign_assign;
92068
- var defaults = {
92069
- nodeDimensionsIncludeLabels: false,
92070
- fit: true,
92071
- padding: 20,
92072
- animate: false,
92073
- animateFilter: function animateFilter() {
92074
- return true;
92075
- },
92076
- animationDuration: 500,
92077
- animationEasing: undefined,
92078
- transform: function transform(node, pos) {
92079
- return pos;
92080
- },
92081
- ready: undefined,
92082
- stop: undefined,
92083
- nodeLayoutOptions: undefined,
92084
- elk: {
92085
- algorithm: undefined
92086
- },
92087
- priority: function priority() {
92088
- return null;
92089
- }
92090
- };
92091
- var src_defaults = defaults;
92092
- function _classCallCheck(instance, Constructor) {
92093
- if (!(instance instanceof Constructor)) {
92094
- throw new TypeError("Cannot call a class as a function");
92095
- }
92096
- }
92097
- function _defineProperties(target, props) {
92098
- for (var i = 0;i < props.length; i++) {
92099
- var descriptor = props[i];
92100
- descriptor.enumerable = descriptor.enumerable || false;
92101
- descriptor.configurable = true;
92102
- if ("value" in descriptor)
92103
- descriptor.writable = true;
92104
- Object.defineProperty(target, descriptor.key, descriptor);
92105
- }
92106
- }
92107
- function _createClass(Constructor, protoProps, staticProps) {
92108
- if (protoProps)
92109
- _defineProperties(Constructor.prototype, protoProps);
92110
- if (staticProps)
92111
- _defineProperties(Constructor, staticProps);
92112
- Object.defineProperty(Constructor, "prototype", { writable: false });
92113
- return Constructor;
92114
- }
92115
- var elkOverrides = {};
92116
- var getPos = function getPos(ele, options) {
92117
- var dims = ele.layoutDimensions(options);
92118
- var parent = ele.parent();
92119
- var k = ele.scratch("elk");
92120
- var p = {
92121
- x: k.x,
92122
- y: k.y
92123
- };
92124
- while (parent.nonempty()) {
92125
- var kp = parent.scratch("elk");
92126
- p.x += kp.x;
92127
- p.y += kp.y;
92128
- parent = parent.parent();
92129
- }
92130
- p.x += dims.w / 2;
92131
- p.y += dims.h / 2;
92132
- return p;
92133
- };
92134
- var makeNode = function makeNode(node, options) {
92135
- var k = {
92136
- _cyEle: node,
92137
- id: node.id()
92138
- };
92139
- if (options.nodeLayoutOptions) {
92140
- k.layoutOptions = options.nodeLayoutOptions(node);
92141
- }
92142
- if (!node.isParent()) {
92143
- var dims = node.layoutDimensions(options);
92144
- var p = node.position();
92145
- k.x = p.x - dims.w / 2;
92146
- k.y = p.y - dims.h / 2;
92147
- k.width = dims.w;
92148
- k.height = dims.h;
92149
- }
92150
- node.scratch("elk", k);
92151
- return k;
92152
- };
92153
- var makeEdge = function makeEdge(edge) {
92154
- var k = {
92155
- _cyEle: edge,
92156
- id: edge.id(),
92157
- source: edge.data("source"),
92158
- target: edge.data("target")
92159
- };
92160
- edge.scratch("elk", k);
92161
- return k;
92162
- };
92163
- var makeGraph = function makeGraph(nodes, edges, options) {
92164
- var elkNodes = [];
92165
- var elkEdges = [];
92166
- var elkEleLookup = {};
92167
- var graph = {
92168
- id: "root",
92169
- children: [],
92170
- edges: []
92171
- };
92172
- for (var i = 0;i < nodes.length; i++) {
92173
- var n = nodes[i];
92174
- var k = makeNode(n, options);
92175
- elkNodes.push(k);
92176
- elkEleLookup[n.id()] = k;
92177
- }
92178
- for (var _i = 0;_i < edges.length; _i++) {
92179
- var e = edges[_i];
92180
- var _k = makeEdge(e, options);
92181
- elkEdges.push(_k);
92182
- elkEleLookup[e.id()] = _k;
92183
- }
92184
- for (var _i2 = 0;_i2 < elkNodes.length; _i2++) {
92185
- var _k2 = elkNodes[_i2];
92186
- var _n = _k2._cyEle;
92187
- if (!_n.isChild()) {
92188
- graph.children.push(_k2);
92189
- } else {
92190
- var parent = _n.parent();
92191
- var parentK = elkEleLookup[parent.id()];
92192
- var children = parentK.children = parentK.children || [];
92193
- children.push(_k2);
92194
- }
92195
- }
92196
- for (var _i3 = 0;_i3 < elkEdges.length; _i3++) {
92197
- var _k3 = elkEdges[_i3];
92198
- graph.edges.push(_k3);
92199
- }
92200
- return graph;
92201
- };
92202
- var Layout = /* @__PURE__ */ function() {
92203
- function Layout(options) {
92204
- _classCallCheck(this, Layout);
92205
- var elkOptions = options.elk;
92206
- var cy = options.cy;
92207
- this.options = src_assign({}, src_defaults, options);
92208
- this.options.elk = src_assign({
92209
- aspectRatio: cy.width() / cy.height()
92210
- }, src_defaults.elk, elkOptions, elkOverrides);
92211
- }
92212
- _createClass(Layout, [{
92213
- key: "run",
92214
- value: function run() {
92215
- var layout = this;
92216
- var options = this.options;
92217
- var eles = options.eles;
92218
- var nodes = eles.nodes();
92219
- var edges = eles.edges();
92220
- var elk = new (elk_bundled_js_amd_elkjs_root_ELK_default());
92221
- var graph = makeGraph(nodes, edges, options);
92222
- graph["layoutOptions"] = options.elk;
92223
- elk.layout(graph).then(function() {
92224
- nodes.filter(function(n) {
92225
- return !n.isParent();
92226
- }).layoutPositions(layout, options, function(n) {
92227
- return getPos(n, options);
92228
- });
92229
- });
92230
- return this;
92231
- }
92232
- }, {
92233
- key: "stop",
92234
- value: function stop() {
92235
- return this;
92236
- }
92237
- }, {
92238
- key: "destroy",
92239
- value: function destroy() {
92240
- return this;
92241
- }
92242
- }]);
92243
- return Layout;
92244
- }();
92245
- var layout = Layout;
92246
- var register = function register(cytoscape2) {
92247
- if (!cytoscape2) {
92248
- return;
92249
- }
92250
- cytoscape2("layout", "elk", layout);
92251
- };
92252
- if (typeof cytoscape !== "undefined") {
92253
- register(cytoscape);
92254
- }
92255
- var src = register;
92256
- })();
92257
- __webpack_exports__ = __webpack_exports__["default"];
92258
- return __webpack_exports__;
92259
- }();
92260
- });
92261
- });
92262
-
92263
91993
  // src/features/graph-view/adapters/inbound/web-artifact/GraphView.tsx
92264
91994
  import React2 from "react";
92265
91995
 
@@ -122622,8 +122352,176 @@ cytoscape2.warnings = function(bool) {
122622
122352
  cytoscape2.version = version;
122623
122353
  cytoscape2.stylesheet = cytoscape2.Stylesheet = _Stylesheet;
122624
122354
 
122625
- // src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.ts
122626
- var import_cytoscape_elk = __toESM(require_cytoscape_elk(), 1);
122355
+ // node_modules/cytoscape-elk/src/layout.js
122356
+ var import_elk_bundled = __toESM(require_elk_bundled());
122357
+
122358
+ // node_modules/cytoscape-elk/src/assign.js
122359
+ function assign2(tgt, ...srcs) {
122360
+ srcs.forEach((src) => {
122361
+ Object.keys(src).forEach((k) => tgt[k] = src[k]);
122362
+ });
122363
+ return tgt;
122364
+ }
122365
+ var assign_default = Object.assign != null ? Object.assign.bind(Object) : assign2;
122366
+
122367
+ // node_modules/cytoscape-elk/src/defaults.js
122368
+ var defaults2 = {
122369
+ nodeDimensionsIncludeLabels: false,
122370
+ fit: true,
122371
+ padding: 20,
122372
+ animate: false,
122373
+ animateFilter: function() {
122374
+ return true;
122375
+ },
122376
+ animationDuration: 500,
122377
+ animationEasing: undefined,
122378
+ transform: function(node, pos) {
122379
+ return pos;
122380
+ },
122381
+ ready: undefined,
122382
+ stop: undefined,
122383
+ nodeLayoutOptions: undefined,
122384
+ elk: {
122385
+ algorithm: undefined
122386
+ },
122387
+ priority: function() {
122388
+ return null;
122389
+ }
122390
+ };
122391
+ var defaults_default = defaults2;
122392
+
122393
+ // node_modules/cytoscape-elk/src/layout.js
122394
+ var elkOverrides = {};
122395
+ var getPos = function(ele, options) {
122396
+ const dims = ele.layoutDimensions(options);
122397
+ let parent = ele.parent();
122398
+ const k = ele.scratch("elk");
122399
+ const p = {
122400
+ x: k.x,
122401
+ y: k.y
122402
+ };
122403
+ while (parent.nonempty()) {
122404
+ const kp = parent.scratch("elk");
122405
+ p.x += kp.x;
122406
+ p.y += kp.y;
122407
+ parent = parent.parent();
122408
+ }
122409
+ p.x += dims.w / 2;
122410
+ p.y += dims.h / 2;
122411
+ return p;
122412
+ };
122413
+ var makeNode = function(node, options) {
122414
+ const k = {
122415
+ _cyEle: node,
122416
+ id: node.id()
122417
+ };
122418
+ if (options.nodeLayoutOptions) {
122419
+ k.layoutOptions = options.nodeLayoutOptions(node);
122420
+ }
122421
+ if (!node.isParent()) {
122422
+ const dims = node.layoutDimensions(options);
122423
+ const p = node.position();
122424
+ k.x = p.x - dims.w / 2;
122425
+ k.y = p.y - dims.h / 2;
122426
+ k.width = dims.w;
122427
+ k.height = dims.h;
122428
+ }
122429
+ node.scratch("elk", k);
122430
+ return k;
122431
+ };
122432
+ var makeEdge = function(edge) {
122433
+ const k = {
122434
+ _cyEle: edge,
122435
+ id: edge.id(),
122436
+ source: edge.data("source"),
122437
+ target: edge.data("target")
122438
+ };
122439
+ edge.scratch("elk", k);
122440
+ return k;
122441
+ };
122442
+ var makeGraph = function(nodes, edges, options) {
122443
+ const elkNodes = [];
122444
+ const elkEdges = [];
122445
+ const elkEleLookup = {};
122446
+ const graph = {
122447
+ id: "root",
122448
+ children: [],
122449
+ edges: []
122450
+ };
122451
+ for (let i = 0;i < nodes.length; i++) {
122452
+ const n = nodes[i];
122453
+ const k = makeNode(n, options);
122454
+ elkNodes.push(k);
122455
+ elkEleLookup[n.id()] = k;
122456
+ }
122457
+ for (let i = 0;i < edges.length; i++) {
122458
+ const e = edges[i];
122459
+ const k = makeEdge(e, options);
122460
+ elkEdges.push(k);
122461
+ elkEleLookup[e.id()] = k;
122462
+ }
122463
+ for (let i = 0;i < elkNodes.length; i++) {
122464
+ const k = elkNodes[i];
122465
+ const n = k._cyEle;
122466
+ if (!n.isChild()) {
122467
+ graph.children.push(k);
122468
+ } else {
122469
+ const parent = n.parent();
122470
+ const parentK = elkEleLookup[parent.id()];
122471
+ const children = parentK.children = parentK.children || [];
122472
+ children.push(k);
122473
+ }
122474
+ }
122475
+ for (let i = 0;i < elkEdges.length; i++) {
122476
+ const k = elkEdges[i];
122477
+ graph.edges.push(k);
122478
+ }
122479
+ return graph;
122480
+ };
122481
+
122482
+ class Layout {
122483
+ constructor(options) {
122484
+ const elkOptions = options.elk;
122485
+ const { cy } = options;
122486
+ this.options = assign_default({}, defaults_default, options);
122487
+ this.options.elk = assign_default({
122488
+ aspectRatio: cy.width() / cy.height()
122489
+ }, defaults_default.elk, elkOptions, elkOverrides);
122490
+ }
122491
+ run() {
122492
+ const layout = this;
122493
+ const { options } = this;
122494
+ const { eles } = options;
122495
+ const nodes = eles.nodes();
122496
+ const edges = eles.edges();
122497
+ const elk = new import_elk_bundled.default;
122498
+ const graph = makeGraph(nodes, edges, options);
122499
+ graph["layoutOptions"] = options.elk;
122500
+ elk.layout(graph).then(() => {
122501
+ nodes.filter((n) => !n.isParent()).layoutPositions(layout, options, (n) => getPos(n, options));
122502
+ });
122503
+ return this;
122504
+ }
122505
+ stop() {
122506
+ return this;
122507
+ }
122508
+ destroy() {
122509
+ return this;
122510
+ }
122511
+ }
122512
+ var layout_default = Layout;
122513
+
122514
+ // node_modules/cytoscape-elk/src/index.js
122515
+ var register = function(cytoscape2) {
122516
+ if (!cytoscape2) {
122517
+ return;
122518
+ }
122519
+ cytoscape2("layout", "elk", layout_default);
122520
+ };
122521
+ if (typeof cytoscape !== "undefined") {
122522
+ register(cytoscape);
122523
+ }
122524
+ var src_default = register;
122627
122525
 
122628
122526
  // src/features/graph-view/adapters/inbound/web-artifact/bindGraphEvents.ts
122629
122527
  function bindGraphEvents(cy, callbacksRef, controller, onRuntimeChange) {
@@ -122878,7 +122776,7 @@ function syncGraphElements(cy, nodes, edges) {
122878
122776
  }
122879
122777
 
122880
122778
  // src/features/graph-view/adapters/inbound/web-artifact/createGraphRuntime.ts
122881
- cytoscape2.use(import_cytoscape_elk.default);
122779
+ cytoscape2.use(src_default);
122882
122780
  function createGraphRuntime(container, callbacksRef) {
122883
122781
  const cy = cytoscape2({
122884
122782
  container,
@@ -123076,7 +122974,6 @@ function destroyRuntime(state) {
123076
122974
  // src/features/graph-view/adapters/inbound/web-artifact/GraphNodeOverlay.tsx
123077
122975
  import React from "react";
123078
122976
  import { jsx } from "react/jsx-runtime";
123079
- "use client";
123080
122977
  function GraphNodeOverlay(props) {
123081
122978
  const nodesById = React.useMemo(() => new Map(props.nodes.map((node) => [node.id, node])), [props.nodes]);
123082
122979
  return /* @__PURE__ */ jsx("div", {
@@ -123158,7 +123055,6 @@ function readResizeObserverConstructor2() {
123158
123055
 
123159
123056
  // src/features/graph-view/adapters/inbound/web-artifact/GraphView.tsx
123160
123057
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
123161
- "use client";
123162
123058
  function GraphView(props) {
123163
123059
  const { containerRef, renderedNodes, runtimeRef } = useGraphViewRuntime(props);
123164
123060
  return /* @__PURE__ */ jsxs("div", {