@vuu-ui/grid-layout 4.0.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +141 -0
- package/package.json +40 -0
- package/src/GridCommand.js +395 -0
- package/src/GridComponentSettings.js +163 -0
- package/src/GridController.js +359 -0
- package/src/GridDragCoordinator.js +293 -0
- package/src/GridGeometry.js +1298 -0
- package/src/GridLayout.css.js +119 -0
- package/src/GridLayout.js +120 -0
- package/src/GridLayoutContext.js +58 -0
- package/src/GridLayoutDocument.js +307 -0
- package/src/GridLayoutDocumentIds.js +110 -0
- package/src/GridLayoutItem.css.js +46 -0
- package/src/GridLayoutItem.js +147 -0
- package/src/GridLayoutLegacyCompatibility.js +66 -0
- package/src/GridLayoutModel.js +138 -0
- package/src/GridLayoutProvider.js +263 -0
- package/src/GridLayoutStackedItem.css.js +26 -0
- package/src/GridLayoutStackedtem.js +140 -0
- package/src/GridModel.js +1289 -0
- package/src/GridPlaceholder.css.js +9 -0
- package/src/GridPlaceholder.js +24 -0
- package/src/GridSnapshot.js +11 -0
- package/src/GridSplitter.css.js +62 -0
- package/src/GridSplitter.js +26 -0
- package/src/GridStack.js +277 -0
- package/src/Icon.css.js +8 -0
- package/src/Icon.js +26 -0
- package/src/IconButton.css.js +9 -0
- package/src/IconButton.js +28 -0
- package/src/TabDialog.css.js +10 -0
- package/src/TabDialog.js +77 -0
- package/src/TabMenu.css.js +8 -0
- package/src/TabMenu.js +78 -0
- package/src/componentToJson.js +41 -0
- package/src/drag-drop-next/DragContextNext.js +173 -0
- package/src/drag-drop-next/DragDropProviderNext.css.js +72 -0
- package/src/drag-drop-next/DragDropProviderNext.js +91 -0
- package/src/drag-drop-next/SpaceMan.js +256 -0
- package/src/drag-drop-next/TemplateDragSession.js +36 -0
- package/src/drag-drop-next/tabstrip-drag-drop.js +251 -0
- package/src/grid-dom-utils.js +57 -0
- package/src/grid-layout-utils.js +39 -0
- package/src/grid-snapshot-adapters.js +435 -0
- package/src/index.js +24 -0
- package/src/json-value.js +56 -0
- package/src/layoutFromJson.js +15 -0
- package/src/layoutToJson.js +5 -0
- package/src/propUtils.js +15 -0
- package/src/react-element-utils.js +15 -0
- package/src/typeOf.js +15 -0
- package/src/useAsDropTarget.js +229 -0
- package/src/useDraggable.js +46 -0
- package/src/useEditTabName.js +70 -0
- package/src/useGridChildProps.js +47 -0
- package/src/useGridControllerSnapshot.js +21 -0
- package/src/useGridLayout.js +727 -0
- package/src/useGridSplitterResizing.js +262 -0
- package/src/useNotDropTarget.js +2 -0
- package/types/AddTabDialog.d.ts +5 -0
- package/types/GridCommand.d.ts +146 -0
- package/types/GridComponentSettings.d.ts +71 -0
- package/types/GridController.d.ts +50 -0
- package/types/GridDragCoordinator.d.ts +80 -0
- package/types/GridGeometry.d.ts +331 -0
- package/types/GridLayout.d.ts +20 -0
- package/types/GridLayoutContext.d.ts +141 -0
- package/types/GridLayoutDocument.d.ts +61 -0
- package/types/GridLayoutDocumentIds.d.ts +15 -0
- package/types/GridLayoutItem.d.ts +28 -0
- package/types/GridLayoutLegacyCompatibility.d.ts +57 -0
- package/types/GridLayoutModel.d.ts +72 -0
- package/types/GridLayoutProvider.d.ts +59 -0
- package/types/GridLayoutStackedtem.d.ts +10 -0
- package/types/GridModel.d.ts +504 -0
- package/types/GridPlaceholder.d.ts +5 -0
- package/types/GridSnapshot.d.ts +49 -0
- package/types/GridSplitter.d.ts +10 -0
- package/types/GridStack.d.ts +160 -0
- package/types/Icon.d.ts +6 -0
- package/types/IconButton.d.ts +6 -0
- package/types/TabDialog.d.ts +9 -0
- package/types/TabMenu.d.ts +7 -0
- package/types/componentToJson.d.ts +38 -0
- package/types/drag-drop-next/DragContextNext.d.ts +92 -0
- package/types/drag-drop-next/DragDropProviderNext.d.ts +23 -0
- package/types/drag-drop-next/SpaceMan.d.ts +35 -0
- package/types/drag-drop-next/TemplateDragSession.d.ts +21 -0
- package/types/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
- package/types/grid-dom-utils.d.ts +17 -0
- package/types/grid-layout-utils.d.ts +18 -0
- package/types/grid-matrix.d.ts +5 -0
- package/types/grid-snapshot-adapters.d.ts +22 -0
- package/types/index.d.ts +24 -0
- package/types/json-value.d.ts +23 -0
- package/types/layoutFromJson.d.ts +4 -0
- package/types/layoutToJson.d.ts +3 -0
- package/types/propUtils.d.ts +5 -0
- package/types/react-element-utils.d.ts +3 -0
- package/types/src/AddTabDialog.d.ts +5 -0
- package/types/src/GridLayout.d.ts +14 -0
- package/types/src/GridLayoutContext.d.ts +88 -0
- package/types/src/GridLayoutItem.d.ts +28 -0
- package/types/src/GridLayoutModel.d.ts +59 -0
- package/types/src/GridLayoutProvider.d.ts +37 -0
- package/types/src/GridLayoutStackedtem.d.ts +10 -0
- package/types/src/GridModel.d.ts +350 -0
- package/types/src/GridPlaceholder.d.ts +5 -0
- package/types/src/GridSplitter.d.ts +9 -0
- package/types/src/Icon.d.ts +6 -0
- package/types/src/IconButton.d.ts +6 -0
- package/types/src/TabMenu.d.ts +6 -0
- package/types/src/componentToJson.d.ts +32 -0
- package/types/src/drag-drop-next/DragContextNext.d.ts +73 -0
- package/types/src/drag-drop-next/DragDropProviderNext.d.ts +20 -0
- package/types/src/drag-drop-next/SpaceMan.d.ts +35 -0
- package/types/src/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
- package/types/src/grid-dom-utils.d.ts +17 -0
- package/types/src/grid-layout-utils.d.ts +80 -0
- package/types/src/grid-matrix.d.ts +5 -0
- package/types/src/index.d.ts +10 -0
- package/types/src/layoutFromJson.d.ts +3 -0
- package/types/src/layoutToJson.d.ts +2 -0
- package/types/src/propUtils.d.ts +5 -0
- package/types/src/react-element-utils.d.ts +3 -0
- package/types/src/typeOf.d.ts +6 -0
- package/types/src/useAsDropTarget.d.ts +7 -0
- package/types/src/useDraggable.d.ts +23 -0
- package/types/src/useGridChildProps.d.ts +13 -0
- package/types/src/useGridLayout.d.ts +43 -0
- package/types/src/useGridSplitterResizing.d.ts +12 -0
- package/types/src/useNotDropTarget.d.ts +1 -0
- package/types/typeOf.d.ts +6 -0
- package/types/useAsDropTarget.d.ts +7 -0
- package/types/useDraggable.d.ts +24 -0
- package/types/useEditTabName.d.ts +11 -0
- package/types/useGridChildProps.d.ts +13 -0
- package/types/useGridControllerSnapshot.d.ts +7 -0
- package/types/useGridLayout.d.ts +53 -0
- package/types/useGridSplitterResizing.d.ts +14 -0
- package/types/useNotDropTarget.d.ts +1 -0
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { boxContainsPoint, getPositionWithinBox, pointPositionWithinRect, queryClosest } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import { useCallback, useEffect, useRef } from "react";
|
|
3
|
+
import { useGridLayoutDragLeaveHandler, useGridLayoutDragPreviewHandler, useGridLayoutDropHandler, useGridLayoutId } from "./GridLayoutContext.js";
|
|
4
|
+
import { useDragContext } from "./drag-drop-next/DragDropProviderNext.js";
|
|
5
|
+
const DROPTARGET_CLASSNAME = "vuuDropTarget";
|
|
6
|
+
const GRIDITEM_QUERY = ".vuuGridLayoutItem";
|
|
7
|
+
const DROPTARGET_QUERY = "[data-drop-target]";
|
|
8
|
+
const removeDropTargetPositionClassName = (el)=>{
|
|
9
|
+
el.classList.forEach((className)=>{
|
|
10
|
+
if (className.match(/(north|east|south|west|centre|tabs|header)$/)) el.classList.remove(className);
|
|
11
|
+
});
|
|
12
|
+
};
|
|
13
|
+
const addDropTargetPositionClassName = (el, position)=>{
|
|
14
|
+
removeDropTargetPositionClassName(el);
|
|
15
|
+
el.classList.add(`${DROPTARGET_CLASSNAME}-${position}`);
|
|
16
|
+
};
|
|
17
|
+
const getDropTarget = (target, currentDropTarget, layoutId)=>{
|
|
18
|
+
let dropTargetEl = queryClosest(target, DROPTARGET_QUERY);
|
|
19
|
+
if (dropTargetEl) {
|
|
20
|
+
const owningLayout = queryClosest(dropTargetEl, ".vuuGridLayout", true);
|
|
21
|
+
if (owningLayout.id !== layoutId) return;
|
|
22
|
+
const { id: gridLayoutItemId } = queryClosest(dropTargetEl, GRIDITEM_QUERY, true);
|
|
23
|
+
if (dropTargetEl === currentDropTarget?.target) return currentDropTarget;
|
|
24
|
+
{
|
|
25
|
+
const { dropTarget: dropTargetValue } = dropTargetEl.dataset;
|
|
26
|
+
switch(dropTargetValue){
|
|
27
|
+
case "true":
|
|
28
|
+
return {
|
|
29
|
+
gridLayoutItemId,
|
|
30
|
+
target: dropTargetEl,
|
|
31
|
+
type: "content"
|
|
32
|
+
};
|
|
33
|
+
case "header":
|
|
34
|
+
return {
|
|
35
|
+
gridLayoutItemId,
|
|
36
|
+
target: dropTargetEl,
|
|
37
|
+
type: "header"
|
|
38
|
+
};
|
|
39
|
+
case void 0:
|
|
40
|
+
throw Error("[useAsDropTarget] getDropTarget, called on element without data-drop-target attribute");
|
|
41
|
+
default:
|
|
42
|
+
dropTargetEl = document.getElementById(dropTargetValue);
|
|
43
|
+
if (dropTargetEl) return {
|
|
44
|
+
gridLayoutItemId,
|
|
45
|
+
target: dropTargetEl,
|
|
46
|
+
type: "remote"
|
|
47
|
+
};
|
|
48
|
+
throw Error(`[useAsDropTarget] getDropTarget, data-drop-target ${dropTargetValue} not found`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
const NullRect = {
|
|
54
|
+
bottom: -1,
|
|
55
|
+
left: -1,
|
|
56
|
+
right: -1,
|
|
57
|
+
top: -1
|
|
58
|
+
};
|
|
59
|
+
const createDropTargetState = ()=>({
|
|
60
|
+
accepted: false,
|
|
61
|
+
mousePos: {
|
|
62
|
+
clientX: -1,
|
|
63
|
+
clientY: -1
|
|
64
|
+
},
|
|
65
|
+
position: void 0,
|
|
66
|
+
rect: {
|
|
67
|
+
...NullRect
|
|
68
|
+
},
|
|
69
|
+
dropTarget: void 0
|
|
70
|
+
});
|
|
71
|
+
const createActiveDropTargetState = (dropTarget)=>{
|
|
72
|
+
const { bottom, left, right, top } = dropTarget.target.getBoundingClientRect();
|
|
73
|
+
return {
|
|
74
|
+
accepted: false,
|
|
75
|
+
dropTarget,
|
|
76
|
+
mousePos: {
|
|
77
|
+
clientX: -1,
|
|
78
|
+
clientY: -1
|
|
79
|
+
},
|
|
80
|
+
position: void 0,
|
|
81
|
+
rect: {
|
|
82
|
+
bottom,
|
|
83
|
+
left,
|
|
84
|
+
right,
|
|
85
|
+
top
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
const useAsDropTarget = ()=>{
|
|
90
|
+
const dropTargetStateRef = useRef(createDropTargetState());
|
|
91
|
+
const drop = useGridLayoutDropHandler();
|
|
92
|
+
const leave = useGridLayoutDragLeaveHandler();
|
|
93
|
+
const preview = useGridLayoutDragPreviewHandler();
|
|
94
|
+
const dragContext = useDragContext();
|
|
95
|
+
const layoutId = useGridLayoutId();
|
|
96
|
+
const clearDropTarget = useCallback(()=>{
|
|
97
|
+
const { dropTarget } = dropTargetStateRef.current;
|
|
98
|
+
if (dropTarget) removeDropTargetPositionClassName(dropTarget.target);
|
|
99
|
+
dropTargetStateRef.current = createDropTargetState();
|
|
100
|
+
}, []);
|
|
101
|
+
useEffect(()=>{
|
|
102
|
+
const unregister = dragContext.registerDragStateCleanup(clearDropTarget);
|
|
103
|
+
return ()=>{
|
|
104
|
+
unregister();
|
|
105
|
+
};
|
|
106
|
+
}, [
|
|
107
|
+
clearDropTarget,
|
|
108
|
+
dragContext
|
|
109
|
+
]);
|
|
110
|
+
const onDragEnter = useCallback((evt)=>{
|
|
111
|
+
if (void 0 === dragContext.dragSource) return;
|
|
112
|
+
const { dropTarget: currentDropTarget } = dropTargetStateRef.current;
|
|
113
|
+
let dropTarget = getDropTarget(evt.target, currentDropTarget, layoutId);
|
|
114
|
+
if (evt.defaultPrevented) dropTarget = void 0;
|
|
115
|
+
if (dropTarget !== currentDropTarget) {
|
|
116
|
+
if (dropTarget) {
|
|
117
|
+
if (currentDropTarget) {
|
|
118
|
+
removeDropTargetPositionClassName(currentDropTarget.target);
|
|
119
|
+
leave();
|
|
120
|
+
}
|
|
121
|
+
dropTargetStateRef.current = createActiveDropTargetState(dropTarget);
|
|
122
|
+
} else if (currentDropTarget) {
|
|
123
|
+
dropTargetStateRef.current.dropTarget = void 0;
|
|
124
|
+
dropTargetStateRef.current.accepted = false;
|
|
125
|
+
dropTargetStateRef.current.position = void 0;
|
|
126
|
+
removeDropTargetPositionClassName(currentDropTarget.target);
|
|
127
|
+
leave();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}, [
|
|
131
|
+
dragContext,
|
|
132
|
+
layoutId,
|
|
133
|
+
leave
|
|
134
|
+
]);
|
|
135
|
+
const onDragOver = useCallback((evt)=>{
|
|
136
|
+
if (void 0 === dragContext.dragSource) return;
|
|
137
|
+
let { dropTarget: currentDropTarget } = dropTargetStateRef.current;
|
|
138
|
+
const dropTarget = getDropTarget(evt.target, currentDropTarget, layoutId);
|
|
139
|
+
if (dropTarget) {
|
|
140
|
+
if (dropTarget !== currentDropTarget) {
|
|
141
|
+
if (currentDropTarget) {
|
|
142
|
+
removeDropTargetPositionClassName(currentDropTarget.target);
|
|
143
|
+
leave();
|
|
144
|
+
}
|
|
145
|
+
dropTargetStateRef.current = createActiveDropTargetState(dropTarget);
|
|
146
|
+
currentDropTarget = dropTarget;
|
|
147
|
+
}
|
|
148
|
+
if (dropTarget === currentDropTarget) {
|
|
149
|
+
const { position: lastPosition } = dropTargetStateRef.current;
|
|
150
|
+
if ("header" === dropTarget.type) {
|
|
151
|
+
if ("header" !== lastPosition || !dropTarget.target.classList.contains("vuuDropTarget-header")) {
|
|
152
|
+
const accepted = preview(dropTarget.gridLayoutItemId, dragContext.dragSource, "header");
|
|
153
|
+
dropTargetStateRef.current.accepted = accepted;
|
|
154
|
+
dropTargetStateRef.current.position = "header";
|
|
155
|
+
if (accepted) addDropTargetPositionClassName(dropTarget.target, "header");
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
const { clientX, clientY } = evt;
|
|
159
|
+
const { mousePos } = dropTargetStateRef.current;
|
|
160
|
+
if (clientX !== mousePos.clientX || clientY !== mousePos.clientY) {
|
|
161
|
+
mousePos.clientX = clientX;
|
|
162
|
+
mousePos.clientY = clientY;
|
|
163
|
+
const { rect } = dropTargetStateRef.current;
|
|
164
|
+
const { pctX, pctY } = pointPositionWithinRect(clientX, clientY, rect);
|
|
165
|
+
const position = getPositionWithinBox(clientX, clientY, rect, pctX, pctY);
|
|
166
|
+
if (position !== lastPosition || !dropTarget.target.classList.contains(`${DROPTARGET_CLASSNAME}-${position}`)) {
|
|
167
|
+
const accepted = preview(dropTarget.gridLayoutItemId, dragContext.dragSource, position);
|
|
168
|
+
dropTargetStateRef.current.accepted = accepted;
|
|
169
|
+
if (accepted && dropTargetStateRef.current.dropTarget) addDropTargetPositionClassName(dropTarget.target, position);
|
|
170
|
+
else removeDropTargetPositionClassName(dropTarget.target);
|
|
171
|
+
dropTargetStateRef.current.position = position;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (dropTargetStateRef.current.accepted) {
|
|
176
|
+
evt.dataTransfer.dropEffect = "move";
|
|
177
|
+
evt.preventDefault();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}, [
|
|
182
|
+
dragContext,
|
|
183
|
+
layoutId,
|
|
184
|
+
leave,
|
|
185
|
+
preview
|
|
186
|
+
]);
|
|
187
|
+
const onDragLeave = useCallback((evt)=>{
|
|
188
|
+
if (void 0 === dragContext.dragSource) return;
|
|
189
|
+
const { dropTarget: currentDropTarget, rect: currentDropTargetRect } = dropTargetStateRef.current;
|
|
190
|
+
if (currentDropTarget?.target && !boxContainsPoint(currentDropTargetRect, evt.clientX, evt.clientY)) {
|
|
191
|
+
dropTargetStateRef.current.dropTarget = void 0;
|
|
192
|
+
dropTargetStateRef.current.accepted = false;
|
|
193
|
+
dropTargetStateRef.current.position = void 0;
|
|
194
|
+
leave();
|
|
195
|
+
removeDropTargetPositionClassName(currentDropTarget.target);
|
|
196
|
+
}
|
|
197
|
+
}, [
|
|
198
|
+
dragContext,
|
|
199
|
+
leave
|
|
200
|
+
]);
|
|
201
|
+
const onDrop = useCallback((evt)=>{
|
|
202
|
+
if (void 0 === dragContext.dragSource) return;
|
|
203
|
+
const { dropTarget: currentDropTarget } = dropTargetStateRef.current;
|
|
204
|
+
const { dragSource } = dragContext;
|
|
205
|
+
if (dragSource && currentDropTarget) {
|
|
206
|
+
const dropTarget = getDropTarget(evt.target, currentDropTarget, layoutId);
|
|
207
|
+
if (dropTarget && dropTargetStateRef.current.accepted && dropTargetStateRef.current.position) {
|
|
208
|
+
evt.preventDefault();
|
|
209
|
+
removeDropTargetPositionClassName(dropTarget.target);
|
|
210
|
+
const dropAccepted = drop(dropTarget.gridLayoutItemId, dragSource, dropTargetStateRef.current.position);
|
|
211
|
+
if (dropAccepted) dragContext.completeDrop();
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
dropTargetStateRef.current.dropTarget = void 0;
|
|
215
|
+
dropTargetStateRef.current.accepted = false;
|
|
216
|
+
dropTargetStateRef.current.position = void 0;
|
|
217
|
+
}, [
|
|
218
|
+
dragContext,
|
|
219
|
+
drop,
|
|
220
|
+
layoutId
|
|
221
|
+
]);
|
|
222
|
+
return {
|
|
223
|
+
onDragEnter,
|
|
224
|
+
onDragOver,
|
|
225
|
+
onDragLeave,
|
|
226
|
+
onDrop
|
|
227
|
+
};
|
|
228
|
+
};
|
|
229
|
+
export { useAsDropTarget };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
import { useDragContext } from "./drag-drop-next/DragDropProviderNext.js";
|
|
3
|
+
import { isTypedComponentTemplate, sourceIsComponent, sourceIsTemplate } from "./GridLayoutContext.js";
|
|
4
|
+
const useDraggable = ({ getDragSource, onDragEnd, onDragStart })=>{
|
|
5
|
+
const dragContext = useDragContext();
|
|
6
|
+
const handleDragStart = useCallback((e)=>{
|
|
7
|
+
const dragSource = getDragSource(e);
|
|
8
|
+
e.stopPropagation();
|
|
9
|
+
if (sourceIsTemplate(dragSource)) onDragStart?.(e, {
|
|
10
|
+
payload: isTypedComponentTemplate(dragSource) ? dragSource.component : JSON.parse(dragSource.componentJson),
|
|
11
|
+
type: "text/json"
|
|
12
|
+
});
|
|
13
|
+
else if (sourceIsComponent(dragSource)) onDragStart?.(e, {
|
|
14
|
+
id: dragSource.id,
|
|
15
|
+
type: "text/plain"
|
|
16
|
+
});
|
|
17
|
+
else throw Error("[useDraggable] unsupported drag source type");
|
|
18
|
+
dragContext.beginDrag(e.nativeEvent, dragSource);
|
|
19
|
+
if (sourceIsComponent(dragSource)) {
|
|
20
|
+
const dragElement = e.currentTarget;
|
|
21
|
+
const targetWindow = dragElement.ownerDocument.defaultView;
|
|
22
|
+
dragElement.addEventListener("dragend", ()=>{
|
|
23
|
+
if (!dragElement.isConnected && targetWindow) targetWindow.dispatchEvent(new targetWindow.Event("dragend"));
|
|
24
|
+
}, {
|
|
25
|
+
once: true
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
}, [
|
|
29
|
+
dragContext,
|
|
30
|
+
getDragSource,
|
|
31
|
+
onDragStart
|
|
32
|
+
]);
|
|
33
|
+
const handleDragEnd = useCallback((e)=>{
|
|
34
|
+
e.target.classList.remove("dragging");
|
|
35
|
+
onDragEnd?.(e, dragContext.dropped);
|
|
36
|
+
dragContext.endDrag();
|
|
37
|
+
}, [
|
|
38
|
+
dragContext,
|
|
39
|
+
onDragEnd
|
|
40
|
+
]);
|
|
41
|
+
return {
|
|
42
|
+
onDragEnd: handleDragEnd,
|
|
43
|
+
onDragStart: handleDragStart
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
export { useDraggable };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useMemo, useState } from "react";
|
|
3
|
+
import { TabDialog } from "./TabDialog.js";
|
|
4
|
+
import { useGridLayoutDispatch } from "./GridLayoutContext.js";
|
|
5
|
+
const useEditTabName = ({ getNewComponent, id, mode = "add", tabLabel })=>{
|
|
6
|
+
const [confirmationOpen, setConfirmationOpen] = useState(false);
|
|
7
|
+
const dispatch = useGridLayoutDispatch();
|
|
8
|
+
const handleConfirm = useCallback((title)=>{
|
|
9
|
+
if ("add" === mode) {
|
|
10
|
+
const componentTemplate = getNewComponent?.();
|
|
11
|
+
if (componentTemplate) dispatch({
|
|
12
|
+
title,
|
|
13
|
+
type: "add-tabbed-child",
|
|
14
|
+
componentTemplate: {
|
|
15
|
+
...componentTemplate,
|
|
16
|
+
label: title
|
|
17
|
+
},
|
|
18
|
+
stackId: id
|
|
19
|
+
});
|
|
20
|
+
} else dispatch({
|
|
21
|
+
type: "rename-tab",
|
|
22
|
+
id,
|
|
23
|
+
title
|
|
24
|
+
});
|
|
25
|
+
setConfirmationOpen(false);
|
|
26
|
+
}, [
|
|
27
|
+
dispatch,
|
|
28
|
+
getNewComponent,
|
|
29
|
+
id,
|
|
30
|
+
mode
|
|
31
|
+
]);
|
|
32
|
+
const handleCancel = useCallback(()=>{
|
|
33
|
+
setConfirmationOpen(false);
|
|
34
|
+
}, []);
|
|
35
|
+
const dialog = useMemo(()=>{
|
|
36
|
+
const getDialogStyle = ()=>{
|
|
37
|
+
const tabElement = document.querySelector(`.saltTabNext[data-grid-layout-item-id="${id}"]`);
|
|
38
|
+
if (!tabElement) return;
|
|
39
|
+
{
|
|
40
|
+
const { left, bottom } = tabElement.getBoundingClientRect();
|
|
41
|
+
return {
|
|
42
|
+
margin: 0,
|
|
43
|
+
top: bottom + 20,
|
|
44
|
+
left: Math.max(10, left - 20)
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
return /*#__PURE__*/ jsx(TabDialog, {
|
|
49
|
+
open: confirmationOpen,
|
|
50
|
+
onConfirm: handleConfirm,
|
|
51
|
+
onCancel: handleCancel,
|
|
52
|
+
style: getDialogStyle(),
|
|
53
|
+
tabLabel: tabLabel
|
|
54
|
+
});
|
|
55
|
+
}, [
|
|
56
|
+
confirmationOpen,
|
|
57
|
+
handleCancel,
|
|
58
|
+
handleConfirm,
|
|
59
|
+
id,
|
|
60
|
+
tabLabel
|
|
61
|
+
]);
|
|
62
|
+
const showTabEditDialog = ()=>{
|
|
63
|
+
setConfirmationOpen(true);
|
|
64
|
+
};
|
|
65
|
+
return {
|
|
66
|
+
dialog: confirmationOpen ? dialog : null,
|
|
67
|
+
showTabEditDialog
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export { useEditTabName };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { GridLayoutContext } from "./GridLayoutContext.js";
|
|
2
|
+
import { getGridPosition } from "./grid-layout-utils.js";
|
|
3
|
+
import { useContext } from "react";
|
|
4
|
+
const useGridChildProps = (props)=>{
|
|
5
|
+
const { contentVisible, dropTarget, header, id, stackId, style, title } = props;
|
|
6
|
+
const { gridModel, gridSnapshot } = useContext(GridLayoutContext);
|
|
7
|
+
const snapshotItem = gridSnapshot?.items.find((item)=>item.id === id);
|
|
8
|
+
const stack = gridSnapshot?.stacks.find(({ id: snapshotStackId })=>snapshotStackId === id) ?? gridSnapshot?.stacks.find(({ itemIds })=>itemIds.includes(id));
|
|
9
|
+
const modelItem = gridModel?.getChildItem(id);
|
|
10
|
+
const fallbackPosition = getGridPosition(style?.gridArea ?? "1/1/2/2");
|
|
11
|
+
const position = snapshotItem ? {
|
|
12
|
+
column: {
|
|
13
|
+
end: snapshotItem.column.start + snapshotItem.column.span,
|
|
14
|
+
start: snapshotItem.column.start
|
|
15
|
+
},
|
|
16
|
+
row: {
|
|
17
|
+
end: snapshotItem.row.start + snapshotItem.row.span,
|
|
18
|
+
start: snapshotItem.row.start
|
|
19
|
+
}
|
|
20
|
+
} : stack ? (()=>{
|
|
21
|
+
const firstMember = gridSnapshot?.items.find(({ id: itemId })=>itemId === stack.itemIds[0]);
|
|
22
|
+
return firstMember ? {
|
|
23
|
+
column: {
|
|
24
|
+
end: firstMember.column.start + firstMember.column.span,
|
|
25
|
+
start: firstMember.column.start
|
|
26
|
+
},
|
|
27
|
+
row: {
|
|
28
|
+
end: firstMember.row.start + firstMember.row.span,
|
|
29
|
+
start: firstMember.row.start
|
|
30
|
+
}
|
|
31
|
+
} : fallbackPosition;
|
|
32
|
+
})() : fallbackPosition;
|
|
33
|
+
const isStackMember = void 0 !== stack && stack.id !== id;
|
|
34
|
+
return {
|
|
35
|
+
contentDetached: modelItem?.contentDetached,
|
|
36
|
+
contentVisible: isStackMember ? stack?.selectedItemId === id : snapshotItem?.contentVisible ?? contentVisible,
|
|
37
|
+
dragging: modelItem?.dragging,
|
|
38
|
+
dropTarget: snapshotItem?.dropTarget ?? dropTarget,
|
|
39
|
+
gridArea: `${position.row.start}/${position.column.start}/${position.row.end}/${position.column.end}`,
|
|
40
|
+
header: snapshotItem?.header ?? header,
|
|
41
|
+
horizontalSplitter: modelItem?.horizontalSplitter,
|
|
42
|
+
stacked: isStackMember || void 0 !== stackId,
|
|
43
|
+
title: snapshotItem?.title ?? title,
|
|
44
|
+
verticalSplitter: modelItem?.verticalSplitter
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
export { useGridChildProps };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useCallback, useSyncExternalStore } from "react";
|
|
2
|
+
const visibleSnapshots = new WeakMap();
|
|
3
|
+
const getVisibleSnapshot = (controller)=>{
|
|
4
|
+
const snapshot = controller.getSnapshot();
|
|
5
|
+
const { revision: _revision, ...visibleState } = snapshot;
|
|
6
|
+
const signature = JSON.stringify(visibleState);
|
|
7
|
+
const cached = visibleSnapshots.get(controller);
|
|
8
|
+
if (cached?.signature === signature) return cached.snapshot;
|
|
9
|
+
visibleSnapshots.set(controller, {
|
|
10
|
+
signature,
|
|
11
|
+
snapshot
|
|
12
|
+
});
|
|
13
|
+
return snapshot;
|
|
14
|
+
};
|
|
15
|
+
const useGridControllerSnapshot = (controller)=>{
|
|
16
|
+
const getSnapshot = useCallback(()=>getVisibleSnapshot(controller), [
|
|
17
|
+
controller
|
|
18
|
+
]);
|
|
19
|
+
return useSyncExternalStore(controller.subscribe, getSnapshot, getSnapshot);
|
|
20
|
+
};
|
|
21
|
+
export { useGridControllerSnapshot };
|