@ankhorage/zora 27.1.1 → 27.1.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 +12 -0
- package/README.md +1 -1
- package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.d.ts.map +1 -1
- package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.js +4 -2
- package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.js.map +1 -1
- package/dist/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.d.ts.map +1 -1
- package/dist/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.js +2 -1
- package/dist/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.js.map +1 -1
- package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.d.ts +4 -0
- package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.d.ts.map +1 -0
- package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.js +9 -0
- package/dist/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.js.map +1 -0
- package/package.json +2 -2
- package/src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts +4 -2
- package/src/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.ts +2 -1
- package/src/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.test.ts +32 -0
- package/src/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.ts +10 -0
- package/web-dist/chunks/{Accordion-enn0479f.js → Accordion-bfszt9f0.js} +12 -15
- package/web-dist/components/game/Game.js +1 -1
- package/web-dist/components/game-entity/GameEntity.js +1 -1
- package/web-dist/components/game-field/GameField.js +1 -1
- package/web-dist/components/game-input-zone/GameInputZone.js +1 -1
- package/web-dist/components/game-measurement-probe/GameMeasurementProbe.js +1 -1
- package/web-dist/components/game-overlay/GameOverlay.js +1 -1
- package/web-dist/components/graph-view/GraphView.js +13 -3
- package/web-dist/manifest.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 27.1.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 22a1773: Update dependencies: `@ankhorage/runtime`.
|
|
8
|
+
|
|
9
|
+
## 27.1.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 7b77abf: Fit GraphView canvases narrower than the requested padding without clipping rendered nodes.
|
|
14
|
+
|
|
3
15
|
## 27.1.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
# @ankhorage/zora
|
|
5
5
|
|
|
6
|
-
         
|
|
7
7
|
|
|
8
8
|
Opinionated React Native and React Native Web UI kit built on @ankhorage/surface.
|
|
9
9
|
|
package/dist/features/graph-view/adapters/inbound/web-artifact/createGraphController.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createGraphController.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"createGraphController.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EACV,mBAAmB,EACnB,mBAAmB,EAEpB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAIhF,kGAAkG;AAClG,wBAAgB,qBAAqB,CACnC,EAAE,EAAE,IAAI,EACR,aAAa,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EAClC,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,IAAI;;qBAkDjC,kBAAkB;IASnC,6EAA6E;;IAI7E,8FAA8F;;IAI9F,6FAA6F;;gBAIjF,OAAO;EAuBtB"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { fitGraphViewport } from './fitGraphViewport';
|
|
2
|
+
import { getGraphFitPadding } from './getGraphFitPadding';
|
|
2
3
|
/*** Own viewport units and limits alongside the public controller, without exposing Cytoscape. */
|
|
3
4
|
export function createGraphController(cy, fitPaddingRef, optimizeFit) {
|
|
4
5
|
const state = {
|
|
@@ -189,8 +190,9 @@ function getNodeFitZoom(cy, padding) {
|
|
|
189
190
|
if (cy.nodes().empty())
|
|
190
191
|
return 1;
|
|
191
192
|
const bounds = cy.nodes().boundingBox();
|
|
192
|
-
const
|
|
193
|
-
const
|
|
193
|
+
const fitPadding = getGraphFitPadding(cy, padding);
|
|
194
|
+
const width = cy.width() - 2 * fitPadding;
|
|
195
|
+
const height = cy.height() - 2 * fitPadding;
|
|
194
196
|
if (width <= 0 || height <= 0 || bounds.w <= 0 || bounds.h <= 0)
|
|
195
197
|
return 1;
|
|
196
198
|
return Math.min(width / bounds.w, height / bounds.h);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createGraphController.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Core } from 'cytoscape';\n\nimport type {\n GraphViewController,\n GraphViewFitOptions,\n GraphViewMeasurement,\n} from '../../../../../types/graph-view';\nimport type { GraphRuntimeUpdate } from '../../../../../types/graphViewRuntime';\nimport { fitGraphViewport } from './fitGraphViewport';\n\n/*** Own viewport units and limits alongside the public controller, without exposing Cytoscape. */\nexport function createGraphController(\n cy: Core,\n fitPaddingRef: { current: number },\n optimizeFit?: (options: GraphViewFitOptions) => void,\n) {\n const state = {\n scale: 1,\n relative: false,\n min: 0.05,\n max: 2,\n readableSize: 0,\n fitSize: Infinity,\n readableZoom: 0,\n fitZoom: Infinity,\n resizeSnapshot: null as GraphResizeSnapshot | null,\n };\n const controller: GraphViewController = {\n fit(options) {\n if (options?.optimizeSpacing && !options.nodeIds?.length && optimizeFit) {\n optimizeFit(options);\n return;\n }\n fitGraphViewport(\n cy,\n {\n nodeIds: options?.nodeIds,\n padding: options?.padding ?? fitPaddingRef.current,\n },\n state.fitZoom,\n );\n },\n measureNodes(nodeIds) {\n return measureRenderedNodes(cy, nodeIds);\n },\n getViewport() {\n return { pan: cy.pan(), zoom: cy.zoom() / state.scale };\n },\n getZoomRange() {\n return { min: cy.minZoom() / state.scale, max: cy.maxZoom() / state.scale };\n },\n setPan(pan) {\n cy.pan(pan);\n },\n setZoom(zoom) {\n setCenteredZoom(cy, zoom * state.scale);\n },\n zoomBy(factor) {\n setCenteredZoom(cy, cy.zoom() * factor);\n },\n };\n\n return {\n controller,\n configure(input: GraphRuntimeUpdate) {\n state.relative = input.zoomMode === 'fit-relative';\n state.min = input.minZoom ?? 0.05;\n state.max = input.maxZoom ?? 2;\n state.readableSize = positiveSize(input.minReadableLabelSize, 0);\n state.fitSize = positiveSize(input.maxFitLabelSize, Infinity);\n if (!state.relative) state.scale = 1;\n applyZoomLimits(cy, state);\n },\n /*** Return the native automatic-fit ceiling used by spacing optimization. */\n getFitZoomLimit() {\n return state.relative ? state.fitZoom : Math.min(state.fitZoom, state.max);\n },\n /*** Return the native label-readability threshold used before allowing background overlap. */\n getReadableZoomTarget() {\n return state.readableZoom;\n },\n /*** Capture the model point beneath the current viewport center before Cytoscape resizes. */\n beginResize() {\n state.resizeSnapshot = captureResizeSnapshot(cy);\n },\n settle(fit: boolean) {\n const logicalZoom = cy.zoom() / state.scale;\n const fonts = cy\n .nodes()\n .filter((node) => !node.isParent() && Boolean(node.style('label')))\n .map((node) => Number.parseFloat(String(node.style('font-size'))))\n .filter((size) => Number.isFinite(size) && size > 0);\n state.readableZoom = fonts.length\n ? state.readableSize / fonts.reduce((minimum, size) => Math.min(minimum, size), Infinity)\n : 0;\n state.fitZoom = fonts.length\n ? state.fitSize / fonts.reduce((maximum, size) => Math.max(maximum, size), 0)\n : Infinity;\n state.scale = state.relative\n ? Math.min(getNodeFitZoom(cy, fitPaddingRef.current), state.fitZoom)\n : 1;\n applyZoomLimits(cy, state);\n if (fit) {\n state.resizeSnapshot = null;\n controller.fit();\n } else if (settlePreservedViewport(cy, state, logicalZoom)) controller.fit();\n },\n };\n}\n\ninterface GraphResizeSnapshot {\n readonly center: { readonly x: number; readonly y: number };\n readonly nodeBounds: GraphNodeBoundsStatus;\n}\n\ntype GraphNodeBoundsStatus = 'clipped' | 'empty' | 'fit' | 'unusable';\n\n/*** Capture the model-space center and whether the prior viewport was an intact graph fit. */\nfunction captureResizeSnapshot(cy: Core): GraphResizeSnapshot | null {\n const viewport = { width: cy.width(), height: cy.height() };\n const zoom = cy.zoom();\n if (!isUsableViewport(viewport) || !Number.isFinite(zoom) || zoom <= 0) return null;\n const pan = cy.pan();\n const renderedCenter = { x: viewport.width / 2, y: viewport.height / 2 };\n return {\n center: {\n x: (renderedCenter.x - pan.x) / zoom,\n y: (renderedCenter.y - pan.y) / zoom,\n },\n nodeBounds: getNodeBoundsStatus(cy, viewport),\n };\n}\n\n/*** Preserve a manual viewport through resize, fitting only when an intact prior fit becomes invalid. */\nfunction settlePreservedViewport(\n cy: Core,\n state: {\n readonly relative: boolean;\n resizeSnapshot: GraphResizeSnapshot | null;\n readonly scale: number;\n },\n logicalZoom: number,\n): boolean {\n const snapshot = state.resizeSnapshot;\n state.resizeSnapshot = null;\n const zoom = state.relative ? logicalZoom * state.scale : cy.zoom();\n if (snapshot === null) {\n if (state.relative) setCenteredZoom(cy, zoom);\n return false;\n }\n const viewport = { width: cy.width(), height: cy.height() };\n if (!isUsableViewport(viewport)) return false;\n cy.viewport({\n zoom,\n pan: {\n x: viewport.width / 2 - snapshot.center.x * zoom,\n y: viewport.height / 2 - snapshot.center.y * zoom,\n },\n });\n const nodeBounds = getNodeBoundsStatus(cy, viewport);\n return nodeBounds === 'unusable' || (snapshot.nodeBounds === 'fit' && nodeBounds === 'clipped');\n}\n\n/*** Accept only finite non-empty node bounds that are wholly visible in a usable viewport. */\nfunction getNodeBoundsStatus(\n cy: Core,\n viewport: { readonly width: number; readonly height: number },\n): GraphNodeBoundsStatus {\n if (cy.nodes().empty()) return 'empty';\n if (!isUsableViewport(viewport)) return 'unusable';\n const bounds = cy.nodes().renderedBoundingBox();\n if (![bounds.x1, bounds.x2, bounds.y1, bounds.y2].every(Number.isFinite)) return 'unusable';\n const fitsHorizontally = bounds.x1 >= 0 && bounds.x2 <= viewport.width;\n const fitsVertically = bounds.y1 >= 0 && bounds.y2 <= viewport.height;\n return fitsHorizontally && fitsVertically ? 'fit' : 'clipped';\n}\n\n/*** Reject zero, negative, and non-finite renderer dimensions before viewport arithmetic. */\nfunction isUsableViewport(viewport: { readonly width: number; readonly height: number }): boolean {\n return (\n Number.isFinite(viewport.width) &&\n Number.isFinite(viewport.height) &&\n viewport.width > 0 &&\n viewport.height > 0\n );\n}\n\n/*** Measure rendered node hit geometry without exposing paint-only outlines or Cytoscape. */\nfunction measureRenderedNodes(cy: Core, nodeIds: readonly string[]): GraphViewMeasurement | null {\n const viewport = { width: cy.width(), height: cy.height() };\n if (viewport.width <= 0 || viewport.height <= 0 || nodeIds.length === 0) return null;\n\n const nodes = [...new Set(nodeIds)].flatMap((id) => {\n const node = cy.getElementById(id);\n if (!node.isNode()) return [];\n\n return [\n {\n id,\n position: node.renderedPosition(),\n size: { width: node.renderedOuterWidth(), height: node.renderedOuterHeight() },\n },\n ];\n });\n return nodes.length === 0 ? null : { nodes, viewport };\n}\n\n/*** Keep pointer, wheel, and programmatic zoom on the same limits in the engine's native units. */\nfunction applyZoomLimits(\n cy: Core,\n state: {\n readonly min: number;\n readonly max: number;\n readonly scale: number;\n readonly readableZoom: number;\n },\n) {\n const min = state.min * state.scale;\n cy.minZoom(Math.min(cy.minZoom(), min));\n cy.maxZoom(Math.max(min, state.max * state.scale, state.readableZoom));\n cy.minZoom(min);\n}\n\n/*** Ignore invalid optional typography targets at the public configuration boundary. */\nfunction positiveSize(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/***\n * Recompute the fit reference only after layout or resize, never on every pan/zoom event.\n * Cache the geometry-derived scale in the viewport owner; labels are included, edges excluded.\n */\nfunction getNodeFitZoom(cy: Core, padding: number): number {\n if (cy.nodes().empty()) return 1;\n const bounds = cy.nodes().boundingBox();\n const width = cy.width() - 2 * padding;\n const height = cy.height() - 2 * padding;\n if (width <= 0 || height <= 0 || bounds.w <= 0 || bounds.h <= 0) return 1;\n return Math.min(width / bounds.w, height / bounds.h);\n}\n\n/*** Zoom around the visible viewport center instead of its top-left corner. */\nfunction setCenteredZoom(cy: Core, zoom: number) {\n cy.zoom({ level: zoom, renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 } });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"createGraphController.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/createGraphController.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Core } from 'cytoscape';\n\nimport type {\n GraphViewController,\n GraphViewFitOptions,\n GraphViewMeasurement,\n} from '../../../../../types/graph-view';\nimport type { GraphRuntimeUpdate } from '../../../../../types/graphViewRuntime';\nimport { fitGraphViewport } from './fitGraphViewport';\nimport { getGraphFitPadding } from './getGraphFitPadding';\n\n/*** Own viewport units and limits alongside the public controller, without exposing Cytoscape. */\nexport function createGraphController(\n cy: Core,\n fitPaddingRef: { current: number },\n optimizeFit?: (options: GraphViewFitOptions) => void,\n) {\n const state = {\n scale: 1,\n relative: false,\n min: 0.05,\n max: 2,\n readableSize: 0,\n fitSize: Infinity,\n readableZoom: 0,\n fitZoom: Infinity,\n resizeSnapshot: null as GraphResizeSnapshot | null,\n };\n const controller: GraphViewController = {\n fit(options) {\n if (options?.optimizeSpacing && !options.nodeIds?.length && optimizeFit) {\n optimizeFit(options);\n return;\n }\n fitGraphViewport(\n cy,\n {\n nodeIds: options?.nodeIds,\n padding: options?.padding ?? fitPaddingRef.current,\n },\n state.fitZoom,\n );\n },\n measureNodes(nodeIds) {\n return measureRenderedNodes(cy, nodeIds);\n },\n getViewport() {\n return { pan: cy.pan(), zoom: cy.zoom() / state.scale };\n },\n getZoomRange() {\n return { min: cy.minZoom() / state.scale, max: cy.maxZoom() / state.scale };\n },\n setPan(pan) {\n cy.pan(pan);\n },\n setZoom(zoom) {\n setCenteredZoom(cy, zoom * state.scale);\n },\n zoomBy(factor) {\n setCenteredZoom(cy, cy.zoom() * factor);\n },\n };\n\n return {\n controller,\n configure(input: GraphRuntimeUpdate) {\n state.relative = input.zoomMode === 'fit-relative';\n state.min = input.minZoom ?? 0.05;\n state.max = input.maxZoom ?? 2;\n state.readableSize = positiveSize(input.minReadableLabelSize, 0);\n state.fitSize = positiveSize(input.maxFitLabelSize, Infinity);\n if (!state.relative) state.scale = 1;\n applyZoomLimits(cy, state);\n },\n /*** Return the native automatic-fit ceiling used by spacing optimization. */\n getFitZoomLimit() {\n return state.relative ? state.fitZoom : Math.min(state.fitZoom, state.max);\n },\n /*** Return the native label-readability threshold used before allowing background overlap. */\n getReadableZoomTarget() {\n return state.readableZoom;\n },\n /*** Capture the model point beneath the current viewport center before Cytoscape resizes. */\n beginResize() {\n state.resizeSnapshot = captureResizeSnapshot(cy);\n },\n settle(fit: boolean) {\n const logicalZoom = cy.zoom() / state.scale;\n const fonts = cy\n .nodes()\n .filter((node) => !node.isParent() && Boolean(node.style('label')))\n .map((node) => Number.parseFloat(String(node.style('font-size'))))\n .filter((size) => Number.isFinite(size) && size > 0);\n state.readableZoom = fonts.length\n ? state.readableSize / fonts.reduce((minimum, size) => Math.min(minimum, size), Infinity)\n : 0;\n state.fitZoom = fonts.length\n ? state.fitSize / fonts.reduce((maximum, size) => Math.max(maximum, size), 0)\n : Infinity;\n state.scale = state.relative\n ? Math.min(getNodeFitZoom(cy, fitPaddingRef.current), state.fitZoom)\n : 1;\n applyZoomLimits(cy, state);\n if (fit) {\n state.resizeSnapshot = null;\n controller.fit();\n } else if (settlePreservedViewport(cy, state, logicalZoom)) controller.fit();\n },\n };\n}\n\ninterface GraphResizeSnapshot {\n readonly center: { readonly x: number; readonly y: number };\n readonly nodeBounds: GraphNodeBoundsStatus;\n}\n\ntype GraphNodeBoundsStatus = 'clipped' | 'empty' | 'fit' | 'unusable';\n\n/*** Capture the model-space center and whether the prior viewport was an intact graph fit. */\nfunction captureResizeSnapshot(cy: Core): GraphResizeSnapshot | null {\n const viewport = { width: cy.width(), height: cy.height() };\n const zoom = cy.zoom();\n if (!isUsableViewport(viewport) || !Number.isFinite(zoom) || zoom <= 0) return null;\n const pan = cy.pan();\n const renderedCenter = { x: viewport.width / 2, y: viewport.height / 2 };\n return {\n center: {\n x: (renderedCenter.x - pan.x) / zoom,\n y: (renderedCenter.y - pan.y) / zoom,\n },\n nodeBounds: getNodeBoundsStatus(cy, viewport),\n };\n}\n\n/*** Preserve a manual viewport through resize, fitting only when an intact prior fit becomes invalid. */\nfunction settlePreservedViewport(\n cy: Core,\n state: {\n readonly relative: boolean;\n resizeSnapshot: GraphResizeSnapshot | null;\n readonly scale: number;\n },\n logicalZoom: number,\n): boolean {\n const snapshot = state.resizeSnapshot;\n state.resizeSnapshot = null;\n const zoom = state.relative ? logicalZoom * state.scale : cy.zoom();\n if (snapshot === null) {\n if (state.relative) setCenteredZoom(cy, zoom);\n return false;\n }\n const viewport = { width: cy.width(), height: cy.height() };\n if (!isUsableViewport(viewport)) return false;\n cy.viewport({\n zoom,\n pan: {\n x: viewport.width / 2 - snapshot.center.x * zoom,\n y: viewport.height / 2 - snapshot.center.y * zoom,\n },\n });\n const nodeBounds = getNodeBoundsStatus(cy, viewport);\n return nodeBounds === 'unusable' || (snapshot.nodeBounds === 'fit' && nodeBounds === 'clipped');\n}\n\n/*** Accept only finite non-empty node bounds that are wholly visible in a usable viewport. */\nfunction getNodeBoundsStatus(\n cy: Core,\n viewport: { readonly width: number; readonly height: number },\n): GraphNodeBoundsStatus {\n if (cy.nodes().empty()) return 'empty';\n if (!isUsableViewport(viewport)) return 'unusable';\n const bounds = cy.nodes().renderedBoundingBox();\n if (![bounds.x1, bounds.x2, bounds.y1, bounds.y2].every(Number.isFinite)) return 'unusable';\n const fitsHorizontally = bounds.x1 >= 0 && bounds.x2 <= viewport.width;\n const fitsVertically = bounds.y1 >= 0 && bounds.y2 <= viewport.height;\n return fitsHorizontally && fitsVertically ? 'fit' : 'clipped';\n}\n\n/*** Reject zero, negative, and non-finite renderer dimensions before viewport arithmetic. */\nfunction isUsableViewport(viewport: { readonly width: number; readonly height: number }): boolean {\n return (\n Number.isFinite(viewport.width) &&\n Number.isFinite(viewport.height) &&\n viewport.width > 0 &&\n viewport.height > 0\n );\n}\n\n/*** Measure rendered node hit geometry without exposing paint-only outlines or Cytoscape. */\nfunction measureRenderedNodes(cy: Core, nodeIds: readonly string[]): GraphViewMeasurement | null {\n const viewport = { width: cy.width(), height: cy.height() };\n if (viewport.width <= 0 || viewport.height <= 0 || nodeIds.length === 0) return null;\n\n const nodes = [...new Set(nodeIds)].flatMap((id) => {\n const node = cy.getElementById(id);\n if (!node.isNode()) return [];\n\n return [\n {\n id,\n position: node.renderedPosition(),\n size: { width: node.renderedOuterWidth(), height: node.renderedOuterHeight() },\n },\n ];\n });\n return nodes.length === 0 ? null : { nodes, viewport };\n}\n\n/*** Keep pointer, wheel, and programmatic zoom on the same limits in the engine's native units. */\nfunction applyZoomLimits(\n cy: Core,\n state: {\n readonly min: number;\n readonly max: number;\n readonly scale: number;\n readonly readableZoom: number;\n },\n) {\n const min = state.min * state.scale;\n cy.minZoom(Math.min(cy.minZoom(), min));\n cy.maxZoom(Math.max(min, state.max * state.scale, state.readableZoom));\n cy.minZoom(min);\n}\n\n/*** Ignore invalid optional typography targets at the public configuration boundary. */\nfunction positiveSize(value: number | undefined, fallback: number): number {\n return value !== undefined && Number.isFinite(value) && value > 0 ? value : fallback;\n}\n\n/***\n * Recompute the fit reference only after layout or resize, never on every pan/zoom event.\n * Cache the geometry-derived scale in the viewport owner; labels are included, edges excluded.\n */\nfunction getNodeFitZoom(cy: Core, padding: number): number {\n if (cy.nodes().empty()) return 1;\n const bounds = cy.nodes().boundingBox();\n const fitPadding = getGraphFitPadding(cy, padding);\n const width = cy.width() - 2 * fitPadding;\n const height = cy.height() - 2 * fitPadding;\n if (width <= 0 || height <= 0 || bounds.w <= 0 || bounds.h <= 0) return 1;\n return Math.min(width / bounds.w, height / bounds.h);\n}\n\n/*** Zoom around the visible viewport center instead of its top-left corner. */\nfunction setCenteredZoom(cy: Core, zoom: number) {\n cy.zoom({ level: zoom, renderedPosition: { x: cy.width() / 2, y: cy.height() / 2 } });\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitGraphViewport.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"fitGraphViewport.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAG3E,2FAA2F;AAC3F,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,IAAI,EACR,OAAO,GAAE,mBAAwB,EACjC,OAAO,SAAW,GACjB,OAAO,CAWT"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getGraphFitPadding } from './getGraphFitPadding';
|
|
1
2
|
/*** Fit the requested visible nodes and never include edge geometry in viewport bounds. */
|
|
2
3
|
export function fitGraphViewport(cy, options = {}, maxZoom = Infinity) {
|
|
3
4
|
if (cy.destroyed())
|
|
@@ -5,7 +6,7 @@ export function fitGraphViewport(cy, options = {}, maxZoom = Infinity) {
|
|
|
5
6
|
const nodes = getFitNodes(cy, options.nodeIds);
|
|
6
7
|
if (nodes.empty())
|
|
7
8
|
return false;
|
|
8
|
-
cy.fit(nodes, options.padding ?? 50);
|
|
9
|
+
cy.fit(nodes, getGraphFitPadding(cy, options.padding ?? 50));
|
|
9
10
|
if (cy.zoom() > maxZoom) {
|
|
10
11
|
cy.zoom(maxZoom);
|
|
11
12
|
cy.center(nodes);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fitGraphViewport.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"fitGraphViewport.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,2FAA2F;AAC3F,MAAM,UAAU,gBAAgB,CAC9B,EAAQ,EACR,UAA+B,EAAE,EACjC,OAAO,GAAG,QAAQ;IAElB,IAAI,EAAE,CAAC,SAAS,EAAE;QAAE,OAAO,KAAK,CAAC;IACjC,MAAM,KAAK,GAAG,WAAW,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,IAAI,KAAK,CAAC,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IAEhC,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,kBAAkB,CAAC,EAAE,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC;IAC7D,IAAI,EAAE,CAAC,IAAI,EAAE,GAAG,OAAO,EAAE,CAAC;QACxB,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACjB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2FAA2F;AAC3F,SAAS,WAAW,CAAC,EAAQ,EAAE,OAAsC;IACnE,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC;IACrE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AAClE,CAAC","sourcesContent":["import type { Core } from 'cytoscape';\n\nimport type { GraphViewFitOptions } from '../../../../../types/graph-view';\nimport { getGraphFitPadding } from './getGraphFitPadding';\n\n/*** Fit the requested visible nodes and never include edge geometry in viewport bounds. */\nexport function fitGraphViewport(\n cy: Core,\n options: GraphViewFitOptions = {},\n maxZoom = Infinity,\n): boolean {\n if (cy.destroyed()) return false;\n const nodes = getFitNodes(cy, options.nodeIds);\n if (nodes.empty()) return false;\n\n cy.fit(nodes, getGraphFitPadding(cy, options.padding ?? 50));\n if (cy.zoom() > maxZoom) {\n cy.zoom(maxZoom);\n cy.center(nodes);\n }\n return true;\n}\n\n/*** Resolve an optional node-id target without ever adding edges to the fit collection. */\nfunction getFitNodes(cy: Core, nodeIds: readonly string[] | undefined) {\n if (nodeIds === undefined || nodeIds.length === 0) return cy.nodes();\n const requestedIds = new Set(nodeIds);\n return cy.nodes().filter((node) => requestedIds.has(node.id()));\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getGraphFitPadding.d.ts","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEtC,gFAAgF;AAChF,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAMpE"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/*** Limits requested fit padding so every usable canvas retains graph space. */
|
|
2
|
+
export function getGraphFitPadding(cy, padding) {
|
|
3
|
+
const viewportSize = Math.min(cy.width(), cy.height());
|
|
4
|
+
if (!Number.isFinite(viewportSize) || viewportSize <= 0)
|
|
5
|
+
return 0;
|
|
6
|
+
const requestedPadding = Number.isFinite(padding) ? Math.max(0, padding) : 0;
|
|
7
|
+
return Math.min(requestedPadding, viewportSize / 4);
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=getGraphFitPadding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getGraphFitPadding.js","sourceRoot":"","sources":["../../../../../../src/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,MAAM,UAAU,kBAAkB,CAAC,EAAQ,EAAE,OAAe;IAC1D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAElE,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,YAAY,GAAG,CAAC,CAAC,CAAC;AACtD,CAAC","sourcesContent":["import type { Core } from 'cytoscape';\n\n/*** Limits requested fit padding so every usable canvas retains graph space. */\nexport function getGraphFitPadding(cy: Core, padding: number): number {\n const viewportSize = Math.min(cy.width(), cy.height());\n if (!Number.isFinite(viewportSize) || viewportSize <= 0) return 0;\n\n const requestedPadding = Number.isFinite(padding) ? Math.max(0, padding) : 0;\n return Math.min(requestedPadding, viewportSize / 4);\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhorage/zora",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "27.1.
|
|
4
|
+
"version": "27.1.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": {
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"@ankhorage/game": "^0.1.3",
|
|
48
48
|
"@ankhorage/grid-view": "^0.5.0",
|
|
49
49
|
"@ankhorage/reader": "^0.1.2",
|
|
50
|
-
"@ankhorage/runtime": "^5.4.
|
|
50
|
+
"@ankhorage/runtime": "^5.4.1",
|
|
51
51
|
"@ankhorage/surface": "^9.5.3",
|
|
52
52
|
"@ankhorage/utility": "^1.10.0",
|
|
53
53
|
"expo-document-picker": "~57.0.3",
|
|
@@ -7,6 +7,7 @@ import type {
|
|
|
7
7
|
} from '../../../../../types/graph-view';
|
|
8
8
|
import type { GraphRuntimeUpdate } from '../../../../../types/graphViewRuntime';
|
|
9
9
|
import { fitGraphViewport } from './fitGraphViewport';
|
|
10
|
+
import { getGraphFitPadding } from './getGraphFitPadding';
|
|
10
11
|
|
|
11
12
|
/*** Own viewport units and limits alongside the public controller, without exposing Cytoscape. */
|
|
12
13
|
export function createGraphController(
|
|
@@ -233,8 +234,9 @@ function positiveSize(value: number | undefined, fallback: number): number {
|
|
|
233
234
|
function getNodeFitZoom(cy: Core, padding: number): number {
|
|
234
235
|
if (cy.nodes().empty()) return 1;
|
|
235
236
|
const bounds = cy.nodes().boundingBox();
|
|
236
|
-
const
|
|
237
|
-
const
|
|
237
|
+
const fitPadding = getGraphFitPadding(cy, padding);
|
|
238
|
+
const width = cy.width() - 2 * fitPadding;
|
|
239
|
+
const height = cy.height() - 2 * fitPadding;
|
|
238
240
|
if (width <= 0 || height <= 0 || bounds.w <= 0 || bounds.h <= 0) return 1;
|
|
239
241
|
return Math.min(width / bounds.w, height / bounds.h);
|
|
240
242
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Core } from 'cytoscape';
|
|
2
2
|
|
|
3
3
|
import type { GraphViewFitOptions } from '../../../../../types/graph-view';
|
|
4
|
+
import { getGraphFitPadding } from './getGraphFitPadding';
|
|
4
5
|
|
|
5
6
|
/*** Fit the requested visible nodes and never include edge geometry in viewport bounds. */
|
|
6
7
|
export function fitGraphViewport(
|
|
@@ -12,7 +13,7 @@ export function fitGraphViewport(
|
|
|
12
13
|
const nodes = getFitNodes(cy, options.nodeIds);
|
|
13
14
|
if (nodes.empty()) return false;
|
|
14
15
|
|
|
15
|
-
cy.fit(nodes, options.padding ?? 50);
|
|
16
|
+
cy.fit(nodes, getGraphFitPadding(cy, options.padding ?? 50));
|
|
16
17
|
if (cy.zoom() > maxZoom) {
|
|
17
18
|
cy.zoom(maxZoom);
|
|
18
19
|
cy.center(nodes);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { expect, test } from 'bun:test';
|
|
2
|
+
import cytoscape from 'cytoscape';
|
|
3
|
+
|
|
4
|
+
import { getGraphFitPadding } from './getGraphFitPadding';
|
|
5
|
+
|
|
6
|
+
test('keeps requested padding only while the canvas retains graph space', () => {
|
|
7
|
+
const cy = cytoscape({ headless: true });
|
|
8
|
+
cy.width = () => 800;
|
|
9
|
+
cy.height = () => 600;
|
|
10
|
+
try {
|
|
11
|
+
expect(getGraphFitPadding(cy, 50)).toBe(50);
|
|
12
|
+
|
|
13
|
+
cy.width = () => 38;
|
|
14
|
+
expect(getGraphFitPadding(cy, 50)).toBe(9.5);
|
|
15
|
+
} finally {
|
|
16
|
+
cy.destroy();
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
test('rejects unusable canvas dimensions and negative padding', () => {
|
|
21
|
+
const cy = cytoscape({ headless: true });
|
|
22
|
+
cy.width = () => 0;
|
|
23
|
+
cy.height = () => 520;
|
|
24
|
+
try {
|
|
25
|
+
expect(getGraphFitPadding(cy, 50)).toBe(0);
|
|
26
|
+
|
|
27
|
+
cy.width = () => 800;
|
|
28
|
+
expect(getGraphFitPadding(cy, -50)).toBe(0);
|
|
29
|
+
} finally {
|
|
30
|
+
cy.destroy();
|
|
31
|
+
}
|
|
32
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Core } from 'cytoscape';
|
|
2
|
+
|
|
3
|
+
/*** Limits requested fit padding so every usable canvas retains graph space. */
|
|
4
|
+
export function getGraphFitPadding(cy: Core, padding: number): number {
|
|
5
|
+
const viewportSize = Math.min(cy.width(), cy.height());
|
|
6
|
+
if (!Number.isFinite(viewportSize) || viewportSize <= 0) return 0;
|
|
7
|
+
|
|
8
|
+
const requestedPadding = Number.isFinite(padding) ? Math.max(0, padding) : 0;
|
|
9
|
+
return Math.min(requestedPadding, viewportSize / 4);
|
|
10
|
+
}
|
|
@@ -59,8 +59,8 @@ var styles = import_react_native.StyleSheet.create({
|
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
// node_modules/@ankhorage/runtime/dist/RuntimeRendererConfig.js
|
|
62
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
62
63
|
import React, { createContext, use } from "react";
|
|
63
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
64
64
|
var EMPTY_RUNTIME_RENDERER_CONFIG = {};
|
|
65
65
|
var RuntimeRendererConfigContext = createContext(EMPTY_RUNTIME_RENDERER_CONFIG);
|
|
66
66
|
function composeRuntimeRendererWrapNode(innerWrapNode, outerWrapNode) {
|
|
@@ -115,10 +115,7 @@ function RuntimeRendererConfigProvider(props) {
|
|
|
115
115
|
const { value, children } = props;
|
|
116
116
|
const inheritedConfig = use(RuntimeRendererConfigContext);
|
|
117
117
|
const mergedConfig = mergeRuntimeRendererConfig(value, inheritedConfig);
|
|
118
|
-
return
|
|
119
|
-
value: mergedConfig,
|
|
120
|
-
children
|
|
121
|
-
});
|
|
118
|
+
return _jsx(RuntimeRendererConfigContext, { value: mergedConfig, children });
|
|
122
119
|
}
|
|
123
120
|
function mergeRecordConfig(inherited, local) {
|
|
124
121
|
if (!inherited && !local)
|
|
@@ -946,18 +943,18 @@ function useLatestValue(value) {
|
|
|
946
943
|
}
|
|
947
944
|
|
|
948
945
|
// src/features/game/adapters/inbound/Game.tsx
|
|
949
|
-
import { jsx as
|
|
946
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
950
947
|
var Game2 = withZoraThemeScope(GameInner);
|
|
951
948
|
function GameInner(props) {
|
|
952
949
|
const runtime = useGameRuntime(props);
|
|
953
950
|
const [measurementRegistry] = React5.useState(createGameMeasurementRegistry);
|
|
954
951
|
const runtimeContext = React5.useMemo(() => ({ ...runtime, ...measurementRegistry, interactionPolicy: props.interactionPolicy }), [measurementRegistry, props.interactionPolicy, runtime]);
|
|
955
952
|
const runtimeBindingConfig = React5.useMemo(() => ({ bindingContext: createGameBindingContext(runtime.session) }), [runtime.session]);
|
|
956
|
-
return /* @__PURE__ */
|
|
953
|
+
return /* @__PURE__ */ jsx2(GameRuntimeContext.Provider, {
|
|
957
954
|
value: runtimeContext,
|
|
958
|
-
children: /* @__PURE__ */
|
|
955
|
+
children: /* @__PURE__ */ jsx2(RuntimeRendererConfigProvider, {
|
|
959
956
|
value: runtimeBindingConfig,
|
|
960
|
-
children: /* @__PURE__ */
|
|
957
|
+
children: /* @__PURE__ */ jsx2(GameField2, {
|
|
961
958
|
...props.aspectRatio === undefined ? {} : { aspectRatio: props.aspectRatio },
|
|
962
959
|
...props.minHeight === undefined ? {} : { minHeight: props.minHeight },
|
|
963
960
|
...props.fill === undefined ? {} : { fill: props.fill },
|
|
@@ -1215,13 +1212,13 @@ function useGameEntityMeasurement(elementRef, measurementId) {
|
|
|
1215
1212
|
}
|
|
1216
1213
|
|
|
1217
1214
|
// src/features/game/adapters/inbound/GameEntity.tsx
|
|
1218
|
-
import { jsx as
|
|
1215
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
1219
1216
|
var GameEntity2 = withZoraThemeScope(GameEntityInner);
|
|
1220
1217
|
function GameEntityInner(props) {
|
|
1221
1218
|
const elementRef = React10.useRef(null);
|
|
1222
1219
|
const animatedStyle = useGameEntityAnimatedStyle(props);
|
|
1223
1220
|
useGameEntityMeasurement(elementRef, props.measurementId);
|
|
1224
|
-
return /* @__PURE__ */
|
|
1221
|
+
return /* @__PURE__ */ jsx3(import_react_native6.Animated.View, {
|
|
1225
1222
|
ref: elementRef,
|
|
1226
1223
|
accessibilityLabel: props.accessibilityLabel,
|
|
1227
1224
|
testID: props.testID,
|
|
@@ -1355,7 +1352,7 @@ function useGameInputZoneResponder(props) {
|
|
|
1355
1352
|
}
|
|
1356
1353
|
|
|
1357
1354
|
// src/features/game/adapters/inbound/GameInputZone.tsx
|
|
1358
|
-
import { jsx as
|
|
1355
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
1359
1356
|
var GameInputZone2 = withZoraThemeScope(GameInputZoneInner);
|
|
1360
1357
|
function GameInputZoneInner({
|
|
1361
1358
|
x = 0,
|
|
@@ -1387,7 +1384,7 @@ function GameInputZoneInner({
|
|
|
1387
1384
|
enabled: enabled && interactionPolicy !== "passive",
|
|
1388
1385
|
keyboardBindings
|
|
1389
1386
|
});
|
|
1390
|
-
return /* @__PURE__ */
|
|
1387
|
+
return /* @__PURE__ */ jsx4(import_react_native7.View, {
|
|
1391
1388
|
...keyboardProps,
|
|
1392
1389
|
...accessibilityLabel === undefined ? {} : { accessibilityLabel },
|
|
1393
1390
|
...testID === undefined ? {} : { testID },
|
|
@@ -1514,7 +1511,7 @@ async function dispatchGameMeasurement(input) {
|
|
|
1514
1511
|
|
|
1515
1512
|
// src/features/game/adapters/inbound/GameOverlay.tsx
|
|
1516
1513
|
var import_react_native8 = __toESM(require_cjs(), 1);
|
|
1517
|
-
import { jsx as
|
|
1514
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
1518
1515
|
var GameOverlay2 = withZoraThemeScope(GameOverlayInner);
|
|
1519
1516
|
function GameOverlayInner({
|
|
1520
1517
|
children,
|
|
@@ -1525,7 +1522,7 @@ function GameOverlayInner({
|
|
|
1525
1522
|
interactionPolicy,
|
|
1526
1523
|
testID
|
|
1527
1524
|
}) {
|
|
1528
|
-
return /* @__PURE__ */
|
|
1525
|
+
return /* @__PURE__ */ jsx5(View2, {
|
|
1529
1526
|
...accessibilityLabel === undefined ? {} : { accessibilityLabel },
|
|
1530
1527
|
...testID === undefined ? {} : { testID },
|
|
1531
1528
|
pointerEvents: interactionPolicy === "passive" ? "none" : blocking ? "auto" : "box-none",
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
GameInputZone2,
|
|
7
7
|
GameMeasurementProbe2,
|
|
8
8
|
GameOverlay2
|
|
9
|
-
} from "../../chunks/Accordion-
|
|
9
|
+
} from "../../chunks/Accordion-bfszt9f0.js";
|
|
10
10
|
import"../../chunks/Accordion-6wrr910w.js";
|
|
11
11
|
import"../../chunks/Accordion-vj1m2wck.js";
|
|
12
12
|
import"../../chunks/Accordion-zj4wnm3e.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
GameInputZone2,
|
|
7
7
|
GameMeasurementProbe2,
|
|
8
8
|
GameOverlay2
|
|
9
|
-
} from "../../chunks/Accordion-
|
|
9
|
+
} from "../../chunks/Accordion-bfszt9f0.js";
|
|
10
10
|
import"../../chunks/Accordion-6wrr910w.js";
|
|
11
11
|
import"../../chunks/Accordion-vj1m2wck.js";
|
|
12
12
|
import"../../chunks/Accordion-zj4wnm3e.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
GameInputZone2,
|
|
7
7
|
GameMeasurementProbe2,
|
|
8
8
|
GameOverlay2
|
|
9
|
-
} from "../../chunks/Accordion-
|
|
9
|
+
} from "../../chunks/Accordion-bfszt9f0.js";
|
|
10
10
|
import"../../chunks/Accordion-6wrr910w.js";
|
|
11
11
|
import"../../chunks/Accordion-vj1m2wck.js";
|
|
12
12
|
import"../../chunks/Accordion-zj4wnm3e.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
GameInputZone2,
|
|
7
7
|
GameMeasurementProbe2,
|
|
8
8
|
GameOverlay2
|
|
9
|
-
} from "../../chunks/Accordion-
|
|
9
|
+
} from "../../chunks/Accordion-bfszt9f0.js";
|
|
10
10
|
import"../../chunks/Accordion-6wrr910w.js";
|
|
11
11
|
import"../../chunks/Accordion-vj1m2wck.js";
|
|
12
12
|
import"../../chunks/Accordion-zj4wnm3e.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
GameInputZone2,
|
|
7
7
|
GameMeasurementProbe2,
|
|
8
8
|
GameOverlay2
|
|
9
|
-
} from "../../chunks/Accordion-
|
|
9
|
+
} from "../../chunks/Accordion-bfszt9f0.js";
|
|
10
10
|
import"../../chunks/Accordion-6wrr910w.js";
|
|
11
11
|
import"../../chunks/Accordion-vj1m2wck.js";
|
|
12
12
|
import"../../chunks/Accordion-zj4wnm3e.js";
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
GameInputZone2,
|
|
7
7
|
GameMeasurementProbe2,
|
|
8
8
|
GameOverlay2
|
|
9
|
-
} from "../../chunks/Accordion-
|
|
9
|
+
} from "../../chunks/Accordion-bfszt9f0.js";
|
|
10
10
|
import"../../chunks/Accordion-6wrr910w.js";
|
|
11
11
|
import"../../chunks/Accordion-vj1m2wck.js";
|
|
12
12
|
import"../../chunks/Accordion-zj4wnm3e.js";
|
|
@@ -123099,6 +123099,15 @@ function findExpansionFactor(accepts) {
|
|
|
123099
123099
|
return findMinimumAcceptedFactor(maximum / 2, maximum, accepts);
|
|
123100
123100
|
}
|
|
123101
123101
|
|
|
123102
|
+
// src/features/graph-view/adapters/inbound/web-artifact/getGraphFitPadding.ts
|
|
123103
|
+
function getGraphFitPadding(cy, padding) {
|
|
123104
|
+
const viewportSize = Math.min(cy.width(), cy.height());
|
|
123105
|
+
if (!Number.isFinite(viewportSize) || viewportSize <= 0)
|
|
123106
|
+
return 0;
|
|
123107
|
+
const requestedPadding = Number.isFinite(padding) ? Math.max(0, padding) : 0;
|
|
123108
|
+
return Math.min(requestedPadding, viewportSize / 4);
|
|
123109
|
+
}
|
|
123110
|
+
|
|
123102
123111
|
// src/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.ts
|
|
123103
123112
|
function fitGraphViewport(cy, options = {}, maxZoom = Infinity) {
|
|
123104
123113
|
if (cy.destroyed())
|
|
@@ -123106,7 +123115,7 @@ function fitGraphViewport(cy, options = {}, maxZoom = Infinity) {
|
|
|
123106
123115
|
const nodes = getFitNodes(cy, options.nodeIds);
|
|
123107
123116
|
if (nodes.empty())
|
|
123108
123117
|
return false;
|
|
123109
|
-
cy.fit(nodes, options.padding ?? 50);
|
|
123118
|
+
cy.fit(nodes, getGraphFitPadding(cy, options.padding ?? 50));
|
|
123110
123119
|
if (cy.zoom() > maxZoom) {
|
|
123111
123120
|
cy.zoom(maxZoom);
|
|
123112
123121
|
cy.center(nodes);
|
|
@@ -123282,8 +123291,9 @@ function getNodeFitZoom(cy, padding) {
|
|
|
123282
123291
|
if (cy.nodes().empty())
|
|
123283
123292
|
return 1;
|
|
123284
123293
|
const bounds = cy.nodes().boundingBox();
|
|
123285
|
-
const
|
|
123286
|
-
const
|
|
123294
|
+
const fitPadding = getGraphFitPadding(cy, padding);
|
|
123295
|
+
const width = cy.width() - 2 * fitPadding;
|
|
123296
|
+
const height = cy.height() - 2 * fitPadding;
|
|
123287
123297
|
if (width <= 0 || height <= 0 || bounds.w <= 0 || bounds.h <= 0)
|
|
123288
123298
|
return 1;
|
|
123289
123299
|
return Math.min(width / bounds.w, height / bounds.h);
|
package/web-dist/manifest.json
CHANGED
|
@@ -1516,7 +1516,7 @@
|
|
|
1516
1516
|
"chunks/Accordion-0x8jncra.js",
|
|
1517
1517
|
"chunks/Accordion-58yzdsab.js",
|
|
1518
1518
|
"chunks/Accordion-6wrr910w.js",
|
|
1519
|
-
"chunks/Accordion-
|
|
1519
|
+
"chunks/Accordion-bfszt9f0.js",
|
|
1520
1520
|
"chunks/Accordion-fcczvwgg.js",
|
|
1521
1521
|
"chunks/Accordion-fre84yaq.js",
|
|
1522
1522
|
"chunks/Accordion-nh0cs9hq.js",
|
|
@@ -1539,7 +1539,7 @@
|
|
|
1539
1539
|
"chunks/Accordion-0x8jncra.js",
|
|
1540
1540
|
"chunks/Accordion-58yzdsab.js",
|
|
1541
1541
|
"chunks/Accordion-6wrr910w.js",
|
|
1542
|
-
"chunks/Accordion-
|
|
1542
|
+
"chunks/Accordion-bfszt9f0.js",
|
|
1543
1543
|
"chunks/Accordion-fcczvwgg.js",
|
|
1544
1544
|
"chunks/Accordion-fre84yaq.js",
|
|
1545
1545
|
"chunks/Accordion-nh0cs9hq.js",
|
|
@@ -1562,7 +1562,7 @@
|
|
|
1562
1562
|
"chunks/Accordion-0x8jncra.js",
|
|
1563
1563
|
"chunks/Accordion-58yzdsab.js",
|
|
1564
1564
|
"chunks/Accordion-6wrr910w.js",
|
|
1565
|
-
"chunks/Accordion-
|
|
1565
|
+
"chunks/Accordion-bfszt9f0.js",
|
|
1566
1566
|
"chunks/Accordion-fcczvwgg.js",
|
|
1567
1567
|
"chunks/Accordion-fre84yaq.js",
|
|
1568
1568
|
"chunks/Accordion-nh0cs9hq.js",
|
|
@@ -1585,7 +1585,7 @@
|
|
|
1585
1585
|
"chunks/Accordion-0x8jncra.js",
|
|
1586
1586
|
"chunks/Accordion-58yzdsab.js",
|
|
1587
1587
|
"chunks/Accordion-6wrr910w.js",
|
|
1588
|
-
"chunks/Accordion-
|
|
1588
|
+
"chunks/Accordion-bfszt9f0.js",
|
|
1589
1589
|
"chunks/Accordion-fcczvwgg.js",
|
|
1590
1590
|
"chunks/Accordion-fre84yaq.js",
|
|
1591
1591
|
"chunks/Accordion-nh0cs9hq.js",
|
|
@@ -1608,7 +1608,7 @@
|
|
|
1608
1608
|
"chunks/Accordion-0x8jncra.js",
|
|
1609
1609
|
"chunks/Accordion-58yzdsab.js",
|
|
1610
1610
|
"chunks/Accordion-6wrr910w.js",
|
|
1611
|
-
"chunks/Accordion-
|
|
1611
|
+
"chunks/Accordion-bfszt9f0.js",
|
|
1612
1612
|
"chunks/Accordion-fcczvwgg.js",
|
|
1613
1613
|
"chunks/Accordion-fre84yaq.js",
|
|
1614
1614
|
"chunks/Accordion-nh0cs9hq.js",
|
|
@@ -1631,7 +1631,7 @@
|
|
|
1631
1631
|
"chunks/Accordion-0x8jncra.js",
|
|
1632
1632
|
"chunks/Accordion-58yzdsab.js",
|
|
1633
1633
|
"chunks/Accordion-6wrr910w.js",
|
|
1634
|
-
"chunks/Accordion-
|
|
1634
|
+
"chunks/Accordion-bfszt9f0.js",
|
|
1635
1635
|
"chunks/Accordion-fcczvwgg.js",
|
|
1636
1636
|
"chunks/Accordion-fre84yaq.js",
|
|
1637
1637
|
"chunks/Accordion-nh0cs9hq.js",
|