react-zeugma 2.2.2 → 3.0.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 +46 -13
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +122 -16
- package/dist/index.d.ts +122 -16
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -12
package/dist/index.d.cts
CHANGED
|
@@ -10,14 +10,19 @@ interface SplitNode {
|
|
|
10
10
|
}
|
|
11
11
|
interface PaneNode {
|
|
12
12
|
type: 'pane';
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
id: string;
|
|
14
|
+
tabs: string[];
|
|
15
|
+
activeTabId: string;
|
|
16
|
+
locked?: boolean;
|
|
17
|
+
tabsMetadata?: Record<string, Record<string, unknown>>;
|
|
15
18
|
}
|
|
16
19
|
type TreeNode = SplitNode | PaneNode;
|
|
17
20
|
|
|
18
21
|
interface ZeugmaClassNames {
|
|
19
22
|
/** CSS class applied to the outer container div of each `<Pane>`. */
|
|
20
23
|
pane?: string;
|
|
24
|
+
/** CSS class applied to the pane container when locked. */
|
|
25
|
+
paneLocked?: string;
|
|
21
26
|
/** CSS class applied to drop zone indicators when hovering over layout edges to split a pane. */
|
|
22
27
|
dropPreview?: string;
|
|
23
28
|
/** CSS class applied to the drop zone indicator when hovering over the center of a pane to swap. */
|
|
@@ -28,6 +33,10 @@ interface ZeugmaClassNames {
|
|
|
28
33
|
resizer?: string;
|
|
29
34
|
/** CSS class applied to the background dismiss zone indicator during a drag-out dismiss gesture. */
|
|
30
35
|
dismissPreview?: string;
|
|
36
|
+
/** CSS class applied to root container when dashboard is globally locked. */
|
|
37
|
+
dashboardLocked?: string;
|
|
38
|
+
/** CSS class applied to drop zone indicator when hovering over a locked pane. */
|
|
39
|
+
lockedPreview?: string;
|
|
31
40
|
}
|
|
32
41
|
interface ZeugmaProps {
|
|
33
42
|
/** The layout tree model (TreeNode) defining pane organization and split percentages. Set to null for empty layout. */
|
|
@@ -36,8 +45,8 @@ interface ZeugmaProps {
|
|
|
36
45
|
onChange: (newLayout: TreeNode | null) => void;
|
|
37
46
|
/** Render function mapping unique pane IDs to React elements. Usually renders a <Pane> wrapper. */
|
|
38
47
|
renderPane: (paneId: string) => ReactNode;
|
|
39
|
-
/** Custom overlay renderer function used to customize the cursor-following drag preview for an active pane. */
|
|
40
|
-
renderDragOverlay?: (activeId: string) => ReactNode;
|
|
48
|
+
/** Custom overlay renderer function used to customize the cursor-following drag preview for an active pane or tab. */
|
|
49
|
+
renderDragOverlay?: (activeId: string, type: 'pane' | 'tab') => ReactNode;
|
|
41
50
|
/** Optional CSS class name mapping overrides for custom styles of components like panes, drop/swap previews, overlays, etc. */
|
|
42
51
|
classNames?: ZeugmaClassNames;
|
|
43
52
|
/** The ID of the pane that is currently taking up the full dashboard area. Null if no pane is fullscreen. */
|
|
@@ -74,6 +83,10 @@ interface ZeugmaProps {
|
|
|
74
83
|
dismissThreshold?: number;
|
|
75
84
|
/** Callback triggered when the drag-out/dismiss intent changes (active pane ID or null when drag returns inside bounds). */
|
|
76
85
|
onDismissIntentChange?: (paneId: string | null) => void;
|
|
86
|
+
/** Whether the layout is locked. When locked, resizing, dragging, and dropping are disabled. */
|
|
87
|
+
locked?: boolean;
|
|
88
|
+
/** Render function mapping tab IDs to React elements. Used to render tab widgets inside portals. */
|
|
89
|
+
renderWidget?: (tabId: string) => ReactNode;
|
|
77
90
|
/** Child nodes nested inside the Zeugma context, usually containing a <PaneTree> or similar layout viewer. */
|
|
78
91
|
children: ReactNode;
|
|
79
92
|
}
|
|
@@ -114,6 +127,8 @@ interface ZeugmaStateValue {
|
|
|
114
127
|
minSplitPercentage?: number;
|
|
115
128
|
/** Maximum split percentage allowed when resizing. */
|
|
116
129
|
maxSplitPercentage?: number;
|
|
130
|
+
/** Whether the layout is globally locked. */
|
|
131
|
+
locked: boolean;
|
|
117
132
|
}
|
|
118
133
|
/**
|
|
119
134
|
* Actions context — holds stable dispatch functions with permanent identity.
|
|
@@ -130,8 +145,18 @@ interface ZeugmaActionsValue {
|
|
|
130
145
|
splitPane: (targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string) => void;
|
|
131
146
|
/** Updates the split percentage of a specific split branch node. */
|
|
132
147
|
updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
|
|
133
|
-
/** Stable callback to update metadata for a specific
|
|
134
|
-
|
|
148
|
+
/** Stable callback to update metadata for a specific tab. */
|
|
149
|
+
updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
150
|
+
/** Stable callback to update the locked status of a specific pane in the layout tree. */
|
|
151
|
+
updatePaneLock: (paneId: string, locked: boolean) => void;
|
|
152
|
+
/** Stable callback to activate a tab within a pane. */
|
|
153
|
+
selectTab: (paneId: string, tabId: string) => void;
|
|
154
|
+
/** Stable callback to merge a dragged tab/pane into another pane's tab list. */
|
|
155
|
+
mergeTab: (draggedTabId: string, targetPaneId: string) => void;
|
|
156
|
+
/** Stable callback to move/reorder a tab to another pane next to a target tab. */
|
|
157
|
+
moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
|
|
158
|
+
/** Stable callback to remove/close a specific tab from the layout. */
|
|
159
|
+
removeTab: (tabId: string) => void;
|
|
135
160
|
}
|
|
136
161
|
|
|
137
162
|
declare const useZeugmaState: () => ZeugmaStateValue;
|
|
@@ -200,12 +225,28 @@ interface PaneRenderProps {
|
|
|
200
225
|
isFullscreen: boolean;
|
|
201
226
|
/** Toggles the pane to and from fullscreen/zoomed mode. */
|
|
202
227
|
toggleFullscreen: () => void;
|
|
203
|
-
/** Closes and removes the
|
|
228
|
+
/** Closes and removes the active tab from the layout tree. */
|
|
204
229
|
remove: () => void;
|
|
205
|
-
/** The metadata values associated with
|
|
230
|
+
/** The metadata values associated with the active tab, or undefined. */
|
|
206
231
|
metadata: Record<string, unknown> | undefined;
|
|
207
|
-
/** Updates the metadata of
|
|
232
|
+
/** Updates the metadata of the active tab using an updater function. */
|
|
208
233
|
updateMetadata: (updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
234
|
+
/** True if this specific pane or the dashboard globally is locked. */
|
|
235
|
+
locked: boolean;
|
|
236
|
+
/** The array of tab IDs in this pane. */
|
|
237
|
+
tabs: string[];
|
|
238
|
+
/** The currently active tab ID. */
|
|
239
|
+
activeTabId: string;
|
|
240
|
+
/** Selects a specific tab to make it active. */
|
|
241
|
+
selectTab: (tabId: string) => void;
|
|
242
|
+
/** Removes/closes a specific tab. */
|
|
243
|
+
removeTab: (tabId: string) => void;
|
|
244
|
+
/** The metadata values associated with all tabs in this pane. */
|
|
245
|
+
tabsMetadata: Record<string, Record<string, unknown>> | undefined;
|
|
246
|
+
/** Updates the metadata of a specific tab. */
|
|
247
|
+
updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
248
|
+
/** Renders the target placeholder element for the currently active tab in the pane. */
|
|
249
|
+
renderActiveTab: () => ReactNode;
|
|
209
250
|
}
|
|
210
251
|
|
|
211
252
|
interface PaneProps {
|
|
@@ -215,12 +256,14 @@ interface PaneProps {
|
|
|
215
256
|
children: (props: PaneRenderProps) => React.ReactNode;
|
|
216
257
|
/** Optional inline CSS styles applied to the pane outer container. */
|
|
217
258
|
style?: React.CSSProperties;
|
|
259
|
+
/** Optional override to lock this specific pane. */
|
|
260
|
+
locked?: boolean;
|
|
218
261
|
}
|
|
219
262
|
declare const Pane: React.FC<PaneProps>;
|
|
220
263
|
|
|
221
264
|
interface DragHandleProps {
|
|
222
265
|
/** The children elements that will trigger dragging when held and dragged. */
|
|
223
|
-
children
|
|
266
|
+
children?: React.ReactNode;
|
|
224
267
|
/** Custom CSS class applied to the drag handle element. */
|
|
225
268
|
className?: string;
|
|
226
269
|
/** Optional inline CSS styles applied to the drag handle. */
|
|
@@ -228,14 +271,36 @@ interface DragHandleProps {
|
|
|
228
271
|
}
|
|
229
272
|
declare const DragHandle: React.FC<DragHandleProps>;
|
|
230
273
|
|
|
274
|
+
interface TabRenderProps {
|
|
275
|
+
isDragging: boolean;
|
|
276
|
+
isOver: boolean;
|
|
277
|
+
}
|
|
278
|
+
interface TabProps {
|
|
279
|
+
/** The unique ID of the tab, which corresponds to the pane/widget ID. */
|
|
280
|
+
id: string;
|
|
281
|
+
/** Whether dragging is locked on this tab. */
|
|
282
|
+
locked?: boolean;
|
|
283
|
+
/** Render prop child function. */
|
|
284
|
+
children: (props: TabRenderProps) => React.ReactNode;
|
|
285
|
+
/** Custom CSS class applied to the tab wrapper. */
|
|
286
|
+
className?: string;
|
|
287
|
+
/** Custom inline CSS style applied to the tab wrapper. */
|
|
288
|
+
style?: React.CSSProperties;
|
|
289
|
+
}
|
|
290
|
+
declare const Tab: React.FC<TabProps>;
|
|
291
|
+
|
|
231
292
|
declare const DEFAULT_SNAP_THRESHOLD = 8;
|
|
232
293
|
declare const DEFAULT_DRAG_ACTIVATION_DISTANCE = 8;
|
|
233
294
|
declare const DEFAULT_RESIZER_SIZE = 4;
|
|
234
295
|
|
|
235
296
|
/**
|
|
236
|
-
* Tree Helper: Remove a pane and consolidate the tree structure.
|
|
297
|
+
* Tree Helper: Remove a pane container and consolidate the tree structure.
|
|
298
|
+
*/
|
|
299
|
+
declare function removePane(tree: TreeNode | null, paneId: string): TreeNode | null;
|
|
300
|
+
/**
|
|
301
|
+
* Tree Helper: Remove a tab from a pane and consolidate the tree structure if no tabs remain.
|
|
237
302
|
*/
|
|
238
|
-
declare function
|
|
303
|
+
declare function removeTab(tree: TreeNode | null, tabId: string): TreeNode | null;
|
|
239
304
|
/**
|
|
240
305
|
* Tree Helper: Insert a pane by splitting an existing target node.
|
|
241
306
|
*/
|
|
@@ -253,13 +318,54 @@ declare function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode;
|
|
|
253
318
|
*/
|
|
254
319
|
declare function updateSplitPercentage(tree: TreeNode | null, target: SplitNode, newPercentage: number): TreeNode | null;
|
|
255
320
|
/**
|
|
256
|
-
* Find a PaneNode by its
|
|
321
|
+
* Find a PaneNode by its ID or by any of its tab IDs.
|
|
257
322
|
*/
|
|
258
323
|
declare function findPane(tree: TreeNode | null, paneId: string): PaneNode | null;
|
|
259
324
|
/**
|
|
260
|
-
* Update metadata on a specific
|
|
325
|
+
* Update metadata on a specific tab node using an updater function.
|
|
326
|
+
*/
|
|
327
|
+
declare function updateTabMetadata(tree: TreeNode | null, tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined): TreeNode | null;
|
|
328
|
+
/**
|
|
329
|
+
* Update the locked status on a specific pane node in the layout tree.
|
|
330
|
+
*/
|
|
331
|
+
declare function updatePaneLock(tree: TreeNode | null, paneId: string, locked: boolean): TreeNode | null;
|
|
332
|
+
/**
|
|
333
|
+
* Tree Helper: Activate a tab within a pane.
|
|
334
|
+
*/
|
|
335
|
+
declare function selectTab(tree: TreeNode | null, paneId: string, tabId: string): TreeNode | null;
|
|
336
|
+
/**
|
|
337
|
+
* Tree Helper: Merge a tab into a target pane node.
|
|
338
|
+
*/
|
|
339
|
+
declare function mergeTab(tree: TreeNode | null, draggedTabId: string, targetPaneId: string): TreeNode | null;
|
|
340
|
+
/**
|
|
341
|
+
* Tree Helper: Move/reorder a tab inside or to a target pane next to a target tab.
|
|
261
342
|
*/
|
|
262
|
-
declare function
|
|
343
|
+
declare function moveTab(tree: TreeNode | null, draggedTabId: string, targetTabId: string, position?: 'before' | 'after'): TreeNode | null;
|
|
344
|
+
interface ComputedPane {
|
|
345
|
+
paneId: string;
|
|
346
|
+
left: number;
|
|
347
|
+
top: number;
|
|
348
|
+
width: number;
|
|
349
|
+
height: number;
|
|
350
|
+
node: PaneNode;
|
|
351
|
+
}
|
|
352
|
+
interface ComputedSplitter {
|
|
353
|
+
id: string;
|
|
354
|
+
currentNode: SplitNode;
|
|
355
|
+
direction: SplitDirection;
|
|
356
|
+
left: number;
|
|
357
|
+
top: number;
|
|
358
|
+
width: number;
|
|
359
|
+
height: number;
|
|
360
|
+
parentLeft: number;
|
|
361
|
+
parentTop: number;
|
|
362
|
+
parentWidth: number;
|
|
363
|
+
parentHeight: number;
|
|
364
|
+
}
|
|
365
|
+
declare function computeLayout(node: TreeNode | null, left?: number, top?: number, width?: number, height?: number, path?: string): {
|
|
366
|
+
panes: ComputedPane[];
|
|
367
|
+
splitters: ComputedSplitter[];
|
|
368
|
+
};
|
|
263
369
|
|
|
264
370
|
/**
|
|
265
371
|
* Shared drag-session lifecycle utility.
|
|
@@ -286,4 +392,4 @@ interface DragSessionConfig {
|
|
|
286
392
|
}
|
|
287
393
|
declare function createDragSession({ cursor, resizerEl, onMove, onEnd }: DragSessionConfig): void;
|
|
288
394
|
|
|
289
|
-
export { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, DragHandle, type DragHandleProps, type DragSessionConfig, Pane, type PaneNode, type PaneProps, type PaneRenderProps, PaneTree, ResizableContainer, type ResizableContainerProps, type SplitDirection, type SplitNode, type TreeNode, Zeugma, type ZeugmaActionsValue, type ZeugmaClassNames, type ZeugmaProps, type ZeugmaStateValue, addPane, createDragSession, findPane, removePane, splitPane, swapPanes,
|
|
395
|
+
export { type ComputedPane, type ComputedSplitter, DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, DragHandle, type DragHandleProps, type DragSessionConfig, Pane, type PaneNode, type PaneProps, type PaneRenderProps, PaneTree, ResizableContainer, type ResizableContainerProps, type SplitDirection, type SplitNode, Tab, type TabProps, type TabRenderProps, type TreeNode, Zeugma, type ZeugmaActionsValue, type ZeugmaClassNames, type ZeugmaProps, type ZeugmaStateValue, addPane, computeLayout, createDragSession, findPane, mergeTab, moveTab, removePane, removeTab, selectTab, splitPane, swapPanes, updatePaneLock, updateSplitPercentage, updateTabMetadata, useResizer, useZeugmaActions, useZeugmaState };
|
package/dist/index.d.ts
CHANGED
|
@@ -10,14 +10,19 @@ interface SplitNode {
|
|
|
10
10
|
}
|
|
11
11
|
interface PaneNode {
|
|
12
12
|
type: 'pane';
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
id: string;
|
|
14
|
+
tabs: string[];
|
|
15
|
+
activeTabId: string;
|
|
16
|
+
locked?: boolean;
|
|
17
|
+
tabsMetadata?: Record<string, Record<string, unknown>>;
|
|
15
18
|
}
|
|
16
19
|
type TreeNode = SplitNode | PaneNode;
|
|
17
20
|
|
|
18
21
|
interface ZeugmaClassNames {
|
|
19
22
|
/** CSS class applied to the outer container div of each `<Pane>`. */
|
|
20
23
|
pane?: string;
|
|
24
|
+
/** CSS class applied to the pane container when locked. */
|
|
25
|
+
paneLocked?: string;
|
|
21
26
|
/** CSS class applied to drop zone indicators when hovering over layout edges to split a pane. */
|
|
22
27
|
dropPreview?: string;
|
|
23
28
|
/** CSS class applied to the drop zone indicator when hovering over the center of a pane to swap. */
|
|
@@ -28,6 +33,10 @@ interface ZeugmaClassNames {
|
|
|
28
33
|
resizer?: string;
|
|
29
34
|
/** CSS class applied to the background dismiss zone indicator during a drag-out dismiss gesture. */
|
|
30
35
|
dismissPreview?: string;
|
|
36
|
+
/** CSS class applied to root container when dashboard is globally locked. */
|
|
37
|
+
dashboardLocked?: string;
|
|
38
|
+
/** CSS class applied to drop zone indicator when hovering over a locked pane. */
|
|
39
|
+
lockedPreview?: string;
|
|
31
40
|
}
|
|
32
41
|
interface ZeugmaProps {
|
|
33
42
|
/** The layout tree model (TreeNode) defining pane organization and split percentages. Set to null for empty layout. */
|
|
@@ -36,8 +45,8 @@ interface ZeugmaProps {
|
|
|
36
45
|
onChange: (newLayout: TreeNode | null) => void;
|
|
37
46
|
/** Render function mapping unique pane IDs to React elements. Usually renders a <Pane> wrapper. */
|
|
38
47
|
renderPane: (paneId: string) => ReactNode;
|
|
39
|
-
/** Custom overlay renderer function used to customize the cursor-following drag preview for an active pane. */
|
|
40
|
-
renderDragOverlay?: (activeId: string) => ReactNode;
|
|
48
|
+
/** Custom overlay renderer function used to customize the cursor-following drag preview for an active pane or tab. */
|
|
49
|
+
renderDragOverlay?: (activeId: string, type: 'pane' | 'tab') => ReactNode;
|
|
41
50
|
/** Optional CSS class name mapping overrides for custom styles of components like panes, drop/swap previews, overlays, etc. */
|
|
42
51
|
classNames?: ZeugmaClassNames;
|
|
43
52
|
/** The ID of the pane that is currently taking up the full dashboard area. Null if no pane is fullscreen. */
|
|
@@ -74,6 +83,10 @@ interface ZeugmaProps {
|
|
|
74
83
|
dismissThreshold?: number;
|
|
75
84
|
/** Callback triggered when the drag-out/dismiss intent changes (active pane ID or null when drag returns inside bounds). */
|
|
76
85
|
onDismissIntentChange?: (paneId: string | null) => void;
|
|
86
|
+
/** Whether the layout is locked. When locked, resizing, dragging, and dropping are disabled. */
|
|
87
|
+
locked?: boolean;
|
|
88
|
+
/** Render function mapping tab IDs to React elements. Used to render tab widgets inside portals. */
|
|
89
|
+
renderWidget?: (tabId: string) => ReactNode;
|
|
77
90
|
/** Child nodes nested inside the Zeugma context, usually containing a <PaneTree> or similar layout viewer. */
|
|
78
91
|
children: ReactNode;
|
|
79
92
|
}
|
|
@@ -114,6 +127,8 @@ interface ZeugmaStateValue {
|
|
|
114
127
|
minSplitPercentage?: number;
|
|
115
128
|
/** Maximum split percentage allowed when resizing. */
|
|
116
129
|
maxSplitPercentage?: number;
|
|
130
|
+
/** Whether the layout is globally locked. */
|
|
131
|
+
locked: boolean;
|
|
117
132
|
}
|
|
118
133
|
/**
|
|
119
134
|
* Actions context — holds stable dispatch functions with permanent identity.
|
|
@@ -130,8 +145,18 @@ interface ZeugmaActionsValue {
|
|
|
130
145
|
splitPane: (targetId: string, direction: SplitDirection, splitType: 'left' | 'right' | 'top' | 'bottom', paneToAdd: string) => void;
|
|
131
146
|
/** Updates the split percentage of a specific split branch node. */
|
|
132
147
|
updateSplitPercentage: (currentNode: SplitNode, percentage: number) => void;
|
|
133
|
-
/** Stable callback to update metadata for a specific
|
|
134
|
-
|
|
148
|
+
/** Stable callback to update metadata for a specific tab. */
|
|
149
|
+
updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
150
|
+
/** Stable callback to update the locked status of a specific pane in the layout tree. */
|
|
151
|
+
updatePaneLock: (paneId: string, locked: boolean) => void;
|
|
152
|
+
/** Stable callback to activate a tab within a pane. */
|
|
153
|
+
selectTab: (paneId: string, tabId: string) => void;
|
|
154
|
+
/** Stable callback to merge a dragged tab/pane into another pane's tab list. */
|
|
155
|
+
mergeTab: (draggedTabId: string, targetPaneId: string) => void;
|
|
156
|
+
/** Stable callback to move/reorder a tab to another pane next to a target tab. */
|
|
157
|
+
moveTab: (draggedTabId: string, targetTabId: string, position?: 'before' | 'after') => void;
|
|
158
|
+
/** Stable callback to remove/close a specific tab from the layout. */
|
|
159
|
+
removeTab: (tabId: string) => void;
|
|
135
160
|
}
|
|
136
161
|
|
|
137
162
|
declare const useZeugmaState: () => ZeugmaStateValue;
|
|
@@ -200,12 +225,28 @@ interface PaneRenderProps {
|
|
|
200
225
|
isFullscreen: boolean;
|
|
201
226
|
/** Toggles the pane to and from fullscreen/zoomed mode. */
|
|
202
227
|
toggleFullscreen: () => void;
|
|
203
|
-
/** Closes and removes the
|
|
228
|
+
/** Closes and removes the active tab from the layout tree. */
|
|
204
229
|
remove: () => void;
|
|
205
|
-
/** The metadata values associated with
|
|
230
|
+
/** The metadata values associated with the active tab, or undefined. */
|
|
206
231
|
metadata: Record<string, unknown> | undefined;
|
|
207
|
-
/** Updates the metadata of
|
|
232
|
+
/** Updates the metadata of the active tab using an updater function. */
|
|
208
233
|
updateMetadata: (updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
234
|
+
/** True if this specific pane or the dashboard globally is locked. */
|
|
235
|
+
locked: boolean;
|
|
236
|
+
/** The array of tab IDs in this pane. */
|
|
237
|
+
tabs: string[];
|
|
238
|
+
/** The currently active tab ID. */
|
|
239
|
+
activeTabId: string;
|
|
240
|
+
/** Selects a specific tab to make it active. */
|
|
241
|
+
selectTab: (tabId: string) => void;
|
|
242
|
+
/** Removes/closes a specific tab. */
|
|
243
|
+
removeTab: (tabId: string) => void;
|
|
244
|
+
/** The metadata values associated with all tabs in this pane. */
|
|
245
|
+
tabsMetadata: Record<string, Record<string, unknown>> | undefined;
|
|
246
|
+
/** Updates the metadata of a specific tab. */
|
|
247
|
+
updateTabMetadata: (tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined) => void;
|
|
248
|
+
/** Renders the target placeholder element for the currently active tab in the pane. */
|
|
249
|
+
renderActiveTab: () => ReactNode;
|
|
209
250
|
}
|
|
210
251
|
|
|
211
252
|
interface PaneProps {
|
|
@@ -215,12 +256,14 @@ interface PaneProps {
|
|
|
215
256
|
children: (props: PaneRenderProps) => React.ReactNode;
|
|
216
257
|
/** Optional inline CSS styles applied to the pane outer container. */
|
|
217
258
|
style?: React.CSSProperties;
|
|
259
|
+
/** Optional override to lock this specific pane. */
|
|
260
|
+
locked?: boolean;
|
|
218
261
|
}
|
|
219
262
|
declare const Pane: React.FC<PaneProps>;
|
|
220
263
|
|
|
221
264
|
interface DragHandleProps {
|
|
222
265
|
/** The children elements that will trigger dragging when held and dragged. */
|
|
223
|
-
children
|
|
266
|
+
children?: React.ReactNode;
|
|
224
267
|
/** Custom CSS class applied to the drag handle element. */
|
|
225
268
|
className?: string;
|
|
226
269
|
/** Optional inline CSS styles applied to the drag handle. */
|
|
@@ -228,14 +271,36 @@ interface DragHandleProps {
|
|
|
228
271
|
}
|
|
229
272
|
declare const DragHandle: React.FC<DragHandleProps>;
|
|
230
273
|
|
|
274
|
+
interface TabRenderProps {
|
|
275
|
+
isDragging: boolean;
|
|
276
|
+
isOver: boolean;
|
|
277
|
+
}
|
|
278
|
+
interface TabProps {
|
|
279
|
+
/** The unique ID of the tab, which corresponds to the pane/widget ID. */
|
|
280
|
+
id: string;
|
|
281
|
+
/** Whether dragging is locked on this tab. */
|
|
282
|
+
locked?: boolean;
|
|
283
|
+
/** Render prop child function. */
|
|
284
|
+
children: (props: TabRenderProps) => React.ReactNode;
|
|
285
|
+
/** Custom CSS class applied to the tab wrapper. */
|
|
286
|
+
className?: string;
|
|
287
|
+
/** Custom inline CSS style applied to the tab wrapper. */
|
|
288
|
+
style?: React.CSSProperties;
|
|
289
|
+
}
|
|
290
|
+
declare const Tab: React.FC<TabProps>;
|
|
291
|
+
|
|
231
292
|
declare const DEFAULT_SNAP_THRESHOLD = 8;
|
|
232
293
|
declare const DEFAULT_DRAG_ACTIVATION_DISTANCE = 8;
|
|
233
294
|
declare const DEFAULT_RESIZER_SIZE = 4;
|
|
234
295
|
|
|
235
296
|
/**
|
|
236
|
-
* Tree Helper: Remove a pane and consolidate the tree structure.
|
|
297
|
+
* Tree Helper: Remove a pane container and consolidate the tree structure.
|
|
298
|
+
*/
|
|
299
|
+
declare function removePane(tree: TreeNode | null, paneId: string): TreeNode | null;
|
|
300
|
+
/**
|
|
301
|
+
* Tree Helper: Remove a tab from a pane and consolidate the tree structure if no tabs remain.
|
|
237
302
|
*/
|
|
238
|
-
declare function
|
|
303
|
+
declare function removeTab(tree: TreeNode | null, tabId: string): TreeNode | null;
|
|
239
304
|
/**
|
|
240
305
|
* Tree Helper: Insert a pane by splitting an existing target node.
|
|
241
306
|
*/
|
|
@@ -253,13 +318,54 @@ declare function addPane(tree: TreeNode | null, paneToAdd: string): TreeNode;
|
|
|
253
318
|
*/
|
|
254
319
|
declare function updateSplitPercentage(tree: TreeNode | null, target: SplitNode, newPercentage: number): TreeNode | null;
|
|
255
320
|
/**
|
|
256
|
-
* Find a PaneNode by its
|
|
321
|
+
* Find a PaneNode by its ID or by any of its tab IDs.
|
|
257
322
|
*/
|
|
258
323
|
declare function findPane(tree: TreeNode | null, paneId: string): PaneNode | null;
|
|
259
324
|
/**
|
|
260
|
-
* Update metadata on a specific
|
|
325
|
+
* Update metadata on a specific tab node using an updater function.
|
|
326
|
+
*/
|
|
327
|
+
declare function updateTabMetadata(tree: TreeNode | null, tabId: string, updater: (current: Record<string, unknown> | undefined) => Record<string, unknown> | undefined): TreeNode | null;
|
|
328
|
+
/**
|
|
329
|
+
* Update the locked status on a specific pane node in the layout tree.
|
|
330
|
+
*/
|
|
331
|
+
declare function updatePaneLock(tree: TreeNode | null, paneId: string, locked: boolean): TreeNode | null;
|
|
332
|
+
/**
|
|
333
|
+
* Tree Helper: Activate a tab within a pane.
|
|
334
|
+
*/
|
|
335
|
+
declare function selectTab(tree: TreeNode | null, paneId: string, tabId: string): TreeNode | null;
|
|
336
|
+
/**
|
|
337
|
+
* Tree Helper: Merge a tab into a target pane node.
|
|
338
|
+
*/
|
|
339
|
+
declare function mergeTab(tree: TreeNode | null, draggedTabId: string, targetPaneId: string): TreeNode | null;
|
|
340
|
+
/**
|
|
341
|
+
* Tree Helper: Move/reorder a tab inside or to a target pane next to a target tab.
|
|
261
342
|
*/
|
|
262
|
-
declare function
|
|
343
|
+
declare function moveTab(tree: TreeNode | null, draggedTabId: string, targetTabId: string, position?: 'before' | 'after'): TreeNode | null;
|
|
344
|
+
interface ComputedPane {
|
|
345
|
+
paneId: string;
|
|
346
|
+
left: number;
|
|
347
|
+
top: number;
|
|
348
|
+
width: number;
|
|
349
|
+
height: number;
|
|
350
|
+
node: PaneNode;
|
|
351
|
+
}
|
|
352
|
+
interface ComputedSplitter {
|
|
353
|
+
id: string;
|
|
354
|
+
currentNode: SplitNode;
|
|
355
|
+
direction: SplitDirection;
|
|
356
|
+
left: number;
|
|
357
|
+
top: number;
|
|
358
|
+
width: number;
|
|
359
|
+
height: number;
|
|
360
|
+
parentLeft: number;
|
|
361
|
+
parentTop: number;
|
|
362
|
+
parentWidth: number;
|
|
363
|
+
parentHeight: number;
|
|
364
|
+
}
|
|
365
|
+
declare function computeLayout(node: TreeNode | null, left?: number, top?: number, width?: number, height?: number, path?: string): {
|
|
366
|
+
panes: ComputedPane[];
|
|
367
|
+
splitters: ComputedSplitter[];
|
|
368
|
+
};
|
|
263
369
|
|
|
264
370
|
/**
|
|
265
371
|
* Shared drag-session lifecycle utility.
|
|
@@ -286,4 +392,4 @@ interface DragSessionConfig {
|
|
|
286
392
|
}
|
|
287
393
|
declare function createDragSession({ cursor, resizerEl, onMove, onEnd }: DragSessionConfig): void;
|
|
288
394
|
|
|
289
|
-
export { DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, DragHandle, type DragHandleProps, type DragSessionConfig, Pane, type PaneNode, type PaneProps, type PaneRenderProps, PaneTree, ResizableContainer, type ResizableContainerProps, type SplitDirection, type SplitNode, type TreeNode, Zeugma, type ZeugmaActionsValue, type ZeugmaClassNames, type ZeugmaProps, type ZeugmaStateValue, addPane, createDragSession, findPane, removePane, splitPane, swapPanes,
|
|
395
|
+
export { type ComputedPane, type ComputedSplitter, DEFAULT_DRAG_ACTIVATION_DISTANCE, DEFAULT_RESIZER_SIZE, DEFAULT_SNAP_THRESHOLD, DragHandle, type DragHandleProps, type DragSessionConfig, Pane, type PaneNode, type PaneProps, type PaneRenderProps, PaneTree, ResizableContainer, type ResizableContainerProps, type SplitDirection, type SplitNode, Tab, type TabProps, type TabRenderProps, type TreeNode, Zeugma, type ZeugmaActionsValue, type ZeugmaClassNames, type ZeugmaProps, type ZeugmaStateValue, addPane, computeLayout, createDragSession, findPane, mergeTab, moveTab, removePane, removeTab, selectTab, splitPane, swapPanes, updatePaneLock, updateSplitPercentage, updateTabMetadata, useResizer, useZeugmaActions, useZeugmaState };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {createContext,useContext,useState,useRef,useCallback,useMemo,useEffect}from'react';import {useSensors,useSensor,DndContext,pointerWithin,useDraggable,PointerSensor,TouchSensor,useDroppable}from'@dnd-kit/core';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var de=createContext(void 0),pe=createContext(void 0);var W=()=>{let e=useContext(de);if(!e)throw new Error("useZeugmaState must be used within a Zeugma provider");return e},we=()=>{let e=useContext(pe);if(!e)throw new Error("useZeugmaActions must be used within a Zeugma provider");return e};function He(e){let t=useRef(null);return useEffect(()=>{if(!e){t.current=null;return}let o=n=>{t.current={x:n.clientX,y:n.clientY};},r=n=>{let i=n.touches[0]||n.changedTouches[0];i&&(t.current={x:i.clientX,y:i.clientY});};return window.addEventListener("pointermove",o,{passive:true}),window.addEventListener("touchmove",r,{passive:true}),()=>{window.removeEventListener("pointermove",o),window.removeEventListener("touchmove",r);}},[e]),t}function ne(e,t){if(e===null)return null;if(e.type==="pane")return e.paneId===t?null:e;let o=ne(e.first,t),r=ne(e.second,t);return o===null?r:r===null?o:{...e,first:o,second:r}}function ie(e,t,o,r,n){if(e===null)return typeof n=="string"?{type:"pane",paneId:n}:n;if(e.type==="pane"){if(e.paneId===t){let i=typeof n=="string"?{type:"pane",paneId:n}:n,a=r==="left"||r==="top";return {type:"split",direction:o,first:a?i:e,second:a?e:i,splitPercentage:50}}return e}return {...e,first:ie(e.first,t,o,r,n)||e.first,second:ie(e.second,t,o,r,n)||e.second}}function Ee(e,t,o){if(e===null)return null;let r=O(e,t),n=O(e,o);if(!r||!n)return e;function i(a){return a.type==="pane"?a.paneId===t?{...n}:a.paneId===o?{...r}:a:{...a,first:i(a.first),second:i(a.second)}}return i(e)}function Fe(e,t){if(e===null)return {type:"pane",paneId:t};function o(r,n){return r.type==="pane"?{type:"split",direction:n==="row"?"column":"row",splitPercentage:50,first:r,second:{type:"pane",paneId:t}}:{...r,second:o(r.second,r.direction)}}return o(e,null)}function G(e,t,o){return e===null?null:e===t?{...e,splitPercentage:o}:e.type==="split"?{...e,first:G(e.first,t,o)||e.first,second:G(e.second,t,o)||e.second}:e}function O(e,t){return e===null?null:e.type==="pane"?e.paneId===t?e:null:O(e.first,t)??O(e.second,t)}function me(e,t,o){if(e===null)return null;if(e.type==="pane"){if(e.paneId===t){let r=o(e.metadata);if(r===void 0){let{metadata:n,...i}=e;return i}return {...e,metadata:r}}return e}return {...e,first:me(e.first,t,o)??e.first,second:me(e.second,t,o)??e.second}}var et=8,tt=8,Yt=4;var _e=({activeId:e,render:t,className:o})=>{let r=useRef(null);return useEffect(()=>{let n=i=>{r.current&&(r.current.style.transform=`translate(${i.clientX+12}px, ${i.clientY+12}px)`);};return document.addEventListener("pointermove",n),()=>document.removeEventListener("pointermove",n)},[]),jsx("div",{ref:r,className:o,style:{position:"fixed",top:0,left:0,zIndex:9999,pointerEvents:"none"},children:t(e)})};var fe=class extends PointerSensor{static activators=[{eventName:"onPointerDown",handler:({nativeEvent:t})=>!t.target?.closest(".drag-cancel")}]},ge=class extends TouchSensor{static activators=[{eventName:"onTouchStart",handler:({nativeEvent:t})=>!t.target?.closest(".drag-cancel")}]};function ke(e){if(e instanceof MouseEvent||e instanceof PointerEvent)return {x:e.clientX,y:e.clientY};if(typeof TouchEvent<"u"&&e instanceof TouchEvent){let t=e.touches[0]||e.changedTouches[0];if(t)return {x:t.clientX,y:t.clientY}}return null}var ut=({layout:e,onChange:t,renderPane:o,renderDragOverlay:r,classNames:n={},fullscreenPaneId:i=null,onFullscreenChange:a,onRemove:c,dragActivationDistance:b=8,snapThreshold:P=8,onDragStart:T,onDragEnd:s,onResizeStart:h,onResize:y,onResizeEnd:v,minSplitPercentage:R=5,maxSplitPercentage:d=95,enableDragToDismiss:m=false,dismissThreshold:I=60,onDismissIntentChange:L,children:E})=>{let[p,f]=useState(e),[K,oe]=useState(e);e!==K&&(oe(e),f(e));let[w,X]=useState(null),[D,Z]=useState(null),V=useRef(null),H=useRef(null),x=He(w),C=useCallback(u=>{V.current=u;},[]),F=useCallback(u=>o(u),[o]),z=useMemo(()=>n,[n.pane,n.dropPreview,n.swapPreview,n.dragOverlay,n.resizer,n.dismissPreview]),A=useSensors(useSensor(fe,{activationConstraint:{distance:b}}),useSensor(ge,{activationConstraint:{delay:250,tolerance:5}})),U=u=>{let g=u.active.id.toString();X(g);let l=u.activatorEvent;x.current=ke(l),m&&V.current?H.current=V.current.getBoundingClientRect():H.current=null,T&&T(g);},Se=u=>{if(!m)return;let g=u.active.id.toString(),l=H.current;if(!l){D!==null&&(Z(null),L?.(null));return}let S=u.activatorEvent,_=null,$=null;if(x.current)_=x.current.x,$=x.current.y;else {let N=ke(S);N&&(_=N.x+u.delta.x,$=N.y+u.delta.y);}let k=0;if(_!==null&&$!==null){let N=0,M=0;_<l.left?N=l.left-_:_>l.right&&(N=_-l.right),$<l.top?M=l.top-$:$>l.bottom&&(M=$-l.bottom),k=Math.sqrt(N*N+M*M);}else {let N=u.active.rect.current.translated;if(N){let M=N.left+N.width/2,q=N.top+N.height/2,ee=0,te=0;M<l.left?ee=l.left-M:M>l.right&&(ee=M-l.right),q<l.top?te=l.top-q:q>l.bottom&&(te=q-l.bottom),k=Math.sqrt(ee*ee+te*te);}}k>I?D!==g&&(Z(g),L?.(g)):D!==null&&(Z(null),L?.(null));},ce=u=>{X(null);let{active:g,over:l}=u,S=g.id.toString(),_=m&&D===S;if(Z(null),L?.(null),H.current=null,_){c?c(S):J(S),s&&s(S,null,null);return}if(!l){s&&s(S,null,null);return}let $=l.id.toString(),k=$.match(/^drop-center-(.+)$/);if(k){let[,Re]=k;if(S!==Re){let Ze=Ee(p,S,Re);f(Ze),t(Ze);}s&&s(S,Re,{type:"swap",position:"center"});return}let ye=$.match(/^drop-(left|right|top|bottom)-(.+)$/);if(!ye){s&&s(S,null,null);return}let[,N,M]=ye;if(S===M){s&&s(S,null,null);return}let q=N==="left"||N==="right"?"row":"column",ee=O(p,S)??{type:"pane",paneId:S},te=ne(p,S),Me=ie(te,M,q,N,ee);f(Me),t(Me),s&&s(S,M,{type:"split",direction:q,position:N});},B=useCallback((u,g=false)=>{f(u),g||t(u);},[t]),J=useCallback(u=>{let g=ne(p,u);f(g),t(g);},[p,t]),Q=useCallback(u=>{let g=Fe(p,u);f(g),t(g);},[p,t]),ue=useCallback((u,g)=>{let l=Ee(p,u,g);f(l),t(l);},[p,t]),re=useCallback((u,g,l,S)=>{let _=O(p,S)??{type:"pane",paneId:S},$=ne(p,S),k=ie($,u,g,l,_);f(k),t(k);},[p,t]),j=useCallback((u,g)=>{let l=G(p,u,g);f(l),t(l);},[p,t]),Ie=useCallback((u,g)=>{let l=me(p,u,g);f(l),t(l);},[p,t]),Ce=useCallback((u,g)=>{v&&v(u,g);},[v]),Ke=useMemo(()=>({layout:p,onLayoutChange:B,renderPane:F,activeId:w,dismissIntentId:D,setContainerRef:C,fullscreenPaneId:i,classNames:z,onRemove:c,onFullscreenChange:a,snapThreshold:P,onResizeStart:h,onResize:y,onResizeEnd:Ce,minSplitPercentage:R,maxSplitPercentage:d}),[p,w,D,C,i,z,c,a,P,h,y,R,d,B,F,Ce]),Je=useMemo(()=>({removePane:J,addPane:Q,swapPanes:ue,splitPane:re,updateSplitPercentage:j,updatePaneMetadata:Ie}),[J,Q,ue,re,j,Ie]);return jsx(pe.Provider,{value:Je,children:jsxs(de.Provider,{value:Ke,children:[jsx(DndContext,{id:"zeugma-dnd-context",sensors:A,collisionDetection:pointerWithin,onDragStart:U,onDragMove:Se,onDragEnd:ce,children:E}),w&&r&&jsx(_e,{activeId:w,render:r,className:`${n.dragOverlay||""} ${w===D?n.dismissPreview||"zeugma-dismiss-preview":""}`.trim()})]})})};function be({cursor:e,resizerEl:t,onMove:o,onEnd:r}){document.body.classList.add("zeugma-resizing");let n=document.createElement("style");n.id="zeugma-global-cursor-style",n.textContent=`
|
|
1
|
+
import nn,{createContext,useContext,useState,useRef,useCallback,useMemo,useEffect}from'react';import {createPortal}from'react-dom';import {useSensors,useSensor,pointerWithin,closestCenter,DndContext,useDraggable,useDroppable,PointerSensor,TouchSensor}from'@dnd-kit/core';import {jsx,Fragment,jsxs}from'react/jsx-runtime';var De=createContext(void 0),Me=createContext(void 0);var Q=()=>{let e=useContext(De);if(!e)throw new Error("useZeugmaState must be used within a Zeugma provider");return e},We=()=>{let e=useContext(Me);if(!e)throw new Error("useZeugmaActions must be used within a Zeugma provider");return e};function bt(e){let t=useRef(null);return useEffect(()=>{if(!e){t.current=null;return}let r=n=>{t.current={x:n.clientX,y:n.clientY};},i=n=>{let o=n.touches[0]||n.changedTouches[0];o&&(t.current={x:o.clientX,y:o.clientY});};return window.addEventListener("pointermove",r,{passive:true}),window.addEventListener("touchmove",i,{passive:true}),()=>{window.removeEventListener("pointermove",r),window.removeEventListener("touchmove",i);}},[e]),t}function gt(e){useEffect(()=>(e?document.body.style.setProperty("cursor","not-allowed","important"):document.body.style.removeProperty("cursor"),()=>{document.body.style.removeProperty("cursor");}),[e]);}function vt(){let[e,t]=useState({}),r=useCallback((i,n)=>{t(o=>o[i]===n?o:{...o,[i]:n});},[]);return {portalTargets:e,registerPortalTarget:r}}var Ce=createContext(void 0);function he(e,t){if(e===null)return null;if(e.type==="pane")return e.id===t?null:e;let r=he(e.first,t),i=he(e.second,t);return r===null?i:i===null?r:{...e,first:r,second:i}}function de(e,t){if(e===null)return null;if(e.type==="pane"){if(e.tabs.includes(t)){let n=e.tabs.filter(s=>s!==t);if(n.length===0)return null;let o=e.activeTabId;return e.activeTabId===t&&(o=n[0]),{...e,tabs:n,activeTabId:o}}return e}let r=de(e.first,t),i=de(e.second,t);return r===null?i:i===null?r:{...e,first:r,second:i}}function we(e,t,r,i,n){if(e===null)return typeof n=="string"?{type:"pane",id:n,tabs:[n],activeTabId:n}:n;if(e.type==="pane"){if(e.id===t||e.tabs.includes(t)){let o=typeof n=="string"?{type:"pane",id:n,tabs:[n],activeTabId:n}:n,s=i==="left"||i==="top";return {type:"split",direction:r,first:s?o:e,second:s?e:o,splitPercentage:50}}return e}return {...e,first:we(e.first,t,r,i,n)||e.first,second:we(e.second,t,r,i,n)||e.second}}function _e(e,t,r){if(e===null)return null;let i=_(e,t),n=_(e,r);if(!i||!n)return e;function o(s){return s.type==="pane"?s.id===i.id?{...n}:s.id===n.id?{...i}:s:{...s,first:o(s.first),second:o(s.second)}}return o(e)}function ht(e,t){if(e===null)return {type:"pane",id:t,tabs:[t],activeTabId:t};function r(i,n){return i.type==="pane"?{type:"split",direction:n==="row"?"column":"row",splitPercentage:50,first:i,second:{type:"pane",id:t,tabs:[t],activeTabId:t}}:{...i,second:r(i.second,i.direction)}}return r(e,null)}function pe(e,t,r){return e===null?null:e===t?{...e,splitPercentage:r}:e.type==="split"?{...e,first:pe(e.first,t,r)||e.first,second:pe(e.second,t,r)||e.second}:e}function _(e,t){return e===null?null:e.type==="pane"?e.id===t||e.tabs.includes(t)?e:null:_(e.first,t)??_(e.second,t)}function ze(e,t,r){if(e===null)return null;if(e.type==="pane"){if(e.id===t||e.tabs.includes(t)){let i=e.tabsMetadata||{},n=i[t],o=r(n),s={...i};return o===void 0?delete s[t]:s[t]=o,{...e,tabsMetadata:Object.keys(s).length>0?s:void 0}}return e}return {...e,first:ze(e.first,t,r)??e.first,second:ze(e.second,t,r)??e.second}}function $e(e,t,r){if(e===null)return null;if(e.type==="pane"){if(e.id===t||e.tabs.includes(t)){if(r===false){let{locked:i,...n}=e;return n}return {...e,locked:r}}return e}return {...e,first:$e(e.first,t,r)??e.first,second:$e(e.second,t,r)??e.second}}function Ie(e,t,r){return e===null?null:e.type==="pane"?e.id===t||e.tabs.includes(t)?{...e,activeTabId:r}:e:{...e,first:Ie(e.first,t,r)??e.first,second:Ie(e.second,t,r)??e.second}}function Pt(e,t,r){if(e===null)return null;let n=_(e,t)?.tabsMetadata?.[t],o=de(e,t);if(o===null)return {type:"pane",id:t,tabs:[t],activeTabId:t,tabsMetadata:n?{[t]:n}:void 0};function s(c){if(c.type==="pane"){if(c.id===r||c.tabs.includes(r)){let d=[...c.tabs];d.includes(t)||d.push(t);let T={...c.tabsMetadata};return n&&(T[t]=n),{...c,tabs:d,activeTabId:t,tabsMetadata:Object.keys(T).length>0?T:void 0}}return c}return {...c,first:s(c.first),second:s(c.second)}}return s(o)}function Ye(e,t,r,i="before"){if(e===null)return null;let o=_(e,t)?.tabsMetadata?.[t],s=de(e,t);if(s===null)return {type:"pane",id:t,tabs:[t],activeTabId:t,tabsMetadata:o?{[t]:o}:void 0};function c(d){if(d.type==="pane"){if(d.id===r||d.tabs.includes(r)){let S=[...d.tabs].filter(x=>x!==t),g=S.indexOf(r);g<0&&(g=0),i==="after"&&(g+=1),S.splice(g,0,t);let p={...d.tabsMetadata};return o&&(p[t]=o),{...d,tabs:S,activeTabId:t,tabsMetadata:Object.keys(p).length>0?p:void 0}}return d}return {...d,first:c(d.first),second:c(d.second)}}return c(s)}function j(e,t=0,r=0,i=100,n=100,o="root"){if(e===null)return {panes:[],splitters:[]};if(e.type==="pane")return {panes:[{paneId:e.id,left:t,top:r,width:i,height:n,node:e}],splitters:[]};let{direction:s,splitPercentage:c,first:d,second:T}=e,g={id:`splitter-${o}-${s}`,currentNode:e,direction:s,left:s==="row"?t+i*(c/100):t,top:s==="column"?r+n*(c/100):r,width:s==="row"?0:i,height:s==="column"?0:n,parentLeft:t,parentTop:r,parentWidth:i,parentHeight:n},p={panes:[],splitters:[]},x={panes:[],splitters:[]};if(s==="row"){let P=i*(c/100);p=j(d,t,r,P,n,`${o}-L`),x=j(T,t+P,r,i-P,n,`${o}-R`);}else {let P=n*(c/100);p=j(d,t,r,i,P,`${o}-T`),x=j(T,t,r+P,i,n-P,`${o}-B`);}return {panes:[...p.panes,...x.panes],splitters:[g,...p.splitters,...x.splitters]}}var Ot=8,Vt=8,Vn=4;var yt=({activeId:e,render:t,className:r})=>{let i=useRef(null);return useEffect(()=>{let n=o=>{i.current&&(i.current.style.transform=`translate(${o.clientX+12}px, ${o.clientY+12}px)`);};return document.addEventListener("pointermove",n),()=>document.removeEventListener("pointermove",n)},[]),jsx("div",{ref:i,className:r,style:{position:"fixed",top:0,left:0,zIndex:9999,pointerEvents:"none"},children:t(e)})};var ke=class extends PointerSensor{static activators=[{eventName:"onPointerDown",handler:({nativeEvent:t})=>!t.target?.closest(".drag-cancel")}]},He=class extends TouchSensor{static activators=[{eventName:"onTouchStart",handler:({nativeEvent:t})=>!t.target?.closest(".drag-cancel")}]};function Be(e){if(e instanceof MouseEvent||e instanceof PointerEvent)return {x:e.clientX,y:e.clientY};if(typeof TouchEvent<"u"&&e instanceof TouchEvent){let t=e.touches[0]||e.changedTouches[0];if(t)return {x:t.clientX,y:t.clientY}}return null}var Qt=({layout:e,onChange:t,renderPane:r,renderWidget:i,renderDragOverlay:n,classNames:o={},fullscreenPaneId:s=null,onFullscreenChange:c,onRemove:d,dragActivationDistance:T=8,snapThreshold:S=8,onDragStart:g,onDragEnd:p,onResizeStart:x,onResize:P,onResizeEnd:E,minSplitPercentage:N=5,maxSplitPercentage:$=95,enableDragToDismiss:b=false,dismissThreshold:y=60,onDismissIntentChange:R,locked:I=false,children:B})=>{let[l,w]=useState(e),[k,ee]=useState(e);e!==k&&(ee(e),w(e));let[D,V]=useState(null),[q,Y]=useState(null),[v,H]=useState(null),{portalTargets:G,registerPortalTarget:F}=vt(),M=useRef(null),f=useRef(null),O=bt(D),me=useCallback(a=>{M.current=a;},[]),[U,le]=useState(false);gt(U);let xe=useCallback(a=>r(a),[r]),be=useMemo(()=>o,[o.pane,o.paneLocked,o.dropPreview,o.swapPreview,o.dragOverlay,o.resizer,o.dismissPreview,o.dashboardLocked,o.lockedPreview]),Se=useSensors(useSensor(ke,{activationConstraint:{distance:T}}),useSensor(He,{activationConstraint:{delay:250,tolerance:5}})),ge=useCallback(a=>{let u=pointerWithin(a);if(u.length>0)return u;if(a.active.id.toString().startsWith("tab-header-")){let C=a.droppableContainers.filter(W=>W.id.toString().startsWith("tab-drop-"));return closestCenter({...a,droppableContainers:C})}return []},[]),ce=a=>{let u=a.active.id.toString(),m=u.startsWith("tab-header-"),C=m?u.substring(11):u;V(C),Y(m?"tab":"pane");let W=a.activatorEvent;O.current=Be(W),b&&M.current?f.current=M.current.getBoundingClientRect():f.current=null,g&&g(C);},te=a=>{let{over:u}=a,C=(u?.id.toString()||"").startsWith("drop-locked-");if(le(C),!b)return;let W=a.active.id.toString(),ne=W.startsWith("tab-header-")?W.substring(11):W,L=f.current;if(!L){v!==null&&(H(null),R?.(null));return}let Ee=a.activatorEvent,K=null,J=null;if(O.current)K=O.current.x,J=O.current.y;else {let z=Be(Ee);z&&(K=z.x+a.delta.x,J=z.y+a.delta.y);}let re=0;if(K!==null&&J!==null){let z=0,X=0;K<L.left?z=L.left-K:K>L.right&&(z=K-L.right),J<L.top?X=L.top-J:J>L.bottom&&(X=J-L.bottom),re=Math.sqrt(z*z+X*X);}else {let z=a.active.rect.current.translated;if(z){let X=z.left+z.width/2,ve=z.top+z.height/2,ue=0,oe=0;X<L.left?ue=L.left-X:X>L.right&&(ue=X-L.right),ve<L.top?oe=L.top-ve:ve>L.bottom&&(oe=ve-L.bottom),re=Math.sqrt(ue*ue+oe*oe);}}re>y?v!==ne&&(H(ne),R?.(ne)):v!==null&&(H(null),R?.(null));},A=a=>{V(null),Y(null),le(false);let{active:u,over:m}=a,C=u.id.toString(),W=C.startsWith("tab-header-"),h=W?C.substring(11):C,ne=b&&v===h;if(H(null),R?.(null),f.current=null,ne){d?d(h):Ve(h),p&&p(h,null,null);return}if(!m){p&&p(h,null,null);return}let L=m.id.toString();if(L.startsWith("drop-locked-")){p&&p(h,null,null);return}let Ee=L.match(/^tab-drop-(.+)$/);if(Ee){let[,ie]=Ee;if(h!==ie){let se="before",ut=m.rect,kt=a.activatorEvent,Le=null;if(O.current)Le=O.current.x;else {let Ne=Be(kt);Ne&&(Le=Ne.x+a.delta.x);}if(Le!==null){let Ne=ut.left+ut.width/2;Le>Ne&&(se="after");}let dt=Ye(l,h,ie,se);w(dt),t(dt);}p&&p(h,ie,{type:"swap",position:"center"});return}let K=L.match(/^drop-center-(.+)$/);if(K){let[,ie]=K;if(h!==ie){let se=_e(l,h,ie);w(se),t(se);}p&&p(h,ie,{type:"swap",position:"center"});return}let J=L.match(/^drop-(left|right|top|bottom)-(.+)$/);if(!J){p&&p(h,null,null);return}let[,re,Te]=J,z=_(l,h),X=z&&z.id===Te,ve=z&&z.tabs.length===1;if(h===Te||X&&ve){p&&p(h,null,null);return}let ue=re==="left"||re==="right"?"row":"column",oe;if(W){let se=_(l,h)?.tabsMetadata?.[h];oe={type:"pane",id:h,tabs:[h],activeTabId:h,tabsMetadata:se?{[h]:se}:void 0};}else oe=_(l,h)??{type:"pane",id:h,tabs:[h],activeTabId:h};let It=W?de(l,h):he(l,h),ct=we(It,Te,ue,re,oe);w(ct),t(ct),p&&p(h,Te,{type:"split",direction:ue,position:re});},Je=useCallback((a,u=false)=>{w(a),u||t(a);},[t]),Qe=useCallback(a=>{let u=he(l,a);w(u),t(u);},[l,t]),je=useCallback(a=>{let u=ht(l,a);w(u),t(u);},[l,t]),et=useCallback((a,u)=>{let m=_e(l,a,u);w(m),t(m);},[l,t]),tt=useCallback((a,u,m,C)=>{let W=_(l,C)??{type:"pane",id:C,tabs:[C],activeTabId:C},h=he(l,C),ne=we(h,a,u,m,W);w(ne),t(ne);},[l,t]),nt=useCallback((a,u)=>{let m=Ie(l,a,u);w(m),t(m);},[l,t]),rt=useCallback((a,u)=>{let m=Pt(l,a,u);w(m),t(m);},[l,t]),ot=useCallback((a,u,m)=>{let C=Ye(l,a,u,m);w(C),t(C);},[l,t]),Ve=useCallback(a=>{let u=de(l,a);w(u),t(u);},[l,t]),it=useCallback((a,u)=>{let m=pe(l,a,u);w(m),t(m);},[l,t]),st=useCallback((a,u)=>{let m=ze(l,a,u);w(m),t(m);},[l,t]),at=useCallback((a,u)=>{let m=$e(l,a,u);w(m),t(m);},[l,t]),lt=useCallback((a,u)=>{E&&E(a,u);},[E]),Mt=useMemo(()=>({layout:l,onLayoutChange:Je,renderPane:xe,activeId:D,dismissIntentId:v,setContainerRef:me,fullscreenPaneId:s,classNames:be,onRemove:d,onFullscreenChange:c,snapThreshold:S,onResizeStart:x,onResize:P,onResizeEnd:lt,minSplitPercentage:N,maxSplitPercentage:$,locked:I}),[l,D,v,me,s,be,d,c,S,x,P,N,$,Je,xe,lt,I]),Ct=useMemo(()=>({removePane:Qe,addPane:je,swapPanes:et,splitPane:tt,updateSplitPercentage:it,updateTabMetadata:st,updatePaneLock:at,selectTab:nt,mergeTab:rt,moveTab:ot,removeTab:Ve}),[Qe,je,et,tt,it,st,at,nt,rt,ot,Ve]),zt=useMemo(()=>{let a=[];function u(m){m&&(m.type==="pane"?a.push(...m.tabs):(u(m.first),u(m.second)));}return u(l),a},[l]),$t=useMemo(()=>({registerPortalTarget:F}),[F]);return jsx(Me.Provider,{value:Ct,children:jsx(De.Provider,{value:Mt,children:jsxs(Ce.Provider,{value:$t,children:[jsx(DndContext,{id:"zeugma-dnd-context",sensors:Se,collisionDetection:ge,onDragStart:ce,onDragMove:te,onDragEnd:A,children:B}),D&&q&&n&&jsx(yt,{activeId:D,render:a=>n(a,q),className:`${o.dragOverlay||""} ${D===v?o.dismissPreview||"zeugma-dismiss-preview":""}`.trim()}),jsx("div",{id:"zeugma-portal-host",style:{display:"none"},children:zt.map(a=>jsx(jt,{tabId:a,target:G[a]||null,renderWidget:i},a))})]})})})},jt=({tabId:e,target:t,renderWidget:r})=>{let i=useRef(null);!i.current&&typeof window<"u"&&(i.current=document.createElement("div"),i.current.className=`zeugma-portal-wrapper-${e}`,i.current.style.width="100%",i.current.style.height="100%");let n=i.current;return useEffect(()=>{if(n)if(t)t.appendChild(n);else {let o=document.getElementById("zeugma-hidden-portal-container");o||(o=document.createElement("div"),o.id="zeugma-hidden-portal-container",o.style.display="none",document.body.appendChild(o)),o.appendChild(n);}},[t,n]),useEffect(()=>()=>{i.current&&i.current.remove();},[]),!n||!r?null:createPortal(r(e),n)};function Ze({cursor:e,resizerEl:t,onMove:r,onEnd:i}){document.body.classList.add("zeugma-resizing");let n=document.createElement("style");n.id="zeugma-global-cursor-style",n.textContent=`
|
|
2
2
|
* {
|
|
3
3
|
cursor: ${e} !important;
|
|
4
4
|
user-select: none !important;
|
|
5
5
|
}
|
|
6
|
-
`,document.head.appendChild(n),t.setAttribute("data-resizing","true");let i=c=>{o(c);},a=()=>{document.body.classList.remove("zeugma-resizing"),t.removeAttribute("data-resizing");let c=document.getElementById("zeugma-global-cursor-style");c&&c.remove(),document.removeEventListener("pointermove",i),document.removeEventListener("pointerup",a),r();};document.addEventListener("pointermove",i),document.addEventListener("pointerup",a);}function De({containerRef:e,isRow:t,direction:o,splitPercentage:r,resizerSize:n,snapThreshold:i,layout:a,currentNode:c,onLayoutChange:b,onResizeStart:P,onResizeEnd:T,parentLeft:s,parentTop:h,parentWidth:y,parentHeight:v}){let{onResizeStart:R,onResize:d,onResizeEnd:m,minSplitPercentage:I=5,maxSplitPercentage:L=95}=W();return useCallback(E=>{E.preventDefault();let p=e.current;if(!p)return;P&&P(),R&&R(c);let f=p.getBoundingClientRect(),K=E.clientX,oe=E.clientY,w=r,X=E.currentTarget,D=f.left+f.width*(s/100),Z=f.top+f.height*(h/100),V=f.width*(y/100),H=f.height*(v/100),C=Array.from(document.querySelectorAll('div[role="separator"][data-direction]')).filter(z=>z!==X&&z.getAttribute("data-direction")===o).map(z=>{let A=z.getBoundingClientRect();return t?A.left+A.width/2:A.top+A.height/2}),F=w;be({cursor:t?"col-resize":"row-resize",resizerEl:X,onMove:z=>{let A=t?(z.clientX-K)/V*100:(z.clientY-oe)/H*100,U=w+A,Se=t?D+(V-n)*(U/100)+n/2:Z+(H-n)*(U/100)+n/2,ce=1/0,B=null;for(let re of C){let j=Math.abs(Se-re);j<i&&j<ce&&(ce=j,B=re);}let J=U;B!==null&&(J=t?(B-n/2-D)/(V-n)*100:(B-n/2-Z)/(H-n)*100);let Q=Math.max(I,Math.min(L,J));F=Q;let ue=G(a,c,Q);b(ue,true),d&&d(c,Q);},onEnd:()=>{let z=G(a,c,F);b(z),T&&T(),m&&m(c,F);}});},[e,t,o,r,n,i,a,c,b,P,T,R,d,m,I,L,s,h,y,v])}function se(e,t=0,o=0,r=100,n=100,i="root"){if(e.type==="pane")return {panes:[{paneId:e.paneId,left:t,top:o,width:r,height:n,node:e}],splitters:[]};let{direction:a,splitPercentage:c,first:b,second:P}=e,s={id:`splitter-${i}-${a}`,currentNode:e,direction:a,left:a==="row"?t+r*(c/100):t,top:a==="column"?o+n*(c/100):o,width:a==="row"?0:r,height:a==="column"?0:n,parentLeft:t,parentTop:o,parentWidth:r,parentHeight:n},h={panes:[],splitters:[]},y={panes:[],splitters:[]};if(a==="row"){let v=r*(c/100);h=se(b,t,o,v,n,`${i}-L`),y=se(P,t+v,o,r-v,n,`${i}-R`);}else {let v=n*(c/100);h=se(b,t,o,r,v,`${i}-T`),y=se(P,t,o+v,r,n-v,`${i}-B`);}return {panes:[...h.panes,...y.panes],splitters:[s,...h.splitters,...y.splitters]}}var vt=({splitter:e,resizerSize:t,snapThreshold:o,containerRef:r})=>{let{layout:n,onLayoutChange:i,classNames:a}=W(),[c,b]=useState(false),{currentNode:P,direction:T,left:s,top:h,width:y,height:v,parentLeft:R,parentTop:d,parentWidth:m,parentHeight:I}=e,L=T==="row",E=De({containerRef:r,isRow:L,direction:T,splitPercentage:P.splitPercentage,resizerSize:t,snapThreshold:o,layout:n,currentNode:P,onLayoutChange:i,onResizeStart:()=>b(true),onResizeEnd:()=>b(false),parentLeft:R,parentTop:d,parentWidth:m,parentHeight:I}),p=L?{position:"absolute",left:`calc(${s}% - ${t/2}px)`,top:`${h}%`,width:`${t}px`,height:`${v}%`,cursor:"col-resize",zIndex:10,userSelect:"none",touchAction:"none",boxSizing:"border-box"}:{position:"absolute",left:`${s}%`,top:`calc(${h}% - ${t/2}px)`,width:`${y}%`,height:`${t}px`,cursor:"row-resize",zIndex:10,userSelect:"none",touchAction:"none",boxSizing:"border-box"};return jsx("div",{className:`zeugma-resizer ${a.resizer||""}`.trim(),"data-direction":T,"data-resizing":c||void 0,style:p,onPointerDown:E,role:"separator","aria-valuenow":P.splitPercentage,"aria-valuemin":5,"aria-valuemax":95})},bt=({tree:e,resizerSize:t=4,snapThreshold:o})=>{let{layout:r,renderPane:n,activeId:i,dismissIntentId:a,setContainerRef:c,fullscreenPaneId:b,snapThreshold:P}=W(),T=o!==void 0?o:P??8,s=e!==void 0?e:r,h=useRef(null),{panes:y,splitters:v}=useMemo(()=>s?se(s):{panes:[],splitters:[]},[s]);if(!s)return null;let R=()=>jsxs(Fragment,{children:[y.map(d=>{let m=b===d.paneId;return jsx("div",{style:{position:"absolute",left:m?"0%":`${d.left}%`,top:m?"0%":`${d.top}%`,width:m?"100%":`${d.width}%`,height:m?"100%":`${d.height}%`,overflow:"hidden",zIndex:m?20:1,display:b&&!m?"none":"block",padding:m?"0px":`${t/2}px`,boxSizing:"border-box"},children:n(d.paneId)},d.paneId)}),!b&&v.map(d=>jsx(vt,{splitter:d,resizerSize:t,snapThreshold:T,containerRef:h},d.id))]});return e===void 0?jsx("div",{ref:I=>{c(I),h.current=I;},className:`zeugma-dashboard-root ${i!==null&&i===a?"zeugma-dashboard-dismiss-active":""}`.trim(),style:{position:"relative",width:"100%",height:"100%",overflow:"hidden"},children:R()}):jsx("div",{ref:h,style:{position:"relative",width:"100%",height:"100%",overflow:"hidden"},children:R()})};var Xe="zeugma-height:",yt="default-pane";function Rt(e){try{let t=localStorage.getItem(Xe+e);if(t!==null){let o=Number(t);if(Number.isFinite(o)&&o>0)return o}}catch{}return null}function We(e,t){try{localStorage.setItem(Xe+e,String(Math.round(t)));}catch{}}var Be=({children:e,active:t=true,height:o,onHeightChange:r,minHeight:n=100,maxHeight:i=1/0,persist:a,localStorageKey:c,resizerHeight:b=6,className:P,resizerClassName:T})=>{let s=a?c||yt:null,h=()=>{let E=(s?Rt(s):null)??o??400;return he(E,n,i)},[y,v]=useState(h),R=useRef(null),d=s?y:o??y,m=useRef(o);useEffect(()=>{if(o!==void 0&&o!==m.current){let E=he(o,n,i);v(E),s&&We(s,E);}m.current=o;},[o,n,i,s]);let I=useCallback(()=>i,[i]),L=useCallback(E=>{E.preventDefault();let p=E.clientY,f=d,K=I(),oe=E.currentTarget,w=qe(R.current),X=w?w.scrollTop:0,D=p,Z=null,V=(x,C)=>{let F=C-X,A=x-p+F,U=he(f+A,n,K);return R.current&&(R.current.style.height=`${U}px`),U},H=()=>{if(!w)return;let x=w===document.documentElement||w===document.body?{top:0,bottom:window.innerHeight}:w.getBoundingClientRect(),C=40,F=10,z=0;D>x.bottom-C?z=Math.min(1,(D-(x.bottom-C))/C)*F:D<x.top+C&&(z=-Math.min(1,(x.top+C-D)/C)*F),z!==0&&(w.scrollTop+=z,V(D,w.scrollTop)),Z=requestAnimationFrame(H);};Z=requestAnimationFrame(H),be({cursor:"row-resize",resizerEl:oe,onMove:x=>{D=x.clientY,w&&V(D,w.scrollTop);},onEnd:()=>{Z!==null&&cancelAnimationFrame(Z);let x=f;R.current&&(x=R.current.getBoundingClientRect().height),x=he(x,n,K),v(x),r&&r(x),s&&We(s,x);}});},[d,n,I,r,s]);return t?jsxs("div",{ref:R,className:`zeugma-resizable-container ${P||""}`.trim(),style:{height:`${d}px`,position:"relative",overflow:"hidden",boxSizing:"border-box"},children:[jsx("div",{style:{height:`calc(100% - ${b}px)`,overflow:"hidden"},children:e}),jsx("div",{className:`zeugma-resizable-handle ${T||""}`.trim(),style:{height:`${b}px`,cursor:"row-resize",position:"relative",zIndex:10,userSelect:"none",touchAction:"none",boxSizing:"border-box",flexShrink:0},onPointerDown:L,role:"separator","aria-orientation":"horizontal","aria-valuenow":Math.round(d),"aria-valuemin":n,"aria-valuemax":i===1/0?void 0:i})]}):jsx("div",{className:`zeugma-resizable-container disabled ${P||""}`.trim(),style:{height:"100%",position:"relative",overflow:"hidden",boxSizing:"border-box"},children:jsx("div",{style:{height:"100%",overflow:"hidden"},children:e})})};function he(e,t,o){return Math.max(t,Math.min(o,e))}function qe(e){if(typeof window>"u"||!e)return null;let t=e.parentElement;if(!t)return document.documentElement;let r=window.getComputedStyle(t).overflowY;return r==="auto"||r==="scroll"?t:qe(t)}var xe=createContext(null);var Dt={top:{position:"absolute",top:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},left:{position:"absolute",top:"25%",left:0,width:"25%",height:"50%",zIndex:20,pointerEvents:"auto"},right:{position:"absolute",top:"25%",right:0,width:"25%",height:"50%",zIndex:20,pointerEvents:"auto"},center:{position:"absolute",top:"25%",left:"25%",width:"50%",height:"50%",zIndex:20,pointerEvents:"auto"}},zt={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},center:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:21,pointerEvents:"none",boxSizing:"border-box"}},Ge=({id:e,position:t,activeClassName:o})=>{let{setNodeRef:r,isOver:n}=useDroppable({id:e});return jsxs(Fragment,{children:[jsx("div",{ref:r,style:Dt[t]}),n&&jsx("div",{className:o,style:zt[t]})]})},Lt=({id:e,children:t,style:o})=>{let{layout:r,activeId:n,classNames:i,fullscreenPaneId:a,onRemove:c,onFullscreenChange:b}=W(),{removePane:P,updatePaneMetadata:T}=we(),s=n!==null&&n!==e,{attributes:h,listeners:y,setNodeRef:v,isDragging:R}=useDraggable({id:e}),d=n===e||R,m=a===e,L=useMemo(()=>O(r,e),[r,e])?.metadata,E=useMemo(()=>({isDragging:d,isFullscreen:m,toggleFullscreen:()=>b?.(m?null:e),remove:()=>{m&&b?.(null),c?c(e):P(e);},metadata:L,updateMetadata:f=>{T(e,f);}}),[d,m,b,e,c,P,L,T]),p=useMemo(()=>({...y,...h}),[y,h]);return jsx(xe.Provider,{value:p,children:jsxs("div",{ref:v,className:i.pane,style:{position:"relative",width:"100%",height:"100%",...o},children:[t(E),s&&jsxs("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:15,pointerEvents:"none"},children:[["top","bottom","left","right"].map(f=>jsx(Ge,{id:`drop-${f}-${e}`,position:f,activeClassName:i.dropPreview},f)),jsx(Ge,{id:`drop-center-${e}`,position:"center",activeClassName:i.swapPreview})]})]})})};var Mt=({children:e,className:t,style:o})=>{let r=useContext(xe);if(!r)throw new Error("<DragHandle> must be used inside a <Pane>");return jsx("div",{className:t,style:{cursor:"grab",userSelect:"none",touchAction:"none",...o},...r,children:e})};export{tt as DEFAULT_DRAG_ACTIVATION_DISTANCE,Yt as DEFAULT_RESIZER_SIZE,et as DEFAULT_SNAP_THRESHOLD,Mt as DragHandle,Lt as Pane,bt as PaneTree,Be as ResizableContainer,ut as Zeugma,Fe as addPane,be as createDragSession,O as findPane,ne as removePane,ie as splitPane,Ee as swapPanes,me as updatePaneMetadata,G as updateSplitPercentage,De as useResizer,we as useZeugmaActions,W as useZeugmaState};//# sourceMappingURL=index.js.map
|
|
6
|
+
`,document.head.appendChild(n),t.setAttribute("data-resizing","true");let o=c=>{r(c);},s=()=>{document.body.classList.remove("zeugma-resizing"),t.removeAttribute("data-resizing");let c=document.getElementById("zeugma-global-cursor-style");c&&c.remove(),document.removeEventListener("pointermove",o),document.removeEventListener("pointerup",s),i();};document.addEventListener("pointermove",o),document.addEventListener("pointerup",s);}function Xe({containerRef:e,isRow:t,direction:r,splitPercentage:i,resizerSize:n,snapThreshold:o,layout:s,currentNode:c,onLayoutChange:d,onResizeStart:T,onResizeEnd:S,parentLeft:g,parentTop:p,parentWidth:x,parentHeight:P}){let{onResizeStart:E,onResize:N,onResizeEnd:$,minSplitPercentage:b=5,maxSplitPercentage:y=95,locked:R=false}=Q();return useCallback(I=>{if(R)return;I.preventDefault();let B=e.current;if(!B)return;T&&T(),E&&E(c);let l=B.getBoundingClientRect(),w=I.clientX,k=I.clientY,ee=i,D=I.currentTarget,V=l.left+l.width*(g/100),q=l.top+l.height*(p/100),Y=l.width*(x/100),v=l.height*(P/100),G=Array.from(document.querySelectorAll('div[role="separator"][data-direction]')).filter(M=>M!==D&&M.getAttribute("data-direction")===r).map(M=>{let f=M.getBoundingClientRect();return t?f.left+f.width/2:f.top+f.height/2}),F=ee;Ze({cursor:t?"col-resize":"row-resize",resizerEl:D,onMove:M=>{let f=t?(M.clientX-w)/Y*100:(M.clientY-k)/v*100,O=ee+f,me=t?V+(Y-n)*(O/100)+n/2:q+(v-n)*(O/100)+n/2,U=1/0,le=null;for(let ge of G){let ce=Math.abs(me-ge);ce<o&&ce<U&&(U=ce,le=ge);}let xe=O;le!==null&&(xe=t?(le-n/2-V)/(Y-n)*100:(le-n/2-q)/(v-n)*100);let be=Math.max(b,Math.min(y,xe));F=be;let Se=pe(s,c,be);if(Se){let{panes:ge,splitters:ce}=j(Se),te=e.current;if(te){for(let A of ge)te.style.setProperty(`--pane-left-${A.paneId}`,`${A.left}%`),te.style.setProperty(`--pane-top-${A.paneId}`,`${A.top}%`),te.style.setProperty(`--pane-width-${A.paneId}`,`${A.width}%`),te.style.setProperty(`--pane-height-${A.paneId}`,`${A.height}%`);for(let A of ce)te.style.setProperty(`--splitter-pos-${A.id}`,`${A.direction==="row"?A.left:A.top}%`);}}N&&N(c,be);},onEnd:()=>{let M=pe(s,c,F),f=e.current;if(f){let{panes:O,splitters:me}=j(M);for(let U of O)f.style.removeProperty(`--pane-left-${U.paneId}`),f.style.removeProperty(`--pane-top-${U.paneId}`),f.style.removeProperty(`--pane-width-${U.paneId}`),f.style.removeProperty(`--pane-height-${U.paneId}`);for(let U of me)f.style.removeProperty(`--splitter-pos-${U.id}`);}d(M),S&&S(),$&&$(c,F);}});},[e,t,r,i,n,o,s,c,d,T,S,E,N,$,b,y,g,p,x,P])}var an=({splitter:e,resizerSize:t,snapThreshold:r,containerRef:i})=>{let{layout:n,onLayoutChange:o,classNames:s,locked:c}=Q(),[d,T]=useState(false),{currentNode:S,direction:g,left:p,top:x,width:P,height:E,parentLeft:N,parentTop:$,parentWidth:b,parentHeight:y}=e,R=g==="row",I=Xe({containerRef:i,isRow:R,direction:g,splitPercentage:S.splitPercentage,resizerSize:t,snapThreshold:r,layout:n,currentNode:S,onLayoutChange:o,onResizeStart:()=>T(true),onResizeEnd:()=>T(false),parentLeft:N,parentTop:$,parentWidth:b,parentHeight:y}),B=R?{position:"absolute",left:`calc(var(--splitter-pos-${e.id}, ${p}%) - ${t/2}px)`,top:`calc(${x}% + ${t/2}px)`,width:`${t}px`,height:`calc(${E}% - ${t}px)`,cursor:c?"default":"col-resize",pointerEvents:c?"none":"auto",zIndex:10,userSelect:"none",touchAction:"none",boxSizing:"border-box"}:{position:"absolute",left:`calc(${p}% + ${t/2}px)`,top:`calc(var(--splitter-pos-${e.id}, ${x}%) - ${t/2}px)`,width:`calc(${P}% - ${t}px)`,height:`${t}px`,cursor:c?"default":"row-resize",pointerEvents:c?"none":"auto",zIndex:10,userSelect:"none",touchAction:"none",boxSizing:"border-box"};return jsx("div",{className:`zeugma-resizer ${s.resizer||""}`.trim(),"data-direction":g,"data-resizing":d||void 0,style:B,onPointerDown:I,role:"separator","aria-valuenow":S.splitPercentage,"aria-valuemin":5,"aria-valuemax":95})},ln=nn.memo(({paneId:e,renderPane:t})=>jsx(Fragment,{children:t(e)}),(e,t)=>e.paneId===t.paneId&&e.renderPane===t.renderPane),cn=({tree:e,resizerSize:t=4,snapThreshold:r})=>{let{layout:i,renderPane:n,activeId:o,dismissIntentId:s,setContainerRef:c,fullscreenPaneId:d,snapThreshold:T,locked:S,classNames:g}=Q(),p=r!==void 0?r:T??8,x=e!==void 0?e:i,P=useRef(null),{panes:E,splitters:N}=useMemo(()=>x?j(x):{panes:[],splitters:[]},[x]);if(!x)return null;let $=()=>jsxs(Fragment,{children:[E.map(b=>{let y=d===b.paneId;return jsx("div",{style:{position:"absolute",left:y?"0%":`var(--pane-left-${b.paneId}, ${b.left}%)`,top:y?"0%":`var(--pane-top-${b.paneId}, ${b.top}%)`,width:y?"100%":`var(--pane-width-${b.paneId}, ${b.width}%)`,height:y?"100%":`var(--pane-height-${b.paneId}, ${b.height}%)`,overflow:"hidden",zIndex:y?20:1,display:d&&!y?"none":"block",padding:y?"0px":`${t/2}px`,boxSizing:"border-box"},children:jsx(ln,{paneId:b.paneId,renderPane:n})},b.paneId)}),!d&&N.map(b=>jsx(an,{splitter:b,resizerSize:t,snapThreshold:p,containerRef:P},b.id))]});if(e===void 0){let b=o!==null&&o===s,y=I=>{c(I),P.current=I;},R=`zeugma-dashboard-root ${b?"zeugma-dashboard-dismiss-active":""} ${S?g.dashboardLocked||"zeugma-dashboard-locked":""}`.trim();return jsx("div",{ref:y,className:R,style:{position:"relative",width:"100%",height:"100%",overflow:"hidden"},children:$()})}return jsx("div",{ref:P,style:{position:"relative",width:"100%",height:"100%",overflow:"hidden"},children:$()})};var Lt="zeugma-height:",fn="default-pane";function mn(e){try{let t=localStorage.getItem(Lt+e);if(t!==null){let r=Number(t);if(Number.isFinite(r)&&r>0)return r}}catch{}return null}function Et(e,t){try{localStorage.setItem(Lt+e,String(Math.round(t)));}catch{}}var Nt=({children:e,active:t=true,height:r,onHeightChange:i,minHeight:n=100,maxHeight:o=1/0,persist:s,localStorageKey:c,resizerHeight:d=6,className:T,resizerClassName:S})=>{let g=s?c||fn:null,p=()=>{let R=(g?mn(g):null)??r??400;return Ae(R,n,o)},[x,P]=useState(p),E=useRef(null),N=g?x:r??x,$=useRef(r);useEffect(()=>{if(r!==void 0&&r!==$.current){let R=Ae(r,n,o);P(R),g&&Et(g,R);}$.current=r;},[r,n,o,g]);let b=useCallback(()=>o,[o]),y=useCallback(R=>{R.preventDefault();let I=R.clientY,B=N,l=b(),w=R.currentTarget,k=Dt(E.current),ee=k?k.scrollTop:0,D=I,V=null,q=(v,H)=>{let G=H-ee,M=v-I+G,f=Ae(B+M,n,l);return E.current&&(E.current.style.height=`${f}px`),f},Y=()=>{if(!k)return;let v=k===document.documentElement||k===document.body?{top:0,bottom:window.innerHeight}:k.getBoundingClientRect(),H=40,G=10,F=0;D>v.bottom-H?F=Math.min(1,(D-(v.bottom-H))/H)*G:D<v.top+H&&(F=-Math.min(1,(v.top+H-D)/H)*G),F!==0&&(k.scrollTop+=F,q(D,k.scrollTop)),V=requestAnimationFrame(Y);};V=requestAnimationFrame(Y),Ze({cursor:"row-resize",resizerEl:w,onMove:v=>{D=v.clientY,k&&q(D,k.scrollTop);},onEnd:()=>{V!==null&&cancelAnimationFrame(V);let v=B;E.current&&(v=E.current.getBoundingClientRect().height),v=Ae(v,n,l),P(v),i&&i(v),g&&Et(g,v);}});},[N,n,b,i,g]);return t?jsxs("div",{ref:E,className:`zeugma-resizable-container ${T||""}`.trim(),style:{height:`${N}px`,position:"relative",overflow:"hidden",boxSizing:"border-box"},children:[jsx("div",{style:{height:`calc(100% - ${d}px)`,overflow:"hidden"},children:e}),jsx("div",{className:`zeugma-resizable-handle ${S||""}`.trim(),style:{height:`${d}px`,cursor:"row-resize",position:"relative",zIndex:10,userSelect:"none",touchAction:"none",boxSizing:"border-box",flexShrink:0},onPointerDown:y,role:"separator","aria-orientation":"horizontal","aria-valuenow":Math.round(N),"aria-valuemin":n,"aria-valuemax":o===1/0?void 0:o})]}):jsx("div",{className:`zeugma-resizable-container disabled ${T||""}`.trim(),style:{height:"100%",position:"relative",overflow:"hidden",boxSizing:"border-box"},children:jsx("div",{style:{height:"100%",overflow:"hidden"},children:e})})};function Ae(e,t,r){return Math.max(t,Math.min(r,e))}function Dt(e){if(typeof window>"u"||!e)return null;let t=e.parentElement;if(!t)return document.documentElement;let i=window.getComputedStyle(t).overflowY;return i==="auto"||i==="scroll"?t:Dt(t)}var Oe=createContext(null);var Tn={top:{position:"absolute",top:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},bottom:{position:"absolute",bottom:0,left:"25%",width:"50%",height:"25%",zIndex:20,pointerEvents:"auto"},left:{position:"absolute",top:"25%",left:0,width:"25%",height:"50%",zIndex:20,pointerEvents:"auto"},right:{position:"absolute",top:"25%",right:0,width:"25%",height:"50%",zIndex:20,pointerEvents:"auto"},center:{position:"absolute",top:"25%",left:"25%",width:"50%",height:"50%",zIndex:20,pointerEvents:"auto"},full:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:20,pointerEvents:"auto",cursor:"not-allowed"}},wn={top:{position:"absolute",top:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},bottom:{position:"absolute",bottom:0,left:0,right:0,height:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},left:{position:"absolute",top:0,bottom:0,left:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},right:{position:"absolute",top:0,bottom:0,right:0,width:"50%",zIndex:21,pointerEvents:"none",boxSizing:"border-box"},center:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:21,pointerEvents:"none",boxSizing:"border-box"},full:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:21,pointerEvents:"none",boxSizing:"border-box"}},Ge=({id:e,position:t,activeClassName:r})=>{let{setNodeRef:i,isOver:n}=useDroppable({id:e});return jsxs(Fragment,{children:[jsx("div",{ref:i,style:Tn[t]}),n&&jsx("div",{className:r,style:wn[t]})]})},Rn=({id:e,children:t,style:r,locked:i=false})=>{let{layout:n,activeId:o,classNames:s,fullscreenPaneId:c,onFullscreenChange:d,locked:T}=Q(),{removePane:S,updateTabMetadata:g,selectTab:p,removeTab:x}=We(),P=useContext(Ce);if(!P)throw new Error("Pane must be used within a Zeugma provider");let{registerPortalTarget:E}=P,N=useMemo(()=>_(n,e),[n,e]),$=N?.id??e,b=N?.tabs??[e],y=N?.activeTabId??e,R=N?.tabsMetadata,I=R?.[e],B=N?.locked??false,l=i||B,w=T||l,k=T||l,ee=o!==null&&o!==e&&(!b.includes(o)||b.length>1)&&!k,{attributes:D,listeners:V,setNodeRef:q}=useDraggable({id:e,disabled:w}),Y=o!==null&&b.includes(o),v=c===e,H=useCallback(()=>jsx("div",{id:`zeugma-tab-target-${y}`,className:"zeugma-tab-content-wrapper",style:{height:"100%",width:"100%"}}),[y]);useEffect(()=>{let f=document.getElementById(`zeugma-tab-target-${y}`);return E(y,f),()=>{E(y,null);}},[y,E]);let G=useMemo(()=>({isDragging:Y,isFullscreen:v,toggleFullscreen:()=>d?.(v?null:e),remove:()=>{v&&d?.(null),S($);},metadata:I,updateMetadata:f=>{g(e,f);},locked:w,tabs:b,activeTabId:y,selectTab:f=>p($,f),removeTab:f=>{v&&f===y&&d?.(null),x(f);},tabsMetadata:R,updateTabMetadata:(f,O)=>{g(f,O);},renderActiveTab:H}),[Y,v,d,e,x,I,g,w,b,y,p,$,R,H]),F=useMemo(()=>w?{disabled:true}:{...V,...D},[V,D,w]),M=`${s.pane||""} ${l?s.paneLocked||"zeugma-pane-locked":""}`.trim();return jsx(Oe.Provider,{value:F,children:jsxs("div",{ref:q,className:M,style:{position:"relative",width:"100%",height:"100%",...r},children:[t(G),ee&&jsxs("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:15,pointerEvents:"none"},children:[["top","bottom","left","right"].map(f=>jsx(Ge,{id:`drop-${f}-${e}`,position:f,activeClassName:s.dropPreview},f)),!b.includes(o)&&jsx(Ge,{id:`drop-center-${e}`,position:"center",activeClassName:s.swapPreview})]}),o!==null&&o!==e&&k&&jsx("div",{style:{position:"absolute",top:0,left:0,right:0,bottom:0,zIndex:15,pointerEvents:"none"},children:jsx(Ge,{id:`drop-locked-${e}`,position:"full",activeClassName:s.lockedPreview||"zeugma-locked-preview"})})]})})};var Ln=({children:e,className:t,style:r})=>{let i=useContext(Oe);if(!i)throw new Error("<DragHandle> must be used inside a <Pane>");let{disabled:n,...o}=i;return jsx("div",{className:t,style:{cursor:n?"default":"grab",userSelect:n?"auto":"none",touchAction:n?"auto":"none",...r},...n?{}:o,children:e})};var Cn=({id:e,locked:t=false,children:r,className:i,style:n})=>{let{locked:o}=Q(),s=t||o,{attributes:c,listeners:d,setNodeRef:T,isDragging:S}=useDraggable({id:`tab-header-${e}`,disabled:s}),{setNodeRef:g,isOver:p}=useDroppable({id:`tab-drop-${e}`,disabled:s});return jsx("div",{ref:P=>{T(P),g(P);},className:i,style:{display:"inline-flex",cursor:s?"default":"grab",...n},...s?{}:d,...s?{}:c,children:r({isDragging:S,isOver:p})})};export{Vt as DEFAULT_DRAG_ACTIVATION_DISTANCE,Vn as DEFAULT_RESIZER_SIZE,Ot as DEFAULT_SNAP_THRESHOLD,Ln as DragHandle,Rn as Pane,cn as PaneTree,Nt as ResizableContainer,Cn as Tab,Qt as Zeugma,ht as addPane,j as computeLayout,Ze as createDragSession,_ as findPane,Pt as mergeTab,Ye as moveTab,he as removePane,de as removeTab,Ie as selectTab,we as splitPane,_e as swapPanes,$e as updatePaneLock,pe as updateSplitPercentage,ze as updateTabMetadata,Xe as useResizer,We as useZeugmaActions,Q as useZeugmaState};//# sourceMappingURL=index.js.map
|
|
7
7
|
//# sourceMappingURL=index.js.map
|