@dashfoo/react 0.8.0 → 0.8.2
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 +24 -11
- package/dist/index.d.ts +70 -43
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +299 -160
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import { canRedo, canUndo, dashfooMachine, decideSnap, dragDockMachine, findTabset, fromJSON, normalize, reducer, resolveDockTarget, resolveSnapGrid, settleSnap, snapEnabled, splitEdge,
|
|
3
|
+
import { canRedo, canUndo, dashfooMachine, decideSnap, dragDockMachine, findTabset, fromJSON, normalize, reducer, resolveDockTarget, resolveSnapGrid, settleSnap, snapEnabled, splitEdge, tabNodeSchema, toJSON, zoneRect } from "@dashfoo/core";
|
|
4
4
|
import { Fragment, createContext, createElement, forwardRef, useCallback, useContext, useEffect, useId, useImperativeHandle, useInsertionEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
5
5
|
import { Accessibility, DragDropManager, Draggable, Droppable, Feedback, PointerSensor } from "@dnd-kit/dom";
|
|
6
6
|
import { useActorRef, useSelector } from "@xstate/react";
|
|
@@ -178,7 +178,7 @@ const useExternalTabSource = ({ createTab, disabled = false, label = "" }) => {
|
|
|
178
178
|
const createTabRef = useRef(createTab);
|
|
179
179
|
useEffect(() => {
|
|
180
180
|
createTabRef.current = createTab;
|
|
181
|
-
});
|
|
181
|
+
}, [createTab]);
|
|
182
182
|
const data = useMemo(() => ({
|
|
183
183
|
createTab: () => createTabRef.current(),
|
|
184
184
|
type: "external"
|
|
@@ -227,7 +227,8 @@ const localStorageAdapter = {
|
|
|
227
227
|
if (typeof window === "undefined") return null;
|
|
228
228
|
try {
|
|
229
229
|
return window.localStorage.getItem(key);
|
|
230
|
-
} catch {
|
|
230
|
+
} catch (error) {
|
|
231
|
+
console.warn("[dashfoo] failed to load persisted layout", error);
|
|
231
232
|
return null;
|
|
232
233
|
}
|
|
233
234
|
},
|
|
@@ -235,7 +236,9 @@ const localStorageAdapter = {
|
|
|
235
236
|
if (typeof window === "undefined") return;
|
|
236
237
|
try {
|
|
237
238
|
window.localStorage.removeItem(key);
|
|
238
|
-
} catch {
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.warn("[dashfoo] failed to clear persisted layout", error);
|
|
241
|
+
}
|
|
239
242
|
},
|
|
240
243
|
setItem: (key, value) => {
|
|
241
244
|
if (typeof window === "undefined") return;
|
|
@@ -246,34 +249,39 @@ const localStorageAdapter = {
|
|
|
246
249
|
}
|
|
247
250
|
}
|
|
248
251
|
};
|
|
252
|
+
const removeStoredLayout = ({ key, storage }) => {
|
|
253
|
+
try {
|
|
254
|
+
storage.removeItem(key);
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.warn("[dashfoo] failed to clear persisted layout", error);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
249
259
|
const usePersistence = (config, defaultModel) => {
|
|
250
260
|
const configRef = useRef(config);
|
|
251
261
|
useEffect(() => {
|
|
252
262
|
configRef.current = config;
|
|
253
|
-
});
|
|
254
|
-
const [
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
if (
|
|
263
|
+
}, [config]);
|
|
264
|
+
const [initialModel, setInitialModel] = useState(defaultModel);
|
|
265
|
+
const loaded = useRef(false);
|
|
266
|
+
useEffect(() => {
|
|
267
|
+
if (loaded.current) return;
|
|
268
|
+
loaded.current = true;
|
|
269
|
+
const current = configRef.current;
|
|
270
|
+
if (current === null || defaultModel === void 0) return;
|
|
258
271
|
try {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
272
|
+
const raw = current.storage.getItem(current.key);
|
|
273
|
+
if (raw === null) return;
|
|
274
|
+
try {
|
|
275
|
+
const restored = fromJSON(raw);
|
|
276
|
+
setInitialModel(restored);
|
|
277
|
+
} catch (error) {
|
|
278
|
+
console.warn("[dashfoo] discarding unreadable persisted layout", error);
|
|
279
|
+
removeStoredLayout(current);
|
|
280
|
+
}
|
|
263
281
|
} catch (error) {
|
|
264
|
-
|
|
265
|
-
error,
|
|
266
|
-
kind: "corrupt"
|
|
267
|
-
};
|
|
282
|
+
console.warn("[dashfoo] failed to load persisted layout", error);
|
|
268
283
|
}
|
|
269
|
-
});
|
|
270
|
-
const initialModel = load.kind === "loaded" && defaultModel !== void 0 ? load.model : defaultModel;
|
|
271
|
-
useEffect(() => {
|
|
272
|
-
const current = configRef.current;
|
|
273
|
-
if (current === null || load.kind !== "corrupt") return;
|
|
274
|
-
console.warn("[dashfoo] discarding unreadable persisted layout", load.error);
|
|
275
|
-
current.storage.removeItem(current.key);
|
|
276
|
-
}, [load]);
|
|
284
|
+
}, [defaultModel]);
|
|
277
285
|
const loadedKey = useRef(config?.key);
|
|
278
286
|
useEffect(() => {
|
|
279
287
|
if (config !== null && config.key !== loadedKey.current) {
|
|
@@ -289,8 +297,13 @@ const usePersistence = (config, defaultModel) => {
|
|
|
289
297
|
timer.current = null;
|
|
290
298
|
}
|
|
291
299
|
if (pending.current !== null) {
|
|
292
|
-
|
|
300
|
+
const write = pending.current;
|
|
293
301
|
pending.current = null;
|
|
302
|
+
try {
|
|
303
|
+
write.storage.setItem(write.key, write.value);
|
|
304
|
+
} catch (error) {
|
|
305
|
+
console.warn("[dashfoo] failed to persist layout", error);
|
|
306
|
+
}
|
|
294
307
|
}
|
|
295
308
|
}, []);
|
|
296
309
|
const save = useCallback((next) => {
|
|
@@ -326,7 +339,7 @@ const usePersistence = (config, defaultModel) => {
|
|
|
326
339
|
}
|
|
327
340
|
pending.current = null;
|
|
328
341
|
const current = configRef.current;
|
|
329
|
-
if (current !== null)
|
|
342
|
+
if (current !== null) removeStoredLayout(current);
|
|
330
343
|
}, []);
|
|
331
344
|
return useMemo(() => ({
|
|
332
345
|
clear,
|
|
@@ -353,23 +366,30 @@ const activeBreakpoint = (breakpoints, width) => {
|
|
|
353
366
|
if (!fallback) throw new Error("useResponsiveModel requires at least one breakpoint.");
|
|
354
367
|
return breakpoints.find((breakpoint) => matchBreakpoint(breakpoint, width)) ?? fallback;
|
|
355
368
|
};
|
|
369
|
+
const observeWidth = (element, onWidth) => {
|
|
370
|
+
const observer = new ResizeObserver((entries) => {
|
|
371
|
+
const entry = entries.at(0);
|
|
372
|
+
if (entry) onWidth(entry.contentRect.width);
|
|
373
|
+
});
|
|
374
|
+
observer.observe(element);
|
|
375
|
+
return () => {
|
|
376
|
+
observer.disconnect();
|
|
377
|
+
};
|
|
378
|
+
};
|
|
379
|
+
const listenToMedia = (list, handleChange) => {
|
|
380
|
+
list.addEventListener("change", handleChange);
|
|
381
|
+
return () => {
|
|
382
|
+
list.removeEventListener("change", handleChange);
|
|
383
|
+
};
|
|
384
|
+
};
|
|
356
385
|
const useContainerWidth = () => {
|
|
357
386
|
const [width, setWidth] = useState(Number.POSITIVE_INFINITY);
|
|
358
|
-
const
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if (entry) setWidth(entry.contentRect.width);
|
|
365
|
-
});
|
|
366
|
-
observer.observe(element);
|
|
367
|
-
observerRef.current = observer;
|
|
368
|
-
}, []);
|
|
369
|
-
useEffect(() => () => {
|
|
370
|
-
observerRef.current?.disconnect();
|
|
371
|
-
}, []);
|
|
372
|
-
return [containerRef, width];
|
|
387
|
+
const [container, setContainer] = useState(null);
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
if (!container) return;
|
|
390
|
+
return observeWidth(container, setWidth);
|
|
391
|
+
}, [container]);
|
|
392
|
+
return [setContainer, width];
|
|
373
393
|
};
|
|
374
394
|
const useResponsiveModel = ({ breakpoints }) => {
|
|
375
395
|
const [containerRef, width] = useContainerWidth();
|
|
@@ -381,9 +401,9 @@ const useResponsiveModel = ({ breakpoints }) => {
|
|
|
381
401
|
const handleChange = () => {
|
|
382
402
|
setMediaTick((tick) => tick + 1);
|
|
383
403
|
};
|
|
384
|
-
|
|
404
|
+
const cleanups = lists.map((list) => listenToMedia(list, handleChange));
|
|
385
405
|
return () => {
|
|
386
|
-
for (const
|
|
406
|
+
for (const cleanup of cleanups) cleanup();
|
|
387
407
|
};
|
|
388
408
|
}, [breakpoints]);
|
|
389
409
|
const active = activeBreakpoint(breakpoints, width);
|
|
@@ -513,6 +533,26 @@ const useDashfooStore = (options) => {
|
|
|
513
533
|
]);
|
|
514
534
|
};
|
|
515
535
|
|
|
536
|
+
//#endregion
|
|
537
|
+
//#region src/lib/compact-model.ts
|
|
538
|
+
const compactRow = (node, orientation) => {
|
|
539
|
+
const children = node.children.map((child) => child.type === "row" ? compactRow(child, orientation) : {
|
|
540
|
+
...child,
|
|
541
|
+
weight: 1
|
|
542
|
+
});
|
|
543
|
+
return {
|
|
544
|
+
...node,
|
|
545
|
+
children,
|
|
546
|
+
orientation,
|
|
547
|
+
weight: children.reduce((sum, child) => sum + child.weight, 0)
|
|
548
|
+
};
|
|
549
|
+
};
|
|
550
|
+
const compactModel = (model, orientation = "column") => ({
|
|
551
|
+
...model,
|
|
552
|
+
layout: compactRow(model.layout, orientation),
|
|
553
|
+
maximizedTabsetId: void 0
|
|
554
|
+
});
|
|
555
|
+
|
|
516
556
|
//#endregion
|
|
517
557
|
//#region src/lib/drag-subject.ts
|
|
518
558
|
const isTabFactory = (value) => typeof value === "function";
|
|
@@ -520,11 +560,11 @@ const isTabFactory = (value) => typeof value === "function";
|
|
|
520
560
|
* gesture on the shared manager, above any one layer. */
|
|
521
561
|
const subjectFor = (source) => {
|
|
522
562
|
const data = source.data;
|
|
523
|
-
if (data
|
|
563
|
+
if (data.type === "tabset") return {
|
|
524
564
|
id: String(data.tabsetId),
|
|
525
565
|
kind: "tabset"
|
|
526
566
|
};
|
|
527
|
-
if (data
|
|
567
|
+
if (data.type === "external") {
|
|
528
568
|
if (!isTabFactory(data.createTab)) {
|
|
529
569
|
console.warn("[dashfoo] external drag source is missing its createTab function");
|
|
530
570
|
return null;
|
|
@@ -637,13 +677,13 @@ const PREVIEW_OFFSET = {
|
|
|
637
677
|
y: 8
|
|
638
678
|
};
|
|
639
679
|
const labelOf = (source) => {
|
|
640
|
-
|
|
641
|
-
return
|
|
680
|
+
if (typeof source?.data.label !== "string") return "";
|
|
681
|
+
return source.data.label;
|
|
642
682
|
};
|
|
643
683
|
const DragPreviewOverlay = ({ manager }) => {
|
|
644
684
|
const [chip, setChip] = useState(null);
|
|
645
685
|
useEffect(() => {
|
|
646
|
-
const
|
|
686
|
+
const handleStart = (event) => {
|
|
647
687
|
const source = event.operation.source;
|
|
648
688
|
if (!source) return;
|
|
649
689
|
const rect = source.element?.getBoundingClientRect();
|
|
@@ -653,13 +693,15 @@ const DragPreviewOverlay = ({ manager }) => {
|
|
|
653
693
|
x: PREVIEW_OFFSET.x + (rect ? point.x - rect.left : 0),
|
|
654
694
|
y: PREVIEW_OFFSET.y + (rect ? point.y - rect.top : 0)
|
|
655
695
|
});
|
|
656
|
-
}
|
|
657
|
-
const
|
|
696
|
+
};
|
|
697
|
+
const handleEnd = () => {
|
|
658
698
|
setChip(null);
|
|
659
|
-
}
|
|
699
|
+
};
|
|
700
|
+
manager.monitor.addEventListener("dragstart", handleStart);
|
|
701
|
+
manager.monitor.addEventListener("dragend", handleEnd);
|
|
660
702
|
return () => {
|
|
661
|
-
|
|
662
|
-
|
|
703
|
+
manager.monitor.removeEventListener("dragstart", handleStart);
|
|
704
|
+
manager.monitor.removeEventListener("dragend", handleEnd);
|
|
663
705
|
};
|
|
664
706
|
}, [manager]);
|
|
665
707
|
const attachOverlay = useCallback((element) => {
|
|
@@ -685,6 +727,7 @@ const DragPreviewOverlay = ({ manager }) => {
|
|
|
685
727
|
|
|
686
728
|
//#endregion
|
|
687
729
|
//#region src/components/dashfoo-drag-provider.tsx
|
|
730
|
+
const isScopedTargetData = (data) => typeof data.layerId === "string" && typeof data.tabsetId === "string";
|
|
688
731
|
const DashfooDragProvider = ({ children }) => {
|
|
689
732
|
const [manager] = useState(createDragManager);
|
|
690
733
|
useInsertionEffect(() => () => {
|
|
@@ -702,9 +745,9 @@ const DashfooDragProvider = ({ children }) => {
|
|
|
702
745
|
const scopedTarget = () => {
|
|
703
746
|
const target = manager.dragOperation.target;
|
|
704
747
|
const data = target?.data;
|
|
705
|
-
const scope = data
|
|
748
|
+
const scope = data && isScopedTargetData(data) ? scopes.get(data.layerId) : void 0;
|
|
706
749
|
const element = target?.element;
|
|
707
|
-
if (!scope || data
|
|
750
|
+
if (!scope || !data || !isScopedTargetData(data) || !(element instanceof HTMLElement)) return null;
|
|
708
751
|
return {
|
|
709
752
|
element,
|
|
710
753
|
scope,
|
|
@@ -763,17 +806,17 @@ const DashfooDragProvider = ({ children }) => {
|
|
|
763
806
|
const commitSubscription = actorRef.on("COMMIT", (emitted) => {
|
|
764
807
|
scopes.get(emitted.scope)?.commit(emitted.action);
|
|
765
808
|
});
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
809
|
+
manager.monitor.addEventListener("dragstart", handleStart);
|
|
810
|
+
manager.monitor.addEventListener("dragmove", scheduleResolve);
|
|
811
|
+
manager.monitor.addEventListener("collision", scheduleResolve);
|
|
812
|
+
manager.monitor.addEventListener("dragend", handleEnd);
|
|
770
813
|
return () => {
|
|
771
814
|
cancelPendingResolve();
|
|
772
815
|
commitSubscription.unsubscribe();
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
816
|
+
manager.monitor.removeEventListener("dragstart", handleStart);
|
|
817
|
+
manager.monitor.removeEventListener("dragmove", scheduleResolve);
|
|
818
|
+
manager.monitor.removeEventListener("collision", scheduleResolve);
|
|
819
|
+
manager.monitor.removeEventListener("dragend", handleEnd);
|
|
777
820
|
};
|
|
778
821
|
}, [
|
|
779
822
|
actorRef,
|
|
@@ -1102,16 +1145,29 @@ const useFloatGesture = ({ editable, geometry, minimized, onCommit, onTap }) =>
|
|
|
1102
1145
|
if (prior && panel.hasPointerCapture?.(prior.pointerId)) panel.releasePointerCapture(prior.pointerId);
|
|
1103
1146
|
const edgeKey = event.currentTarget.dataset.edge;
|
|
1104
1147
|
const parent = panel.offsetParent instanceof HTMLElement ? panel.offsetParent : null;
|
|
1148
|
+
const rect = panel.getBoundingClientRect();
|
|
1149
|
+
const visibleGeometry = {
|
|
1150
|
+
height: minimized ? geometry.height : rect.height,
|
|
1151
|
+
left: rect.left,
|
|
1152
|
+
top: rect.top,
|
|
1153
|
+
width: minimized ? geometry.width : rect.width
|
|
1154
|
+
};
|
|
1105
1155
|
const gesture = {
|
|
1106
1156
|
bounds: {
|
|
1107
1157
|
height: parent?.clientHeight ?? 0,
|
|
1108
1158
|
width: parent?.clientWidth ?? 0
|
|
1109
1159
|
},
|
|
1110
1160
|
edges: edgeKey === void 0 ? null : EDGE_BY_KEY.get(edgeKey) ?? null,
|
|
1111
|
-
|
|
1161
|
+
initialStyle: {
|
|
1162
|
+
height: panel.style.height,
|
|
1163
|
+
left: panel.style.left,
|
|
1164
|
+
top: panel.style.top,
|
|
1165
|
+
width: panel.style.width
|
|
1166
|
+
},
|
|
1167
|
+
latest: visibleGeometry,
|
|
1112
1168
|
moved: false,
|
|
1113
1169
|
pointerId: event.pointerId,
|
|
1114
|
-
start:
|
|
1170
|
+
start: visibleGeometry,
|
|
1115
1171
|
startX: event.clientX,
|
|
1116
1172
|
startY: event.clientY
|
|
1117
1173
|
};
|
|
@@ -1165,12 +1221,7 @@ const useFloatGesture = ({ editable, geometry, minimized, onCommit, onTap }) =>
|
|
|
1165
1221
|
gestureRef.current = null;
|
|
1166
1222
|
if (panel.hasPointerCapture?.(event.pointerId)) panel.releasePointerCapture(event.pointerId);
|
|
1167
1223
|
if (!gesture.moved) return;
|
|
1168
|
-
panel.style
|
|
1169
|
-
panel.style.top = `${gesture.start.top}px`;
|
|
1170
|
-
if (!minimized) {
|
|
1171
|
-
panel.style.width = `${gesture.start.width}px`;
|
|
1172
|
-
panel.style.height = `${gesture.start.height}px`;
|
|
1173
|
-
}
|
|
1224
|
+
Object.assign(panel.style, gesture.initialStyle);
|
|
1174
1225
|
};
|
|
1175
1226
|
return {
|
|
1176
1227
|
handlers: {
|
|
@@ -1180,14 +1231,11 @@ const useFloatGesture = ({ editable, geometry, minimized, onCommit, onTap }) =>
|
|
|
1180
1231
|
onPointerUp: handlePointerUp
|
|
1181
1232
|
},
|
|
1182
1233
|
ref: setPanel,
|
|
1183
|
-
style:
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
left: geometry.left,
|
|
1189
|
-
top: geometry.top,
|
|
1190
|
-
width: geometry.width
|
|
1234
|
+
style: {
|
|
1235
|
+
height: minimized ? void 0 : `min(${geometry.height}px, 100dvh)`,
|
|
1236
|
+
left: `clamp(0px, ${geometry.left}px, calc(100vw - min(${minimized ? CHIP_SIZE.width : geometry.width}px, 100vw)))`,
|
|
1237
|
+
top: `clamp(0px, ${geometry.top}px, calc(100dvh - min(${minimized ? CHIP_SIZE.height : geometry.height}px, 100dvh)))`,
|
|
1238
|
+
width: minimized ? void 0 : `min(${geometry.width}px, 100vw)`
|
|
1191
1239
|
}
|
|
1192
1240
|
};
|
|
1193
1241
|
};
|
|
@@ -1323,23 +1371,39 @@ const rootStyle = {
|
|
|
1323
1371
|
position: "relative",
|
|
1324
1372
|
width: "100%"
|
|
1325
1373
|
};
|
|
1326
|
-
const
|
|
1374
|
+
const resolveCapabilities = (global, options) => {
|
|
1375
|
+
const structural = options.editable && options.restructurable;
|
|
1376
|
+
return {
|
|
1377
|
+
closableTabs: options.editable && options.closableTabs && global.tabEnableClose !== false,
|
|
1378
|
+
draggableTabs: structural && options.draggableTabs && global.tabEnableDrag !== false,
|
|
1379
|
+
draggableTabsets: structural && options.draggableTabsets,
|
|
1380
|
+
floatable: structural && options.floatable,
|
|
1381
|
+
maximizable: options.maximizable && global.tabSetEnableMaximize !== false,
|
|
1382
|
+
renamableTabs: options.editable && options.renamableTabs && global.tabEnableRename !== false,
|
|
1383
|
+
resizableSplits: structural && options.resizableSplits && global.enableSplitResize !== false
|
|
1384
|
+
};
|
|
1385
|
+
};
|
|
1386
|
+
const LayoutRoot = ({ children, closableTabs = true, dispatch, draggableTabs = true, draggableTabsets = true, editable = true, floatable = false, keepMounted = false, maximizable = true, model, renamableTabs = true, renderers, resizableSplits = true, restructurable = true, rootRef, snap, style, ...props }) => {
|
|
1327
1387
|
const global = model.global;
|
|
1328
1388
|
const snapshot = {
|
|
1329
|
-
|
|
1389
|
+
...resolveCapabilities(global, {
|
|
1390
|
+
closableTabs,
|
|
1391
|
+
draggableTabs,
|
|
1392
|
+
draggableTabsets,
|
|
1393
|
+
editable,
|
|
1394
|
+
floatable,
|
|
1395
|
+
maximizable,
|
|
1396
|
+
renamableTabs,
|
|
1397
|
+
resizableSplits,
|
|
1398
|
+
restructurable
|
|
1399
|
+
}),
|
|
1330
1400
|
dispatch,
|
|
1331
|
-
draggableTabs: editable && restructurable && draggableTabs && global.tabEnableDrag !== false,
|
|
1332
|
-
draggableTabsets: editable && restructurable && draggableTabsets,
|
|
1333
1401
|
editable,
|
|
1334
|
-
floatable: editable && restructurable && floatable,
|
|
1335
1402
|
keepMounted,
|
|
1336
|
-
maximizable: maximizable && global.tabSetEnableMaximize !== false,
|
|
1337
1403
|
maximizedTabsetId: model.maximizedTabsetId,
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
renderTabsetToolbar,
|
|
1342
|
-
resizableSplits: editable && restructurable && resizableSplits && global.enableSplitResize !== false,
|
|
1404
|
+
renderTab: renderers.tab,
|
|
1405
|
+
renderTabLabel: renderers.tabLabel,
|
|
1406
|
+
renderTabsetToolbar: renderers.tabsetToolbar,
|
|
1343
1407
|
snap: snap ?? global.snap ?? null,
|
|
1344
1408
|
splitDock: global.enableSplitDock !== false,
|
|
1345
1409
|
tabLocation: global.tabLocation ?? "top",
|
|
@@ -1350,14 +1414,11 @@ const LayoutRoot = ({ children, closableTabs = true, dispatch, draggableTabs = t
|
|
|
1350
1414
|
useLayoutEffect(() => {
|
|
1351
1415
|
store.setState(snapshot);
|
|
1352
1416
|
});
|
|
1353
|
-
const layoutStyle =
|
|
1354
|
-
...rootStyle,
|
|
1355
|
-
...style
|
|
1356
|
-
} : {
|
|
1417
|
+
const layoutStyle = {
|
|
1357
1418
|
...rootStyle,
|
|
1358
|
-
"--dashfoo-splitter-size": `${global.splitterSize}px`,
|
|
1359
1419
|
...style
|
|
1360
1420
|
};
|
|
1421
|
+
if (global.splitterSize !== void 0) layoutStyle["--dashfoo-splitter-size"] = `${global.splitterSize}px`;
|
|
1361
1422
|
return /* @__PURE__ */ jsx(LayoutStoreContext.Provider, {
|
|
1362
1423
|
value: store,
|
|
1363
1424
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -1617,8 +1678,9 @@ const TabPanel = ({ render, tab }) => {
|
|
|
1617
1678
|
const renderTab = useLayout((state) => state.renderTab);
|
|
1618
1679
|
return render ? render(tab) : renderTab(tab);
|
|
1619
1680
|
};
|
|
1620
|
-
const TabsetContent = ({ children, style, ...props }) => {
|
|
1681
|
+
const TabsetContent = forwardRef(({ children, style, ...props }, ref) => {
|
|
1621
1682
|
const node = useTabset((state) => state.node);
|
|
1683
|
+
const editingTabId = useTabset((state) => state.editingTabId);
|
|
1622
1684
|
const visualSelected = useTabset((state) => state.visualSelected);
|
|
1623
1685
|
const keepMounted = useLayout((state) => state.keepMounted);
|
|
1624
1686
|
const mergedStyle = {
|
|
@@ -1627,11 +1689,13 @@ const TabsetContent = ({ children, style, ...props }) => {
|
|
|
1627
1689
|
};
|
|
1628
1690
|
if (keepMounted && node.children.length > 0) return node.children.map((tab, index) => /* @__PURE__ */ createElement("div", {
|
|
1629
1691
|
...props,
|
|
1630
|
-
"aria-
|
|
1692
|
+
"aria-label": editingTabId === tab.id ? tab.name : void 0,
|
|
1693
|
+
"aria-labelledby": editingTabId === tab.id ? void 0 : tabDomId(node.id, tab.id),
|
|
1631
1694
|
"data-dashfoo": "tabcontent",
|
|
1632
1695
|
hidden: index !== visualSelected || void 0,
|
|
1633
1696
|
id: index === visualSelected ? panelDomId(node.id) : void 0,
|
|
1634
1697
|
key: tab.id,
|
|
1698
|
+
ref: index === visualSelected ? ref : void 0,
|
|
1635
1699
|
role: index === visualSelected ? "tabpanel" : void 0,
|
|
1636
1700
|
style: mergedStyle,
|
|
1637
1701
|
tabIndex: index === visualSelected ? 0 : void 0
|
|
@@ -1642,9 +1706,11 @@ const TabsetContent = ({ children, style, ...props }) => {
|
|
|
1642
1706
|
const active = node.children[visualSelected];
|
|
1643
1707
|
if (active) return /* @__PURE__ */ jsx("div", {
|
|
1644
1708
|
...props,
|
|
1645
|
-
"aria-
|
|
1709
|
+
"aria-label": editingTabId === active.id ? active.name : void 0,
|
|
1710
|
+
"aria-labelledby": editingTabId === active.id ? void 0 : tabDomId(node.id, active.id),
|
|
1646
1711
|
"data-dashfoo": "tabcontent",
|
|
1647
1712
|
id: panelDomId(node.id),
|
|
1713
|
+
ref,
|
|
1648
1714
|
role: "tabpanel",
|
|
1649
1715
|
style: mergedStyle,
|
|
1650
1716
|
tabIndex: 0,
|
|
@@ -1656,9 +1722,11 @@ const TabsetContent = ({ children, style, ...props }) => {
|
|
|
1656
1722
|
return /* @__PURE__ */ jsx("div", {
|
|
1657
1723
|
...props,
|
|
1658
1724
|
"data-dashfoo": "tabcontent",
|
|
1725
|
+
ref,
|
|
1659
1726
|
style: mergedStyle
|
|
1660
1727
|
});
|
|
1661
|
-
};
|
|
1728
|
+
});
|
|
1729
|
+
TabsetContent.displayName = "TabsetContent";
|
|
1662
1730
|
|
|
1663
1731
|
//#endregion
|
|
1664
1732
|
//#region src/components/tab-overflow-menu.tsx
|
|
@@ -1817,7 +1885,7 @@ const mergeRefs = (...refs) => (value) => {
|
|
|
1817
1885
|
|
|
1818
1886
|
//#endregion
|
|
1819
1887
|
//#region src/components/tabset/tabset-rename-input.tsx
|
|
1820
|
-
const RenameEditor = ({ defaultValue, onBlur, onKeyDown,
|
|
1888
|
+
const RenameEditor = forwardRef(({ defaultValue, onBlur, onKeyDown, ...props }, userRef) => {
|
|
1821
1889
|
const { tab } = useTab();
|
|
1822
1890
|
const cancelRename = useTabset((state) => state.cancelRename);
|
|
1823
1891
|
const commitRename = useTabset((state) => state.commitRename);
|
|
@@ -1849,16 +1917,21 @@ const RenameEditor = ({ defaultValue, onBlur, onKeyDown, ref: userRef, ...props
|
|
|
1849
1917
|
ref: refCallback,
|
|
1850
1918
|
type: "text"
|
|
1851
1919
|
});
|
|
1852
|
-
};
|
|
1853
|
-
|
|
1920
|
+
});
|
|
1921
|
+
RenameEditor.displayName = "RenameEditor";
|
|
1922
|
+
const TabsetRenameInput = forwardRef((props, ref) => {
|
|
1854
1923
|
const { tab } = useTab();
|
|
1855
1924
|
const editing = useTabset((state) => state.editingTabId === tab.id);
|
|
1856
1925
|
const registerRenameInput = useTabset((state) => state.registerRenameInput);
|
|
1857
1926
|
useEffect(() => registerRenameInput(), [registerRenameInput]);
|
|
1858
1927
|
if (!editing) return null;
|
|
1859
|
-
return /* @__PURE__ */ jsx(RenameEditor, {
|
|
1860
|
-
|
|
1861
|
-
|
|
1928
|
+
return /* @__PURE__ */ jsx(RenameEditor, {
|
|
1929
|
+
...props,
|
|
1930
|
+
ref
|
|
1931
|
+
});
|
|
1932
|
+
});
|
|
1933
|
+
TabsetRenameInput.displayName = "TabsetRenameInput";
|
|
1934
|
+
const TabsetCloseButton = forwardRef(({ children, onClick, ...props }, ref) => {
|
|
1862
1935
|
const { index, tab } = useTab();
|
|
1863
1936
|
const closeTab = useTabset((state) => state.closeTab);
|
|
1864
1937
|
const editing = useTabset((state) => state.editingTabId === tab.id);
|
|
@@ -1876,11 +1949,13 @@ const TabsetCloseButton = ({ children, onClick, ...props }) => {
|
|
|
1876
1949
|
...props,
|
|
1877
1950
|
"data-dashfoo": "tab-close",
|
|
1878
1951
|
onClick: handleClick,
|
|
1952
|
+
ref,
|
|
1879
1953
|
tabIndex: index === visualSelected ? 0 : -1,
|
|
1880
1954
|
type: "button",
|
|
1881
1955
|
children: children ?? /* @__PURE__ */ jsx(CloseIcon, {})
|
|
1882
1956
|
});
|
|
1883
|
-
};
|
|
1957
|
+
});
|
|
1958
|
+
TabsetCloseButton.displayName = "TabsetCloseButton";
|
|
1884
1959
|
|
|
1885
1960
|
//#endregion
|
|
1886
1961
|
//#region src/hooks/use-tab-overflow.ts
|
|
@@ -1930,7 +2005,7 @@ const tabsetStyle = {
|
|
|
1930
2005
|
minWidth: 0,
|
|
1931
2006
|
width: "100%"
|
|
1932
2007
|
};
|
|
1933
|
-
const TabsetRoot = ({ children, node,
|
|
2008
|
+
const TabsetRoot = forwardRef(({ children, node, style, ...props }, userRef) => {
|
|
1934
2009
|
const closableTabs = useLayout((state) => state.closableTabs);
|
|
1935
2010
|
const dispatch = useLayout((state) => state.dispatch);
|
|
1936
2011
|
const maximizable = useLayout((state) => state.maximizable);
|
|
@@ -2010,11 +2085,12 @@ const TabsetRoot = ({ children, node, ref: userRef, style, ...props }) => {
|
|
|
2010
2085
|
children
|
|
2011
2086
|
})
|
|
2012
2087
|
});
|
|
2013
|
-
};
|
|
2088
|
+
});
|
|
2089
|
+
TabsetRoot.displayName = "TabsetRoot";
|
|
2014
2090
|
|
|
2015
2091
|
//#endregion
|
|
2016
2092
|
//#region src/components/tabset/tabset-tab.tsx
|
|
2017
|
-
const TabsetTab = ({ children,
|
|
2093
|
+
const TabsetTab = forwardRef(({ children, tab, ...props }, userRef) => {
|
|
2018
2094
|
const store = useContext(TabsetStoreContext);
|
|
2019
2095
|
const node = useTabset((state) => state.node);
|
|
2020
2096
|
const editing = useTabset((state) => state.editingTabId === tab.id);
|
|
@@ -2049,8 +2125,9 @@ const TabsetTab = ({ children, ref: userRef, tab, ...props }) => {
|
|
|
2049
2125
|
children
|
|
2050
2126
|
})
|
|
2051
2127
|
});
|
|
2052
|
-
};
|
|
2053
|
-
|
|
2128
|
+
});
|
|
2129
|
+
TabsetTab.displayName = "TabsetTab";
|
|
2130
|
+
const TabsetTrigger = forwardRef(({ children, onClick, onDoubleClick, ...props }, userRef) => {
|
|
2054
2131
|
const { index, tab } = useTab();
|
|
2055
2132
|
const node = useTabset((state) => state.node);
|
|
2056
2133
|
const editing = useTabset((state) => state.editingTabId === tab.id);
|
|
@@ -2089,7 +2166,8 @@ const TabsetTrigger = ({ children, onClick, onDoubleClick, ref: userRef, ...prop
|
|
|
2089
2166
|
type: "button",
|
|
2090
2167
|
children: children ?? (renderTabLabel ? renderTabLabel(tab) : tab.name)
|
|
2091
2168
|
});
|
|
2092
|
-
};
|
|
2169
|
+
});
|
|
2170
|
+
TabsetTrigger.displayName = "TabsetTrigger";
|
|
2093
2171
|
|
|
2094
2172
|
//#endregion
|
|
2095
2173
|
//#region src/components/tabset/tabset-tablist.tsx
|
|
@@ -2102,18 +2180,21 @@ const tablistStyle = {
|
|
|
2102
2180
|
minWidth: 0,
|
|
2103
2181
|
overflowX: "auto"
|
|
2104
2182
|
};
|
|
2105
|
-
const TabsetTabStrip = ({ style, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2183
|
+
const TabsetTabStrip = forwardRef(({ style, ...props }, ref) => /* @__PURE__ */ jsx("div", {
|
|
2106
2184
|
...props,
|
|
2107
2185
|
"data-dashfoo": "tabstrip",
|
|
2186
|
+
ref,
|
|
2108
2187
|
style: {
|
|
2109
2188
|
...stripStyle,
|
|
2110
2189
|
...style
|
|
2111
2190
|
}
|
|
2112
|
-
});
|
|
2113
|
-
|
|
2191
|
+
}));
|
|
2192
|
+
TabsetTabStrip.displayName = "TabsetTabStrip";
|
|
2193
|
+
const TabsetTablist = forwardRef(({ "aria-label": ariaLabel, children, onKeyDown, style, ...props }, userRef) => {
|
|
2114
2194
|
const node = useTabset((state) => state.node);
|
|
2115
2195
|
const registerTablist = useTabset((state) => state.registerTablist);
|
|
2116
2196
|
const selectTab = useTabset((state) => state.selectTab);
|
|
2197
|
+
const editingTabId = useTabset((state) => state.editingTabId);
|
|
2117
2198
|
const visualSelected = useTabset((state) => state.visualSelected);
|
|
2118
2199
|
const handleKeyDown = (event) => {
|
|
2119
2200
|
onKeyDown?.(event);
|
|
@@ -2122,32 +2203,37 @@ const TabsetTablist = ({ onKeyDown, ref: userRef, style, ...props }) => {
|
|
|
2122
2203
|
const count = node.children.length;
|
|
2123
2204
|
if (count === 0) return;
|
|
2124
2205
|
const from = Math.max(visualSelected, 0);
|
|
2125
|
-
const next =
|
|
2126
|
-
ArrowLeft
|
|
2127
|
-
ArrowRight
|
|
2128
|
-
End
|
|
2129
|
-
Home
|
|
2130
|
-
|
|
2206
|
+
const next = (/* @__PURE__ */ new Map([
|
|
2207
|
+
["ArrowLeft", (from - 1 + count) % count],
|
|
2208
|
+
["ArrowRight", (from + 1) % count],
|
|
2209
|
+
["End", count - 1],
|
|
2210
|
+
["Home", 0]
|
|
2211
|
+
])).get(event.key);
|
|
2131
2212
|
if (next === void 0) return;
|
|
2132
2213
|
event.preventDefault();
|
|
2133
2214
|
selectTab(next, { focus: true });
|
|
2134
2215
|
};
|
|
2135
2216
|
const refCallback = useMemo(() => mergeRefs(registerTablist, userRef), [registerTablist, userRef]);
|
|
2136
|
-
|
|
2137
|
-
|
|
2217
|
+
const ownedTabs = node.children.filter((tab) => tab.id !== editingTabId).map((tab) => tabDomId(node.id, tab.id)).join(" ");
|
|
2218
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
2138
2219
|
...props,
|
|
2139
|
-
"aria-orientation": "horizontal",
|
|
2140
2220
|
"data-dashfoo": "tablist",
|
|
2141
2221
|
onKeyDown: handleKeyDown,
|
|
2142
2222
|
ref: refCallback,
|
|
2143
|
-
role: "tablist",
|
|
2144
2223
|
style: {
|
|
2145
2224
|
...tablistStyle,
|
|
2146
2225
|
...style
|
|
2147
2226
|
},
|
|
2148
|
-
tabIndex: -1
|
|
2227
|
+
tabIndex: -1,
|
|
2228
|
+
children: [ownedTabs ? /* @__PURE__ */ jsx("span", {
|
|
2229
|
+
"aria-label": ariaLabel ?? node.name ?? "Tabs",
|
|
2230
|
+
"aria-orientation": "horizontal",
|
|
2231
|
+
"aria-owns": ownedTabs,
|
|
2232
|
+
role: "tablist"
|
|
2233
|
+
}) : null, children]
|
|
2149
2234
|
});
|
|
2150
|
-
};
|
|
2235
|
+
});
|
|
2236
|
+
TabsetTablist.displayName = "TabsetTablist";
|
|
2151
2237
|
|
|
2152
2238
|
//#endregion
|
|
2153
2239
|
//#region src/components/tabset/tabset-toolbar.tsx
|
|
@@ -2157,14 +2243,16 @@ const toolbarStyle = {
|
|
|
2157
2243
|
flexShrink: 0,
|
|
2158
2244
|
marginInlineStart: "auto"
|
|
2159
2245
|
};
|
|
2160
|
-
const TabsetToolbar = ({ style, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
2246
|
+
const TabsetToolbar = forwardRef(({ style, ...props }, ref) => /* @__PURE__ */ jsx("div", {
|
|
2161
2247
|
...props,
|
|
2162
2248
|
"data-dashfoo": "tabset-toolbar",
|
|
2249
|
+
ref,
|
|
2163
2250
|
style: {
|
|
2164
2251
|
...toolbarStyle,
|
|
2165
2252
|
...style
|
|
2166
2253
|
}
|
|
2167
|
-
});
|
|
2254
|
+
}));
|
|
2255
|
+
TabsetToolbar.displayName = "TabsetToolbar";
|
|
2168
2256
|
/**
|
|
2169
2257
|
* One answer per control, shared by the controls and by the layout deciding
|
|
2170
2258
|
* whether to render a toolbar at all, so the two cannot disagree.
|
|
@@ -2184,7 +2272,7 @@ const useTabsetChrome = () => {
|
|
|
2184
2272
|
overflow: overflowCount > 0
|
|
2185
2273
|
};
|
|
2186
2274
|
};
|
|
2187
|
-
const TabsetGrip = ({ children,
|
|
2275
|
+
const TabsetGrip = forwardRef(({ children, ...props }, userRef) => {
|
|
2188
2276
|
const activeTabName = useTabset((state) => state.activeTab?.name ?? "");
|
|
2189
2277
|
const node = useTabset((state) => state.node);
|
|
2190
2278
|
const { grip } = useTabsetChrome();
|
|
@@ -2200,8 +2288,9 @@ const TabsetGrip = ({ children, ref: userRef, ...props }) => {
|
|
|
2200
2288
|
type: "button",
|
|
2201
2289
|
children: children ?? /* @__PURE__ */ jsx(GripIcon, {})
|
|
2202
2290
|
});
|
|
2203
|
-
};
|
|
2204
|
-
|
|
2291
|
+
});
|
|
2292
|
+
TabsetGrip.displayName = "TabsetGrip";
|
|
2293
|
+
const TabsetMaximizeButton = forwardRef(({ children, onClick, ...props }, ref) => {
|
|
2205
2294
|
const isMaximized = useTabset((state) => state.isMaximized);
|
|
2206
2295
|
const toggleMaximize = useTabset((state) => state.toggleMaximize);
|
|
2207
2296
|
const { maximize } = useTabsetChrome();
|
|
@@ -2217,11 +2306,13 @@ const TabsetMaximizeButton = ({ children, onClick, ...props }) => {
|
|
|
2217
2306
|
"aria-pressed": isMaximized,
|
|
2218
2307
|
"data-dashfoo": "tabset-maximize",
|
|
2219
2308
|
onClick: handleClick,
|
|
2309
|
+
ref,
|
|
2220
2310
|
type: "button",
|
|
2221
2311
|
children: children ?? /* @__PURE__ */ jsx(MaximizeIcon, { maximized: isMaximized })
|
|
2222
2312
|
});
|
|
2223
|
-
};
|
|
2224
|
-
|
|
2313
|
+
});
|
|
2314
|
+
TabsetMaximizeButton.displayName = "TabsetMaximizeButton";
|
|
2315
|
+
const TabsetFloatButton = forwardRef(({ children, onClick, ...props }, ref) => {
|
|
2225
2316
|
const dispatch = useLayout((state) => state.dispatch);
|
|
2226
2317
|
const node = useTabset((state) => state.node);
|
|
2227
2318
|
const { float } = useTabsetChrome();
|
|
@@ -2241,10 +2332,12 @@ const TabsetFloatButton = ({ children, onClick, ...props }) => {
|
|
|
2241
2332
|
...props,
|
|
2242
2333
|
"data-dashfoo": "tabset-float",
|
|
2243
2334
|
onClick: handleClick,
|
|
2335
|
+
ref,
|
|
2244
2336
|
type: "button",
|
|
2245
2337
|
children: children ?? /* @__PURE__ */ jsx(FloatIcon, {})
|
|
2246
2338
|
});
|
|
2247
|
-
};
|
|
2339
|
+
});
|
|
2340
|
+
TabsetFloatButton.displayName = "TabsetFloatButton";
|
|
2248
2341
|
|
|
2249
2342
|
//#endregion
|
|
2250
2343
|
//#region src/components/tabset/tabset-view.tsx
|
|
@@ -2638,7 +2731,7 @@ const resolvePersist = (persist) => {
|
|
|
2638
2731
|
const warnedComponents = /* @__PURE__ */ new Set();
|
|
2639
2732
|
const DashfooLayout = forwardRef((props, ref) => {
|
|
2640
2733
|
const { closableTabs = true, components, defaultModel, draggableTabs = true, draggableTabsets = true, editable = true, factory, floatable = false, keepMounted = false, maximizable = true, model, onAction, onActiveTabsetChange, onMaximizedTabsetChange, onModelChange, persist, renamableTabs = true, renderTabLabel, renderTabsetToolbar, resizableSplits = true, responsive, snap } = props;
|
|
2641
|
-
const persistConfig = useMemo(() => resolvePersist(persist), [persist]);
|
|
2734
|
+
const persistConfig = useMemo(() => model === void 0 ? resolvePersist(persist) : null, [model, persist]);
|
|
2642
2735
|
const persistence = usePersistence(persistConfig, defaultModel);
|
|
2643
2736
|
const handleModelChange = useCallback((next, action) => {
|
|
2644
2737
|
persistence.save(next);
|
|
@@ -2652,6 +2745,14 @@ const DashfooLayout = forwardRef((props, ref) => {
|
|
|
2652
2745
|
onMaximizedTabsetChange,
|
|
2653
2746
|
onModelChange: handleModelChange
|
|
2654
2747
|
});
|
|
2748
|
+
const { setModel } = store;
|
|
2749
|
+
const appliedInitialModel = useRef(persistence.initialModel);
|
|
2750
|
+
useEffect(() => {
|
|
2751
|
+
if (persistence.initialModel !== void 0 && persistence.initialModel !== appliedInitialModel.current) {
|
|
2752
|
+
appliedInitialModel.current = persistence.initialModel;
|
|
2753
|
+
setModel(persistence.initialModel);
|
|
2754
|
+
}
|
|
2755
|
+
}, [persistence.initialModel, setModel]);
|
|
2655
2756
|
const hasSharedManager = useContext(SharedDragManagerContext) !== null;
|
|
2656
2757
|
useImperativeHandle(ref, () => ({
|
|
2657
2758
|
addTab: (tab, target) => {
|
|
@@ -2728,12 +2829,21 @@ const DashfooLayout = forwardRef((props, ref) => {
|
|
|
2728
2829
|
}
|
|
2729
2830
|
return /* @__PURE__ */ jsx(Component, { node: tab });
|
|
2730
2831
|
}, [components, factory]);
|
|
2832
|
+
const renderers = useMemo(() => ({
|
|
2833
|
+
tab: renderTab,
|
|
2834
|
+
tabLabel: renderTabLabel,
|
|
2835
|
+
tabsetToolbar: renderTabsetToolbar
|
|
2836
|
+
}), [
|
|
2837
|
+
renderTab,
|
|
2838
|
+
renderTabLabel,
|
|
2839
|
+
renderTabsetToolbar
|
|
2840
|
+
]);
|
|
2731
2841
|
const [containerRef, width] = useContainerWidth();
|
|
2732
2842
|
const isCompact = responsive !== void 0 && width <= responsive.maxWidth;
|
|
2733
2843
|
/** Everything the compact breakpoint changes, decided once. */
|
|
2734
2844
|
const presentation = useMemo(() => isCompact ? {
|
|
2735
2845
|
maximizable: false,
|
|
2736
|
-
model:
|
|
2846
|
+
model: compactModel(store.model, responsive?.orientation),
|
|
2737
2847
|
restructurable: false
|
|
2738
2848
|
} : {
|
|
2739
2849
|
maximizable,
|
|
@@ -2762,9 +2872,7 @@ const DashfooLayout = forwardRef((props, ref) => {
|
|
|
2762
2872
|
maximizable: presentation.maximizable,
|
|
2763
2873
|
model: view,
|
|
2764
2874
|
renamableTabs,
|
|
2765
|
-
|
|
2766
|
-
renderTabLabel,
|
|
2767
|
-
renderTabsetToolbar,
|
|
2875
|
+
renderers,
|
|
2768
2876
|
resizableSplits,
|
|
2769
2877
|
restructurable: presentation.restructurable,
|
|
2770
2878
|
rootRef: containerRef,
|
|
@@ -2775,31 +2883,62 @@ const DashfooLayout = forwardRef((props, ref) => {
|
|
|
2775
2883
|
DashfooLayout.displayName = "DashfooLayout";
|
|
2776
2884
|
|
|
2777
2885
|
//#endregion
|
|
2778
|
-
//#region src/components/panel.tsx
|
|
2779
|
-
const
|
|
2886
|
+
//#region src/components/panel-badge.tsx
|
|
2887
|
+
const PanelBadge = forwardRef((props, ref) => /* @__PURE__ */ jsx("span", {
|
|
2780
2888
|
...props,
|
|
2781
|
-
"data-dashfoo": "panel"
|
|
2782
|
-
|
|
2783
|
-
|
|
2889
|
+
"data-dashfoo": "panel-badge",
|
|
2890
|
+
ref
|
|
2891
|
+
}));
|
|
2892
|
+
PanelBadge.displayName = "PanelBadge";
|
|
2893
|
+
|
|
2894
|
+
//#endregion
|
|
2895
|
+
//#region src/components/panel-body.tsx
|
|
2896
|
+
const PanelBody = forwardRef((props, ref) => /* @__PURE__ */ jsx("div", {
|
|
2784
2897
|
...props,
|
|
2785
|
-
"data-dashfoo": "panel-
|
|
2786
|
-
|
|
2787
|
-
|
|
2898
|
+
"data-dashfoo": "panel-body",
|
|
2899
|
+
ref,
|
|
2900
|
+
tabIndex: props.tabIndex ?? 0
|
|
2901
|
+
}));
|
|
2902
|
+
PanelBody.displayName = "PanelBody";
|
|
2903
|
+
|
|
2904
|
+
//#endregion
|
|
2905
|
+
//#region src/components/panel-header.tsx
|
|
2906
|
+
const PanelHeader = forwardRef((props, ref) => /* @__PURE__ */ jsx("div", {
|
|
2788
2907
|
...props,
|
|
2789
|
-
"data-dashfoo": "panel-
|
|
2790
|
-
|
|
2791
|
-
|
|
2908
|
+
"data-dashfoo": "panel-header",
|
|
2909
|
+
ref
|
|
2910
|
+
}));
|
|
2911
|
+
PanelHeader.displayName = "PanelHeader";
|
|
2912
|
+
|
|
2913
|
+
//#endregion
|
|
2914
|
+
//#region src/components/panel-icon.tsx
|
|
2915
|
+
const PanelIcon = forwardRef((props, ref) => /* @__PURE__ */ jsx("span", {
|
|
2792
2916
|
...props,
|
|
2793
|
-
"data-dashfoo": "panel-
|
|
2794
|
-
|
|
2795
|
-
|
|
2917
|
+
"data-dashfoo": "panel-icon",
|
|
2918
|
+
ref
|
|
2919
|
+
}));
|
|
2920
|
+
PanelIcon.displayName = "PanelIcon";
|
|
2921
|
+
|
|
2922
|
+
//#endregion
|
|
2923
|
+
//#region src/components/panel-root.tsx
|
|
2924
|
+
const PanelRoot = forwardRef((props, ref) => /* @__PURE__ */ jsx("div", {
|
|
2796
2925
|
...props,
|
|
2797
|
-
"data-dashfoo": "panel
|
|
2798
|
-
|
|
2799
|
-
|
|
2926
|
+
"data-dashfoo": "panel",
|
|
2927
|
+
ref
|
|
2928
|
+
}));
|
|
2929
|
+
PanelRoot.displayName = "PanelRoot";
|
|
2930
|
+
|
|
2931
|
+
//#endregion
|
|
2932
|
+
//#region src/components/panel-title.tsx
|
|
2933
|
+
const PanelTitle = forwardRef((props, ref) => /* @__PURE__ */ jsx("span", {
|
|
2800
2934
|
...props,
|
|
2801
|
-
"data-dashfoo": "panel-
|
|
2802
|
-
|
|
2935
|
+
"data-dashfoo": "panel-title",
|
|
2936
|
+
ref
|
|
2937
|
+
}));
|
|
2938
|
+
PanelTitle.displayName = "PanelTitle";
|
|
2939
|
+
|
|
2940
|
+
//#endregion
|
|
2941
|
+
//#region src/components/panel.tsx
|
|
2803
2942
|
const Panel = {
|
|
2804
2943
|
Badge: PanelBadge,
|
|
2805
2944
|
Body: PanelBody,
|