@dimina-kit/electron-deck 0.1.0-dev.20260616102751 → 0.1.0-dev.20260624040247
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 +26 -24
- package/dist/client/index.js +1 -1
- package/dist/client/index.js.map +1 -1
- package/dist/client/layout-client.d.ts +1 -1
- package/dist/dock-react/dock-view.d.ts +14 -9
- package/dist/dock-react/dock-view.d.ts.map +1 -1
- package/dist/dock-react/drag-redock.d.ts +15 -0
- package/dist/dock-react/drag-redock.d.ts.map +1 -1
- package/dist/dock-react/index.d.ts +2 -2
- package/dist/dock-react/index.d.ts.map +1 -1
- package/dist/dock-react/index.js +201 -42
- package/dist/dock-react/index.js.map +1 -1
- package/dist/{electron-deck-DfFKeFEC.js → electron-deck-C9_Yu3fd.js} +56 -62
- package/dist/electron-deck-C9_Yu3fd.js.map +1 -0
- package/dist/electron-deck.d.ts +2 -2
- package/dist/host/capability.d.ts +1 -1
- package/dist/host/control-bus.d.ts +3 -3
- package/dist/host/index.d.ts +1 -1
- package/dist/host/index.js +1 -1
- package/dist/index.js +1 -1
- package/dist/internal/deck-app.d.ts +57 -63
- package/dist/internal/deck-app.d.ts.map +1 -1
- package/dist/internal/electron-types.d.ts +3 -3
- package/dist/internal/trust-set.d.ts +3 -3
- package/dist/internal/wire-transport.d.ts +5 -5
- package/dist/internal/wire-transport.d.ts.map +1 -1
- package/dist/layout/index.d.ts +3 -1
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js +2 -2
- package/dist/layout/mutations.d.ts.map +1 -1
- package/dist/layout/sanitize.d.ts +27 -0
- package/dist/layout/sanitize.d.ts.map +1 -0
- package/dist/layout/serialize.d.ts.map +1 -1
- package/dist/layout/types.d.ts +55 -7
- package/dist/layout/types.d.ts.map +1 -1
- package/dist/layout/user-actions.d.ts +9 -0
- package/dist/layout/user-actions.d.ts.map +1 -0
- package/dist/{layout-CZtF0auJ.js → layout-oJQ9hind.js} +73 -6
- package/dist/layout-oJQ9hind.js.map +1 -0
- package/dist/main/compositor.d.ts +1 -1
- package/dist/main/index.d.ts +2 -2
- package/dist/main/view-handle.d.ts +8 -8
- package/dist/types.d.ts +2 -2
- package/dist/view-handle-CR-yWNfr.js.map +1 -1
- package/package.json +7 -5
- package/dist/electron-deck-DfFKeFEC.js.map +0 -1
- package/dist/layout-CZtF0auJ.js.map +0 -1
package/dist/dock-react/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Fragment, useCallback, useEffect, useRef, useState } from "react";
|
|
1
|
+
import { i as extractPanel, l as setSizes, o as movePanel, s as setActive, t as closePanelForUser, u as splitPanel } from "../layout-oJQ9hind.js";
|
|
2
|
+
import { Fragment, createContext, useCallback, useContext, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { Group, Panel, Separator } from "react-resizable-panels";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
//#region src/dock-react/drag-redock.ts
|
|
@@ -89,6 +89,24 @@ function isNoopRedock(dragged, draggedGroupId, target, zone) {
|
|
|
89
89
|
if (zone === "center" && draggedGroupId !== void 0 && draggedGroupId === target.groupId) return true;
|
|
90
90
|
return false;
|
|
91
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Map a pointer x-position over a horizontal tab strip to an insertion index for
|
|
94
|
+
* a within-strip REORDER (the `dropPolicy:'reorder-only'` gesture). The strip is
|
|
95
|
+
* the dragged tab's own group; `tabRects` are the tab buttons' rects in visual
|
|
96
|
+
* order (each `left` is the rect's left edge, `width` its width). The index is
|
|
97
|
+
* the count of tabs whose MIDPOINT the pointer has passed: the LEFT half of a tab
|
|
98
|
+
* inserts BEFORE it, the RIGHT half (and the exact midpoint) inserts AFTER it. A
|
|
99
|
+
* pointer left of the first tab → 0; past the last tab → `tabRects.length`. Pure
|
|
100
|
+
* (no DOM): the caller measures the rects and passes the pointer x. An empty
|
|
101
|
+
* strip or a non-finite pointer → 0.
|
|
102
|
+
*/
|
|
103
|
+
function computeReorderIndex(tabRects, pointerX) {
|
|
104
|
+
if (!Number.isFinite(pointerX)) return 0;
|
|
105
|
+
let index = 0;
|
|
106
|
+
for (const rect of tabRects) if (pointerX >= rect.left + rect.width / 2) index += 1;
|
|
107
|
+
else break;
|
|
108
|
+
return index;
|
|
109
|
+
}
|
|
92
110
|
//#endregion
|
|
93
111
|
//#region src/dock-react/dock-view.tsx
|
|
94
112
|
/**
|
|
@@ -110,6 +128,33 @@ function isNoopRedock(dragged, draggedGroupId, target, zone) {
|
|
|
110
128
|
* tab's `data-deck-tab` attribute (the jsdom seam relies on the latter).
|
|
111
129
|
*/
|
|
112
130
|
var DRAG_PANEL_MIME = "application/x-deck-panel";
|
|
131
|
+
/**
|
|
132
|
+
* The current layout EPOCH — the model's revision, bumped once per committed
|
|
133
|
+
* mutation. `DockView` provides it; descendant panels read it via
|
|
134
|
+
* `useDockLayoutEpoch`.
|
|
135
|
+
*
|
|
136
|
+
* Its reason to exist: a native-view overlay anchored inside a dock panel
|
|
137
|
+
* (a `WebContentsView` tracking its slot's geometry) re-publishes its bounds
|
|
138
|
+
* only on GEOMETRY events (ResizeObserver / window-resize / splitter-drag). A
|
|
139
|
+
* layout mutation that REORDERS a slot without resizing it — flipping a
|
|
140
|
+
* fixed-width simulator column left↔right, moving a region — produces NO such
|
|
141
|
+
* event (a same-size flex reorder fires nothing), so the overlay would freeze
|
|
142
|
+
* at its old position. The epoch is the layout layer's explicit "something
|
|
143
|
+
* moved" signal: a panel hosting a native overlay re-measures (e.g. pulses its
|
|
144
|
+
* view-anchor) when the epoch changes, catching the translate the browser never
|
|
145
|
+
* reports. Default 0 (outside a provider): the consuming effect runs once on
|
|
146
|
+
* mount, which is harmless.
|
|
147
|
+
*/
|
|
148
|
+
var LayoutEpochContext = createContext(0);
|
|
149
|
+
/**
|
|
150
|
+
* Read the current dock layout epoch (the model revision). Re-renders the caller
|
|
151
|
+
* whenever a layout mutation commits. Keyed into a panel's effect deps, it lets
|
|
152
|
+
* a native-overlay host re-measure on a reorder that fires no geometry event.
|
|
153
|
+
* Returns 0 when used outside a `<DockView>`.
|
|
154
|
+
*/
|
|
155
|
+
function useDockLayoutEpoch() {
|
|
156
|
+
return useContext(LayoutEpochContext);
|
|
157
|
+
}
|
|
113
158
|
/** Normalize raw split weights to percentages summing ~100 for `defaultSize`. */
|
|
114
159
|
function toPercentages(sizes) {
|
|
115
160
|
const total = sizes.reduce((a, b) => a + (b > 0 ? b : 0), 0);
|
|
@@ -120,11 +165,11 @@ function toPercentages(sizes) {
|
|
|
120
165
|
return sizes.map((s) => (s > 0 ? s : 0) / total * 100);
|
|
121
166
|
}
|
|
122
167
|
/**
|
|
123
|
-
* Compute the `defaultSize` percentage for each FLEXIBLE
|
|
124
|
-
*
|
|
125
|
-
* from the pool
|
|
126
|
-
*
|
|
127
|
-
* absent from the returned map.
|
|
168
|
+
* Compute the `defaultSize` percentage for each FLEXIBLE child, keyed by its
|
|
169
|
+
* ORIGINAL child index. Px-sized children (a non-null `constraint` — `fixedPx`
|
|
170
|
+
* locked OR `minPx` floored) are EXCLUDED from the pool: their size is px, not a
|
|
171
|
+
* weight, so it must never pollute the flexible siblings' normalization (FIX E1).
|
|
172
|
+
* `constraints[i]` non-null ⇒ child i is px-sized and absent from the returned map.
|
|
128
173
|
*/
|
|
129
174
|
function computeFlexiblePercentages(sizes, constraints) {
|
|
130
175
|
const flexibleIndices = sizes.map((_, i) => i).filter((i) => (constraints?.[i] ?? null) === null);
|
|
@@ -138,29 +183,45 @@ function computeFlexiblePercentages(sizes, constraints) {
|
|
|
138
183
|
function DockView(props) {
|
|
139
184
|
const { model, registry, renderDomPanel, bindNativeSlot } = props;
|
|
140
185
|
const [tree, setTree] = useState(() => model.get());
|
|
186
|
+
const [epoch, setEpoch] = useState(0);
|
|
141
187
|
useEffect(() => {
|
|
142
188
|
setTree(model.get());
|
|
143
189
|
return model.subscribe((snap) => {
|
|
144
190
|
setTree(snap.tree);
|
|
191
|
+
setEpoch(snap.revision);
|
|
145
192
|
});
|
|
146
193
|
}, [model]);
|
|
147
194
|
const handleActivate = useCallback((groupId, panelId) => {
|
|
148
195
|
model.apply((t) => setActive(t, groupId, panelId));
|
|
149
196
|
}, [model]);
|
|
150
197
|
const handleClose = useCallback((panelId) => {
|
|
151
|
-
model.apply((t) =>
|
|
152
|
-
}, [model]);
|
|
198
|
+
model.apply((t) => closePanelForUser(t, panelId, registry));
|
|
199
|
+
}, [model, registry]);
|
|
153
200
|
const canClose = countPanels(tree.root) > 1;
|
|
154
201
|
const isPanelInTree = useCallback((panelId) => findPanelGroupId(tree.root, panelId) !== void 0, [tree]);
|
|
155
202
|
const handleApplyLayout = useCallback((splitId, weights) => {
|
|
156
203
|
model.apply((t) => setSizes(t, splitId, weights));
|
|
157
204
|
}, [model]);
|
|
158
|
-
const handleRedock = useCallback((groupId, activePanelId, draggedPanelId, zone) => {
|
|
205
|
+
const handleRedock = useCallback((groupId, activePanelId, draggedPanelId, zone, reorderIndex) => {
|
|
159
206
|
const target = {
|
|
160
207
|
groupId,
|
|
161
208
|
panelId: activePanelId
|
|
162
209
|
};
|
|
163
|
-
|
|
210
|
+
const draggedGroupId = findPanelGroupId(model.get().root, draggedPanelId);
|
|
211
|
+
if (registry.get(draggedPanelId)?.draggable === false) return;
|
|
212
|
+
if (registry.get(activePanelId)?.draggable === false) return;
|
|
213
|
+
if (registry.get(draggedPanelId)?.dropPolicy === "reorder-only") {
|
|
214
|
+
if (draggedGroupId === void 0 || draggedGroupId !== groupId) return;
|
|
215
|
+
if (zone !== "center") return;
|
|
216
|
+
const group = findGroupById(model.get().root, groupId);
|
|
217
|
+
const index = reorderIndex ?? (group ? group.panels.indexOf(activePanelId) : void 0);
|
|
218
|
+
model.apply((t) => movePanel(t, draggedPanelId, {
|
|
219
|
+
groupId,
|
|
220
|
+
index
|
|
221
|
+
}));
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
if (isNoopRedock(draggedPanelId, draggedGroupId, target, zone)) return;
|
|
164
225
|
const mutation = dropZoneToMutation(zone, draggedPanelId, target);
|
|
165
226
|
if (mutation.kind === "move") {
|
|
166
227
|
model.apply((t) => movePanel(t, mutation.panelId, { groupId: mutation.destGroupId }));
|
|
@@ -171,18 +232,21 @@ function DockView(props) {
|
|
|
171
232
|
if (findPanelGroupId(tree.root, mutation.atPanelId) === void 0) return t;
|
|
172
233
|
return splitPanel(tree, mutation.atPanelId, mutation.dir, mutation.newPanelId, mutation.side);
|
|
173
234
|
});
|
|
174
|
-
}, [model]);
|
|
175
|
-
return /* @__PURE__ */ jsx(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
235
|
+
}, [model, registry]);
|
|
236
|
+
return /* @__PURE__ */ jsx(LayoutEpochContext.Provider, {
|
|
237
|
+
value: epoch,
|
|
238
|
+
children: renderNode(tree.root, {
|
|
239
|
+
registry,
|
|
240
|
+
renderDomPanel,
|
|
241
|
+
bindNativeSlot,
|
|
242
|
+
onActivate: handleActivate,
|
|
243
|
+
onApplyLayout: handleApplyLayout,
|
|
244
|
+
onRedock: handleRedock,
|
|
245
|
+
onClose: handleClose,
|
|
246
|
+
canClose,
|
|
247
|
+
isPanelInTree
|
|
248
|
+
})
|
|
249
|
+
});
|
|
186
250
|
}
|
|
187
251
|
/** The id of the tab group currently holding `panelId`, or `undefined` if the
|
|
188
252
|
* panel is not in the tree. Used by `handleRedock` to detect a drop back into
|
|
@@ -194,6 +258,17 @@ function findPanelGroupId(node, panelId) {
|
|
|
194
258
|
if (found !== void 0) return found;
|
|
195
259
|
}
|
|
196
260
|
}
|
|
261
|
+
/** The tab-group node with `groupId`, or `undefined`. Used by `handleRedock` to
|
|
262
|
+
* read the live `panels` order of a reorder target (to anchor a same-group
|
|
263
|
+
* reorder on the active panel's current index when the gesture carries no
|
|
264
|
+
* pointer-derived index — e.g. the `__deckHandleDrop` test seam). */
|
|
265
|
+
function findGroupById(node, groupId) {
|
|
266
|
+
if (node.kind === "tabs") return node.id === groupId ? node : void 0;
|
|
267
|
+
for (const child of node.children) {
|
|
268
|
+
const found = findGroupById(child, groupId);
|
|
269
|
+
if (found !== void 0) return found;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
197
272
|
/** Total panels anywhere in the tree. Drives the last-panel close suppression:
|
|
198
273
|
* a GroupView only knows its own node, so DockView computes this global count
|
|
199
274
|
* once and threads the resulting `canClose` boolean down. */
|
|
@@ -243,6 +318,36 @@ var LAYOUT_EPSILON = .5;
|
|
|
243
318
|
* self-healing (the next, larger resize writes back). If that ever matters,
|
|
244
319
|
* scale the tolerance down by the flexible child count. */
|
|
245
320
|
var FLEX_RATIO_TOLERANCE = .1;
|
|
321
|
+
/**
|
|
322
|
+
* The minimum weight a FLEXIBLE child may hold, given how many flexible children
|
|
323
|
+
* share the split (Bug #1). A flexible `<Panel>` has no rrp `minSize` by default
|
|
324
|
+
* (rrp floor is 0%), so a user can drag it to ~0 width; the resize write-back
|
|
325
|
+
* would then persist a ~0 weight and the panel comes back invisible/stuck.
|
|
326
|
+
*
|
|
327
|
+
* The floor is `min(1, floor(90 / flexCount))` — i.e. ~1 weight unit (a flexible
|
|
328
|
+
* split's weights are normalized to percentages downstream, so ~1 reads as ~1%
|
|
329
|
+
* of the flexible pool). With any realistic flexible count this is exactly 1; the
|
|
330
|
+
* `min(1, …)` only matters for a hypothetical 90+ flexible-child split. It is the
|
|
331
|
+
* SAME value used for the rrp `minSize` (A) and the write-back clamp (B) so the
|
|
332
|
+
* two defenses never disagree.
|
|
333
|
+
*/
|
|
334
|
+
function flexibleFloor(flexCount) {
|
|
335
|
+
return Math.min(1, Math.max(.5, Math.floor(90 / Math.max(1, flexCount))));
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Clamp the FLEXIBLE entries of a full-length weights array up to `floor` (Bug #1
|
|
339
|
+
* defense B). Px-sized children (a non-null constraint) are left untouched — their
|
|
340
|
+
* `sizes[i]` is a preserved placeholder, not a live weight. Returns a new array;
|
|
341
|
+
* a weight already ≥ floor is kept verbatim so a healthy ratio is undisturbed.
|
|
342
|
+
*/
|
|
343
|
+
function clampFlexibleWeights(weights, constraints) {
|
|
344
|
+
const flexCount = weights.filter((_, i) => (constraints?.[i] ?? null) === null).length;
|
|
345
|
+
const floor = flexibleFloor(flexCount);
|
|
346
|
+
return weights.map((w, i) => {
|
|
347
|
+
if ((constraints?.[i] ?? null) !== null) return w;
|
|
348
|
+
return Number.isFinite(w) && w >= floor ? w : floor;
|
|
349
|
+
});
|
|
350
|
+
}
|
|
246
351
|
/** Are two panelId→percentage maps equivalent within `epsilon` percentage
|
|
247
352
|
* points? Both maps must cover EXACTLY the `ids` key set — a missing key OR an
|
|
248
353
|
* extra key (a key present in `a`/`b` but absent from `ids`) counts as NOT
|
|
@@ -340,6 +445,8 @@ function SplitView(props) {
|
|
|
340
445
|
const { node, ctx } = props;
|
|
341
446
|
const orientation = node.orientation === "row" ? "horizontal" : "vertical";
|
|
342
447
|
const percentageByIndex = computeFlexiblePercentages(node.sizes, node.constraints);
|
|
448
|
+
const flexCount = node.children.filter((_, i) => (node.constraints?.[i] ?? null) === null).length;
|
|
449
|
+
const flexMinSize = String(flexibleFloor(flexCount));
|
|
343
450
|
const groupRef = useRef(null);
|
|
344
451
|
const nodeRef = useRef(node);
|
|
345
452
|
nodeRef.current = node;
|
|
@@ -347,7 +454,7 @@ function SplitView(props) {
|
|
|
347
454
|
node.children.forEach((child, i) => {
|
|
348
455
|
if (i > 0) items.push(/* @__PURE__ */ jsx(Separator, { "data-deck-resize-handle": "" }, `handle-${i}`));
|
|
349
456
|
const constraint = node.constraints?.[i] ?? null;
|
|
350
|
-
if (constraint) {
|
|
457
|
+
if (constraint?.fixedPx != null) {
|
|
351
458
|
const px = `${constraint.fixedPx}px`;
|
|
352
459
|
items.push(/* @__PURE__ */ jsx(Panel, {
|
|
353
460
|
id: child.id,
|
|
@@ -357,11 +464,24 @@ function SplitView(props) {
|
|
|
357
464
|
groupResizeBehavior: "preserve-pixel-size",
|
|
358
465
|
children: renderNode(child, ctx)
|
|
359
466
|
}, panelKey(child)));
|
|
360
|
-
} else
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
467
|
+
} else if (constraint?.minPx != null) {
|
|
468
|
+
const px = `${constraint.minPx}px`;
|
|
469
|
+
items.push(/* @__PURE__ */ jsx(Panel, {
|
|
470
|
+
id: child.id,
|
|
471
|
+
defaultSize: px,
|
|
472
|
+
minSize: px,
|
|
473
|
+
groupResizeBehavior: "preserve-pixel-size",
|
|
474
|
+
children: renderNode(child, ctx)
|
|
475
|
+
}, panelKey(child)));
|
|
476
|
+
} else {
|
|
477
|
+
const pct = percentageByIndex.get(i);
|
|
478
|
+
items.push(/* @__PURE__ */ jsx(Panel, {
|
|
479
|
+
id: child.id,
|
|
480
|
+
defaultSize: pct != null ? String(pct) : void 0,
|
|
481
|
+
minSize: flexMinSize,
|
|
482
|
+
children: renderNode(child, ctx)
|
|
483
|
+
}, panelKey(child)));
|
|
484
|
+
}
|
|
365
485
|
});
|
|
366
486
|
const handleLayoutChanged = (layout) => {
|
|
367
487
|
const cur = nodeRef.current;
|
|
@@ -373,7 +493,7 @@ function SplitView(props) {
|
|
|
373
493
|
const modelNorm = incoming.indices.map((i) => modelPctByIndex.get(i) ?? 0);
|
|
374
494
|
if (!incoming.ratios.some((r, k) => Math.abs(r - modelNorm[k]) > FLEX_RATIO_TOLERANCE)) return;
|
|
375
495
|
const weights = curChildIds.map((id, i) => isFixedAt(i) ? cur.sizes[i] ?? 1 : layout[id]);
|
|
376
|
-
ctx.onApplyLayout(cur.id, weights);
|
|
496
|
+
ctx.onApplyLayout(cur.id, clampFlexibleWeights(weights, cur.constraints));
|
|
377
497
|
};
|
|
378
498
|
const setSplitRef = (el) => {
|
|
379
499
|
if (el) {
|
|
@@ -381,7 +501,7 @@ function SplitView(props) {
|
|
|
381
501
|
const cur = nodeRef.current;
|
|
382
502
|
const isFixedAt = (i) => (cur.constraints?.[i] ?? null) !== null;
|
|
383
503
|
const next = weights.map((w, i) => isFixedAt(i) ? cur.sizes[i] ?? 1 : w);
|
|
384
|
-
ctx.onApplyLayout(cur.id, next);
|
|
504
|
+
ctx.onApplyLayout(cur.id, clampFlexibleWeights(next, cur.constraints));
|
|
385
505
|
};
|
|
386
506
|
Object.defineProperty(el, "__deckGroupApi", {
|
|
387
507
|
configurable: true,
|
|
@@ -401,9 +521,15 @@ function SplitView(props) {
|
|
|
401
521
|
api.setLayout(targetMap);
|
|
402
522
|
return true;
|
|
403
523
|
}, []);
|
|
524
|
+
const sizesKey = node.sizes.join(",");
|
|
525
|
+
const childCountKey = node.children.length;
|
|
404
526
|
useEffect(() => {
|
|
405
527
|
runSync();
|
|
406
|
-
}, [
|
|
528
|
+
}, [
|
|
529
|
+
sizesKey,
|
|
530
|
+
childCountKey,
|
|
531
|
+
runSync
|
|
532
|
+
]);
|
|
407
533
|
return /* @__PURE__ */ jsx("div", {
|
|
408
534
|
ref: setSplitRef,
|
|
409
535
|
"data-deck-split": node.id,
|
|
@@ -422,7 +548,7 @@ function SplitView(props) {
|
|
|
422
548
|
height: "100%"
|
|
423
549
|
},
|
|
424
550
|
children: items
|
|
425
|
-
})
|
|
551
|
+
}, node.children.length)
|
|
426
552
|
});
|
|
427
553
|
}
|
|
428
554
|
/** Stable React key for a child node (split id or group id). */
|
|
@@ -479,8 +605,37 @@ function GroupView(props) {
|
|
|
479
605
|
setDropZone(null);
|
|
480
606
|
const dragged = e.dataTransfer.getData(DRAG_PANEL_MIME) || e.dataTransfer.getData("text/plain");
|
|
481
607
|
if (!dragged || ctx.registry.get(dragged) === void 0 || !ctx.isPanelInTree(dragged)) return;
|
|
482
|
-
|
|
608
|
+
const reorderIndex = computeReorderIndex(Array.from(e.currentTarget.querySelectorAll("[data-deck-tab]")).map((el) => {
|
|
609
|
+
const r = el.getBoundingClientRect();
|
|
610
|
+
return {
|
|
611
|
+
left: r.left,
|
|
612
|
+
width: r.width
|
|
613
|
+
};
|
|
614
|
+
}), e.clientX);
|
|
615
|
+
ctx.onRedock(node.id, node.active, dragged, zone, reorderIndex);
|
|
616
|
+
};
|
|
617
|
+
const handleTabStripDragOver = (e) => {
|
|
618
|
+
if (!e.dataTransfer.types.includes(DRAG_PANEL_MIME)) return;
|
|
619
|
+
e.preventDefault();
|
|
620
|
+
e.stopPropagation();
|
|
621
|
+
setDropZone(null);
|
|
622
|
+
};
|
|
623
|
+
const handleTabStripDrop = (e) => {
|
|
624
|
+
e.preventDefault();
|
|
625
|
+
e.stopPropagation();
|
|
626
|
+
setDropZone(null);
|
|
627
|
+
const dragged = e.dataTransfer.getData(DRAG_PANEL_MIME) || e.dataTransfer.getData("text/plain");
|
|
628
|
+
if (!dragged || ctx.registry.get(dragged) === void 0 || !ctx.isPanelInTree(dragged)) return;
|
|
629
|
+
const reorderIndex = computeReorderIndex(Array.from(e.currentTarget.querySelectorAll("[data-deck-tab]")).map((el) => {
|
|
630
|
+
const r = el.getBoundingClientRect();
|
|
631
|
+
return {
|
|
632
|
+
left: r.left,
|
|
633
|
+
width: r.width
|
|
634
|
+
};
|
|
635
|
+
}), e.clientX);
|
|
636
|
+
ctx.onRedock(node.id, node.active, dragged, "center", reorderIndex);
|
|
483
637
|
};
|
|
638
|
+
const visibleTabs = node.panels.filter((panelId) => !ctx.registry.get(panelId)?.hideTab);
|
|
484
639
|
return /* @__PURE__ */ jsxs("div", {
|
|
485
640
|
ref: setGroupRef,
|
|
486
641
|
"data-deck-group": node.id,
|
|
@@ -497,16 +652,19 @@ function GroupView(props) {
|
|
|
497
652
|
minHeight: 0
|
|
498
653
|
},
|
|
499
654
|
children: [
|
|
500
|
-
/* @__PURE__ */ jsx("div", {
|
|
655
|
+
visibleTabs.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
501
656
|
role: "tablist",
|
|
502
657
|
style: { flexShrink: 0 },
|
|
503
|
-
|
|
658
|
+
onDragOver: handleTabStripDragOver,
|
|
659
|
+
onDrop: handleTabStripDrop,
|
|
660
|
+
children: visibleTabs.map((panelId) => {
|
|
504
661
|
const active = panelId === node.active;
|
|
505
|
-
const
|
|
662
|
+
const descriptor = ctx.registry.get(panelId);
|
|
663
|
+
const title = descriptor?.title ?? panelId;
|
|
506
664
|
return /* @__PURE__ */ jsxs("button", {
|
|
507
665
|
type: "button",
|
|
508
666
|
role: "tab",
|
|
509
|
-
draggable: "true",
|
|
667
|
+
draggable: descriptor?.draggable !== false ? "true" : void 0,
|
|
510
668
|
"data-deck-tab": panelId,
|
|
511
669
|
"data-active": active ? "true" : "false",
|
|
512
670
|
onDragStart: (e) => {
|
|
@@ -521,7 +679,7 @@ function GroupView(props) {
|
|
|
521
679
|
onClick: () => {
|
|
522
680
|
if (!active) ctx.onActivate(node.id, panelId);
|
|
523
681
|
},
|
|
524
|
-
children: [title, ctx.canClose ? /* @__PURE__ */ jsx("span", {
|
|
682
|
+
children: [title, ctx.canClose && descriptor?.closable !== false ? /* @__PURE__ */ jsx("span", {
|
|
525
683
|
role: "button",
|
|
526
684
|
tabIndex: 0,
|
|
527
685
|
"data-deck-tab-close": panelId,
|
|
@@ -543,7 +701,7 @@ function GroupView(props) {
|
|
|
543
701
|
}) : null]
|
|
544
702
|
}, panelId);
|
|
545
703
|
})
|
|
546
|
-
}),
|
|
704
|
+
}) : null,
|
|
547
705
|
renderActiveBody(node, ctx),
|
|
548
706
|
dropZone ? /* @__PURE__ */ jsx(DropIndicator, { zone: dropZone }) : null
|
|
549
707
|
]
|
|
@@ -633,7 +791,8 @@ function renderActiveBody(node, ctx) {
|
|
|
633
791
|
return /* @__PURE__ */ jsx("div", {
|
|
634
792
|
"data-deck-panel-body": panelId,
|
|
635
793
|
style: {
|
|
636
|
-
display: active ?
|
|
794
|
+
display: active ? "flex" : "none",
|
|
795
|
+
flexDirection: "column",
|
|
637
796
|
flex: 1,
|
|
638
797
|
minWidth: 0,
|
|
639
798
|
minHeight: 0
|
|
@@ -666,6 +825,6 @@ function NativeSlot(props) {
|
|
|
666
825
|
});
|
|
667
826
|
}
|
|
668
827
|
//#endregion
|
|
669
|
-
export { DockView, computeDropZone, computeFlexiblePercentages, dropZoneToMutation, isNoopRedock, layoutsEquivalent };
|
|
828
|
+
export { DockView, computeDropZone, computeFlexiblePercentages, computeReorderIndex, dropZoneToMutation, isNoopRedock, layoutsEquivalent, useDockLayoutEpoch };
|
|
670
829
|
|
|
671
830
|
//# sourceMappingURL=index.js.map
|