@dashfoo/react 0.5.2 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +173 -115
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@ paint.
|
|
|
15
15
|
It builds on three engines:
|
|
16
16
|
|
|
17
17
|
- **[react-resizable-panels](https://github.com/bvaughn/react-resizable-panels)** for splitter resize (the resize adapter is the only file that imports it).
|
|
18
|
-
- **[@dnd-kit/dom](https://github.com/clauderic/dnd-kit) 0.5** — the framework-agnostic core (no React bindings) — for drag (the drag adapter
|
|
18
|
+
- **[@dnd-kit/dom](https://github.com/clauderic/dnd-kit) 0.5** — the framework-agnostic core (no React bindings) — for drag (touched only by the drag adapter modules: `drag-adapter`/`drag-hooks`/`drag-overlays`; pointer-only). Tabsets are dnd-kit droppables behind a custom occlusion-aware collision detector; the preview chip rides the Feedback plugin's `overlay` accessor.
|
|
19
19
|
- **[@dashfoo/core](https://www.npmjs.com/package/@dashfoo/core)** for the document: a zod schema, a pure reducer, and the XState machines that drive state and the drag lifecycle.
|
|
20
20
|
|
|
21
21
|
## Install
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/hooks/persistence.ts","../src/components/dashfoo-layout.tsx","../src/components/drag-root.tsx","../src/hooks/drag-hooks.tsx","../src/components/drag-adapter.tsx","../src/components/float-layer.tsx","../src/components/layout-root.tsx","../src/components/row-view.tsx","../src/components/tabset/tabset-view.tsx","../src/components/layout.tsx","../src/components/panel.tsx","../src/components/tabset/tabset-tab-controls.tsx","../src/components/tabset/tabset-content.tsx","../src/components/tabset/tabset-toolbar.tsx","../src/components/tabset/tabset-root.tsx","../src/components/tabset/tabset-tab.tsx","../src/components/tabset/tabset-tablist.tsx","../src/components/tabset/tabset.ts","../src/components/tab-overflow.tsx","../src/components/tabset/tabset-store.ts","../src/hooks/layout-store.ts","../src/hooks/responsive.ts","../src/hooks/store.ts"],"mappings":";;;;KAQK,cAAA;EACH,OAAA,GAAU,GAAA;EACV,UAAA,GAAa,GAAA;EACb,OAAA,GAAU,GAAA,UAAa,KAAA;AAAA;AAAA,cAGnB,oBAAA,QAA2B,cAWhC;AAAA,cAIK,mBAAA,EAAqB,cAiC1B;AAAA,KAII,aAAA;EACH,UAAA;EACA,GAAA;EACA,OAAA,EAAS,cAAc;AAAA;AAAA,KAGpB,WAAA;EACH,KAAA;EAEA,YAAA,EAAc,OAAA;EACd,IAAA,GAAO,KAAA,EAAO,OAAO;AAAA;AAAA,cASjB,cAAA,GACJ,MAAA,EAAQ,aAAA,SACR,YAAA,EAAc,OAAA,iBACb,WAAA;;;KC3DE,YAAA;EAA0B,UAAA;EAAqB,GAAA;EAAa,OAAA,GAAU,cAAc;AAAA;AAAA,KAmBpF,YAAA,GAAe,aAAa;EAAG,IAAA,EAAM,OAAA;AAAA;AAAA,KAOrC,aAAA;EACH,MAAA,GACE,GAAA,EAAK,OAAA,EACL,MAAA;IAAU,KAAA;IAAgB,QAAA,GAAW,YAAA;IAAc,QAAA;EAAA;EAErD,OAAA;EACA,OAAA;EACA,QAAA,GAAW,KAAA;EACX,QAAA,GAAW,MAAA,EAAQ,MAAA;EAEnB,SAAA,GAAY,OAAA;EAEZ,QAAA,GAAW,KAAA;EACX,QAAA,QAAgB,OAAA;EAChB,cAAA,GAAiB,QAAA;EACjB,IAAA;EACA,SAAA,GAAY,KAAA,UAAe,IAAA;EAG3B,WAAA;EACA,SAAA,GAAY,QAAA,UAAkB,KAAA;EAC9B,IAAA;AAAA;AAAA,KAGG,kBAAA;EACH,YAAA;EACA,UAAA,GAAa,MAAA,SAAe,YAAA;EAC5B,YAAA,GAAe,OAAA;EACf,aAAA;EACA,gBAAA;EAGA,QAAA;EACA,OAAA,IAAW,GAAA,EAAK,OAAA,KAAY,SAAA;EAI5B,SAAA;EACA,WAAA;EACA,WAAA;EACA,KAAA,GAAQ,OAAA;EACR,QAAA,IAAY,MAAA,EAAQ,MAAA,KAAW,MAAA;EAC/B,oBAAA,IAAwB,QAAA;EACxB,uBAAA,IAA2B,QAAA;EAC3B,aAAA,IAAiB,KAAA,EAAO,OAAA,EAAS,MAAA,GAAS,MAAA;EAC1C,OAAA,GAAU,YAAA;EACV,aAAA;EACA,cAAA,IAAkB,GAAA,EAAK,OAAA,KAAY,SAAA;EACnC,mBAAA,IAAuB,MAAA,EAAQ,UAAA,KAAe,SAAA;EAK9C,eAAA;EACA,UAAA;IAAe,QAAA;IAAkB,WAAA,GAAc,WAAA;EAAA;EAI/C,IAAA,GAAO,UAAA;AAAA;AAAA,cAOH,aAAA,kBAAa,yBAAA,CAAA,kBAAA,mBAAA,aAAA,CAAA,aAAA;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/hooks/persistence.ts","../src/components/dashfoo-layout.tsx","../src/components/drag-root.tsx","../src/hooks/drag-hooks.tsx","../src/components/drag-adapter.tsx","../src/components/float-layer.tsx","../src/components/layout-root.tsx","../src/components/row-view.tsx","../src/components/tabset/tabset-view.tsx","../src/components/layout.tsx","../src/components/panel.tsx","../src/components/tabset/tabset-tab-controls.tsx","../src/components/tabset/tabset-content.tsx","../src/components/tabset/tabset-toolbar.tsx","../src/components/tabset/tabset-root.tsx","../src/components/tabset/tabset-tab.tsx","../src/components/tabset/tabset-tablist.tsx","../src/components/tabset/tabset.ts","../src/components/tab-overflow.tsx","../src/components/tabset/tabset-store.ts","../src/hooks/layout-store.ts","../src/hooks/responsive.ts","../src/hooks/store.ts"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,12 +2,48 @@
|
|
|
2
2
|
|
|
3
3
|
import { canRedo, canUndo, dashfooMachine, dragDockMachine, findTabset, fromJSON, normalize, reducer, resolveDockTarget, snapEnabled, snapSizes, stackModel, tabNodeSchema, toJSON, zoneRect } from "@dashfoo/core";
|
|
4
4
|
import { Fragment, createContext, forwardRef, useCallback, useContext, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
|
-
import { Accessibility, DragDropManager, Draggable, Feedback, PointerSensor } from "@dnd-kit/dom";
|
|
5
|
+
import { Accessibility, DragDropManager, Draggable, Droppable, Feedback, PointerSensor } from "@dnd-kit/dom";
|
|
6
6
|
import { createStore, useStore } from "zustand";
|
|
7
|
+
import { CollisionPriority, CollisionType } from "@dnd-kit/abstract";
|
|
7
8
|
import { useActorRef, useSelector } from "@xstate/react";
|
|
8
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
9
10
|
import { Group, Panel as Panel$1, Separator } from "react-resizable-panels";
|
|
10
11
|
|
|
12
|
+
//#region src/lib/topmost-collision.ts
|
|
13
|
+
const createTopmostPointerIntersection = (topElementAt = (x, y) => document.elementFromPoint(x, y)) => {
|
|
14
|
+
let cached = null;
|
|
15
|
+
const topAt = (x, y) => {
|
|
16
|
+
if (cached && cached.x === x && cached.y === y) return cached.top;
|
|
17
|
+
const top = topElementAt(x, y);
|
|
18
|
+
cached = {
|
|
19
|
+
top,
|
|
20
|
+
x,
|
|
21
|
+
y
|
|
22
|
+
};
|
|
23
|
+
queueMicrotask(() => {
|
|
24
|
+
cached = null;
|
|
25
|
+
});
|
|
26
|
+
return top;
|
|
27
|
+
};
|
|
28
|
+
return ({ dragOperation, droppable }) => {
|
|
29
|
+
const { element } = droppable;
|
|
30
|
+
if (!element) return null;
|
|
31
|
+
const point = dragOperation.position.current;
|
|
32
|
+
const top = topAt(point.x, point.y);
|
|
33
|
+
if (!top || !element.contains(top)) return null;
|
|
34
|
+
let depth = 0;
|
|
35
|
+
for (let node = element; node; node = node.parentElement) depth += 1;
|
|
36
|
+
return {
|
|
37
|
+
id: droppable.id,
|
|
38
|
+
priority: CollisionPriority.High,
|
|
39
|
+
type: CollisionType.PointerIntersection,
|
|
40
|
+
value: depth
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const topmostPointerIntersection = createTopmostPointerIntersection();
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
11
47
|
//#region src/hooks/drag-hooks.tsx
|
|
12
48
|
const INTERACTIVE_SELECTOR = `
|
|
13
49
|
input:not([disabled]),
|
|
@@ -24,7 +60,7 @@ const preventActivation = (event, source) => {
|
|
|
24
60
|
return interactive !== null && interactive !== source.element;
|
|
25
61
|
};
|
|
26
62
|
const createDragManager = () => new DragDropManager({
|
|
27
|
-
plugins: (defaults) => defaults.filter((plugin) => plugin !== Accessibility && plugin !== Feedback),
|
|
63
|
+
plugins: (defaults) => [...defaults.filter((plugin) => plugin !== Accessibility && plugin !== Feedback), Feedback.configure({ dropAnimation: null })],
|
|
28
64
|
sensors: () => [PointerSensor.configure({ preventActivation })]
|
|
29
65
|
});
|
|
30
66
|
const DragContext = createContext(null);
|
|
@@ -109,9 +145,37 @@ const useTabsetDraggable = (tabsetId, disabled = false, label = "") => {
|
|
|
109
145
|
};
|
|
110
146
|
const useTabsetDroppable = (tabsetId) => {
|
|
111
147
|
const context = useContext(DragContext);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
148
|
+
const elementRef = useRef(null);
|
|
149
|
+
const droppableRef = useRef(null);
|
|
150
|
+
const ref = useCallback((element) => {
|
|
151
|
+
elementRef.current = element;
|
|
152
|
+
if (droppableRef.current) droppableRef.current.element = element ?? void 0;
|
|
153
|
+
}, []);
|
|
154
|
+
const layerId = context?.layerId;
|
|
155
|
+
const manager = context?.manager;
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (!manager || layerId === void 0) return;
|
|
158
|
+
const droppable = new Droppable({
|
|
159
|
+
collisionDetector: topmostPointerIntersection,
|
|
160
|
+
data: {
|
|
161
|
+
layerId,
|
|
162
|
+
tabsetId,
|
|
163
|
+
type: "tabset"
|
|
164
|
+
},
|
|
165
|
+
id: `${layerId}:${tabsetId}`
|
|
166
|
+
}, manager);
|
|
167
|
+
droppable.element = elementRef.current ?? void 0;
|
|
168
|
+
droppableRef.current = droppable;
|
|
169
|
+
return () => {
|
|
170
|
+
droppable.destroy();
|
|
171
|
+
droppableRef.current = null;
|
|
172
|
+
};
|
|
173
|
+
}, [
|
|
174
|
+
layerId,
|
|
175
|
+
manager,
|
|
176
|
+
tabsetId
|
|
177
|
+
]);
|
|
178
|
+
return { ref };
|
|
115
179
|
};
|
|
116
180
|
const useExternalTabSource = ({ createTab, disabled = false, label = "" }) => {
|
|
117
181
|
const id = useId();
|
|
@@ -422,31 +486,6 @@ const useDashfooStore = (options) => {
|
|
|
422
486
|
]);
|
|
423
487
|
};
|
|
424
488
|
|
|
425
|
-
//#endregion
|
|
426
|
-
//#region src/components/drag-root.tsx
|
|
427
|
-
const DashfooDragProvider = ({ children }) => {
|
|
428
|
-
const [manager] = useState(createDragManager);
|
|
429
|
-
useInsertionEffect(() => () => manager.destroy(), [manager]);
|
|
430
|
-
const [subjectStore] = useState(createDragSubjectStore);
|
|
431
|
-
return /* @__PURE__ */ jsx(SharedDragManagerContext.Provider, {
|
|
432
|
-
value: manager,
|
|
433
|
-
children: /* @__PURE__ */ jsx(DragSubjectStoreContext.Provider, {
|
|
434
|
-
value: subjectStore,
|
|
435
|
-
children
|
|
436
|
-
})
|
|
437
|
-
});
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
//#endregion
|
|
441
|
-
//#region src/hooks/layout-store.ts
|
|
442
|
-
const createLayoutStore = (initial) => createStore(() => initial);
|
|
443
|
-
const LayoutStoreContext = createContext(null);
|
|
444
|
-
const useLayout = (selector) => {
|
|
445
|
-
const store = useContext(LayoutStoreContext);
|
|
446
|
-
if (store === null) throw new Error("dashfoo components must be rendered inside <DashfooLayout> or <Layout.Root>.");
|
|
447
|
-
return useStore(store, selector);
|
|
448
|
-
};
|
|
449
|
-
|
|
450
489
|
//#endregion
|
|
451
490
|
//#region src/lib/tab-insertion.ts
|
|
452
491
|
const pointInRect = (point, rect) => point.x >= rect.x && point.x <= rect.x + rect.width && point.y >= rect.y && point.y <= rect.y + rect.height;
|
|
@@ -472,15 +511,6 @@ const shouldAllowDrop = (draggedId, targetId, tabIds) => {
|
|
|
472
511
|
return true;
|
|
473
512
|
};
|
|
474
513
|
|
|
475
|
-
//#endregion
|
|
476
|
-
//#region src/lib/warn-once.ts
|
|
477
|
-
const warned = /* @__PURE__ */ new Set();
|
|
478
|
-
const warnOnce = (key, message) => {
|
|
479
|
-
if (warned.has(key)) return;
|
|
480
|
-
warned.add(key);
|
|
481
|
-
console.warn(`[dashfoo] ${message}`);
|
|
482
|
-
};
|
|
483
|
-
|
|
484
514
|
//#endregion
|
|
485
515
|
//#region src/components/drag-overlays.tsx
|
|
486
516
|
const overlayBase = {
|
|
@@ -530,25 +560,88 @@ const DockIndicator = ({ actorRef, getTabsetElement }) => {
|
|
|
530
560
|
}
|
|
531
561
|
});
|
|
532
562
|
};
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
top: 0,
|
|
537
|
-
zIndex: 9999
|
|
563
|
+
const PREVIEW_OFFSET = {
|
|
564
|
+
x: 12,
|
|
565
|
+
y: 8
|
|
538
566
|
};
|
|
539
|
-
const
|
|
540
|
-
|
|
567
|
+
const labelOf = (source) => {
|
|
568
|
+
const raw = source?.data?.label;
|
|
569
|
+
return typeof raw === "string" ? raw : "";
|
|
570
|
+
};
|
|
571
|
+
const DragPreviewOverlay = ({ manager }) => {
|
|
572
|
+
const [chip, setChip] = useState(null);
|
|
573
|
+
useEffect(() => {
|
|
574
|
+
const offStart = manager.monitor.addEventListener("dragstart", (event) => {
|
|
575
|
+
const source = event.operation.source;
|
|
576
|
+
if (!source) return;
|
|
577
|
+
const rect = source.element?.getBoundingClientRect();
|
|
578
|
+
const point = event.operation.position.current;
|
|
579
|
+
setChip({
|
|
580
|
+
label: labelOf(source),
|
|
581
|
+
x: PREVIEW_OFFSET.x + (rect ? point.x - rect.left : 0),
|
|
582
|
+
y: PREVIEW_OFFSET.y + (rect ? point.y - rect.top : 0)
|
|
583
|
+
});
|
|
584
|
+
});
|
|
585
|
+
const offEnd = manager.monitor.addEventListener("dragend", () => setChip(null));
|
|
586
|
+
return () => {
|
|
587
|
+
offStart();
|
|
588
|
+
offEnd();
|
|
589
|
+
};
|
|
590
|
+
}, [manager]);
|
|
541
591
|
return /* @__PURE__ */ jsx("div", {
|
|
542
|
-
"data-
|
|
543
|
-
ref:
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
592
|
+
"data-dnd-overlay": "",
|
|
593
|
+
ref: useCallback((element) => {
|
|
594
|
+
const feedback = manager.registry.plugins.get(Feedback);
|
|
595
|
+
if (feedback) feedback.overlay = element ?? void 0;
|
|
596
|
+
}, [manager]),
|
|
597
|
+
children: chip === null ? null : /* @__PURE__ */ jsx("div", {
|
|
598
|
+
"data-dashfoo": "drag-preview",
|
|
599
|
+
style: {
|
|
600
|
+
left: 0,
|
|
601
|
+
position: "absolute",
|
|
602
|
+
top: 0,
|
|
603
|
+
transform: `translate(${chip.x}px, ${chip.y}px)`,
|
|
604
|
+
width: "max-content"
|
|
605
|
+
},
|
|
606
|
+
children: chip.label
|
|
607
|
+
})
|
|
608
|
+
});
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
//#endregion
|
|
612
|
+
//#region src/components/drag-root.tsx
|
|
613
|
+
const DashfooDragProvider = ({ children }) => {
|
|
614
|
+
const [manager] = useState(createDragManager);
|
|
615
|
+
useInsertionEffect(() => () => manager.destroy(), [manager]);
|
|
616
|
+
const [subjectStore] = useState(createDragSubjectStore);
|
|
617
|
+
return /* @__PURE__ */ jsx(SharedDragManagerContext.Provider, {
|
|
618
|
+
value: manager,
|
|
619
|
+
children: /* @__PURE__ */ jsxs(DragSubjectStoreContext.Provider, {
|
|
620
|
+
value: subjectStore,
|
|
621
|
+
children: [children, /* @__PURE__ */ jsx(DragPreviewOverlay, { manager })]
|
|
622
|
+
})
|
|
549
623
|
});
|
|
550
624
|
};
|
|
551
625
|
|
|
626
|
+
//#endregion
|
|
627
|
+
//#region src/hooks/layout-store.ts
|
|
628
|
+
const createLayoutStore = (initial) => createStore(() => initial);
|
|
629
|
+
const LayoutStoreContext = createContext(null);
|
|
630
|
+
const useLayout = (selector) => {
|
|
631
|
+
const store = useContext(LayoutStoreContext);
|
|
632
|
+
if (store === null) throw new Error("dashfoo components must be rendered inside <DashfooLayout> or <Layout.Root>.");
|
|
633
|
+
return useStore(store, selector);
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
//#endregion
|
|
637
|
+
//#region src/lib/warn-once.ts
|
|
638
|
+
const warned = /* @__PURE__ */ new Set();
|
|
639
|
+
const warnOnce = (key, message) => {
|
|
640
|
+
if (warned.has(key)) return;
|
|
641
|
+
warned.add(key);
|
|
642
|
+
console.warn(`[dashfoo] ${message}`);
|
|
643
|
+
};
|
|
644
|
+
|
|
552
645
|
//#endregion
|
|
553
646
|
//#region src/components/drag-adapter.tsx
|
|
554
647
|
const tabRects = (strip, excludeId) => [...strip.querySelectorAll("[data-dashfoo=\"tab\"]")].flatMap((tab) => tab.dataset.tabId === excludeId ? [] : [tab.getBoundingClientRect()]);
|
|
@@ -571,14 +664,6 @@ const intentForTabset = (id, element, point, draggedId) => {
|
|
|
571
664
|
targetId: id
|
|
572
665
|
};
|
|
573
666
|
};
|
|
574
|
-
const PREVIEW_OFFSET = {
|
|
575
|
-
x: 12,
|
|
576
|
-
y: 8
|
|
577
|
-
};
|
|
578
|
-
const labelOf = (source) => {
|
|
579
|
-
const raw = source?.data?.label;
|
|
580
|
-
return typeof raw === "string" ? raw : "";
|
|
581
|
-
};
|
|
582
667
|
const isTabFactory = (value) => typeof value === "function";
|
|
583
668
|
const subjectFor = (source) => {
|
|
584
669
|
const data = source.data;
|
|
@@ -617,9 +702,6 @@ const subjectFor = (source) => {
|
|
|
617
702
|
const DragProvider = ({ children, onCommit, splitDock }) => {
|
|
618
703
|
const actorRef = useActorRef(dragDockMachine);
|
|
619
704
|
const layoutStore = useContext(LayoutStoreContext);
|
|
620
|
-
const [tabsets] = useState(() => /* @__PURE__ */ new Map());
|
|
621
|
-
const overlayRef = useRef(null);
|
|
622
|
-
const [preview, setPreview] = useState(null);
|
|
623
705
|
const sharedManager = useContext(SharedDragManagerContext);
|
|
624
706
|
const [ownManager] = useState(() => sharedManager ? null : createDragManager());
|
|
625
707
|
useInsertionEffect(() => () => ownManager?.destroy(), [ownManager]);
|
|
@@ -657,6 +739,10 @@ const DragProvider = ({ children, onCommit, splitDock }) => {
|
|
|
657
739
|
onCommitRef.current = onCommit;
|
|
658
740
|
splitDockRef.current = splitDock;
|
|
659
741
|
});
|
|
742
|
+
const getTabsetElement = useCallback((id) => {
|
|
743
|
+
const element = manager.registry.droppables.get(`${ownerId}:${id}`)?.element;
|
|
744
|
+
return element instanceof HTMLElement ? element : void 0;
|
|
745
|
+
}, [manager, ownerId]);
|
|
660
746
|
useEffect(() => {
|
|
661
747
|
const subscription = actorRef.on("COMMIT", (emitted) => {
|
|
662
748
|
if (layoutStore?.getState().editable === false) return;
|
|
@@ -671,23 +757,7 @@ const DragProvider = ({ children, onCommit, splitDock }) => {
|
|
|
671
757
|
subscription.unsubscribe();
|
|
672
758
|
};
|
|
673
759
|
}, [actorRef, layoutStore]);
|
|
674
|
-
const registerTabset = useCallback((id, element) => {
|
|
675
|
-
if (element) tabsets.set(id, element);
|
|
676
|
-
else tabsets.delete(id);
|
|
677
|
-
}, [tabsets]);
|
|
678
|
-
const getTabsetElement = useCallback((id) => tabsets.get(id), [tabsets]);
|
|
679
|
-
const attachOverlay = useCallback((element) => {
|
|
680
|
-
overlayRef.current = element;
|
|
681
|
-
}, []);
|
|
682
760
|
useEffect(() => {
|
|
683
|
-
const tabsetAt = (point) => {
|
|
684
|
-
const top = document.elementFromPoint(point.x, point.y);
|
|
685
|
-
if (!top) return;
|
|
686
|
-
for (const [id, element] of tabsets) if (element.contains(top)) return {
|
|
687
|
-
element,
|
|
688
|
-
id
|
|
689
|
-
};
|
|
690
|
-
};
|
|
691
761
|
const resolveIntent = (targetId, element, point, draggedId) => {
|
|
692
762
|
if (layoutStore?.getState().editable === false) return null;
|
|
693
763
|
if (!shouldAllowDrop(draggedId, targetId, [...element.querySelectorAll("[data-dashfoo=\"tab\"]")].map((tab) => tab.dataset.tabId ?? ""))) return null;
|
|
@@ -698,71 +768,62 @@ const DragProvider = ({ children, onCommit, splitDock }) => {
|
|
|
698
768
|
};
|
|
699
769
|
return intent;
|
|
700
770
|
};
|
|
701
|
-
const positionOverlay = (point) => {
|
|
702
|
-
const element = overlayRef.current;
|
|
703
|
-
if (element) element.style.transform = `translate(${point.x + PREVIEW_OFFSET.x}px, ${point.y + PREVIEW_OFFSET.y}px)`;
|
|
704
|
-
};
|
|
705
771
|
const handleStart = (event) => {
|
|
706
772
|
const source = event.operation.source;
|
|
707
773
|
if (!source) return;
|
|
708
774
|
const subject = subjectFor(source);
|
|
709
|
-
if (!subject)
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
x: point.x + PREVIEW_OFFSET.x,
|
|
714
|
-
y: point.y + PREVIEW_OFFSET.y
|
|
715
|
-
});
|
|
775
|
+
if (!subject) {
|
|
776
|
+
manager.actions.stop({ canceled: true });
|
|
777
|
+
return;
|
|
778
|
+
}
|
|
716
779
|
actorRef.send({
|
|
717
780
|
subject,
|
|
718
781
|
type: "START"
|
|
719
782
|
});
|
|
720
783
|
};
|
|
721
|
-
const
|
|
722
|
-
const
|
|
723
|
-
const point =
|
|
724
|
-
|
|
725
|
-
const
|
|
726
|
-
const
|
|
784
|
+
const syncIntent = () => {
|
|
785
|
+
const operation = manager.dragOperation;
|
|
786
|
+
const point = operation.position.current;
|
|
787
|
+
const target = operation.target;
|
|
788
|
+
const data = target?.data;
|
|
789
|
+
const tabsetId = data?.layerId === ownerId ? data.tabsetId : void 0;
|
|
790
|
+
const element = tabsetId === void 0 ? void 0 : target?.element;
|
|
791
|
+
const draggedId = operation.source ? String(operation.source.id) : void 0;
|
|
727
792
|
actorRef.send({
|
|
728
|
-
intent:
|
|
793
|
+
intent: tabsetId !== void 0 && element instanceof HTMLElement ? resolveIntent(tabsetId, element, point, draggedId) : null,
|
|
729
794
|
type: "OVER"
|
|
730
795
|
});
|
|
731
796
|
};
|
|
797
|
+
const handleMove = () => syncIntent();
|
|
798
|
+
const handleCollision = () => syncIntent();
|
|
732
799
|
const handleEnd = (event) => {
|
|
733
|
-
setPreview(null);
|
|
734
800
|
if (event.canceled) {
|
|
735
801
|
actorRef.send({ type: "CANCEL" });
|
|
736
802
|
return;
|
|
737
803
|
}
|
|
738
|
-
|
|
739
|
-
const point = op.position.current;
|
|
740
|
-
const draggedId = op.source ? String(op.source.id) : void 0;
|
|
741
|
-
const hit = tabsetAt(point);
|
|
742
|
-
if (hit) actorRef.send({
|
|
743
|
-
intent: resolveIntent(hit.id, hit.element, point, draggedId),
|
|
744
|
-
type: "OVER"
|
|
745
|
-
});
|
|
804
|
+
syncIntent();
|
|
746
805
|
actorRef.send({ type: "DROP" });
|
|
747
806
|
};
|
|
748
807
|
const offStart = manager.monitor.addEventListener("dragstart", handleStart);
|
|
749
808
|
const offMove = manager.monitor.addEventListener("dragmove", handleMove);
|
|
809
|
+
const offCollision = manager.monitor.addEventListener("collision", handleCollision);
|
|
750
810
|
const offEnd = manager.monitor.addEventListener("dragend", handleEnd);
|
|
751
811
|
return () => {
|
|
752
812
|
offStart();
|
|
753
813
|
offMove();
|
|
814
|
+
offCollision();
|
|
754
815
|
offEnd();
|
|
755
816
|
};
|
|
756
817
|
}, [
|
|
757
818
|
actorRef,
|
|
758
819
|
layoutStore,
|
|
759
820
|
manager,
|
|
760
|
-
|
|
821
|
+
ownerId
|
|
761
822
|
]);
|
|
762
823
|
const contextValue = useMemo(() => ({
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
}), [manager,
|
|
824
|
+
layerId: ownerId,
|
|
825
|
+
manager
|
|
826
|
+
}), [manager, ownerId]);
|
|
766
827
|
return /* @__PURE__ */ jsx(DragContext.Provider, {
|
|
767
828
|
value: contextValue,
|
|
768
829
|
children: /* @__PURE__ */ jsxs(DragSubjectStoreContext.Provider, {
|
|
@@ -773,10 +834,7 @@ const DragProvider = ({ children, onCommit, splitDock }) => {
|
|
|
773
834
|
actorRef,
|
|
774
835
|
getTabsetElement
|
|
775
836
|
}),
|
|
776
|
-
/* @__PURE__ */ jsx(
|
|
777
|
-
overlayRef: attachOverlay,
|
|
778
|
-
preview
|
|
779
|
-
})
|
|
837
|
+
ownManager === null ? null : /* @__PURE__ */ jsx(DragPreviewOverlay, { manager: ownManager })
|
|
780
838
|
]
|
|
781
839
|
})
|
|
782
840
|
});
|