@pixerate/editor-svelte 0.10.1 → 0.11.1

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.
@@ -93,6 +93,7 @@ export interface CanvasInteractionPresetConfig {
93
93
  multiSelectionKey?: string[];
94
94
  minZoom?: number;
95
95
  maxZoom?: number;
96
+ selectionMode?: 'partial' | 'full';
96
97
  }
97
98
 
98
99
  /**
@@ -571,3 +572,117 @@ export declare function createCanvasExplosion<
571
572
  getSnapshot(parentId: string): ExplosionSnapshot<TNode, TEdge> | undefined;
572
573
  };
573
574
 
575
+ export interface HandleConfig {
576
+ id?: string | null;
577
+ type: 'source' | 'target';
578
+ position: any;
579
+ x?: number;
580
+ y?: number;
581
+ width?: number;
582
+ height?: number;
583
+ }
584
+
585
+ export interface NodeMeasurement {
586
+ width: number;
587
+ height: number;
588
+ }
589
+
590
+ export declare function preserveNodeMeasurements<TNode extends CanvasNode = CanvasNode>(
591
+ newNodes: TNode[],
592
+ existingNodes: TNode[] | Map<string, TNode>
593
+ ): TNode[];
594
+
595
+ export declare function normalizeNodeHandles<TNode extends CanvasNode = CanvasNode>(
596
+ node: TNode,
597
+ handles?: HandleConfig[]
598
+ ): TNode;
599
+
600
+ export interface CreateCanvasNodeSyncOptions<
601
+ TItem,
602
+ TNode extends CanvasNode = CanvasNode,
603
+ TEdge extends CanvasEdge = CanvasEdge
604
+ > {
605
+ items: () => TItem[];
606
+ toNode: (
607
+ item: TItem,
608
+ index: number,
609
+ context: { existingNode?: TNode; prevNodesMap: Map<string, TNode> }
610
+ ) => TNode;
611
+ toEdges?: (items: TItem[], nodes: TNode[]) => TEdge[];
612
+ defaultHandles?: (node: TNode) => HandleConfig[] | undefined;
613
+ }
614
+
615
+ export declare function createCanvasNodeSync<
616
+ TItem,
617
+ TNode extends CanvasNode = CanvasNode,
618
+ TEdge extends CanvasEdge = CanvasEdge
619
+ >(options: CreateCanvasNodeSyncOptions<TItem, TNode, TEdge>): {
620
+ nodes: TNode[];
621
+ edges: TEdge[];
622
+ updateNodeMeasurements(id: string, width: number, height: number): void;
623
+ };
624
+
625
+ export interface MultiDragFollowerOffset {
626
+ deltaX: number;
627
+ deltaY: number;
628
+ originalPosition: XYPosition;
629
+ stackOffsetX: number;
630
+ stackOffsetY: number;
631
+ rotationDeg: number;
632
+ }
633
+
634
+ export interface MultiDragState {
635
+ leadId: string;
636
+ offsets: Record<string, MultiDragFollowerOffset>;
637
+ count: number;
638
+ }
639
+
640
+ export interface CreateCanvasMultiDragOptions {
641
+ stackOffsetStepX?: number;
642
+ stackOffsetStepY?: number;
643
+ rotationAngles?: number[];
644
+ baseZIndex?: number;
645
+ }
646
+
647
+ export interface FollowerTransform {
648
+ isFollower: boolean;
649
+ stackOffsetX: number;
650
+ stackOffsetY: number;
651
+ rotationDeg: number;
652
+ zIndex: number;
653
+ }
654
+
655
+ export declare function createCanvasMultiDrag(options?: CreateCanvasMultiDragOptions): {
656
+ readonly dragState: MultiDragState | null;
657
+ readonly isMultiDrag: boolean;
658
+ readonly count: number;
659
+ readonly leadId: string | null;
660
+ startMultiDrag(
661
+ leadNodeId: string,
662
+ selectedNodeIds: string[] | Set<string>,
663
+ nodes: CanvasNode[] | Map<string, CanvasNode>
664
+ ): MultiDragState | null;
665
+ getFollowerTransform(nodeId: string): FollowerTransform;
666
+ cancelMultiDrag(
667
+ applyRestore?: (restores: { id: string; originalPosition: XYPosition }[]) => void
668
+ ): { id: string; originalPosition: XYPosition }[];
669
+ commitMultiDrag(): void;
670
+ };
671
+
672
+ export interface CanvasSelectionOptions {
673
+ isSpacebarPanning?: boolean;
674
+ selectionMode?: 'partial' | 'full';
675
+ multiSelectionKey?: string[];
676
+ }
677
+
678
+ export declare function getMarqueeSelectionPreset(
679
+ options?: CanvasSelectionOptions
680
+ ): CanvasInteractionPresetConfig;
681
+
682
+ export declare function handleDeselectOnEscape(
683
+ event: KeyboardEvent,
684
+ onDeselect: () => void
685
+ ): boolean;
686
+
687
+ export declare const FloatingHorizontalScrollbar: any;
688
+
@@ -279,8 +279,8 @@ function getLayoutedNodes(nodes, edges, getNodesBounds, options = {}) {
279
279
  // src/canvas/createCanvasClipboard.svelte.ts
280
280
  import * as $2 from "svelte/internal/client";
281
281
  import { tick } from "svelte";
282
- function isEventFromTextInput(event) {
283
- const target = event.target;
282
+ function isEventFromTextInput(event2) {
283
+ const target = event2.target;
284
284
  if (!target) return false;
285
285
  if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.tagName === "SELECT" || target.isContentEditable || target.closest?.('[contenteditable="true"]') || target.closest?.(".ProseMirror")) {
286
286
  return true;
@@ -299,44 +299,44 @@ function isValidUrl(url) {
299
299
  }
300
300
  }
301
301
  function createCanvasClipboard(options = {}) {
302
- function copySelectedNodes(selectedNodes, connectedEdges, event) {
303
- if (event && isEventFromTextInput(event)) {
302
+ function copySelectedNodes(selectedNodes, connectedEdges, event2) {
303
+ if (event2 && isEventFromTextInput(event2)) {
304
304
  return false;
305
305
  }
306
306
  if (selectedNodes.length === 0) return false;
307
307
  const payload = { version: 1, nodes: selectedNodes, edges: connectedEdges };
308
308
  const serialized = JSON.stringify(payload);
309
- if (event?.clipboardData) {
310
- event.clipboardData.setData("application/json", serialized);
311
- event.clipboardData.setData("text/plain", serialized);
312
- event.preventDefault();
309
+ if (event2?.clipboardData) {
310
+ event2.clipboardData.setData("application/json", serialized);
311
+ event2.clipboardData.setData("text/plain", serialized);
312
+ event2.preventDefault();
313
313
  } else if (typeof navigator !== "undefined" && navigator.clipboard) {
314
314
  navigator.clipboard.writeText(serialized).catch(() => {
315
315
  });
316
316
  }
317
317
  return true;
318
318
  }
319
- function cutSelectedNodes(selectedNodes, connectedEdges, onRemove, event) {
320
- if (event && isEventFromTextInput(event)) {
319
+ function cutSelectedNodes(selectedNodes, connectedEdges, onRemove, event2) {
320
+ if (event2 && isEventFromTextInput(event2)) {
321
321
  return false;
322
322
  }
323
- const copied = copySelectedNodes(selectedNodes, connectedEdges, event);
323
+ const copied = copySelectedNodes(selectedNodes, connectedEdges, event2);
324
324
  if (copied && onRemove) {
325
325
  onRemove(selectedNodes);
326
326
  }
327
327
  return copied;
328
328
  }
329
- async function handlePasteEvent(event) {
330
- if (isEventFromTextInput(event)) {
329
+ async function handlePasteEvent(event2) {
330
+ if (isEventFromTextInput(event2)) {
331
331
  return false;
332
332
  }
333
- const clipboardData = event.clipboardData;
333
+ const clipboardData = event2.clipboardData;
334
334
  if (!clipboardData) return false;
335
335
  const files = clipboardData.files;
336
336
  if (files && files.length > 0) {
337
337
  const imageFile = Array.from(files).find((f) => f.type.startsWith("image/"));
338
338
  if (imageFile && options.onPasteImage) {
339
- event.preventDefault();
339
+ event2.preventDefault();
340
340
  await options.onPasteImage(imageFile);
341
341
  return true;
342
342
  }
@@ -354,7 +354,7 @@ function createCanvasClipboard(options = {}) {
354
354
  rawEdges = parsed.edges;
355
355
  }
356
356
  if (rawNodes && rawNodes.length > 0) {
357
- event.preventDefault();
357
+ event2.preventDefault();
358
358
  const idMap = /* @__PURE__ */ new Map();
359
359
  const newNodes = rawNodes.map((node) => {
360
360
  const newId = crypto.randomUUID();
@@ -384,11 +384,11 @@ function createCanvasClipboard(options = {}) {
384
384
  const text = clipboardData.getData("text/plain")?.trim();
385
385
  if (text) {
386
386
  if (isValidUrl(text) && options.onPasteUrl) {
387
- event.preventDefault();
387
+ event2.preventDefault();
388
388
  options.onPasteUrl(text);
389
389
  return true;
390
390
  } else if (options.onPasteText) {
391
- event.preventDefault();
391
+ event2.preventDefault();
392
392
  options.onPasteText(text);
393
393
  return true;
394
394
  }
@@ -421,19 +421,19 @@ function getOverlapArea(rectA, rectB) {
421
421
  const yOverlap = Math.max(0, Math.min(rectA.y + rectA.height, rectB.y + rectB.height) - Math.max(rectA.y, rectB.y));
422
422
  return xOverlap * yOverlap;
423
423
  }
424
- function resolvePrimaryTarget(targets, draggedNode, strategy, customResolver, event) {
424
+ function resolvePrimaryTarget(targets, draggedNode, strategy, customResolver, event2) {
425
425
  if (targets.length === 0) return null;
426
426
  if (targets.length === 1) return targets[0];
427
427
  if (customResolver) {
428
- const resolved = customResolver(targets, draggedNode, event);
428
+ const resolved = customResolver(targets, draggedNode, event2);
429
429
  if (resolved !== void 0) return resolved;
430
430
  }
431
431
  if (strategy === "first") {
432
432
  return targets[0];
433
433
  }
434
- if (strategy === "pointer" && event) {
435
- const clientX = "clientX" in event ? event.clientX : event.touches?.[0]?.clientX;
436
- const clientY = "clientY" in event ? event.clientY : event.touches?.[0]?.clientY;
434
+ if (strategy === "pointer" && event2) {
435
+ const clientX = "clientX" in event2 ? event2.clientX : event2.touches?.[0]?.clientX;
436
+ const clientY = "clientY" in event2 ? event2.clientY : event2.touches?.[0]?.clientY;
437
437
  if (typeof clientX === "number" && typeof clientY === "number") {
438
438
  const pointerInside = targets.filter((target) => {
439
439
  const r = getNodeRect(target);
@@ -596,8 +596,8 @@ function createCanvasShortcuts(options) {
596
596
  const target = options.targetElement ?? (typeof window !== "undefined" ? window : null);
597
597
  if (!target) return () => {
598
598
  };
599
- function handleKeyDown(event) {
600
- const keyboardEvent = event;
599
+ function handleKeyDown(event2) {
600
+ const keyboardEvent = event2;
601
601
  if (isEventFromTextInput(keyboardEvent)) {
602
602
  return;
603
603
  }
@@ -679,9 +679,9 @@ function createCanvasInteractions(options = {}) {
679
679
  let isSpacebarPanning = $4.state(false);
680
680
  let trackpadDetected = $4.state(false);
681
681
  let toggledPanMode = false;
682
- function handleKeyDown(event) {
683
- if (event.key === " " || event.code === "Space") {
684
- if ($4.get(isSpacebarPanning) || isEventFromTextInput(event)) return;
682
+ function handleKeyDown(event2) {
683
+ if (event2.key === " " || event2.code === "Space") {
684
+ if ($4.get(isSpacebarPanning) || isEventFromTextInput(event2)) return;
685
685
  $4.set(isSpacebarPanning, true);
686
686
  toggledPanMode = true;
687
687
  options.onPanModeChange?.(true);
@@ -690,8 +690,8 @@ function createCanvasInteractions(options = {}) {
690
690
  }
691
691
  }
692
692
  }
693
- function handleKeyUp(event) {
694
- if (event.key === " " || event.code === "Space") {
693
+ function handleKeyUp(event2) {
694
+ if (event2.key === " " || event2.code === "Space") {
695
695
  if (!$4.get(isSpacebarPanning) && !toggledPanMode) return;
696
696
  $4.set(isSpacebarPanning, false);
697
697
  toggledPanMode = false;
@@ -701,8 +701,8 @@ function createCanvasInteractions(options = {}) {
701
701
  }
702
702
  }
703
703
  }
704
- function handleWheel(event) {
705
- if (event.ctrlKey && !$4.get(trackpadDetected)) {
704
+ function handleWheel(event2) {
705
+ if (event2.ctrlKey && !$4.get(trackpadDetected)) {
706
706
  $4.set(trackpadDetected, true);
707
707
  options.onTrackpadDetected?.();
708
708
  }
@@ -1380,7 +1380,290 @@ function createCanvasExplosion(graph, options = {}) {
1380
1380
  getSnapshot
1381
1381
  };
1382
1382
  }
1383
+
1384
+ // src/canvas/createCanvasNodeSync.svelte.ts
1385
+ import * as $6 from "svelte/internal/client";
1386
+ import { untrack } from "svelte";
1387
+ function preserveNodeMeasurements(newNodes, existingNodes) {
1388
+ const map = existingNodes instanceof Map ? existingNodes : new Map(existingNodes.map((n) => [n.id, n]));
1389
+ for (const node of newNodes) {
1390
+ const prev = map.get(node.id);
1391
+ if (prev && prev.measured) {
1392
+ node.measured = { ...prev.measured };
1393
+ }
1394
+ }
1395
+ return newNodes;
1396
+ }
1397
+ function normalizeNodeHandles(node, handles = []) {
1398
+ node.handles = handles;
1399
+ return node;
1400
+ }
1401
+ function createCanvasNodeSync(options) {
1402
+ let nodes = $6.state($6.proxy([]));
1403
+ let edges = $6.state($6.proxy([]));
1404
+ $6.user_pre_effect(() => {
1405
+ const rawItems = options.items();
1406
+ const existingNodesMap = untrack(() => new Map($6.get(nodes).map((n) => [n.id, n])));
1407
+ const newNodes = rawItems.map((item, index) => {
1408
+ const existing = existingNodesMap.get(item?.id);
1409
+ const node = options.toNode(item, index, { existingNode: existing, prevNodesMap: existingNodesMap });
1410
+ if (existing && existing.measured && !node.measured) {
1411
+ node.measured = { ...existing.measured };
1412
+ }
1413
+ if (options.defaultHandles && !node.handles) {
1414
+ const handles = options.defaultHandles(node);
1415
+ if (handles) {
1416
+ node.handles = handles;
1417
+ }
1418
+ }
1419
+ return node;
1420
+ });
1421
+ const newEdges = options.toEdges ? options.toEdges(rawItems, newNodes) : [];
1422
+ $6.set(nodes, newNodes, true);
1423
+ $6.set(edges, newEdges, true);
1424
+ });
1425
+ return {
1426
+ get nodes() {
1427
+ return $6.get(nodes);
1428
+ },
1429
+ set nodes(value) {
1430
+ $6.set(nodes, value, true);
1431
+ },
1432
+ get edges() {
1433
+ return $6.get(edges);
1434
+ },
1435
+ set edges(value) {
1436
+ $6.set(edges, value, true);
1437
+ },
1438
+ updateNodeMeasurements(id, width, height) {
1439
+ const node = $6.get(nodes).find((n) => n.id === id);
1440
+ if (node) {
1441
+ node.measured = { width, height };
1442
+ }
1443
+ }
1444
+ };
1445
+ }
1446
+
1447
+ // src/canvas/createCanvasMultiDrag.svelte.ts
1448
+ import * as $7 from "svelte/internal/client";
1449
+ function createCanvasMultiDrag(options = {}) {
1450
+ const stepX = options.stackOffsetStepX ?? 4;
1451
+ const stepY = options.stackOffsetStepY ?? 4;
1452
+ const angles = options.rotationAngles ?? [-2, 2.5, -3, 3];
1453
+ const baseZIndex = options.baseZIndex ?? 50;
1454
+ let dragState = $7.state(null);
1455
+ function startMultiDrag(leadNodeId, selectedNodeIds, nodes) {
1456
+ const selectedSet = selectedNodeIds instanceof Set ? selectedNodeIds : new Set(selectedNodeIds);
1457
+ if (selectedSet.size <= 1 || !selectedSet.has(leadNodeId)) {
1458
+ $7.set(dragState, null);
1459
+ return null;
1460
+ }
1461
+ const nodeMap = nodes instanceof Map ? nodes : new Map(nodes.map((n) => [n.id, n]));
1462
+ const leadNode = nodeMap.get(leadNodeId);
1463
+ if (!leadNode) {
1464
+ $7.set(dragState, null);
1465
+ return null;
1466
+ }
1467
+ const leadPos = leadNode.position ?? { x: 0, y: 0 };
1468
+ const offsets = {};
1469
+ let followerIndex = 0;
1470
+ for (const id of selectedSet) {
1471
+ if (id === leadNodeId) continue;
1472
+ const follower = nodeMap.get(id);
1473
+ const fPos = follower?.position ?? { x: 0, y: 0 };
1474
+ const angle = angles[followerIndex % angles.length];
1475
+ offsets[id] = {
1476
+ deltaX: fPos.x - leadPos.x,
1477
+ deltaY: fPos.y - leadPos.y,
1478
+ originalPosition: { ...fPos },
1479
+ stackOffsetX: (followerIndex + 1) * stepX,
1480
+ stackOffsetY: (followerIndex + 1) * stepY,
1481
+ rotationDeg: angle
1482
+ };
1483
+ followerIndex++;
1484
+ }
1485
+ const state8 = { leadId: leadNodeId, offsets, count: selectedSet.size };
1486
+ $7.set(dragState, state8, true);
1487
+ return state8;
1488
+ }
1489
+ function getFollowerTransform(nodeId) {
1490
+ if (!$7.get(dragState) || !(nodeId in $7.get(dragState).offsets)) {
1491
+ return {
1492
+ isFollower: false,
1493
+ stackOffsetX: 0,
1494
+ stackOffsetY: 0,
1495
+ rotationDeg: 0,
1496
+ zIndex: 0
1497
+ };
1498
+ }
1499
+ const offset = $7.get(dragState).offsets[nodeId];
1500
+ const followerKeys = Object.keys($7.get(dragState).offsets);
1501
+ const index = followerKeys.indexOf(nodeId);
1502
+ return {
1503
+ isFollower: true,
1504
+ stackOffsetX: offset.stackOffsetX,
1505
+ stackOffsetY: offset.stackOffsetY,
1506
+ rotationDeg: offset.rotationDeg,
1507
+ zIndex: baseZIndex - (index + 1)
1508
+ };
1509
+ }
1510
+ function cancelMultiDrag(applyRestore) {
1511
+ if (!$7.get(dragState)) return [];
1512
+ const restores = Object.entries($7.get(dragState).offsets).map(([id, offset]) => ({ id, originalPosition: { ...offset.originalPosition } }));
1513
+ if (applyRestore) {
1514
+ applyRestore(restores);
1515
+ }
1516
+ $7.set(dragState, null);
1517
+ return restores;
1518
+ }
1519
+ function commitMultiDrag() {
1520
+ $7.set(dragState, null);
1521
+ }
1522
+ return {
1523
+ get dragState() {
1524
+ return $7.get(dragState);
1525
+ },
1526
+ get isMultiDrag() {
1527
+ return Boolean($7.get(dragState) && $7.get(dragState).count > 1);
1528
+ },
1529
+ get count() {
1530
+ return $7.get(dragState) ? $7.get(dragState).count : 0;
1531
+ },
1532
+ get leadId() {
1533
+ return $7.get(dragState)?.leadId ?? null;
1534
+ },
1535
+ startMultiDrag,
1536
+ getFollowerTransform,
1537
+ cancelMultiDrag,
1538
+ commitMultiDrag
1539
+ };
1540
+ }
1541
+
1542
+ // src/canvas/createCanvasSelection.svelte.ts
1543
+ import * as $8 from "svelte/internal/client";
1544
+ function getMarqueeSelectionPreset(options = {}) {
1545
+ const isSpacebarPanning = options.isSpacebarPanning ?? false;
1546
+ return {
1547
+ snapGrid: [25, 25],
1548
+ panOnDrag: isSpacebarPanning ? [0, 1, 2] : [1, 2],
1549
+ panOnScroll: false,
1550
+ selectionOnDrag: !isSpacebarPanning,
1551
+ colorMode: "system",
1552
+ multiSelectionKey: options.multiSelectionKey ?? ["Shift", "Meta"],
1553
+ selectionMode: options.selectionMode ?? "partial"
1554
+ };
1555
+ }
1556
+ function handleDeselectOnEscape(event2, onDeselect) {
1557
+ if (event2.key === "Escape" || event2.code === "Escape") {
1558
+ onDeselect();
1559
+ return true;
1560
+ }
1561
+ return false;
1562
+ }
1563
+
1564
+ // src/canvas/FloatingHorizontalScrollbar.svelte
1565
+ import "svelte/internal/disclose-version";
1566
+ import * as $9 from "svelte/internal/client";
1567
+ import { onMount } from "svelte";
1568
+ var root = $9.from_html(`<div class="fixed bottom-0 z-50 overflow-x-auto overflow-y-hidden border-t border-border/40 bg-background/80 shadow-md backdrop-blur-sm transition-opacity duration-150" role="scrollbar" aria-orientation="horizontal"><div></div></div>`);
1569
+ function FloatingHorizontalScrollbar($$anchor, $$props) {
1570
+ $9.push($$props, true);
1571
+ let targetElement = $9.prop($$props, "targetElement", 7, null), totalWidth = $9.prop($$props, "totalWidth", 3, 1e3), minHeightAboveFold = $9.prop($$props, "minHeightAboveFold", 3, 80);
1572
+ let scrollbarRef = $9.state(null);
1573
+ let isVisible = $9.state(false);
1574
+ let barLeft = $9.state(0);
1575
+ let barWidth = $9.state(0);
1576
+ let isSyncing = false;
1577
+ function updateMetrics() {
1578
+ if (!targetElement()) {
1579
+ $9.set(isVisible, false);
1580
+ return;
1581
+ }
1582
+ const rect = targetElement().getBoundingClientRect();
1583
+ const hasHorizontalOverflow = targetElement().scrollWidth > targetElement().clientWidth;
1584
+ const isTopInView = rect.top < window.innerHeight;
1585
+ const isBottomBelowViewport = rect.bottom > window.innerHeight;
1586
+ const isBottomAboveTop = rect.bottom > minHeightAboveFold();
1587
+ const shouldShow = hasHorizontalOverflow && isTopInView && isBottomBelowViewport && isBottomAboveTop;
1588
+ $9.set(isVisible, shouldShow, true);
1589
+ if (shouldShow) {
1590
+ const left = Math.max(0, rect.left);
1591
+ const right = Math.min(window.innerWidth, rect.right);
1592
+ $9.set(barLeft, left, true);
1593
+ $9.set(barWidth, Math.max(0, right - left), true);
1594
+ if ($9.get(scrollbarRef) && Math.abs($9.get(scrollbarRef).scrollLeft - targetElement().scrollLeft) > 1) {
1595
+ isSyncing = true;
1596
+ $9.get(scrollbarRef).scrollLeft = targetElement().scrollLeft;
1597
+ requestAnimationFrame(() => {
1598
+ isSyncing = false;
1599
+ });
1600
+ }
1601
+ }
1602
+ }
1603
+ function handleFloatingScroll() {
1604
+ if (!$9.get(scrollbarRef) || !targetElement() || isSyncing) return;
1605
+ isSyncing = true;
1606
+ targetElement().scrollLeft = $9.get(scrollbarRef).scrollLeft;
1607
+ requestAnimationFrame(() => {
1608
+ isSyncing = false;
1609
+ });
1610
+ }
1611
+ onMount(() => {
1612
+ updateMetrics();
1613
+ const onScrollOrResize = () => {
1614
+ updateMetrics();
1615
+ };
1616
+ window.addEventListener("scroll", onScrollOrResize, { passive: true });
1617
+ window.addEventListener("resize", onScrollOrResize, { passive: true });
1618
+ const target = targetElement();
1619
+ if (target) {
1620
+ target.addEventListener("scroll", onScrollOrResize, { passive: true });
1621
+ }
1622
+ return () => {
1623
+ window.removeEventListener("scroll", onScrollOrResize);
1624
+ window.removeEventListener("resize", onScrollOrResize);
1625
+ if (target) {
1626
+ target.removeEventListener("scroll", onScrollOrResize);
1627
+ }
1628
+ };
1629
+ });
1630
+ $9.user_effect(() => {
1631
+ if (targetElement()) {
1632
+ updateMetrics();
1633
+ }
1634
+ });
1635
+ var fragment = $9.comment();
1636
+ var node = $9.first_child(fragment);
1637
+ {
1638
+ var consequent = ($$anchor2) => {
1639
+ var div = root();
1640
+ $9.set_attribute(div, "aria-valuemin", 0);
1641
+ var div_1 = $9.only_child(div);
1642
+ $9.bind_this(div, ($$value) => $9.set(scrollbarRef, $$value), () => $9.get(scrollbarRef));
1643
+ $9.template_effect(
1644
+ ($0) => {
1645
+ $9.set_style(div, `left: ${$9.get(barLeft) ?? ""}px; width: ${$9.get(barWidth) ?? ""}px; height: 14px;`);
1646
+ $9.set_attribute(div, "aria-controls", targetElement()?.id);
1647
+ $9.set_attribute(div, "aria-valuenow", targetElement()?.scrollLeft ?? 0);
1648
+ $9.set_attribute(div, "aria-valuemax", (targetElement()?.scrollWidth ?? totalWidth()) - (targetElement()?.clientWidth ?? 0));
1649
+ $9.set_style(div_1, `width: ${$0 ?? ""}px; height: 1px;`);
1650
+ },
1651
+ [
1652
+ () => Math.max(totalWidth(), targetElement()?.scrollWidth ?? 0)
1653
+ ]
1654
+ );
1655
+ $9.event("scroll", div, handleFloatingScroll);
1656
+ $9.append($$anchor2, div);
1657
+ };
1658
+ $9.if(node, ($$render) => {
1659
+ if ($9.get(isVisible)) $$render(consequent);
1660
+ });
1661
+ }
1662
+ $9.append($$anchor, fragment);
1663
+ $9.pop();
1664
+ }
1383
1665
  export {
1666
+ FloatingHorizontalScrollbar,
1384
1667
  calculateDirectionalDisplacement,
1385
1668
  calculateGraphDifferences,
1386
1669
  calculateReflowDisplacement,
@@ -1392,17 +1675,23 @@ export {
1392
1675
  createCanvasExplosion,
1393
1676
  createCanvasGraph,
1394
1677
  createCanvasInteractions,
1678
+ createCanvasMultiDrag,
1679
+ createCanvasNodeSync,
1395
1680
  createCanvasShortcuts,
1396
1681
  createFanOutTrajectory,
1397
1682
  defaultSvelteFlowPreset,
1398
1683
  getCenteredNodePosition,
1399
1684
  getLayoutedNodes,
1685
+ getMarqueeSelectionPreset,
1686
+ handleDeselectOnEscape,
1400
1687
  isEventFromTextInput,
1401
1688
  isValidCanvasNode,
1402
1689
  isValidUrl,
1403
1690
  linearPositionTrajectory,
1404
1691
  linearTrajectory,
1405
1692
  miroCompatiblePreset,
1693
+ normalizeNodeHandles,
1694
+ preserveNodeMeasurements,
1406
1695
  replaceNodeInGraph,
1407
1696
  restorePanelPointerEvents,
1408
1697
  runMultiNodeTransition