react-zeugma 6.3.0 → 6.4.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.
- package/README.md +149 -157
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -103
- package/dist/index.d.ts +81 -103
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/{types-Diujkc-H.d.cts → types-BN5W7EvY.d.cts} +84 -168
- package/dist/{types-Diujkc-H.d.ts → types-BN5W7EvY.d.ts} +84 -168
- package/dist/utils.cjs +1 -1
- package/dist/utils.cjs.map +1 -1
- package/dist/utils.d.cts +17 -10
- package/dist/utils.d.ts +17 -10
- package/dist/utils.js +1 -1
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dispatch, SetStateAction,
|
|
1
|
+
import { Dispatch, SetStateAction, ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
type SplitDirection = 'row' | 'column';
|
|
4
4
|
interface SplitNode {
|
|
@@ -16,14 +16,7 @@ interface PaneNode {
|
|
|
16
16
|
locked?: boolean;
|
|
17
17
|
tabsMetadata?: Record<string, Record<string, unknown>>;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
type: 'widget';
|
|
21
|
-
id: string;
|
|
22
|
-
locked?: boolean;
|
|
23
|
-
metadata?: Record<string, unknown>;
|
|
24
|
-
}
|
|
25
|
-
type LeafNode = PaneNode | WidgetNode;
|
|
26
|
-
type TreeNode = SplitNode | LeafNode;
|
|
19
|
+
type TreeNode = SplitNode | PaneNode;
|
|
27
20
|
interface TabDetails {
|
|
28
21
|
id: string;
|
|
29
22
|
paneId: string;
|
|
@@ -44,86 +37,26 @@ interface UseZeugmaOptions {
|
|
|
44
37
|
onFullscreenChange?: (paneId: string | null) => void;
|
|
45
38
|
/** Whether the layout is locked. When locked, resizing, dragging, and dropping are disabled. */
|
|
46
39
|
locked?: boolean;
|
|
47
|
-
/** Minimum pixel distance that a user must drag a pane handle before dragging triggers. Defaults to 8. */
|
|
48
|
-
dragActivationDistance?: number;
|
|
49
|
-
/** Threshold value in pixels for snapping layout resizing handles to adjacent edges. Defaults to 8. */
|
|
50
|
-
snapThreshold?: number;
|
|
51
|
-
/** Minimum split percentage allowed when resizing split panes. Defaults to 5. */
|
|
52
|
-
minSplitPercentage?: number;
|
|
53
|
-
/** Maximum split percentage allowed when resizing split panes. Defaults to 95. */
|
|
54
|
-
maxSplitPercentage?: number;
|
|
55
|
-
/** Whether dragging a pane far enough outside the container triggers a drag-out/dismiss action. Defaults to false. */
|
|
56
|
-
enableDragToDismiss?: boolean;
|
|
57
|
-
/** The threshold in pixels beyond the container boundaries required to activate the drag-out/dismiss action. Defaults to 60. */
|
|
58
|
-
dismissThreshold?: number;
|
|
59
|
-
/** Callback triggered when a pane is removed from the dashboard layout tree. */
|
|
60
|
-
onRemove?: (paneId: string) => void;
|
|
61
|
-
/** Callback triggered when dragging starts for a pane. */
|
|
62
|
-
onDragStart?: (activeId: string) => void;
|
|
63
|
-
/** Callback triggered when dragging ends, providing details on target pane and drop action (split or move). */
|
|
64
|
-
onDragEnd?: (activeId: string, overId: string | null, dropAction: {
|
|
65
|
-
type: 'split' | 'move';
|
|
66
|
-
direction?: SplitDirection;
|
|
67
|
-
position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
68
|
-
} | null) => void;
|
|
69
|
-
/** Callback triggered when the user starts dragging a resizing handle between split panes. */
|
|
70
|
-
onResizeStart?: (currentNode: SplitNode) => void;
|
|
71
|
-
/** Callback triggered continuously while the user is dragging a resizing handle. Passes the new split percentage. */
|
|
72
|
-
onResize?: (currentNode: SplitNode, percentage: number) => void;
|
|
73
|
-
/** Callback triggered when the user stops dragging a resizing handle. Passes the final split percentage. */
|
|
74
|
-
onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
|
|
75
|
-
/** Callback triggered when the drag-out/dismiss intent changes. */
|
|
76
|
-
onDismissIntentChange?: (paneId: string | null) => void;
|
|
77
40
|
}
|
|
78
|
-
interface
|
|
41
|
+
interface ZeugmaState {
|
|
79
42
|
/** The current active layout tree structure, or null if empty. */
|
|
80
43
|
layout: TreeNode | null;
|
|
81
|
-
/** Updates the layout tree. Also resets transient states like fullscreenPaneId. */
|
|
82
|
-
setLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
83
|
-
/** @internal Raw layout setter used by DnD internals — does NOT reset transient states. */
|
|
84
|
-
_internalSetLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
85
44
|
/** The ID of the pane currently zoomed to fullscreen, or null. */
|
|
86
45
|
fullscreenPaneId: string | null;
|
|
87
|
-
/** Programmatically sets the fullscreen pane ID. */
|
|
88
|
-
setFullscreenPaneId: (paneId: string | null) => void;
|
|
89
46
|
/** Whether the layout is globally locked. */
|
|
90
47
|
locked: boolean;
|
|
48
|
+
}
|
|
49
|
+
interface ZeugmaStateSetters {
|
|
50
|
+
/** Updates the layout tree. Also resets transient states like fullscreenPaneId. */
|
|
51
|
+
setLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
52
|
+
/** Programmatically sets the fullscreen pane ID. */
|
|
53
|
+
setFullscreenPaneId: (paneId: string | null) => void;
|
|
91
54
|
/** Programmatically updates the global locked status. */
|
|
92
55
|
setLocked: Dispatch<SetStateAction<boolean>>;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/** The type of the active dragged item ('pane' | 'tab'). */
|
|
96
|
-
activeType: 'pane' | 'tab' | null;
|
|
97
|
-
/** The ID of the item with active dismiss intent, or null. */
|
|
98
|
-
dismissIntentId: string | null;
|
|
99
|
-
setActiveId: Dispatch<SetStateAction<string | null>>;
|
|
100
|
-
setActiveType: Dispatch<SetStateAction<'pane' | 'tab' | null>>;
|
|
101
|
-
setDismissIntentId: Dispatch<SetStateAction<string | null>>;
|
|
102
|
-
containerRef: RefObject<HTMLElement | null>;
|
|
103
|
-
setContainerRef: (element: HTMLElement | null) => void;
|
|
104
|
-
layoutBeforeDrag: TreeNode | null;
|
|
105
|
-
setLayoutBeforeDrag: Dispatch<SetStateAction<TreeNode | null>>;
|
|
106
|
-
dragActivationDistance: number;
|
|
107
|
-
snapThreshold: number;
|
|
108
|
-
minSplitPercentage: number;
|
|
109
|
-
maxSplitPercentage: number;
|
|
110
|
-
enableDragToDismiss: boolean;
|
|
111
|
-
dismissThreshold: number;
|
|
112
|
-
onRemove?: (paneId: string) => void;
|
|
113
|
-
onDragStart?: (activeId: string) => void;
|
|
114
|
-
onDragEnd?: (activeId: string, overId: string | null, dropAction: {
|
|
115
|
-
type: 'split' | 'move';
|
|
116
|
-
direction?: SplitDirection;
|
|
117
|
-
position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
118
|
-
} | null) => void;
|
|
119
|
-
onResizeStart?: (currentNode: SplitNode) => void;
|
|
120
|
-
onResize?: (currentNode: SplitNode, percentage: number) => void;
|
|
121
|
-
onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
|
|
122
|
-
onDismissIntentChange?: (paneId: string | null) => void;
|
|
56
|
+
}
|
|
57
|
+
interface ZeugmaActions {
|
|
123
58
|
/** Removes the specified pane or widget from the layout tree and collapses its parent split. */
|
|
124
59
|
removePane: (paneId: string) => void;
|
|
125
|
-
/** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
|
|
126
|
-
addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
|
|
127
60
|
/** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
|
|
128
61
|
addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
|
|
129
62
|
/** Stable callback to update metadata for a specific tab or widget. */
|
|
@@ -142,12 +75,20 @@ interface ZeugmaController {
|
|
|
142
75
|
updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
|
|
143
76
|
/** Moves/reorders a tab relative to another target tab. */
|
|
144
77
|
moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
|
|
78
|
+
}
|
|
79
|
+
interface ZeugmaQueries {
|
|
145
80
|
/** Find a PaneNode or WidgetNode by its ID in the layout tree. */
|
|
146
|
-
findPaneById: (paneId: string) =>
|
|
81
|
+
findPaneById: (paneId: string) => PaneNode | null;
|
|
147
82
|
/** Find the PaneNode containing the given tab ID in the layout tree. */
|
|
148
83
|
findPaneContainingTab: (tabId: string) => PaneNode | null;
|
|
149
84
|
/** Find the details of a tab by its ID in the layout tree. */
|
|
150
85
|
findTabById: (tabId: string) => TabDetails | null;
|
|
86
|
+
/** Get the metadata for a specific tab by its ID. */
|
|
87
|
+
getTabMetadata: (tabId: string) => Record<string, unknown> | undefined;
|
|
88
|
+
/** Get the metadata of the active tab in a specific pane by the pane ID. */
|
|
89
|
+
getActiveTabMetadata: (paneId: string) => Record<string, unknown> | undefined;
|
|
90
|
+
}
|
|
91
|
+
interface ZeugmaController extends ZeugmaState, ZeugmaStateSetters, ZeugmaActions, ZeugmaQueries {
|
|
151
92
|
}
|
|
152
93
|
interface ZeugmaClassNames {
|
|
153
94
|
/** CSS class applied to the root dashboard container. */
|
|
@@ -172,106 +113,81 @@ interface ZeugmaClassNames {
|
|
|
172
113
|
dashboardLocked?: string;
|
|
173
114
|
/** CSS class applied to drop zone indicator when hovering over a locked pane. */
|
|
174
115
|
lockedPreview?: string;
|
|
175
|
-
/** CSS class applied to
|
|
116
|
+
/** CSS class applied to drop zone indicator when hovering over a locked pane. */
|
|
176
117
|
tabDropPreview?: string;
|
|
177
118
|
/** CSS class applied to the separator line between tabs. */
|
|
178
119
|
tabSeparator?: string;
|
|
120
|
+
/** CSS class applied to the wrapper element for a tab's contents. */
|
|
121
|
+
tabContentWrapper?: string;
|
|
122
|
+
/** CSS class applied to the tabs container div. */
|
|
123
|
+
tabsContainer?: string;
|
|
124
|
+
/** CSS class applied to individual tabs (as static string or dynamic callback). */
|
|
125
|
+
tab?: string | ((tabId: string) => string);
|
|
126
|
+
/** CSS class applied to the pane inner container (containing header and content). */
|
|
127
|
+
paneContainer?: string;
|
|
128
|
+
/** CSS class applied to the pane header bar. */
|
|
129
|
+
paneHeader?: string;
|
|
130
|
+
/** CSS class applied to the pane controls wrapper. */
|
|
131
|
+
paneControls?: string;
|
|
132
|
+
/** CSS class applied to the pane buttons (maximize/close). */
|
|
133
|
+
paneButton?: string;
|
|
134
|
+
/** CSS class applied to the default tab close button. */
|
|
135
|
+
tabCloseButton?: string;
|
|
136
|
+
/** CSS class applied to the drag handle. */
|
|
137
|
+
dragHandle?: string;
|
|
138
|
+
}
|
|
139
|
+
interface DragOverlayActiveItem {
|
|
140
|
+
type: 'tab' | 'pane';
|
|
141
|
+
id: string;
|
|
142
|
+
isDismissing: boolean;
|
|
179
143
|
}
|
|
180
|
-
interface ZeugmaProps
|
|
181
|
-
/**
|
|
182
|
-
|
|
144
|
+
interface ZeugmaProps {
|
|
145
|
+
/** The Zeugma Controller returned by useZeugma() */
|
|
146
|
+
controller?: ZeugmaController;
|
|
183
147
|
/** Custom overlay renderer function used to customize the cursor-following drag preview for an active pane or tab. */
|
|
184
|
-
renderDragOverlay?: (
|
|
148
|
+
renderDragOverlay?: (active: DragOverlayActiveItem) => ReactNode;
|
|
185
149
|
/** Optional CSS class name mapping overrides for custom styles of components like panes, drop previews, overlays, etc. */
|
|
186
150
|
classNames?: ZeugmaClassNames;
|
|
187
|
-
/** Render function mapping
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
* All consumers of this context will re-render when any of these values change.
|
|
195
|
-
*/
|
|
196
|
-
interface ZeugmaStateValue {
|
|
197
|
-
/** The current active layout tree structure, or null if empty. */
|
|
198
|
-
layout: TreeNode | null;
|
|
199
|
-
/** Callback to update the layout tree. */
|
|
200
|
-
setLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
201
|
-
/** Renders the inner content of a pane given its unique ID. */
|
|
202
|
-
renderPane: (paneId: string) => ReactNode;
|
|
203
|
-
/** The ID of the pane currently zoomed to fullscreen, or null. */
|
|
204
|
-
fullscreenPaneId: string | null;
|
|
205
|
-
/** Normalized or overridden CSS classes for custom layout styling. */
|
|
206
|
-
classNames: ZeugmaClassNames;
|
|
207
|
-
/** Whether the layout is globally locked. */
|
|
208
|
-
locked: boolean;
|
|
209
|
-
/** Programmatically updates the global locked status. */
|
|
210
|
-
setLocked: Dispatch<SetStateAction<boolean>>;
|
|
211
|
-
/** Find a PaneNode or WidgetNode by its ID in the layout tree. */
|
|
212
|
-
findPaneById: (paneId: string) => LeafNode | null;
|
|
213
|
-
/** Find the PaneNode containing the given tab ID in the layout tree. */
|
|
214
|
-
findPaneContainingTab: (tabId: string) => PaneNode | null;
|
|
215
|
-
/** Find the details of a tab by its ID in the layout tree. */
|
|
216
|
-
findTabById: (tabId: string) => TabDetails | null;
|
|
217
|
-
/** The ID of the active dragged item (pane or tab). */
|
|
218
|
-
activeId: string | null;
|
|
219
|
-
/** The type of the active dragged item ('pane' | 'tab'). */
|
|
220
|
-
activeType: 'pane' | 'tab' | null;
|
|
221
|
-
/** The ID of the item with active dismiss intent, or null. */
|
|
222
|
-
dismissIntentId: string | null;
|
|
223
|
-
setContainerRef: (element: HTMLElement | null) => void;
|
|
224
|
-
onRemove?: (paneId: string) => void;
|
|
225
|
-
onFullscreenChange?: (paneId: string | null) => void;
|
|
151
|
+
/** Render function mapping unique pane nodes to React elements. Usually renders a <Pane> wrapper. */
|
|
152
|
+
renderPane?: (paneId: string) => ReactNode;
|
|
153
|
+
/** Size/thickness of the split handle resizer bars in pixels. */
|
|
154
|
+
resizerSize?: number;
|
|
155
|
+
/** Minimum pixel distance that a user must drag a pane handle before dragging triggers. Defaults to 8. */
|
|
156
|
+
dragActivationDistance?: number;
|
|
157
|
+
/** Threshold value in pixels for snapping layout resizing handles to adjacent edges. Defaults to 8. */
|
|
226
158
|
snapThreshold?: number;
|
|
159
|
+
/** Minimum split percentage allowed when resizing split panes. Defaults to 5. */
|
|
160
|
+
minSplitPercentage?: number;
|
|
161
|
+
/** Maximum split percentage allowed when resizing split panes. Defaults to 95. */
|
|
162
|
+
maxSplitPercentage?: number;
|
|
163
|
+
/** Whether dragging a pane far enough outside the container triggers a drag-out/dismiss action. Defaults to false. */
|
|
164
|
+
enableDragToDismiss?: boolean;
|
|
165
|
+
/** The threshold in pixels beyond the container boundaries required to activate the drag-out/dismiss action. Defaults to 60. */
|
|
166
|
+
dismissThreshold?: number;
|
|
167
|
+
/** Callback triggered when a pane is removed from the dashboard layout tree. */
|
|
168
|
+
onRemove?: (paneId: string) => void;
|
|
169
|
+
/** Callback triggered when dragging starts for a pane. */
|
|
170
|
+
onDragStart?: (activeId: string) => void;
|
|
171
|
+
/** Callback triggered when dragging ends, providing details on target pane and drop action (split or move). */
|
|
172
|
+
onDragEnd?: (activeId: string, overId: string | null, dropAction: {
|
|
173
|
+
type: 'split' | 'move';
|
|
174
|
+
direction?: SplitDirection;
|
|
175
|
+
position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
176
|
+
} | null) => void;
|
|
177
|
+
/** Callback triggered when the user starts dragging a resizing handle between split panes. */
|
|
227
178
|
onResizeStart?: (currentNode: SplitNode) => void;
|
|
179
|
+
/** Callback triggered continuously while the user is dragging a resizing handle. Passes the new split percentage. */
|
|
228
180
|
onResize?: (currentNode: SplitNode, percentage: number) => void;
|
|
181
|
+
/** Callback triggered when the user stops dragging a resizing handle. Passes the final split percentage. */
|
|
229
182
|
onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
interface ZeugmaDragStateValue {
|
|
234
|
-
/** The ID of the tab currently hovered over during a tab drag, or null. */
|
|
235
|
-
overTabId: string | null;
|
|
236
|
-
/** The position of the tab drop preview relative to the hovered tab ('before' | 'after'). */
|
|
237
|
-
overTabPosition: 'before' | 'after' | null;
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Actions context — holds stable dispatch functions with permanent identity.
|
|
241
|
-
* Consumers of only this context will never re-render from layout/drag state changes.
|
|
242
|
-
*/
|
|
243
|
-
interface ZeugmaActionsValue {
|
|
244
|
-
/** Removes the specified pane or widget from the layout tree and collapses its parent split. */
|
|
245
|
-
removePane: (paneId: string) => void;
|
|
246
|
-
/** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
|
|
247
|
-
addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
|
|
248
|
-
/** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
|
|
249
|
-
addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
|
|
250
|
-
/** Stable callback to update metadata for a specific tab or widget. */
|
|
251
|
-
updateMetadata: (id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
252
|
-
/** Stable callback to update the locked status of a specific pane in the layout tree. */
|
|
253
|
-
updatePaneLock: (paneId: string, locked: boolean) => void;
|
|
254
|
-
/** Stable callback to activate a tab within a pane. */
|
|
255
|
-
selectTab: (paneId: string, tabId: string) => void;
|
|
256
|
-
/** Stable callback to merge a dragged tab/pane into another pane's tab list. */
|
|
257
|
-
mergeTab: (draggedTabId: string, targetPaneId: string) => void;
|
|
258
|
-
/** Stable callback to remove/close a specific tab from the layout. */
|
|
259
|
-
removeTab: (tabId: string) => void;
|
|
260
|
-
/** Programmatically sets the fullscreen pane ID. */
|
|
261
|
-
setFullscreenPaneId: (paneId: string | null) => void;
|
|
262
|
-
/** Programmatically updates the global locked status. */
|
|
263
|
-
setLocked: Dispatch<SetStateAction<boolean>>;
|
|
264
|
-
/** Splits an existing pane and adds a new one. */
|
|
265
|
-
splitPane: (targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string) => void;
|
|
266
|
-
/** Updates the split percentage of a split node. */
|
|
267
|
-
updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
|
|
268
|
-
/** Moves/reorders a tab relative to another target tab. */
|
|
269
|
-
moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
|
|
270
|
-
}
|
|
271
|
-
interface ZeugmaContextValue extends ZeugmaStateValue, ZeugmaActionsValue {
|
|
183
|
+
/** Callback triggered when the drag-out/dismiss intent changes. */
|
|
184
|
+
onDismissIntentChange?: (paneId: string | null) => void;
|
|
272
185
|
}
|
|
273
|
-
interface
|
|
274
|
-
|
|
186
|
+
interface ZeugmaProviderProps extends Omit<ZeugmaProps, 'controller'> {
|
|
187
|
+
/** The Zeugma Controller returned by useZeugma() */
|
|
188
|
+
controller: ZeugmaController;
|
|
189
|
+
/** Children components that will have access to the Zeugma context */
|
|
190
|
+
children: ReactNode;
|
|
275
191
|
}
|
|
276
192
|
|
|
277
|
-
export type {
|
|
193
|
+
export type { DragOverlayActiveItem as D, PaneNode as P, SplitDirection as S, TreeNode as T, UseZeugmaOptions as U, ZeugmaController as Z, ZeugmaProps as a, ZeugmaProviderProps as b, SplitNode as c, TabDetails as d, ZeugmaClassNames as e };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Dispatch, SetStateAction,
|
|
1
|
+
import { Dispatch, SetStateAction, ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
type SplitDirection = 'row' | 'column';
|
|
4
4
|
interface SplitNode {
|
|
@@ -16,14 +16,7 @@ interface PaneNode {
|
|
|
16
16
|
locked?: boolean;
|
|
17
17
|
tabsMetadata?: Record<string, Record<string, unknown>>;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
type: 'widget';
|
|
21
|
-
id: string;
|
|
22
|
-
locked?: boolean;
|
|
23
|
-
metadata?: Record<string, unknown>;
|
|
24
|
-
}
|
|
25
|
-
type LeafNode = PaneNode | WidgetNode;
|
|
26
|
-
type TreeNode = SplitNode | LeafNode;
|
|
19
|
+
type TreeNode = SplitNode | PaneNode;
|
|
27
20
|
interface TabDetails {
|
|
28
21
|
id: string;
|
|
29
22
|
paneId: string;
|
|
@@ -44,86 +37,26 @@ interface UseZeugmaOptions {
|
|
|
44
37
|
onFullscreenChange?: (paneId: string | null) => void;
|
|
45
38
|
/** Whether the layout is locked. When locked, resizing, dragging, and dropping are disabled. */
|
|
46
39
|
locked?: boolean;
|
|
47
|
-
/** Minimum pixel distance that a user must drag a pane handle before dragging triggers. Defaults to 8. */
|
|
48
|
-
dragActivationDistance?: number;
|
|
49
|
-
/** Threshold value in pixels for snapping layout resizing handles to adjacent edges. Defaults to 8. */
|
|
50
|
-
snapThreshold?: number;
|
|
51
|
-
/** Minimum split percentage allowed when resizing split panes. Defaults to 5. */
|
|
52
|
-
minSplitPercentage?: number;
|
|
53
|
-
/** Maximum split percentage allowed when resizing split panes. Defaults to 95. */
|
|
54
|
-
maxSplitPercentage?: number;
|
|
55
|
-
/** Whether dragging a pane far enough outside the container triggers a drag-out/dismiss action. Defaults to false. */
|
|
56
|
-
enableDragToDismiss?: boolean;
|
|
57
|
-
/** The threshold in pixels beyond the container boundaries required to activate the drag-out/dismiss action. Defaults to 60. */
|
|
58
|
-
dismissThreshold?: number;
|
|
59
|
-
/** Callback triggered when a pane is removed from the dashboard layout tree. */
|
|
60
|
-
onRemove?: (paneId: string) => void;
|
|
61
|
-
/** Callback triggered when dragging starts for a pane. */
|
|
62
|
-
onDragStart?: (activeId: string) => void;
|
|
63
|
-
/** Callback triggered when dragging ends, providing details on target pane and drop action (split or move). */
|
|
64
|
-
onDragEnd?: (activeId: string, overId: string | null, dropAction: {
|
|
65
|
-
type: 'split' | 'move';
|
|
66
|
-
direction?: SplitDirection;
|
|
67
|
-
position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
68
|
-
} | null) => void;
|
|
69
|
-
/** Callback triggered when the user starts dragging a resizing handle between split panes. */
|
|
70
|
-
onResizeStart?: (currentNode: SplitNode) => void;
|
|
71
|
-
/** Callback triggered continuously while the user is dragging a resizing handle. Passes the new split percentage. */
|
|
72
|
-
onResize?: (currentNode: SplitNode, percentage: number) => void;
|
|
73
|
-
/** Callback triggered when the user stops dragging a resizing handle. Passes the final split percentage. */
|
|
74
|
-
onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
|
|
75
|
-
/** Callback triggered when the drag-out/dismiss intent changes. */
|
|
76
|
-
onDismissIntentChange?: (paneId: string | null) => void;
|
|
77
40
|
}
|
|
78
|
-
interface
|
|
41
|
+
interface ZeugmaState {
|
|
79
42
|
/** The current active layout tree structure, or null if empty. */
|
|
80
43
|
layout: TreeNode | null;
|
|
81
|
-
/** Updates the layout tree. Also resets transient states like fullscreenPaneId. */
|
|
82
|
-
setLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
83
|
-
/** @internal Raw layout setter used by DnD internals — does NOT reset transient states. */
|
|
84
|
-
_internalSetLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
85
44
|
/** The ID of the pane currently zoomed to fullscreen, or null. */
|
|
86
45
|
fullscreenPaneId: string | null;
|
|
87
|
-
/** Programmatically sets the fullscreen pane ID. */
|
|
88
|
-
setFullscreenPaneId: (paneId: string | null) => void;
|
|
89
46
|
/** Whether the layout is globally locked. */
|
|
90
47
|
locked: boolean;
|
|
48
|
+
}
|
|
49
|
+
interface ZeugmaStateSetters {
|
|
50
|
+
/** Updates the layout tree. Also resets transient states like fullscreenPaneId. */
|
|
51
|
+
setLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
52
|
+
/** Programmatically sets the fullscreen pane ID. */
|
|
53
|
+
setFullscreenPaneId: (paneId: string | null) => void;
|
|
91
54
|
/** Programmatically updates the global locked status. */
|
|
92
55
|
setLocked: Dispatch<SetStateAction<boolean>>;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/** The type of the active dragged item ('pane' | 'tab'). */
|
|
96
|
-
activeType: 'pane' | 'tab' | null;
|
|
97
|
-
/** The ID of the item with active dismiss intent, or null. */
|
|
98
|
-
dismissIntentId: string | null;
|
|
99
|
-
setActiveId: Dispatch<SetStateAction<string | null>>;
|
|
100
|
-
setActiveType: Dispatch<SetStateAction<'pane' | 'tab' | null>>;
|
|
101
|
-
setDismissIntentId: Dispatch<SetStateAction<string | null>>;
|
|
102
|
-
containerRef: RefObject<HTMLElement | null>;
|
|
103
|
-
setContainerRef: (element: HTMLElement | null) => void;
|
|
104
|
-
layoutBeforeDrag: TreeNode | null;
|
|
105
|
-
setLayoutBeforeDrag: Dispatch<SetStateAction<TreeNode | null>>;
|
|
106
|
-
dragActivationDistance: number;
|
|
107
|
-
snapThreshold: number;
|
|
108
|
-
minSplitPercentage: number;
|
|
109
|
-
maxSplitPercentage: number;
|
|
110
|
-
enableDragToDismiss: boolean;
|
|
111
|
-
dismissThreshold: number;
|
|
112
|
-
onRemove?: (paneId: string) => void;
|
|
113
|
-
onDragStart?: (activeId: string) => void;
|
|
114
|
-
onDragEnd?: (activeId: string, overId: string | null, dropAction: {
|
|
115
|
-
type: 'split' | 'move';
|
|
116
|
-
direction?: SplitDirection;
|
|
117
|
-
position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
118
|
-
} | null) => void;
|
|
119
|
-
onResizeStart?: (currentNode: SplitNode) => void;
|
|
120
|
-
onResize?: (currentNode: SplitNode, percentage: number) => void;
|
|
121
|
-
onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
|
|
122
|
-
onDismissIntentChange?: (paneId: string | null) => void;
|
|
56
|
+
}
|
|
57
|
+
interface ZeugmaActions {
|
|
123
58
|
/** Removes the specified pane or widget from the layout tree and collapses its parent split. */
|
|
124
59
|
removePane: (paneId: string) => void;
|
|
125
|
-
/** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
|
|
126
|
-
addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
|
|
127
60
|
/** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
|
|
128
61
|
addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
|
|
129
62
|
/** Stable callback to update metadata for a specific tab or widget. */
|
|
@@ -142,12 +75,20 @@ interface ZeugmaController {
|
|
|
142
75
|
updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
|
|
143
76
|
/** Moves/reorders a tab relative to another target tab. */
|
|
144
77
|
moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
|
|
78
|
+
}
|
|
79
|
+
interface ZeugmaQueries {
|
|
145
80
|
/** Find a PaneNode or WidgetNode by its ID in the layout tree. */
|
|
146
|
-
findPaneById: (paneId: string) =>
|
|
81
|
+
findPaneById: (paneId: string) => PaneNode | null;
|
|
147
82
|
/** Find the PaneNode containing the given tab ID in the layout tree. */
|
|
148
83
|
findPaneContainingTab: (tabId: string) => PaneNode | null;
|
|
149
84
|
/** Find the details of a tab by its ID in the layout tree. */
|
|
150
85
|
findTabById: (tabId: string) => TabDetails | null;
|
|
86
|
+
/** Get the metadata for a specific tab by its ID. */
|
|
87
|
+
getTabMetadata: (tabId: string) => Record<string, unknown> | undefined;
|
|
88
|
+
/** Get the metadata of the active tab in a specific pane by the pane ID. */
|
|
89
|
+
getActiveTabMetadata: (paneId: string) => Record<string, unknown> | undefined;
|
|
90
|
+
}
|
|
91
|
+
interface ZeugmaController extends ZeugmaState, ZeugmaStateSetters, ZeugmaActions, ZeugmaQueries {
|
|
151
92
|
}
|
|
152
93
|
interface ZeugmaClassNames {
|
|
153
94
|
/** CSS class applied to the root dashboard container. */
|
|
@@ -172,106 +113,81 @@ interface ZeugmaClassNames {
|
|
|
172
113
|
dashboardLocked?: string;
|
|
173
114
|
/** CSS class applied to drop zone indicator when hovering over a locked pane. */
|
|
174
115
|
lockedPreview?: string;
|
|
175
|
-
/** CSS class applied to
|
|
116
|
+
/** CSS class applied to drop zone indicator when hovering over a locked pane. */
|
|
176
117
|
tabDropPreview?: string;
|
|
177
118
|
/** CSS class applied to the separator line between tabs. */
|
|
178
119
|
tabSeparator?: string;
|
|
120
|
+
/** CSS class applied to the wrapper element for a tab's contents. */
|
|
121
|
+
tabContentWrapper?: string;
|
|
122
|
+
/** CSS class applied to the tabs container div. */
|
|
123
|
+
tabsContainer?: string;
|
|
124
|
+
/** CSS class applied to individual tabs (as static string or dynamic callback). */
|
|
125
|
+
tab?: string | ((tabId: string) => string);
|
|
126
|
+
/** CSS class applied to the pane inner container (containing header and content). */
|
|
127
|
+
paneContainer?: string;
|
|
128
|
+
/** CSS class applied to the pane header bar. */
|
|
129
|
+
paneHeader?: string;
|
|
130
|
+
/** CSS class applied to the pane controls wrapper. */
|
|
131
|
+
paneControls?: string;
|
|
132
|
+
/** CSS class applied to the pane buttons (maximize/close). */
|
|
133
|
+
paneButton?: string;
|
|
134
|
+
/** CSS class applied to the default tab close button. */
|
|
135
|
+
tabCloseButton?: string;
|
|
136
|
+
/** CSS class applied to the drag handle. */
|
|
137
|
+
dragHandle?: string;
|
|
138
|
+
}
|
|
139
|
+
interface DragOverlayActiveItem {
|
|
140
|
+
type: 'tab' | 'pane';
|
|
141
|
+
id: string;
|
|
142
|
+
isDismissing: boolean;
|
|
179
143
|
}
|
|
180
|
-
interface ZeugmaProps
|
|
181
|
-
/**
|
|
182
|
-
|
|
144
|
+
interface ZeugmaProps {
|
|
145
|
+
/** The Zeugma Controller returned by useZeugma() */
|
|
146
|
+
controller?: ZeugmaController;
|
|
183
147
|
/** Custom overlay renderer function used to customize the cursor-following drag preview for an active pane or tab. */
|
|
184
|
-
renderDragOverlay?: (
|
|
148
|
+
renderDragOverlay?: (active: DragOverlayActiveItem) => ReactNode;
|
|
185
149
|
/** Optional CSS class name mapping overrides for custom styles of components like panes, drop previews, overlays, etc. */
|
|
186
150
|
classNames?: ZeugmaClassNames;
|
|
187
|
-
/** Render function mapping
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
* All consumers of this context will re-render when any of these values change.
|
|
195
|
-
*/
|
|
196
|
-
interface ZeugmaStateValue {
|
|
197
|
-
/** The current active layout tree structure, or null if empty. */
|
|
198
|
-
layout: TreeNode | null;
|
|
199
|
-
/** Callback to update the layout tree. */
|
|
200
|
-
setLayout: Dispatch<SetStateAction<TreeNode | null>>;
|
|
201
|
-
/** Renders the inner content of a pane given its unique ID. */
|
|
202
|
-
renderPane: (paneId: string) => ReactNode;
|
|
203
|
-
/** The ID of the pane currently zoomed to fullscreen, or null. */
|
|
204
|
-
fullscreenPaneId: string | null;
|
|
205
|
-
/** Normalized or overridden CSS classes for custom layout styling. */
|
|
206
|
-
classNames: ZeugmaClassNames;
|
|
207
|
-
/** Whether the layout is globally locked. */
|
|
208
|
-
locked: boolean;
|
|
209
|
-
/** Programmatically updates the global locked status. */
|
|
210
|
-
setLocked: Dispatch<SetStateAction<boolean>>;
|
|
211
|
-
/** Find a PaneNode or WidgetNode by its ID in the layout tree. */
|
|
212
|
-
findPaneById: (paneId: string) => LeafNode | null;
|
|
213
|
-
/** Find the PaneNode containing the given tab ID in the layout tree. */
|
|
214
|
-
findPaneContainingTab: (tabId: string) => PaneNode | null;
|
|
215
|
-
/** Find the details of a tab by its ID in the layout tree. */
|
|
216
|
-
findTabById: (tabId: string) => TabDetails | null;
|
|
217
|
-
/** The ID of the active dragged item (pane or tab). */
|
|
218
|
-
activeId: string | null;
|
|
219
|
-
/** The type of the active dragged item ('pane' | 'tab'). */
|
|
220
|
-
activeType: 'pane' | 'tab' | null;
|
|
221
|
-
/** The ID of the item with active dismiss intent, or null. */
|
|
222
|
-
dismissIntentId: string | null;
|
|
223
|
-
setContainerRef: (element: HTMLElement | null) => void;
|
|
224
|
-
onRemove?: (paneId: string) => void;
|
|
225
|
-
onFullscreenChange?: (paneId: string | null) => void;
|
|
151
|
+
/** Render function mapping unique pane nodes to React elements. Usually renders a <Pane> wrapper. */
|
|
152
|
+
renderPane?: (paneId: string) => ReactNode;
|
|
153
|
+
/** Size/thickness of the split handle resizer bars in pixels. */
|
|
154
|
+
resizerSize?: number;
|
|
155
|
+
/** Minimum pixel distance that a user must drag a pane handle before dragging triggers. Defaults to 8. */
|
|
156
|
+
dragActivationDistance?: number;
|
|
157
|
+
/** Threshold value in pixels for snapping layout resizing handles to adjacent edges. Defaults to 8. */
|
|
226
158
|
snapThreshold?: number;
|
|
159
|
+
/** Minimum split percentage allowed when resizing split panes. Defaults to 5. */
|
|
160
|
+
minSplitPercentage?: number;
|
|
161
|
+
/** Maximum split percentage allowed when resizing split panes. Defaults to 95. */
|
|
162
|
+
maxSplitPercentage?: number;
|
|
163
|
+
/** Whether dragging a pane far enough outside the container triggers a drag-out/dismiss action. Defaults to false. */
|
|
164
|
+
enableDragToDismiss?: boolean;
|
|
165
|
+
/** The threshold in pixels beyond the container boundaries required to activate the drag-out/dismiss action. Defaults to 60. */
|
|
166
|
+
dismissThreshold?: number;
|
|
167
|
+
/** Callback triggered when a pane is removed from the dashboard layout tree. */
|
|
168
|
+
onRemove?: (paneId: string) => void;
|
|
169
|
+
/** Callback triggered when dragging starts for a pane. */
|
|
170
|
+
onDragStart?: (activeId: string) => void;
|
|
171
|
+
/** Callback triggered when dragging ends, providing details on target pane and drop action (split or move). */
|
|
172
|
+
onDragEnd?: (activeId: string, overId: string | null, dropAction: {
|
|
173
|
+
type: 'split' | 'move';
|
|
174
|
+
direction?: SplitDirection;
|
|
175
|
+
position?: 'top' | 'bottom' | 'left' | 'right' | 'center';
|
|
176
|
+
} | null) => void;
|
|
177
|
+
/** Callback triggered when the user starts dragging a resizing handle between split panes. */
|
|
227
178
|
onResizeStart?: (currentNode: SplitNode) => void;
|
|
179
|
+
/** Callback triggered continuously while the user is dragging a resizing handle. Passes the new split percentage. */
|
|
228
180
|
onResize?: (currentNode: SplitNode, percentage: number) => void;
|
|
181
|
+
/** Callback triggered when the user stops dragging a resizing handle. Passes the final split percentage. */
|
|
229
182
|
onResizeEnd?: (currentNode: SplitNode, percentage: number) => void;
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
}
|
|
233
|
-
interface ZeugmaDragStateValue {
|
|
234
|
-
/** The ID of the tab currently hovered over during a tab drag, or null. */
|
|
235
|
-
overTabId: string | null;
|
|
236
|
-
/** The position of the tab drop preview relative to the hovered tab ('before' | 'after'). */
|
|
237
|
-
overTabPosition: 'before' | 'after' | null;
|
|
238
|
-
}
|
|
239
|
-
/**
|
|
240
|
-
* Actions context — holds stable dispatch functions with permanent identity.
|
|
241
|
-
* Consumers of only this context will never re-render from layout/drag state changes.
|
|
242
|
-
*/
|
|
243
|
-
interface ZeugmaActionsValue {
|
|
244
|
-
/** Removes the specified pane or widget from the layout tree and collapses its parent split. */
|
|
245
|
-
removePane: (paneId: string) => void;
|
|
246
|
-
/** Appends/inserts a widget at the bottom-rightmost leaf of the layout tree. */
|
|
247
|
-
addWidget: (widgetId: string, metadata?: Record<string, unknown>) => void;
|
|
248
|
-
/** Appends a tab into a target pane node, or splits/creates a new pane if no target pane ID is provided. */
|
|
249
|
-
addTab: (tabId: string, targetPaneId?: string, metadata?: Record<string, unknown>) => void;
|
|
250
|
-
/** Stable callback to update metadata for a specific tab or widget. */
|
|
251
|
-
updateMetadata: (id: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
252
|
-
/** Stable callback to update the locked status of a specific pane in the layout tree. */
|
|
253
|
-
updatePaneLock: (paneId: string, locked: boolean) => void;
|
|
254
|
-
/** Stable callback to activate a tab within a pane. */
|
|
255
|
-
selectTab: (paneId: string, tabId: string) => void;
|
|
256
|
-
/** Stable callback to merge a dragged tab/pane into another pane's tab list. */
|
|
257
|
-
mergeTab: (draggedTabId: string, targetPaneId: string) => void;
|
|
258
|
-
/** Stable callback to remove/close a specific tab from the layout. */
|
|
259
|
-
removeTab: (tabId: string) => void;
|
|
260
|
-
/** Programmatically sets the fullscreen pane ID. */
|
|
261
|
-
setFullscreenPaneId: (paneId: string | null) => void;
|
|
262
|
-
/** Programmatically updates the global locked status. */
|
|
263
|
-
setLocked: Dispatch<SetStateAction<boolean>>;
|
|
264
|
-
/** Splits an existing pane and adds a new one. */
|
|
265
|
-
splitPane: (targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string) => void;
|
|
266
|
-
/** Updates the split percentage of a split node. */
|
|
267
|
-
updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
|
|
268
|
-
/** Moves/reorders a tab relative to another target tab. */
|
|
269
|
-
moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
|
|
270
|
-
}
|
|
271
|
-
interface ZeugmaContextValue extends ZeugmaStateValue, ZeugmaActionsValue {
|
|
183
|
+
/** Callback triggered when the drag-out/dismiss intent changes. */
|
|
184
|
+
onDismissIntentChange?: (paneId: string | null) => void;
|
|
272
185
|
}
|
|
273
|
-
interface
|
|
274
|
-
|
|
186
|
+
interface ZeugmaProviderProps extends Omit<ZeugmaProps, 'controller'> {
|
|
187
|
+
/** The Zeugma Controller returned by useZeugma() */
|
|
188
|
+
controller: ZeugmaController;
|
|
189
|
+
/** Children components that will have access to the Zeugma context */
|
|
190
|
+
children: ReactNode;
|
|
275
191
|
}
|
|
276
192
|
|
|
277
|
-
export type {
|
|
193
|
+
export type { DragOverlayActiveItem as D, PaneNode as P, SplitDirection as S, TreeNode as T, UseZeugmaOptions as U, ZeugmaController as Z, ZeugmaProps as a, ZeugmaProviderProps as b, SplitNode as c, TabDetails as d, ZeugmaClassNames as e };
|