@ankhorage/zora 21.0.8 → 21.0.10

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.
Files changed (29) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +1 -1
  3. package/dist/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.d.ts +4 -5
  4. package/dist/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.d.ts.map +1 -1
  5. package/dist/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.js +171 -85
  6. package/dist/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.js.map +1 -1
  7. package/dist/features/tabs/adapters/inbound/TabList.js +3 -3
  8. package/dist/features/tabs/adapters/inbound/TabList.js.map +1 -1
  9. package/dist/features/tabs/tabListMeta.d.ts +8 -1
  10. package/dist/features/tabs/tabListMeta.d.ts.map +1 -1
  11. package/dist/features/tabs/tabListMeta.js +3 -1
  12. package/dist/features/tabs/tabListMeta.js.map +1 -1
  13. package/dist/types/tabs.d.ts +3 -7
  14. package/dist/types/tabs.d.ts.map +1 -1
  15. package/dist/types/tabs.js.map +1 -1
  16. package/package.json +2 -2
  17. package/src/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.test.ts +60 -25
  18. package/src/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.ts +243 -93
  19. package/src/features/tabs/adapters/inbound/TabList.tsx +3 -4
  20. package/src/features/tabs/adapters/inbound/Tabs.layout.test.tsx +33 -0
  21. package/src/features/tabs/tabListMeta.ts +3 -1
  22. package/src/types/tabs.ts +5 -7
  23. package/web-dist/chunks/{Accordion-aj6fsjhv.js → Accordion-j4d58grp.js} +62 -37
  24. package/web-dist/components/graph-view/GraphView.js +189 -72
  25. package/web-dist/components/tab/Tab.js +1 -1
  26. package/web-dist/components/tab-list/TabList.js +1 -1
  27. package/web-dist/components/tab-panel/TabPanel.js +1 -1
  28. package/web-dist/components/tabs/Tabs.js +1 -1
  29. package/web-dist/manifest.json +4 -4
@@ -62,13 +62,14 @@ function useTabRegistration({ disabled, value }) {
62
62
  }
63
63
 
64
64
  // node_modules/@ankhorage/surface/src/features/tabs/adapters/inbound/Tab.tsx
65
- import { jsx } from "react/jsx-runtime";
65
+ import { jsx, jsxs } from "react/jsx-runtime";
66
66
  function Tab({
67
67
  value,
68
68
  children,
69
69
  disabled = false,
70
70
  interactionPolicy = "enabled",
71
- testID
71
+ testID,
72
+ trailing
72
73
  }) {
73
74
  const { theme } = useTheme();
74
75
  const { activeValue, getPanelId, getTabId, setActiveValue, setFocusedValue } = useTabsContext();
@@ -95,15 +96,29 @@ function Tab({
95
96
  borderColor: selected ? theme.semantics.action.primary.base : theme.semantics.border.default,
96
97
  disabled
97
98
  }),
98
- children: /* @__PURE__ */ jsx(Text3, {
99
- color: selected ? "primary" : undefined,
100
- variant: "label",
101
- weight: "medium",
102
- children
103
- })
99
+ children: renderTabContent(children, trailing, selected)
104
100
  })
105
101
  });
106
102
  }
103
+ function renderTabContent(children, trailing, selected) {
104
+ const label = /* @__PURE__ */ jsx(Text3, {
105
+ color: selected ? "primary" : undefined,
106
+ variant: "label",
107
+ weight: "medium",
108
+ children
109
+ });
110
+ if (trailing === undefined)
111
+ return label;
112
+ return /* @__PURE__ */ jsxs(View3, {
113
+ align: "center",
114
+ direction: "row",
115
+ gap: "xs",
116
+ children: [
117
+ label,
118
+ trailing
119
+ ]
120
+ });
121
+ }
107
122
  function resolveTabStyle({
108
123
  borderColor,
109
124
  disabled
@@ -137,7 +152,7 @@ function TabInner({
137
152
  }
138
153
 
139
154
  // node_modules/@ankhorage/surface/src/features/tabs/adapters/inbound/TabList.tsx
140
- import React5 from "react";
155
+ import React6 from "react";
141
156
 
142
157
  // node_modules/@ankhorage/surface/src/features/tabs/utils/resolveNextTabValue.ts
143
158
  function resolveNextTabValue(tabs, currentValue, key) {
@@ -155,8 +170,20 @@ function resolveNextTabValue(tabs, currentValue, key) {
155
170
  return enabledTabs.at(nextIndex)?.value;
156
171
  }
157
172
 
158
- // node_modules/@ankhorage/surface/src/features/tabs/adapters/inbound/TabList.tsx
173
+ // node_modules/@ankhorage/surface/src/features/tabs/utils/wrapTabListChildren.tsx
174
+ import React5 from "react";
159
175
  import { jsx as jsx3 } from "react/jsx-runtime";
176
+ function wrapTabListChildren(children, fill) {
177
+ if (!fill)
178
+ return children;
179
+ return React5.Children.map(children, (child) => /* @__PURE__ */ jsx3(View3, {
180
+ flex: 1,
181
+ children: child
182
+ }));
183
+ }
184
+
185
+ // node_modules/@ankhorage/surface/src/features/tabs/adapters/inbound/TabList.tsx
186
+ import { jsx as jsx4 } from "react/jsx-runtime";
160
187
  var navigationKeys = [
161
188
  "ArrowLeft",
162
189
  "ArrowRight",
@@ -165,10 +192,10 @@ var navigationKeys = [
165
192
  "Home",
166
193
  "End"
167
194
  ];
168
- function TabList({ children, testID }) {
195
+ function TabList({ children, fill = false, testID }) {
169
196
  const { bindKeydown } = useFocusManager();
170
197
  const { focusedValue, setActiveValue, tabs } = useTabsContext();
171
- React5.useEffect(() => {
198
+ React6.useEffect(() => {
172
199
  if (!focusedValue)
173
200
  return;
174
201
  return bindKeydown((event) => {
@@ -182,11 +209,11 @@ function TabList({ children, testID }) {
182
209
  setActiveValue(nextValue);
183
210
  });
184
211
  }, [bindKeydown, focusedValue, setActiveValue, tabs]);
185
- return /* @__PURE__ */ jsx3(View3, {
212
+ return /* @__PURE__ */ jsx4(View3, {
186
213
  accessibilityRole: "tablist",
187
214
  direction: "row",
188
215
  testID,
189
- children
216
+ children: wrapTabListChildren(children, fill)
190
217
  });
191
218
  }
192
219
  function isTabNavigationKey(key) {
@@ -194,29 +221,27 @@ function isTabNavigationKey(key) {
194
221
  }
195
222
 
196
223
  // src/features/tabs/adapters/inbound/TabList.tsx
197
- import { jsx as jsx4 } from "react/jsx-runtime";
224
+ import { jsx as jsx5 } from "react/jsx-runtime";
198
225
  var TabList2 = withZoraThemeScope(TabListInner);
199
226
  function TabListInner({
200
227
  themeId: _themeId,
201
228
  mode: _mode,
202
229
  interactionPolicy: _interactionPolicy,
203
- children,
204
- testID
230
+ ...props
205
231
  }) {
206
- return /* @__PURE__ */ jsx4(TabList, {
207
- testID,
208
- children
232
+ return /* @__PURE__ */ jsx5(TabList, {
233
+ ...props
209
234
  });
210
235
  }
211
236
 
212
237
  // node_modules/@ankhorage/surface/src/features/tabs/adapters/inbound/TabPanel.tsx
213
- import { jsx as jsx5 } from "react/jsx-runtime";
238
+ import { jsx as jsx6 } from "react/jsx-runtime";
214
239
  var TAB_PANEL_ROLE = "tabpanel";
215
240
  function TabPanel({ value, children, testID, ...layoutProps }) {
216
241
  const { activeValue, getPanelId, getTabId } = useTabsContext();
217
242
  if (activeValue !== value)
218
243
  return null;
219
- return /* @__PURE__ */ jsx5(View3, {
244
+ return /* @__PURE__ */ jsx6(View3, {
220
245
  ...layoutProps,
221
246
  accessibilityLabelledBy: getTabId(value),
222
247
  accessibilityRole: TAB_PANEL_ROLE,
@@ -227,7 +252,7 @@ function TabPanel({ value, children, testID, ...layoutProps }) {
227
252
  }
228
253
 
229
254
  // src/features/tabs/adapters/inbound/TabPanel.tsx
230
- import { jsx as jsx6 } from "react/jsx-runtime";
255
+ import { jsx as jsx7 } from "react/jsx-runtime";
231
256
  var TabPanel2 = withZoraThemeScope(TabPanelInner);
232
257
  function TabPanelInner({
233
258
  themeId: _themeId,
@@ -235,13 +260,13 @@ function TabPanelInner({
235
260
  interactionPolicy: _interactionPolicy,
236
261
  ...props
237
262
  }) {
238
- return /* @__PURE__ */ jsx6(TabPanel, {
263
+ return /* @__PURE__ */ jsx7(TabPanel, {
239
264
  ...props
240
265
  });
241
266
  }
242
267
 
243
268
  // node_modules/@ankhorage/surface/src/features/tabs/composition/useTabsController.ts
244
- import React6 from "react";
269
+ import React7 from "react";
245
270
 
246
271
  // node_modules/@ankhorage/surface/src/features/tabs/utils/resolveTabElementId.ts
247
272
  function resolveTabElementId(kind, testID, value) {
@@ -267,22 +292,22 @@ function useTabsController({
267
292
  },
268
293
  value
269
294
  });
270
- const [focusedValue, setFocusedValue] = React6.useState(undefined);
271
- const [tabs, setTabs] = React6.useState([]);
272
- const registerTab = React6.useCallback((tab) => {
295
+ const [focusedValue, setFocusedValue] = React7.useState(undefined);
296
+ const [tabs, setTabs] = React7.useState([]);
297
+ const registerTab = React7.useCallback((tab) => {
273
298
  setTabs((current) => current.some((entry) => entry.value === tab.value) ? current.map((entry) => entry.value === tab.value ? tab : entry) : [...current, tab]);
274
299
  }, []);
275
- const unregisterTab = React6.useCallback((valueToRemove) => {
300
+ const unregisterTab = React7.useCallback((valueToRemove) => {
276
301
  setTabs((current) => current.filter((entry) => entry.value !== valueToRemove));
277
302
  }, []);
278
- React6.useEffect(() => {
303
+ React7.useEffect(() => {
279
304
  if (activeValue !== undefined)
280
305
  return;
281
306
  const firstEnabledTab = tabs.find((entry) => !entry.disabled);
282
307
  if (firstEnabledTab)
283
308
  setActiveValue(firstEnabledTab.value);
284
309
  }, [activeValue, setActiveValue, tabs]);
285
- return React6.useMemo(() => ({
310
+ return React7.useMemo(() => ({
286
311
  activeValue,
287
312
  focusedValue,
288
313
  getPanelId: (tabValue) => resolveTabElementId("panel", testID, tabValue),
@@ -296,7 +321,7 @@ function useTabsController({
296
321
  }
297
322
 
298
323
  // node_modules/@ankhorage/surface/src/features/tabs/adapters/inbound/Tabs.tsx
299
- import { jsx as jsx7 } from "react/jsx-runtime";
324
+ import { jsx as jsx8 } from "react/jsx-runtime";
300
325
  function Tabs({
301
326
  children,
302
327
  defaultValue,
@@ -306,9 +331,9 @@ function Tabs({
306
331
  ...layoutProps
307
332
  }) {
308
333
  const contextValue = useTabsController({ defaultValue, onValueChange, testID, value });
309
- return /* @__PURE__ */ jsx7(TabsContext, {
334
+ return /* @__PURE__ */ jsx8(TabsContext, {
310
335
  value: contextValue,
311
- children: /* @__PURE__ */ jsx7(View3, {
336
+ children: /* @__PURE__ */ jsx8(View3, {
312
337
  ...layoutProps,
313
338
  testID,
314
339
  children
@@ -317,7 +342,7 @@ function Tabs({
317
342
  }
318
343
 
319
344
  // src/features/tabs/adapters/inbound/Tabs.tsx
320
- import { jsx as jsx8 } from "react/jsx-runtime";
345
+ import { jsx as jsx9 } from "react/jsx-runtime";
321
346
  var Tabs2 = withZoraThemeScope(TabsInner);
322
347
  function TabsInner({
323
348
  themeId: _themeId,
@@ -326,9 +351,9 @@ function TabsInner({
326
351
  children,
327
352
  ...props
328
353
  }) {
329
- return /* @__PURE__ */ jsx8(TabsInteractionPolicyContext, {
354
+ return /* @__PURE__ */ jsx9(TabsInteractionPolicyContext, {
330
355
  value: interactionPolicy,
331
- children: /* @__PURE__ */ jsx8(Tabs, {
356
+ children: /* @__PURE__ */ jsx9(Tabs, {
332
357
  ...props,
333
358
  children
334
359
  })
@@ -122375,99 +122375,216 @@ var EVENT_TYPES = [
122375
122375
  ["mouseout", "pointer-leave"]
122376
122376
  ];
122377
122377
 
122378
- // src/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.ts
122379
- function compactGraphSpacing(cy, spacingFactor) {
122380
- const leaves = cy.nodes(":childless");
122381
- if (leaves.length < 2 || cy.nodes().length > 2000 || leaves.filter(":locked").length > 0)
122382
- return spacingFactor;
122383
- const ancestors = new Map(cy.nodes().map((node) => [node.id(), new Set(node.ancestors().map((parent) => parent.id()))]));
122384
- const positions = new Map(leaves.map((node) => [node.id(), { ...node.position() }]));
122385
- const bounds = leaves.boundingBox();
122386
- const center = { x: (bounds.x1 + bounds.x2) / 2, y: (bounds.y1 + bounds.y2) / 2 };
122387
- if (hasCollisions(cy, ancestors))
122388
- return expandGraphSpacing(cy, ancestors, center, positions, spacingFactor);
122389
- return compressGraphSpacing(cy, ancestors, center, positions, spacingFactor);
122378
+ // node_modules/@ankhorage/utility/dist/algorithms/findMinimumAcceptedNumber.js
122379
+ var DEFAULT_ITERATIONS = 16;
122380
+ var MAX_ITERATIONS = 64;
122381
+ function findMinimumAcceptedNumber(input) {
122382
+ validateInput(input);
122383
+ const { accepts, maximum, minimum } = input;
122384
+ const iterations = input.iterations ?? DEFAULT_ITERATIONS;
122385
+ if (accepts(minimum))
122386
+ return minimum;
122387
+ if (!accepts(maximum))
122388
+ return;
122389
+ return searchAcceptedBoundary(minimum, maximum, iterations, accepts);
122390
122390
  }
122391
- function compressGraphSpacing(cy, ancestors, center, positions, spacingFactor) {
122392
- const search = { low: Math.min(1, 0.1 / spacingFactor), high: 1 };
122393
- for (const attempt of Array.from({ length: 8 }, (_, index) => index)) {
122394
- const factor = attempt === 0 ? search.low : (search.low + search.high) / 2;
122395
- applyScale(cy, positions, center, factor);
122396
- if (hasCollisions(cy, ancestors))
122397
- search.low = factor;
122398
- else
122399
- search.high = factor;
122400
- if (search.high === search.low)
122391
+ function searchAcceptedBoundary(minimum, maximum, iterations, accepts) {
122392
+ let lower = minimum;
122393
+ let upper = maximum;
122394
+ for (let iteration = 0;iteration < iterations; iteration += 1) {
122395
+ const midpoint = lower + (upper - lower) / 2;
122396
+ if (midpoint === lower || midpoint === upper)
122401
122397
  break;
122398
+ if (accepts(midpoint))
122399
+ upper = midpoint;
122400
+ else
122401
+ lower = midpoint;
122402
122402
  }
122403
- applyScale(cy, positions, center, search.high);
122404
- return spacingFactor * search.high;
122403
+ return upper;
122405
122404
  }
122406
- function expandGraphSpacing(cy, ancestors, center, positions, spacingFactor) {
122407
- let low = 1;
122408
- let high = 1;
122409
- let attempts = 0;
122410
- while (attempts < 8) {
122411
- high *= 2;
122412
- attempts += 1;
122413
- applyScale(cy, positions, center, high);
122414
- if (!hasCollisions(cy, ancestors))
122415
- break;
122416
- low = high;
122405
+ function validateInput(input) {
122406
+ const iterations = input.iterations ?? DEFAULT_ITERATIONS;
122407
+ if (!Number.isFinite(input.minimum) || !Number.isFinite(input.maximum)) {
122408
+ throw new RangeError("Search bounds must be finite numbers.");
122417
122409
  }
122418
- if (hasCollisions(cy, ancestors)) {
122419
- applyScale(cy, positions, center, 1);
122420
- return spacingFactor;
122410
+ if (input.minimum > input.maximum) {
122411
+ throw new RangeError("Search minimum must not exceed maximum.");
122421
122412
  }
122422
- for (const _attempt of Array.from({ length: 8 - attempts }, (_, index) => index)) {
122423
- const factor = (low + high) / 2;
122424
- applyScale(cy, positions, center, factor);
122425
- if (hasCollisions(cy, ancestors))
122426
- low = factor;
122427
- else
122428
- high = factor;
122413
+ if (!Number.isInteger(iterations) || iterations < 0 || iterations > MAX_ITERATIONS) {
122414
+ throw new RangeError(`Search iterations must be an integer from 0 to ${MAX_ITERATIONS}.`);
122429
122415
  }
122430
- applyScale(cy, positions, center, high);
122431
- return spacingFactor * high;
122432
122416
  }
122433
- function applyScale(cy, positions, center, factor) {
122434
- cy.batch(() => {
122435
- cy.nodes().not(":parent").positions((node) => {
122436
- const original = positions.get(node.id()) ?? node.position();
122437
- return {
122438
- x: center.x + (original.x - center.x) * factor,
122439
- y: center.y + (original.y - center.y) * factor
122440
- };
122441
- });
122417
+ // src/features/graph-view/adapters/inbound/web-artifact/compactGraphSpacing.ts
122418
+ var LABEL_OVERLAP_RATIO = 0.12;
122419
+ var MAX_EXPANSION_ATTEMPTS = 8;
122420
+ var MAX_NODE_COUNT = 2000;
122421
+ var MAX_PAIR_CHECKS = 200000;
122422
+ var SEARCH_ITERATIONS = 8;
122423
+ function compactGraphSpacing(cy, spacingFactor) {
122424
+ const leaves = cy.nodes(":childless");
122425
+ if (leaves.length < 2 || cy.nodes().length > MAX_NODE_COUNT || cy.nodes(":locked").length > 0)
122426
+ return spacingFactor;
122427
+ const bounds = leaves.boundingBox();
122428
+ const center = { x: (bounds.x1 + bounds.x2) / 2, y: (bounds.y1 + bounds.y2) / 2 };
122429
+ const leafGeometry = leaves.map(readLeafGeometry);
122430
+ const groups = cy.nodes(":parent").map((node) => readGroupGeometry(node.id(), node.ancestors().map((parent) => parent.id()), node.boundingBox(), leafGeometry));
122431
+ const accepts = (factor) => !hasUnsafeCollisions(resolveCollisionBoxes(leafGeometry, groups, center, factor));
122432
+ const currentAccepted = accepts(1);
122433
+ const minimum = currentAccepted ? Math.min(1, 0.1 / spacingFactor) : 1;
122434
+ const maximum = currentAccepted ? 1 : findExpansionMaximum(accepts);
122435
+ if (maximum === undefined)
122436
+ return spacingFactor;
122437
+ const factor = findMinimumAcceptedNumber({
122438
+ minimum,
122439
+ maximum,
122440
+ iterations: SEARCH_ITERATIONS,
122441
+ accepts
122442
122442
  });
122443
+ if (factor === undefined)
122444
+ return spacingFactor;
122445
+ applyScale(cy, leafGeometry, center, factor);
122446
+ return spacingFactor * factor;
122443
122447
  }
122444
- function hasCollisions(cy, ancestors) {
122445
- const boxes = cy.nodes().map((node) => ({
122448
+ function readLeafGeometry(node) {
122449
+ const nodeBox = node.boundingBox({
122450
+ includeLabels: true,
122451
+ includeOverlays: false,
122452
+ includeUnderlays: false
122453
+ });
122454
+ const labelBox = node.boundingBox({
122455
+ includeNodes: false,
122456
+ includeEdges: false,
122457
+ includeLabels: true,
122458
+ includeOverlays: false,
122459
+ includeUnderlays: false
122460
+ });
122461
+ return {
122446
122462
  id: node.id(),
122447
- box: node.boundingBox({
122448
- includeLabels: true,
122449
- includeOverlays: false,
122450
- includeUnderlays: false
122451
- })
122452
- })).sort((a, b) => a.box.x1 - b.box.x1);
122453
- const budget = { remaining: 200000 };
122454
- for (const [index, first] of boxes.entries()) {
122455
- for (let next = index + 1;next < boxes.length; next += 1) {
122456
- const second = boxes.at(next);
122463
+ ancestors: new Set(node.ancestors().map((parent) => parent.id())),
122464
+ position: { ...node.position() },
122465
+ labelBox: isUsableBox(labelBox) ? labelBox : nodeBox,
122466
+ nodeBox
122467
+ };
122468
+ }
122469
+ function readGroupGeometry(id, ancestorIds, parentBox, leaves) {
122470
+ const descendants = leaves.filter((leaf) => leaf.ancestors.has(id));
122471
+ const descendantUnion = unionBounds(descendants.map((leaf) => leaf.nodeBox)) ?? parentBox;
122472
+ return {
122473
+ id,
122474
+ ancestors: new Set(ancestorIds),
122475
+ descendants,
122476
+ insets: {
122477
+ left: Math.max(0, descendantUnion.x1 - parentBox.x1),
122478
+ right: Math.max(0, parentBox.x2 - descendantUnion.x2),
122479
+ top: Math.max(0, descendantUnion.y1 - parentBox.y1),
122480
+ bottom: Math.max(0, parentBox.y2 - descendantUnion.y2)
122481
+ }
122482
+ };
122483
+ }
122484
+ function resolveCollisionBoxes(leaves, groups, center, factor) {
122485
+ const labels = leaves.map((leaf) => ({
122486
+ id: leaf.id,
122487
+ ancestors: leaf.ancestors,
122488
+ kind: "label",
122489
+ box: shiftBounds(leaf.labelBox, leaf.position, center, factor)
122490
+ }));
122491
+ const compoundBoxes = groups.flatMap((group) => {
122492
+ const descendants = group.descendants.map((leaf) => shiftBounds(leaf.nodeBox, leaf.position, center, factor));
122493
+ const union = unionBounds(descendants);
122494
+ if (!union)
122495
+ return [];
122496
+ return [
122497
+ {
122498
+ id: group.id,
122499
+ ancestors: group.ancestors,
122500
+ kind: "group",
122501
+ box: expandBounds(union, group.insets)
122502
+ }
122503
+ ];
122504
+ });
122505
+ return [...labels, ...compoundBoxes];
122506
+ }
122507
+ function findExpansionMaximum(accepts) {
122508
+ return Array.from({ length: MAX_EXPANSION_ATTEMPTS }, (_, index) => 2 ** (index + 1)).find(accepts);
122509
+ }
122510
+ function hasUnsafeCollisions(boxes) {
122511
+ const sorted = [...boxes].sort((first, second) => first.box.x1 - second.box.x1);
122512
+ const budget = { remaining: MAX_PAIR_CHECKS };
122513
+ for (const [index, first] of sorted.entries()) {
122514
+ for (let next = index + 1;next < sorted.length; next += 1) {
122515
+ const second = sorted.at(next);
122457
122516
  if (!second)
122458
122517
  break;
122459
- if (second.box.x1 >= first.box.x2 + 8)
122518
+ if (second.box.x1 >= first.box.x2)
122460
122519
  break;
122461
- if (--budget.remaining < 0)
122520
+ budget.remaining -= 1;
122521
+ if (budget.remaining < 0)
122462
122522
  return true;
122463
- if (ancestors.get(first.id)?.has(second.id) || ancestors.get(second.id)?.has(first.id))
122523
+ if (isIntentionalContainment(first, second))
122464
122524
  continue;
122465
- if (first.box.y1 < second.box.y2 + 8 && second.box.y1 < first.box.y2 + 8)
122525
+ if (isUnsafeOverlap(first, second))
122466
122526
  return true;
122467
122527
  }
122468
122528
  }
122469
122529
  return false;
122470
122530
  }
122531
+ function isIntentionalContainment(first, second) {
122532
+ return first.ancestors.has(second.id) || second.ancestors.has(first.id);
122533
+ }
122534
+ function isUnsafeOverlap(first, second) {
122535
+ const overlapWidth = Math.min(first.box.x2, second.box.x2) - Math.max(first.box.x1, second.box.x1);
122536
+ const overlapHeight = Math.min(first.box.y2, second.box.y2) - Math.max(first.box.y1, second.box.y1);
122537
+ if (overlapWidth <= 0 || overlapHeight <= 0)
122538
+ return false;
122539
+ if (first.kind !== "label" || second.kind !== "label")
122540
+ return true;
122541
+ const widthRatio = overlapWidth / Math.min(first.box.w, second.box.w);
122542
+ const heightRatio = overlapHeight / Math.min(first.box.h, second.box.h);
122543
+ return widthRatio > LABEL_OVERLAP_RATIO && heightRatio > LABEL_OVERLAP_RATIO;
122544
+ }
122545
+ function shiftBounds(box, position, center, factor) {
122546
+ const dx = (position.x - center.x) * (factor - 1);
122547
+ const dy = (position.y - center.y) * (factor - 1);
122548
+ return {
122549
+ x1: box.x1 + dx,
122550
+ y1: box.y1 + dy,
122551
+ x2: box.x2 + dx,
122552
+ y2: box.y2 + dy,
122553
+ w: box.w,
122554
+ h: box.h
122555
+ };
122556
+ }
122557
+ function expandBounds(box, insets) {
122558
+ const x1 = box.x1 - insets.left;
122559
+ const y1 = box.y1 - insets.top;
122560
+ const x2 = box.x2 + insets.right;
122561
+ const y2 = box.y2 + insets.bottom;
122562
+ return { x1, y1, x2, y2, w: x2 - x1, h: y2 - y1 };
122563
+ }
122564
+ function unionBounds(boxes) {
122565
+ if (boxes.length === 0)
122566
+ return;
122567
+ const x1 = Math.min(...boxes.map((box) => box.x1));
122568
+ const y1 = Math.min(...boxes.map((box) => box.y1));
122569
+ const x2 = Math.max(...boxes.map((box) => box.x2));
122570
+ const y2 = Math.max(...boxes.map((box) => box.y2));
122571
+ return { x1, y1, x2, y2, w: x2 - x1, h: y2 - y1 };
122572
+ }
122573
+ function isUsableBox(box) {
122574
+ return box.w > 0 && box.h > 0;
122575
+ }
122576
+ function applyScale(cy, leaves, center, factor) {
122577
+ const positions = new Map(leaves.map((leaf) => [leaf.id, leaf.position]));
122578
+ cy.batch(() => {
122579
+ cy.nodes().not(":parent").positions((node) => {
122580
+ const original = positions.get(node.id()) ?? node.position();
122581
+ return {
122582
+ x: center.x + (original.x - center.x) * factor,
122583
+ y: center.y + (original.y - center.y) * factor
122584
+ };
122585
+ });
122586
+ });
122587
+ }
122471
122588
 
122472
122589
  // src/features/graph-view/adapters/inbound/web-artifact/fitGraphViewport.ts
122473
122590
  function fitGraphViewport(cy, options = {}, maxZoom = Infinity) {
@@ -8,7 +8,7 @@ import {
8
8
  TabList2,
9
9
  TabPanel2,
10
10
  Tabs2
11
- } from "../../chunks/Accordion-aj6fsjhv.js";
11
+ } from "../../chunks/Accordion-j4d58grp.js";
12
12
  import"../../chunks/Accordion-kcx57mk5.js";
13
13
  import"../../chunks/Accordion-grfbz6f2.js";
14
14
  import"../../chunks/Accordion-6zb9d92y.js";
@@ -8,7 +8,7 @@ import {
8
8
  TabList2,
9
9
  TabPanel2,
10
10
  Tabs2
11
- } from "../../chunks/Accordion-aj6fsjhv.js";
11
+ } from "../../chunks/Accordion-j4d58grp.js";
12
12
  import"../../chunks/Accordion-kcx57mk5.js";
13
13
  import"../../chunks/Accordion-grfbz6f2.js";
14
14
  import"../../chunks/Accordion-6zb9d92y.js";
@@ -8,7 +8,7 @@ import {
8
8
  TabList2,
9
9
  TabPanel2,
10
10
  Tabs2
11
- } from "../../chunks/Accordion-aj6fsjhv.js";
11
+ } from "../../chunks/Accordion-j4d58grp.js";
12
12
  import"../../chunks/Accordion-kcx57mk5.js";
13
13
  import"../../chunks/Accordion-grfbz6f2.js";
14
14
  import"../../chunks/Accordion-6zb9d92y.js";
@@ -8,7 +8,7 @@ import {
8
8
  TabList2,
9
9
  TabPanel2,
10
10
  Tabs2
11
- } from "../../chunks/Accordion-aj6fsjhv.js";
11
+ } from "../../chunks/Accordion-j4d58grp.js";
12
12
  import"../../chunks/Accordion-kcx57mk5.js";
13
13
  import"../../chunks/Accordion-grfbz6f2.js";
14
14
  import"../../chunks/Accordion-6zb9d92y.js";
@@ -2790,11 +2790,11 @@
2790
2790
  "chunks/Accordion-59pa0677.js",
2791
2791
  "chunks/Accordion-6zb9d92y.js",
2792
2792
  "chunks/Accordion-9qvmwkxe.js",
2793
- "chunks/Accordion-aj6fsjhv.js",
2794
2793
  "chunks/Accordion-ars389m1.js",
2795
2794
  "chunks/Accordion-f5swy5bs.js",
2796
2795
  "chunks/Accordion-fre84yaq.js",
2797
2796
  "chunks/Accordion-grfbz6f2.js",
2797
+ "chunks/Accordion-j4d58grp.js",
2798
2798
  "chunks/Accordion-jh7nxehr.js",
2799
2799
  "chunks/Accordion-kcx57mk5.js",
2800
2800
  "chunks/Accordion-mnac2z83.js",
@@ -2817,11 +2817,11 @@
2817
2817
  "chunks/Accordion-59pa0677.js",
2818
2818
  "chunks/Accordion-6zb9d92y.js",
2819
2819
  "chunks/Accordion-9qvmwkxe.js",
2820
- "chunks/Accordion-aj6fsjhv.js",
2821
2820
  "chunks/Accordion-ars389m1.js",
2822
2821
  "chunks/Accordion-f5swy5bs.js",
2823
2822
  "chunks/Accordion-fre84yaq.js",
2824
2823
  "chunks/Accordion-grfbz6f2.js",
2824
+ "chunks/Accordion-j4d58grp.js",
2825
2825
  "chunks/Accordion-jh7nxehr.js",
2826
2826
  "chunks/Accordion-kcx57mk5.js",
2827
2827
  "chunks/Accordion-mnac2z83.js",
@@ -2844,11 +2844,11 @@
2844
2844
  "chunks/Accordion-59pa0677.js",
2845
2845
  "chunks/Accordion-6zb9d92y.js",
2846
2846
  "chunks/Accordion-9qvmwkxe.js",
2847
- "chunks/Accordion-aj6fsjhv.js",
2848
2847
  "chunks/Accordion-ars389m1.js",
2849
2848
  "chunks/Accordion-f5swy5bs.js",
2850
2849
  "chunks/Accordion-fre84yaq.js",
2851
2850
  "chunks/Accordion-grfbz6f2.js",
2851
+ "chunks/Accordion-j4d58grp.js",
2852
2852
  "chunks/Accordion-jh7nxehr.js",
2853
2853
  "chunks/Accordion-kcx57mk5.js",
2854
2854
  "chunks/Accordion-mnac2z83.js",
@@ -2871,11 +2871,11 @@
2871
2871
  "chunks/Accordion-59pa0677.js",
2872
2872
  "chunks/Accordion-6zb9d92y.js",
2873
2873
  "chunks/Accordion-9qvmwkxe.js",
2874
- "chunks/Accordion-aj6fsjhv.js",
2875
2874
  "chunks/Accordion-ars389m1.js",
2876
2875
  "chunks/Accordion-f5swy5bs.js",
2877
2876
  "chunks/Accordion-fre84yaq.js",
2878
2877
  "chunks/Accordion-grfbz6f2.js",
2878
+ "chunks/Accordion-j4d58grp.js",
2879
2879
  "chunks/Accordion-jh7nxehr.js",
2880
2880
  "chunks/Accordion-kcx57mk5.js",
2881
2881
  "chunks/Accordion-mnac2z83.js",