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