@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.
Files changed (142) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +141 -0
  3. package/package.json +40 -0
  4. package/src/GridCommand.js +395 -0
  5. package/src/GridComponentSettings.js +163 -0
  6. package/src/GridController.js +359 -0
  7. package/src/GridDragCoordinator.js +293 -0
  8. package/src/GridGeometry.js +1298 -0
  9. package/src/GridLayout.css.js +119 -0
  10. package/src/GridLayout.js +120 -0
  11. package/src/GridLayoutContext.js +58 -0
  12. package/src/GridLayoutDocument.js +307 -0
  13. package/src/GridLayoutDocumentIds.js +110 -0
  14. package/src/GridLayoutItem.css.js +46 -0
  15. package/src/GridLayoutItem.js +147 -0
  16. package/src/GridLayoutLegacyCompatibility.js +66 -0
  17. package/src/GridLayoutModel.js +138 -0
  18. package/src/GridLayoutProvider.js +263 -0
  19. package/src/GridLayoutStackedItem.css.js +26 -0
  20. package/src/GridLayoutStackedtem.js +140 -0
  21. package/src/GridModel.js +1289 -0
  22. package/src/GridPlaceholder.css.js +9 -0
  23. package/src/GridPlaceholder.js +24 -0
  24. package/src/GridSnapshot.js +11 -0
  25. package/src/GridSplitter.css.js +62 -0
  26. package/src/GridSplitter.js +26 -0
  27. package/src/GridStack.js +277 -0
  28. package/src/Icon.css.js +8 -0
  29. package/src/Icon.js +26 -0
  30. package/src/IconButton.css.js +9 -0
  31. package/src/IconButton.js +28 -0
  32. package/src/TabDialog.css.js +10 -0
  33. package/src/TabDialog.js +77 -0
  34. package/src/TabMenu.css.js +8 -0
  35. package/src/TabMenu.js +78 -0
  36. package/src/componentToJson.js +41 -0
  37. package/src/drag-drop-next/DragContextNext.js +173 -0
  38. package/src/drag-drop-next/DragDropProviderNext.css.js +72 -0
  39. package/src/drag-drop-next/DragDropProviderNext.js +91 -0
  40. package/src/drag-drop-next/SpaceMan.js +256 -0
  41. package/src/drag-drop-next/TemplateDragSession.js +36 -0
  42. package/src/drag-drop-next/tabstrip-drag-drop.js +251 -0
  43. package/src/grid-dom-utils.js +57 -0
  44. package/src/grid-layout-utils.js +39 -0
  45. package/src/grid-snapshot-adapters.js +435 -0
  46. package/src/index.js +24 -0
  47. package/src/json-value.js +56 -0
  48. package/src/layoutFromJson.js +15 -0
  49. package/src/layoutToJson.js +5 -0
  50. package/src/propUtils.js +15 -0
  51. package/src/react-element-utils.js +15 -0
  52. package/src/typeOf.js +15 -0
  53. package/src/useAsDropTarget.js +229 -0
  54. package/src/useDraggable.js +46 -0
  55. package/src/useEditTabName.js +70 -0
  56. package/src/useGridChildProps.js +47 -0
  57. package/src/useGridControllerSnapshot.js +21 -0
  58. package/src/useGridLayout.js +727 -0
  59. package/src/useGridSplitterResizing.js +262 -0
  60. package/src/useNotDropTarget.js +2 -0
  61. package/types/AddTabDialog.d.ts +5 -0
  62. package/types/GridCommand.d.ts +146 -0
  63. package/types/GridComponentSettings.d.ts +71 -0
  64. package/types/GridController.d.ts +50 -0
  65. package/types/GridDragCoordinator.d.ts +80 -0
  66. package/types/GridGeometry.d.ts +331 -0
  67. package/types/GridLayout.d.ts +20 -0
  68. package/types/GridLayoutContext.d.ts +141 -0
  69. package/types/GridLayoutDocument.d.ts +61 -0
  70. package/types/GridLayoutDocumentIds.d.ts +15 -0
  71. package/types/GridLayoutItem.d.ts +28 -0
  72. package/types/GridLayoutLegacyCompatibility.d.ts +57 -0
  73. package/types/GridLayoutModel.d.ts +72 -0
  74. package/types/GridLayoutProvider.d.ts +59 -0
  75. package/types/GridLayoutStackedtem.d.ts +10 -0
  76. package/types/GridModel.d.ts +504 -0
  77. package/types/GridPlaceholder.d.ts +5 -0
  78. package/types/GridSnapshot.d.ts +49 -0
  79. package/types/GridSplitter.d.ts +10 -0
  80. package/types/GridStack.d.ts +160 -0
  81. package/types/Icon.d.ts +6 -0
  82. package/types/IconButton.d.ts +6 -0
  83. package/types/TabDialog.d.ts +9 -0
  84. package/types/TabMenu.d.ts +7 -0
  85. package/types/componentToJson.d.ts +38 -0
  86. package/types/drag-drop-next/DragContextNext.d.ts +92 -0
  87. package/types/drag-drop-next/DragDropProviderNext.d.ts +23 -0
  88. package/types/drag-drop-next/SpaceMan.d.ts +35 -0
  89. package/types/drag-drop-next/TemplateDragSession.d.ts +21 -0
  90. package/types/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
  91. package/types/grid-dom-utils.d.ts +17 -0
  92. package/types/grid-layout-utils.d.ts +18 -0
  93. package/types/grid-matrix.d.ts +5 -0
  94. package/types/grid-snapshot-adapters.d.ts +22 -0
  95. package/types/index.d.ts +24 -0
  96. package/types/json-value.d.ts +23 -0
  97. package/types/layoutFromJson.d.ts +4 -0
  98. package/types/layoutToJson.d.ts +3 -0
  99. package/types/propUtils.d.ts +5 -0
  100. package/types/react-element-utils.d.ts +3 -0
  101. package/types/src/AddTabDialog.d.ts +5 -0
  102. package/types/src/GridLayout.d.ts +14 -0
  103. package/types/src/GridLayoutContext.d.ts +88 -0
  104. package/types/src/GridLayoutItem.d.ts +28 -0
  105. package/types/src/GridLayoutModel.d.ts +59 -0
  106. package/types/src/GridLayoutProvider.d.ts +37 -0
  107. package/types/src/GridLayoutStackedtem.d.ts +10 -0
  108. package/types/src/GridModel.d.ts +350 -0
  109. package/types/src/GridPlaceholder.d.ts +5 -0
  110. package/types/src/GridSplitter.d.ts +9 -0
  111. package/types/src/Icon.d.ts +6 -0
  112. package/types/src/IconButton.d.ts +6 -0
  113. package/types/src/TabMenu.d.ts +6 -0
  114. package/types/src/componentToJson.d.ts +32 -0
  115. package/types/src/drag-drop-next/DragContextNext.d.ts +73 -0
  116. package/types/src/drag-drop-next/DragDropProviderNext.d.ts +20 -0
  117. package/types/src/drag-drop-next/SpaceMan.d.ts +35 -0
  118. package/types/src/drag-drop-next/tabstrip-drag-drop.d.ts +3 -0
  119. package/types/src/grid-dom-utils.d.ts +17 -0
  120. package/types/src/grid-layout-utils.d.ts +80 -0
  121. package/types/src/grid-matrix.d.ts +5 -0
  122. package/types/src/index.d.ts +10 -0
  123. package/types/src/layoutFromJson.d.ts +3 -0
  124. package/types/src/layoutToJson.d.ts +2 -0
  125. package/types/src/propUtils.d.ts +5 -0
  126. package/types/src/react-element-utils.d.ts +3 -0
  127. package/types/src/typeOf.d.ts +6 -0
  128. package/types/src/useAsDropTarget.d.ts +7 -0
  129. package/types/src/useDraggable.d.ts +23 -0
  130. package/types/src/useGridChildProps.d.ts +13 -0
  131. package/types/src/useGridLayout.d.ts +43 -0
  132. package/types/src/useGridSplitterResizing.d.ts +12 -0
  133. package/types/src/useNotDropTarget.d.ts +1 -0
  134. package/types/typeOf.d.ts +6 -0
  135. package/types/useAsDropTarget.d.ts +7 -0
  136. package/types/useDraggable.d.ts +24 -0
  137. package/types/useEditTabName.d.ts +11 -0
  138. package/types/useGridChildProps.d.ts +13 -0
  139. package/types/useGridControllerSnapshot.d.ts +7 -0
  140. package/types/useGridLayout.d.ts +53 -0
  141. package/types/useGridSplitterResizing.d.ts +14 -0
  142. 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 };