@dxos/react-ui-mosaic 0.8.4-main.bc674ce → 0.8.4-main.bcb3aa67d6

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 (190) hide show
  1. package/dist/lib/browser/chunk-UTD5AWW5.mjs +1009 -0
  2. package/dist/lib/browser/chunk-UTD5AWW5.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +604 -71
  4. package/dist/lib/browser/index.mjs.map +4 -4
  5. package/dist/lib/browser/meta.json +1 -1
  6. package/dist/lib/browser/playwright/index.mjs +148 -0
  7. package/dist/lib/browser/playwright/index.mjs.map +7 -0
  8. package/dist/lib/browser/testing/index.mjs +69 -236
  9. package/dist/lib/browser/testing/index.mjs.map +4 -4
  10. package/dist/lib/node-esm/chunk-5K56GSJL.mjs +1011 -0
  11. package/dist/lib/node-esm/chunk-5K56GSJL.mjs.map +7 -0
  12. package/dist/lib/node-esm/index.mjs +604 -71
  13. package/dist/lib/node-esm/index.mjs.map +4 -4
  14. package/dist/lib/node-esm/meta.json +1 -1
  15. package/dist/lib/node-esm/playwright/index.mjs +150 -0
  16. package/dist/lib/node-esm/playwright/index.mjs.map +7 -0
  17. package/dist/lib/node-esm/testing/index.mjs +69 -236
  18. package/dist/lib/node-esm/testing/index.mjs.map +4 -4
  19. package/dist/types/src/components/Board/Board.d.ts +88 -0
  20. package/dist/types/src/components/Board/Board.d.ts.map +1 -0
  21. package/dist/types/src/components/Board/Board.stories.d.ts +41 -0
  22. package/dist/types/src/components/Board/Board.stories.d.ts.map +1 -0
  23. package/dist/types/src/components/Board/Column.d.ts +48 -0
  24. package/dist/types/src/components/Board/Column.d.ts.map +1 -0
  25. package/dist/types/src/components/Board/Item.d.ts +12 -0
  26. package/dist/types/src/components/Board/Item.d.ts.map +1 -0
  27. package/dist/types/src/components/Board/index.d.ts +2 -0
  28. package/dist/types/src/components/Board/index.d.ts.map +1 -0
  29. package/dist/types/src/components/Focus/Focus.d.ts +1 -24
  30. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -1
  31. package/dist/types/src/components/Focus/index.d.ts +0 -1
  32. package/dist/types/src/components/Focus/index.d.ts.map +1 -1
  33. package/dist/types/src/components/Mosaic/Container.d.ts +49 -0
  34. package/dist/types/src/components/Mosaic/Container.d.ts.map +1 -0
  35. package/dist/types/src/components/Mosaic/Mosaic.d.ts +36 -126
  36. package/dist/types/src/components/Mosaic/Mosaic.d.ts.map +1 -1
  37. package/dist/types/src/components/Mosaic/Placeholder.d.ts +21 -0
  38. package/dist/types/src/components/Mosaic/Placeholder.d.ts.map +1 -0
  39. package/dist/types/src/components/Mosaic/Root.d.ts +36 -0
  40. package/dist/types/src/components/Mosaic/Root.d.ts.map +1 -0
  41. package/dist/types/src/components/Mosaic/Stack.d.ts +23 -0
  42. package/dist/types/src/components/Mosaic/Stack.d.ts.map +1 -0
  43. package/dist/types/src/components/Mosaic/Stack.stories.d.ts +20 -0
  44. package/dist/types/src/components/Mosaic/Stack.stories.d.ts.map +1 -0
  45. package/dist/types/src/components/Mosaic/Tile.d.ts +57 -0
  46. package/dist/types/src/components/Mosaic/Tile.d.ts.map +1 -0
  47. package/dist/types/src/components/Mosaic/styles.d.ts.map +1 -1
  48. package/dist/types/src/components/Mosaic/types.d.ts +9 -2
  49. package/dist/types/src/components/Mosaic/types.d.ts.map +1 -1
  50. package/dist/types/src/components/index.d.ts +1 -4
  51. package/dist/types/src/components/index.d.ts.map +1 -1
  52. package/dist/types/src/hooks/index.d.ts +1 -0
  53. package/dist/types/src/hooks/index.d.ts.map +1 -1
  54. package/dist/types/src/hooks/useDefaultColumnEventHandler.d.ts +15 -0
  55. package/dist/types/src/hooks/useDefaultColumnEventHandler.d.ts.map +1 -0
  56. package/dist/types/src/hooks/useEventHandlerAdapter.d.ts +1 -1
  57. package/dist/types/src/hooks/useEventHandlerAdapter.d.ts.map +1 -1
  58. package/dist/types/src/hooks/useVisibleItems.d.ts +2 -2
  59. package/dist/types/src/hooks/useVisibleItems.d.ts.map +1 -1
  60. package/dist/types/src/playwright/board-manager.d.ts +45 -0
  61. package/dist/types/src/playwright/board-manager.d.ts.map +1 -0
  62. package/dist/types/src/playwright/index.d.ts +9 -0
  63. package/dist/types/src/playwright/index.d.ts.map +1 -0
  64. package/dist/types/src/playwright/playwright.config.d.ts +3 -0
  65. package/dist/types/src/playwright/playwright.config.d.ts.map +1 -0
  66. package/dist/types/src/playwright/smoke.spec.d.ts +2 -0
  67. package/dist/types/src/playwright/smoke.spec.d.ts.map +1 -0
  68. package/dist/types/src/testing/CardContainer.d.ts +5 -4
  69. package/dist/types/src/testing/CardContainer.d.ts.map +1 -1
  70. package/dist/types/src/testing/DefaultStackTile.d.ts +2 -2
  71. package/dist/types/src/testing/DefaultStackTile.d.ts.map +1 -1
  72. package/dist/types/src/testing/index.d.ts +1 -1
  73. package/dist/types/src/testing/index.d.ts.map +1 -1
  74. package/dist/types/src/testing/types.d.ts +21 -0
  75. package/dist/types/src/testing/types.d.ts.map +1 -0
  76. package/dist/types/src/translations.d.ts +5 -1
  77. package/dist/types/src/translations.d.ts.map +1 -1
  78. package/dist/types/tsconfig.tsbuildinfo +1 -1
  79. package/package.json +43 -28
  80. package/src/AUDIT.md +106 -0
  81. package/src/components/Board/Board.stories.tsx +273 -0
  82. package/src/components/Board/Board.tsx +191 -0
  83. package/src/components/Board/Column.tsx +302 -0
  84. package/src/components/Board/Item.tsx +116 -0
  85. package/src/components/{Layout → Board}/index.ts +1 -1
  86. package/src/components/Focus/Focus.tsx +2 -93
  87. package/src/components/Focus/index.ts +0 -2
  88. package/src/components/Mosaic/Container.tsx +318 -0
  89. package/src/components/Mosaic/Mosaic.tsx +35 -913
  90. package/src/components/Mosaic/Placeholder.tsx +133 -0
  91. package/src/components/Mosaic/Root.tsx +292 -0
  92. package/src/components/Mosaic/Stack.stories.tsx +176 -0
  93. package/src/components/Mosaic/Stack.tsx +321 -0
  94. package/src/components/Mosaic/Tile.tsx +247 -0
  95. package/src/components/Mosaic/extension.ts +1 -1
  96. package/src/components/Mosaic/styles.ts +9 -8
  97. package/src/components/Mosaic/types.ts +15 -3
  98. package/src/components/index.ts +1 -4
  99. package/src/hooks/index.ts +1 -0
  100. package/src/hooks/useContainerDebug.tsx +5 -3
  101. package/src/hooks/useDefaultColumnEventHandler.ts +35 -0
  102. package/src/hooks/useEventHandlerAdapter.ts +15 -6
  103. package/src/hooks/useVisibleItems.ts +7 -2
  104. package/src/playwright/board-manager.ts +159 -0
  105. package/src/playwright/index.ts +13 -0
  106. package/src/playwright/playwright.config.ts +17 -0
  107. package/src/playwright/smoke.spec.ts +143 -0
  108. package/src/testing/CardContainer.tsx +31 -19
  109. package/src/testing/DefaultStackTile.tsx +36 -22
  110. package/src/testing/index.ts +1 -1
  111. package/src/testing/types.ts +38 -0
  112. package/src/translations.ts +5 -1
  113. package/dist/lib/browser/chunk-UMBPEG4F.mjs +0 -1637
  114. package/dist/lib/browser/chunk-UMBPEG4F.mjs.map +0 -7
  115. package/dist/lib/browser/index.css +0 -13
  116. package/dist/lib/browser/index.css.map +0 -7
  117. package/dist/lib/browser/testing/index.css +0 -13
  118. package/dist/lib/browser/testing/index.css.map +0 -7
  119. package/dist/lib/node-esm/chunk-X6GV7SMK.mjs +0 -1639
  120. package/dist/lib/node-esm/chunk-X6GV7SMK.mjs.map +0 -7
  121. package/dist/lib/node-esm/index.css +0 -13
  122. package/dist/lib/node-esm/index.css.map +0 -7
  123. package/dist/lib/node-esm/testing/index.css +0 -13
  124. package/dist/lib/node-esm/testing/index.css.map +0 -7
  125. package/dist/types/src/components/Card/Card.d.ts +0 -121
  126. package/dist/types/src/components/Card/Card.d.ts.map +0 -1
  127. package/dist/types/src/components/Card/Card.stories.d.ts +0 -21
  128. package/dist/types/src/components/Card/Card.stories.d.ts.map +0 -1
  129. package/dist/types/src/components/Card/CardDragPreview.d.ts +0 -6
  130. package/dist/types/src/components/Card/CardDragPreview.d.ts.map +0 -1
  131. package/dist/types/src/components/Card/index.d.ts +0 -4
  132. package/dist/types/src/components/Card/index.d.ts.map +0 -1
  133. package/dist/types/src/components/Card/styles.d.ts +0 -13
  134. package/dist/types/src/components/Card/styles.d.ts.map +0 -1
  135. package/dist/types/src/components/Focus/styles.d.ts +0 -6
  136. package/dist/types/src/components/Focus/styles.d.ts.map +0 -1
  137. package/dist/types/src/components/Image/Image.d.ts +0 -14
  138. package/dist/types/src/components/Image/Image.d.ts.map +0 -1
  139. package/dist/types/src/components/Image/Image.stories.d.ts +0 -33
  140. package/dist/types/src/components/Image/Image.stories.d.ts.map +0 -1
  141. package/dist/types/src/components/Image/index.d.ts +0 -2
  142. package/dist/types/src/components/Image/index.d.ts.map +0 -1
  143. package/dist/types/src/components/Layout/Layout.d.ts +0 -33
  144. package/dist/types/src/components/Layout/Layout.d.ts.map +0 -1
  145. package/dist/types/src/components/Layout/Layout.stories.d.ts +0 -10
  146. package/dist/types/src/components/Layout/Layout.stories.d.ts.map +0 -1
  147. package/dist/types/src/components/Layout/index.d.ts +0 -2
  148. package/dist/types/src/components/Layout/index.d.ts.map +0 -1
  149. package/dist/types/src/components/Mosaic/Mosaic.stories.d.ts +0 -27
  150. package/dist/types/src/components/Mosaic/Mosaic.stories.d.ts.map +0 -1
  151. package/dist/types/src/components/Scrollable/Scrollable.d.ts +0 -24
  152. package/dist/types/src/components/Scrollable/Scrollable.d.ts.map +0 -1
  153. package/dist/types/src/components/Scrollable/Scrollable.stories.d.ts +0 -10
  154. package/dist/types/src/components/Scrollable/Scrollable.stories.d.ts.map +0 -1
  155. package/dist/types/src/components/Scrollable/index.d.ts +0 -2
  156. package/dist/types/src/components/Scrollable/index.d.ts.map +0 -1
  157. package/dist/types/src/components/Stack/Stack.d.ts +0 -22
  158. package/dist/types/src/components/Stack/Stack.d.ts.map +0 -1
  159. package/dist/types/src/components/Stack/Stack.stories.d.ts +0 -9
  160. package/dist/types/src/components/Stack/Stack.stories.d.ts.map +0 -1
  161. package/dist/types/src/components/Stack/index.d.ts +0 -2
  162. package/dist/types/src/components/Stack/index.d.ts.map +0 -1
  163. package/dist/types/src/testing/Board.d.ts +0 -45
  164. package/dist/types/src/testing/Board.d.ts.map +0 -1
  165. package/dist/types/src/testing/Slot.stories.d.ts +0 -14
  166. package/dist/types/src/testing/Slot.stories.d.ts.map +0 -1
  167. package/dist/types/src/testing/Virtualizer.stories.d.ts +0 -12
  168. package/dist/types/src/testing/Virtualizer.stories.d.ts.map +0 -1
  169. package/src/components/Card/Card.stories.tsx +0 -148
  170. package/src/components/Card/Card.tsx +0 -458
  171. package/src/components/Card/CardDragPreview.tsx +0 -23
  172. package/src/components/Card/index.ts +0 -8
  173. package/src/components/Card/styles.ts +0 -23
  174. package/src/components/Focus/styles.ts +0 -24
  175. package/src/components/Image/Image.stories.tsx +0 -86
  176. package/src/components/Image/Image.tsx +0 -223
  177. package/src/components/Image/index.ts +0 -5
  178. package/src/components/Layout/Layout.stories.tsx +0 -59
  179. package/src/components/Layout/Layout.tsx +0 -108
  180. package/src/components/Mosaic/Mosaic.stories.tsx +0 -113
  181. package/src/components/Scrollable/Scrollable.stories.tsx +0 -59
  182. package/src/components/Scrollable/Scrollable.tsx +0 -88
  183. package/src/components/Scrollable/index.ts +0 -5
  184. package/src/components/Scrollable/scrollable.css +0 -20
  185. package/src/components/Stack/Stack.stories.tsx +0 -115
  186. package/src/components/Stack/Stack.tsx +0 -210
  187. package/src/components/Stack/index.ts +0 -5
  188. package/src/testing/Board.tsx +0 -278
  189. package/src/testing/Slot.stories.tsx +0 -101
  190. package/src/testing/Virtualizer.stories.tsx +0 -133
@@ -0,0 +1,1011 @@
1
+ import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
+
3
+ // src/hooks/useVisibleItems.ts
4
+ import { useMemo } from "react";
5
+ var useVisibleItems = ({ id, items, dragging, getId }) => {
6
+ const visibleItems = useMemo(() => {
7
+ if (!items || !dragging || id !== dragging.containerId) {
8
+ return items ?? [];
9
+ }
10
+ const idx = items.findIndex((item) => getId(item) === dragging.id);
11
+ if (idx === -1) {
12
+ return items;
13
+ }
14
+ const visibleItems2 = items.slice();
15
+ visibleItems2.splice(idx, 1);
16
+ return visibleItems2;
17
+ }, [
18
+ id,
19
+ items,
20
+ dragging,
21
+ getId
22
+ ]);
23
+ return visibleItems;
24
+ };
25
+
26
+ // src/components/Focus/Focus.tsx
27
+ import { Focus, useFocus } from "@dxos/react-ui";
28
+
29
+ // src/components/Mosaic/styles.ts
30
+ var styles = {
31
+ placeholder: {
32
+ root: [
33
+ "group opacity-0",
34
+ 'group-data-[mosaic-debug="true"]:opacity-100',
35
+ 'group-data-[mosaic-debug="true"]:bg-orange-500',
36
+ "data-[mosaic-placeholder-state=active]:opacity-100",
37
+ "data-[mosaic-placeholder-orientation=vertical]:snap-start",
38
+ "data-[mosaic-placeholder-orientation=vertical]:py-1",
39
+ "data-[mosaic-placeholder-orientation=vertical]:data-[mosaic-placeholder-state=active]:py-2.5",
40
+ "data-[mosaic-placeholder-orientation=horizontal]:px-1",
41
+ "data-[mosaic-placeholder-orientation=horizontal]:data-[mosaic-placeholder-state=active]:px-2.5"
42
+ ],
43
+ content: [
44
+ "transition-all duration-0",
45
+ // TODO(burdon): Don't animate open if placeholder is the source.
46
+ // TODO(burdon): Flickers when start to drag since source is removed and then the placeholder shows up.
47
+ // - Use absolute positioning?
48
+ // 'group-data-[mosaic-placeholder-state=active]:duration-200',
49
+ "group-data-[mosaic-placeholder-orientation=vertical]:h-0",
50
+ "group-data-[mosaic-placeholder-orientation=vertical]:group-data-[mosaic-placeholder-state=active]:h-[var(--mosaic-placeholder-height)]",
51
+ "group-data-[mosaic-placeholder-orientation=horizontal]:w-0",
52
+ "group-data-[mosaic-placeholder-orientation=horizontal]:group-data-[mosaic-placeholder-state=active]:w-[var(--mosaic-placeholder-width)]"
53
+ ]
54
+ }
55
+ };
56
+
57
+ // src/components/Mosaic/types.ts
58
+ var getSourceData = (source) => {
59
+ return source.data.type === "tile" ? source.data : null;
60
+ };
61
+
62
+ // src/components/Mosaic/Root.tsx
63
+ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
64
+ import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
65
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
66
+ import { createContext } from "@radix-ui/react-context";
67
+ import { Primitive } from "@radix-ui/react-primitive";
68
+ import { Slot } from "@radix-ui/react-slot";
69
+ import React, { forwardRef, useCallback, useEffect, useRef, useState } from "react";
70
+ import { log } from "@dxos/log";
71
+ import { mx } from "@dxos/ui-theme";
72
+ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-mosaic/src/components/Mosaic/Root.tsx";
73
+ var [MosaicRootContextProvider, useMosaicRootContext] = createContext("MosaicRoot");
74
+ var MOSAIC_ROOT_NAME = "Mosaic.Root";
75
+ var MOSAIC_ROOT_DEBUG_ATTR = "mosaic-debug";
76
+ var MosaicRoot = /* @__PURE__ */ forwardRef(({ classNames, children, asChild, debug }, forwardedRef) => {
77
+ const rootRef = useRef(null);
78
+ const composedRef = useComposedRefs(rootRef, forwardedRef);
79
+ const Comp = asChild ? Slot : Primitive.div;
80
+ const [handlers, setHandlers] = useState({});
81
+ const [dragging, setDragging] = useState();
82
+ const getSourceHandler = useCallback((source) => {
83
+ const data = source.data;
84
+ return {
85
+ data,
86
+ handler: handlers[data.containerId]
87
+ };
88
+ }, [
89
+ handlers
90
+ ]);
91
+ const getTargetHandler = useCallback((location) => {
92
+ for (const target of location.current.dropTargets) {
93
+ const data = target.data;
94
+ let containerId;
95
+ switch (data.type) {
96
+ case "tile":
97
+ case "placeholder":
98
+ containerId = data.containerId;
99
+ break;
100
+ case "container":
101
+ containerId = data.id;
102
+ break;
103
+ }
104
+ const handler = handlers[containerId];
105
+ if (handler) {
106
+ return {
107
+ data,
108
+ handler
109
+ };
110
+ }
111
+ }
112
+ return {};
113
+ }, [
114
+ handlers
115
+ ]);
116
+ useEffect(() => {
117
+ const handleChange = ({ source, location }) => {
118
+ const { data: sourceData } = getSourceHandler(source);
119
+ const { data: targetData, handler } = getTargetHandler(location);
120
+ setDragging((dragging2) => {
121
+ dragging2?.target?.handler?.onCancel?.();
122
+ return {
123
+ source: {
124
+ data: sourceData,
125
+ handler: handlers[sourceData.containerId],
126
+ // TOOD(burdon): Check id matches.
127
+ container: location.initial.dropTargets.find((target) => target.data.type === "container")?.element
128
+ },
129
+ target: targetData && {
130
+ data: targetData,
131
+ handler
132
+ }
133
+ };
134
+ });
135
+ };
136
+ const handleCancel = () => {
137
+ setDragging((dragging2) => {
138
+ requestAnimationFrame(() => {
139
+ dragging2?.target?.handler?.onCancel?.();
140
+ dragging2?.source?.container?.dispatchEvent(new CustomEvent("dnd:cancel", {
141
+ bubbles: true
142
+ }));
143
+ });
144
+ return void 0;
145
+ });
146
+ };
147
+ let noTargetTimeout;
148
+ return combine(monitorForElements({
149
+ /**
150
+ * Dragging started within any container.
151
+ */
152
+ onDragStart: ({ source, location }) => {
153
+ log("Root.onDragStart", {
154
+ source: source.data,
155
+ location: location.current.dropTargets.map((target) => target.data)
156
+ }, {
157
+ F: __dxlog_file,
158
+ L: 149,
159
+ S: void 0,
160
+ C: (f, a) => f(...a)
161
+ });
162
+ handleChange({
163
+ source,
164
+ location
165
+ });
166
+ },
167
+ /**
168
+ * Dragging entered a new container.
169
+ */
170
+ onDropTargetChange: ({ source, location }) => {
171
+ clearTimeout(noTargetTimeout);
172
+ log("Root.onDropTargetChange", {
173
+ source: source.data,
174
+ location: location.current.dropTargets.map((target) => target.data)
175
+ }, {
176
+ F: __dxlog_file,
177
+ L: 162,
178
+ S: void 0,
179
+ C: (f, a) => f(...a)
180
+ });
181
+ if (location.current.dropTargets.length === 0) {
182
+ noTargetTimeout = setTimeout(() => setDragging(void 0), 1e3);
183
+ } else {
184
+ handleChange({
185
+ source,
186
+ location
187
+ });
188
+ }
189
+ },
190
+ /**
191
+ * Dragging within any container.
192
+ */
193
+ onDrag: ({ source, location }) => {
194
+ const { data } = getSourceHandler(source);
195
+ const { handler } = getTargetHandler(location);
196
+ if (handler) {
197
+ const { clientX: x, clientY: y } = location.current.input;
198
+ handler.onDrag?.({
199
+ source: data,
200
+ position: {
201
+ x,
202
+ y
203
+ }
204
+ });
205
+ }
206
+ },
207
+ /**
208
+ * Dragging ended.
209
+ */
210
+ onDrop: ({ source, location }) => {
211
+ log.info("Root.onDrop", {
212
+ source: source.data,
213
+ location: location.current.dropTargets.map((target) => target.data)
214
+ }, {
215
+ F: __dxlog_file,
216
+ L: 191,
217
+ S: void 0,
218
+ C: (f, a) => f(...a)
219
+ });
220
+ const { data: sourceData, handler: sourceHandler } = getSourceHandler(source);
221
+ if (!sourceHandler) {
222
+ log.warn("invalid source", {
223
+ source: sourceData,
224
+ handlers: Object.keys(handlers)
225
+ }, {
226
+ F: __dxlog_file,
227
+ L: 199,
228
+ S: void 0,
229
+ C: (f, a) => f(...a)
230
+ });
231
+ return;
232
+ }
233
+ try {
234
+ if (location.current.dropTargets.length === 0) {
235
+ log.info("cancelled", void 0, {
236
+ F: __dxlog_file,
237
+ L: 214,
238
+ S: void 0,
239
+ C: (f, a) => f(...a)
240
+ });
241
+ } else {
242
+ const { data: targetData, handler: targetHandler } = getTargetHandler(location);
243
+ if (!targetHandler) {
244
+ log.warn("invalid target", {
245
+ source: sourceData,
246
+ location,
247
+ handlers: Object.keys(handlers)
248
+ }, {
249
+ F: __dxlog_file,
250
+ L: 219,
251
+ S: void 0,
252
+ C: (f, a) => f(...a)
253
+ });
254
+ return;
255
+ }
256
+ if (sourceHandler === targetHandler) {
257
+ targetHandler.onDrop?.({
258
+ source: sourceData,
259
+ target: targetData
260
+ });
261
+ } else {
262
+ if (!sourceHandler.onTake) {
263
+ log.warn("invalid source", {
264
+ source: sourceData
265
+ }, {
266
+ F: __dxlog_file,
267
+ L: 235,
268
+ S: void 0,
269
+ C: (f, a) => f(...a)
270
+ });
271
+ return;
272
+ }
273
+ sourceHandler.onTake?.({
274
+ source: sourceData
275
+ }, async (object) => {
276
+ targetHandler.onDrop?.({
277
+ source: {
278
+ ...sourceData,
279
+ data: object
280
+ },
281
+ target: targetData
282
+ });
283
+ return true;
284
+ });
285
+ }
286
+ }
287
+ } finally {
288
+ handleCancel();
289
+ }
290
+ }
291
+ }));
292
+ }, [
293
+ handlers,
294
+ getSourceHandler,
295
+ getTargetHandler
296
+ ]);
297
+ return /* @__PURE__ */ React.createElement(MosaicRootContextProvider, {
298
+ containers: handlers,
299
+ addContainer: (container) => setHandlers((containers) => ({
300
+ ...containers,
301
+ [container.id]: container
302
+ })),
303
+ removeContainer: (id) => setHandlers((containers) => {
304
+ delete containers[id];
305
+ return {
306
+ ...containers
307
+ };
308
+ }),
309
+ dragging
310
+ }, /* @__PURE__ */ React.createElement(Comp, {
311
+ className: mx("group", classNames),
312
+ [`data-${MOSAIC_ROOT_DEBUG_ATTR}`]: debug,
313
+ ref: composedRef
314
+ }, children));
315
+ });
316
+ MosaicRoot.displayName = MOSAIC_ROOT_NAME;
317
+
318
+ // src/components/Mosaic/Container.tsx
319
+ import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
320
+ import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
321
+ import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
322
+ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
323
+ import { createContext as createContext2 } from "@radix-ui/react-context";
324
+ import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
325
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
326
+ import { bind } from "bind-event-listener";
327
+ import React2, { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
328
+ import { composable, composableProps, mx as mx2 } from "@dxos/ui-theme";
329
+ import { isTruthy } from "@dxos/util";
330
+ var MOSAIC_CONTAINER_NAME = "Mosaic.Container";
331
+ var [MosaicContainerContextProvider, useMosaicContainerContext] = createContext2("MosaicContainer");
332
+ var MOSAIC_CONTAINER_STATE_ATTR = "mosaic-container-state";
333
+ var MOSAIC_CONTAINER_PLACEHOLDER_WIDTH = "--mosaic-placeholder-width";
334
+ var MOSAIC_CONTAINER_PLACEHOLDER_HEIGHT = "--mosaic-placeholder-height";
335
+ var counter = 0;
336
+ var MosaicContainer = composable(({ children, eventHandler: eventHandlerProp, orientation = "vertical", asChild, autoScroll: autoscrollElement, withFocus, currentId, onCurrentChange, debug, ...props }, forwardedRef) => {
337
+ const { className, ...rest } = composableProps(props);
338
+ const Comp = asChild ? Slot2 : Primitive2.div;
339
+ const rootRef = useRef2(null);
340
+ const composedRef = useComposedRefs2(rootRef, forwardedRef);
341
+ const eventHandler = useMemo2(() => eventHandlerProp ?? {
342
+ id: `mosaic-container-${counter++}`
343
+ }, [
344
+ eventHandlerProp
345
+ ]);
346
+ const { dragging } = useMosaicRootContext(MOSAIC_CONTAINER_NAME);
347
+ const [state, setState] = useState2({
348
+ type: "idle"
349
+ });
350
+ const [activeLocation, setActiveLocation] = useState2();
351
+ const [scrolling, setScrolling] = useState2(false);
352
+ const setCurrentId = useCallback2((id) => onCurrentChange?.(id), [
353
+ onCurrentChange
354
+ ]);
355
+ const scrollToRef = useRef2(void 0);
356
+ const registerScrollTo = useCallback2((fn) => {
357
+ scrollToRef.current = fn;
358
+ }, []);
359
+ useEffect2(() => {
360
+ if (currentId) {
361
+ scrollToRef.current?.(currentId);
362
+ }
363
+ }, [
364
+ currentId
365
+ ]);
366
+ const { setFocus } = useFocus();
367
+ useEffect2(() => {
368
+ if (withFocus) {
369
+ setFocus?.(state.type === "active" ? "active" : void 0);
370
+ }
371
+ }, [
372
+ setFocus,
373
+ withFocus,
374
+ state
375
+ ]);
376
+ const { addContainer, removeContainer } = useMosaicRootContext(eventHandler.id);
377
+ useEffect2(() => {
378
+ addContainer(eventHandler);
379
+ return () => removeContainer(eventHandler.id);
380
+ }, [
381
+ eventHandler
382
+ ]);
383
+ const data = useMemo2(() => ({
384
+ type: "container",
385
+ id: eventHandler.id
386
+ }), [
387
+ eventHandler.id
388
+ ]);
389
+ useEffect2(() => {
390
+ if (!rootRef.current) {
391
+ return;
392
+ }
393
+ let timeout;
394
+ const handleScroll = () => {
395
+ setScrolling(true);
396
+ clearTimeout(timeout);
397
+ timeout = setTimeout(() => {
398
+ setScrolling(false);
399
+ }, 500);
400
+ };
401
+ return combine2(...[
402
+ /**
403
+ * Custom event for dragging cancellation.
404
+ */
405
+ bind(rootRef.current, {
406
+ type: "dnd:cancel",
407
+ listener: () => {
408
+ setState({
409
+ type: "idle"
410
+ });
411
+ }
412
+ }),
413
+ // Target.
414
+ dropTargetForElements({
415
+ element: rootRef.current,
416
+ getData: () => data,
417
+ /**
418
+ * Test if permitted to drop here.
419
+ * NOTE: Contained Tile and Placeholder elements do the same.
420
+ */
421
+ canDrop: ({ source }) => {
422
+ const data2 = getSourceData(source);
423
+ return data2 && eventHandler.canDrop?.({
424
+ source: data2
425
+ }) || false;
426
+ },
427
+ // TODO(burdon): Provide semantic intent to onDrop.
428
+ // getDropEffect: () => {
429
+ // return 'move';
430
+ // },
431
+ /**
432
+ * Dragging started in this container.
433
+ */
434
+ onDragStart: ({ source }) => {
435
+ const sourceData = source.data;
436
+ setState({
437
+ type: "active",
438
+ bounds: sourceData.bounds
439
+ });
440
+ },
441
+ /**
442
+ * Dragging entered this container.
443
+ */
444
+ onDragEnter: ({ source }) => {
445
+ const sourceData = source.data;
446
+ setState({
447
+ type: "active",
448
+ bounds: sourceData.bounds
449
+ });
450
+ },
451
+ /**
452
+ * Dragging left this container.
453
+ * NOTE: If the container isn't full-height, then when the dragged item is temporarily removed the container will shrink,
454
+ * triggering `onDragLeave`, which then causes the item to be added and removed continually (flickering).
455
+ */
456
+ onDragLeave: ({ source }) => {
457
+ const sourceData = source.data;
458
+ if (sourceData.containerId !== eventHandler.id) {
459
+ setState({
460
+ type: "idle"
461
+ });
462
+ }
463
+ },
464
+ /**
465
+ * Dropped in this container.
466
+ */
467
+ onDrop: () => {
468
+ setState({
469
+ type: "idle"
470
+ });
471
+ }
472
+ }),
473
+ // Autoscroll.
474
+ // NOTE: When used with Scrollable we get a spurious warning (in dev mode).
475
+ // "Auto scrolling has been attached to an element that appears not to be scrollable."
476
+ autoscrollElement && [
477
+ autoScrollForElements({
478
+ element: autoscrollElement,
479
+ // canScroll: ({ element: _ }) => {
480
+ // return true;
481
+ // },
482
+ getAllowedAxis: () => orientation,
483
+ getConfiguration: () => ({
484
+ maxScrollSpeed: "fast"
485
+ })
486
+ }),
487
+ bind(autoscrollElement, {
488
+ type: "scroll",
489
+ listener: handleScroll
490
+ }),
491
+ () => setScrolling(false)
492
+ ]
493
+ ].filter(isTruthy).flatMap((x) => x));
494
+ }, [
495
+ rootRef,
496
+ eventHandler,
497
+ data,
498
+ autoscrollElement
499
+ ]);
500
+ return /* @__PURE__ */ React2.createElement(MosaicContainerContextProvider, {
501
+ id: eventHandler.id,
502
+ eventHandler,
503
+ orientation,
504
+ state,
505
+ dragging: state.type === "active" ? dragging : void 0,
506
+ scrolling,
507
+ activeLocation,
508
+ setActiveLocation,
509
+ currentId,
510
+ setCurrentId,
511
+ registerScrollTo
512
+ }, /* @__PURE__ */ React2.createElement(Comp, {
513
+ className: mx2("h-full", className),
514
+ style: {
515
+ [MOSAIC_CONTAINER_PLACEHOLDER_WIDTH]: state.type === "active" && state.bounds ? `${state.bounds.width}px` : "0px",
516
+ [MOSAIC_CONTAINER_PLACEHOLDER_HEIGHT]: state.type === "active" && state.bounds ? `${state.bounds.height}px` : "0px"
517
+ },
518
+ ...rest,
519
+ [`data-${MOSAIC_CONTAINER_STATE_ATTR}`]: state.type,
520
+ ref: composedRef
521
+ }, children), debug?.());
522
+ });
523
+ MosaicContainer.displayName = MOSAIC_CONTAINER_NAME;
524
+
525
+ // src/components/Mosaic/Tile.tsx
526
+ import { combine as combine3 } from "@atlaskit/pragmatic-drag-and-drop/combine";
527
+ import { draggable, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
528
+ import { preserveOffsetOnSource } from "@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source";
529
+ import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
530
+ import { attachClosestEdge, extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
531
+ import { composeRefs } from "@radix-ui/react-compose-refs";
532
+ import { createContext as createContext3 } from "@radix-ui/react-context";
533
+ import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
534
+ import { Slot as Slot3 } from "@radix-ui/react-slot";
535
+ import React3, { useLayoutEffect, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
536
+ import { createPortal } from "react-dom";
537
+ import { composableProps as composableProps2, slottable } from "@dxos/ui-theme";
538
+ var MOSAIC_TILE_NAME = "Mosaic.Tile";
539
+ var [MosaicTileContextProvider, useMosaicTileContext] = createContext3("MosaicTile");
540
+ var MOSAIC_TILE_STATE_ATTR = "mosaic-tile-state";
541
+ var MosaicTile = slottable(({ children, asChild, dragHandle, allowedEdges: allowedEdgesProp, location, id, data: dataProp, draggable: draggableProp, current: _current, debug: _, ...props }, forwardedRef) => {
542
+ const Comp = asChild ? Slot3 : Primitive3.div;
543
+ const rootRef = useRef3(null);
544
+ const composedRef = composeRefs(rootRef, forwardedRef);
545
+ const { id: containerId, eventHandler, orientation, scrolling, setActiveLocation } = useMosaicContainerContext(MOSAIC_TILE_NAME);
546
+ const [state, setState] = useState3({
547
+ type: "idle"
548
+ });
549
+ const allowedEdges = useMemo3(() => allowedEdgesProp || (orientation === "vertical" ? [
550
+ "top",
551
+ "bottom"
552
+ ] : [
553
+ "left",
554
+ "right"
555
+ ]), [
556
+ allowedEdgesProp,
557
+ orientation
558
+ ]);
559
+ const data = useMemo3(() => ({
560
+ type: "tile",
561
+ id,
562
+ containerId,
563
+ data: dataProp,
564
+ location
565
+ }), [
566
+ containerId,
567
+ location,
568
+ dataProp
569
+ ]);
570
+ useLayoutEffect(() => {
571
+ const root = rootRef.current;
572
+ if (!draggableProp || !root || !containerId || scrolling) {
573
+ return;
574
+ }
575
+ const handleChange = ({ self, source }) => {
576
+ if (source.data.id !== dataProp.id) {
577
+ const closestEdge = extractClosestEdge(self.data);
578
+ const location2 = data.location + (closestEdge === "top" || closestEdge === "left" ? -0.5 : 0.5);
579
+ setActiveLocation(location2);
580
+ setState({
581
+ type: "target",
582
+ closestEdge
583
+ });
584
+ }
585
+ };
586
+ return combine3(
587
+ // Source.
588
+ draggable({
589
+ element: root,
590
+ dragHandle: dragHandle && state.type !== "preview" ? dragHandle : void 0,
591
+ canDrag: () => true,
592
+ getInitialData: () => data,
593
+ onGenerateDragPreview: ({ location: location2, nativeSetDragImage }) => {
594
+ setCustomNativeDragPreview({
595
+ nativeSetDragImage,
596
+ getOffset: preserveOffsetOnSource({
597
+ element: root,
598
+ input: location2.current.input
599
+ }),
600
+ render: ({ container }) => {
601
+ data.bounds = root.getBoundingClientRect();
602
+ setState({
603
+ type: "preview",
604
+ container,
605
+ rect: root.getBoundingClientRect()
606
+ });
607
+ return () => setState({
608
+ type: "dragging"
609
+ });
610
+ }
611
+ });
612
+ },
613
+ onDragStart: () => {
614
+ setState({
615
+ type: "dragging"
616
+ });
617
+ },
618
+ onDrop: () => {
619
+ setState({
620
+ type: "idle"
621
+ });
622
+ }
623
+ }),
624
+ // Target.
625
+ dropTargetForElements2({
626
+ element: root,
627
+ getData: ({ input, element }) => attachClosestEdge(data, {
628
+ input,
629
+ element,
630
+ allowedEdges
631
+ }),
632
+ canDrop: ({ source }) => {
633
+ const data2 = getSourceData(source);
634
+ return data2 && eventHandler.canDrop?.({
635
+ source: data2
636
+ }) || false;
637
+ },
638
+ onDragEnter: ({ self, source }) => {
639
+ handleChange({
640
+ self,
641
+ source
642
+ });
643
+ },
644
+ onDragLeave: () => {
645
+ setState({
646
+ type: "idle"
647
+ });
648
+ setActiveLocation(void 0);
649
+ },
650
+ onDrag: ({ self, source }) => {
651
+ handleChange({
652
+ self,
653
+ source
654
+ });
655
+ },
656
+ onDrop: () => {
657
+ setState({
658
+ type: "idle"
659
+ });
660
+ setActiveLocation(void 0);
661
+ }
662
+ })
663
+ );
664
+ }, [
665
+ rootRef,
666
+ forwardedRef,
667
+ containerId,
668
+ dragHandle,
669
+ eventHandler,
670
+ data,
671
+ scrolling,
672
+ allowedEdges,
673
+ setActiveLocation
674
+ ]);
675
+ const { className, ...rest } = composableProps2(props, {
676
+ classNames: "relative outline-none"
677
+ });
678
+ return /* @__PURE__ */ React3.createElement(MosaicTileContextProvider, {
679
+ state
680
+ }, /* @__PURE__ */ React3.createElement(Comp, {
681
+ ...rest,
682
+ "data-mosaic-tile-id": id,
683
+ [`data-${MOSAIC_TILE_STATE_ATTR}`]: state.type,
684
+ role: "listitem",
685
+ className,
686
+ ref: composedRef
687
+ }, children), state.type === "preview" && /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement(Comp, {
688
+ // NOTE: Use to control appearance while dragging.
689
+ [`data-${MOSAIC_TILE_STATE_ATTR}`]: state.type,
690
+ className,
691
+ style: {
692
+ width: `${state.rect.width}px`,
693
+ height: `${state.rect.height}px`
694
+ }
695
+ }, children), state.container));
696
+ });
697
+ MosaicTile.displayName = MOSAIC_TILE_NAME;
698
+
699
+ // src/components/Mosaic/Placeholder.tsx
700
+ import { dropTargetForElements as dropTargetForElements3 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
701
+ import { DropIndicator as NaturalDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box";
702
+ import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
703
+ import { Slot as Slot4 } from "@radix-ui/react-slot";
704
+ import React4, { useLayoutEffect as useLayoutEffect2, useMemo as useMemo4, useRef as useRef4 } from "react";
705
+ import { mx as mx3 } from "@dxos/ui-theme";
706
+ var MOSAIC_PLACEHOLDER_NAME = "Mosaic.Placeholder";
707
+ var MOSAIC_PLACEHOLDER_ORIENTATION_ATTR = "mosaic-placeholder-orientation";
708
+ var MOSAIC_PLACEHOLDER_STATE_ATTR = "mosaic-placeholder-state";
709
+ var MosaicPlaceholder = ({ classNames, children, asChild, orientation = "vertical", location }) => {
710
+ const rootRef = useRef4(null);
711
+ const Comp = asChild ? Slot4 : Primitive4.div;
712
+ const { id: containerId, eventHandler, scrolling, activeLocation, setActiveLocation } = useMosaicContainerContext(MOSAIC_PLACEHOLDER_NAME);
713
+ const data = useMemo4(() => ({
714
+ type: "placeholder",
715
+ containerId,
716
+ location
717
+ }), [
718
+ containerId,
719
+ location
720
+ ]);
721
+ useLayoutEffect2(() => {
722
+ const root = rootRef.current;
723
+ if (!root || scrolling) {
724
+ return;
725
+ }
726
+ return dropTargetForElements3({
727
+ element: root,
728
+ getData: () => data,
729
+ canDrop: ({ source }) => {
730
+ const data2 = getSourceData(source);
731
+ return data2 && eventHandler.canDrop?.({
732
+ source: data2
733
+ }) || false;
734
+ },
735
+ onDragEnter: () => {
736
+ setActiveLocation(data.location);
737
+ },
738
+ onDragLeave: () => {
739
+ setActiveLocation(void 0);
740
+ },
741
+ onDrop: () => {
742
+ setActiveLocation(void 0);
743
+ }
744
+ });
745
+ }, [
746
+ rootRef,
747
+ data,
748
+ scrolling,
749
+ setActiveLocation
750
+ ]);
751
+ return /* @__PURE__ */ React4.createElement(Comp, {
752
+ [`data-${MOSAIC_PLACEHOLDER_ORIENTATION_ATTR}`]: orientation,
753
+ [`data-${MOSAIC_PLACEHOLDER_STATE_ATTR}`]: data.location === activeLocation ? "active" : "idle",
754
+ role: "none",
755
+ className: mx3("relative", classNames),
756
+ ref: rootRef
757
+ }, children);
758
+ };
759
+ MosaicPlaceholder.displayName = MOSAIC_PLACEHOLDER_NAME;
760
+ var DROP_INDICATOR_NAME = "Mosaic.DropIndicator";
761
+ var MosaicDropIndicator = (props) => {
762
+ const { state } = useMosaicTileContext(DROP_INDICATOR_NAME);
763
+ return state.type === "target" && state.closestEdge ? /* @__PURE__ */ React4.createElement(NaturalDropIndicator, {
764
+ ...props,
765
+ edge: state.closestEdge
766
+ }) : null;
767
+ };
768
+ MosaicDropIndicator.displayName = DROP_INDICATOR_NAME;
769
+
770
+ // src/components/Mosaic/Stack.tsx
771
+ import { useVirtualizer } from "@tanstack/react-virtual";
772
+ import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
773
+ import React5, { forwardRef as forwardRef2, Fragment, useCallback as useCallback3, useEffect as useEffect3, useRef as useRef5 } from "react";
774
+ import { invariant } from "@dxos/invariant";
775
+ import { composable as composable2, composableProps as composableProps3, mx as mx4 } from "@dxos/ui-theme";
776
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-mosaic/src/components/Mosaic/Stack.tsx";
777
+ var MOSAIC_STACK_NAME = "MosaicStack";
778
+ var MosaicStackInner = composable2(({ getId, orientation: orientationProp = "vertical", items, Tile, draggable: draggable2 = true, debug, ...props }, forwardedRef) => {
779
+ invariant(Tile, void 0, {
780
+ F: __dxlog_file2,
781
+ L: 74,
782
+ S: void 0,
783
+ A: [
784
+ "Tile",
785
+ ""
786
+ ]
787
+ });
788
+ const { id, orientation = orientationProp, dragging, currentId, registerScrollTo } = useMosaicContainerContext(MOSAIC_STACK_NAME);
789
+ const visibleItems = useVisibleItems({
790
+ id,
791
+ items,
792
+ dragging: dragging?.source.data,
793
+ getId
794
+ });
795
+ invariant(orientation === "vertical" || orientation === "horizontal", `Invalid orientation: ${orientation}`, {
796
+ F: __dxlog_file2,
797
+ L: 83,
798
+ S: void 0,
799
+ A: [
800
+ "orientation === 'vertical' || orientation === 'horizontal'",
801
+ "`Invalid orientation: ${orientation}`"
802
+ ]
803
+ });
804
+ const rootRef = useRef5(null);
805
+ const scrollToId = useCallback3((targetId) => {
806
+ const el = rootRef.current?.querySelector(`[data-mosaic-tile-id="${CSS.escape(targetId)}"]`);
807
+ el?.scrollIntoView({
808
+ block: "nearest",
809
+ behavior: "smooth"
810
+ });
811
+ }, []);
812
+ useEffect3(() => {
813
+ registerScrollTo(scrollToId);
814
+ return () => registerScrollTo(void 0);
815
+ }, [
816
+ registerScrollTo,
817
+ scrollToId
818
+ ]);
819
+ const composedRef = useComposedRefs3(rootRef, forwardedRef);
820
+ return /* @__PURE__ */ React5.createElement("div", {
821
+ ...composableProps3(props, {
822
+ role: "list",
823
+ classNames: [
824
+ "flex",
825
+ orientation === "horizontal" && "h-full [&>*]:shrink-0",
826
+ orientation === "vertical" && "flex-col"
827
+ ]
828
+ }),
829
+ ref: composedRef
830
+ }, draggable2 && /* @__PURE__ */ React5.createElement(InternalPlaceholder, {
831
+ orientation,
832
+ location: 0.5
833
+ }), visibleItems?.map((item, index) => /* @__PURE__ */ React5.createElement(Fragment, {
834
+ key: getId(item)
835
+ }, /* @__PURE__ */ React5.createElement(Tile, {
836
+ id: getId(item),
837
+ data: item,
838
+ location: index + 1,
839
+ draggable: draggable2,
840
+ current: getId(item) === currentId,
841
+ debug
842
+ }), draggable2 && /* @__PURE__ */ React5.createElement(InternalPlaceholder, {
843
+ orientation,
844
+ location: index + 1.5
845
+ }))));
846
+ });
847
+ MosaicStackInner.displayName = MOSAIC_STACK_NAME;
848
+ var MosaicStack = MosaicStackInner;
849
+ var MOSAIC_VIRTUAL_STACK_NAME = "MosaicVirtualStack";
850
+ var MosaicVirtualStackInner = /* @__PURE__ */ forwardRef2(({ orientation = "vertical", items, getId, Tile, estimateSize, getScrollElement, overscan = 8, gap, onChange, draggable: draggable2 = true, debug, ...props }, forwardedRef) => {
851
+ invariant(Tile, void 0, {
852
+ F: __dxlog_file2,
853
+ L: 164,
854
+ S: void 0,
855
+ A: [
856
+ "Tile",
857
+ ""
858
+ ]
859
+ });
860
+ const { id, dragging, currentId, registerScrollTo } = useMosaicContainerContext(MOSAIC_VIRTUAL_STACK_NAME);
861
+ const visibleItems = useVisibleItems({
862
+ id,
863
+ items,
864
+ dragging: dragging?.source.data,
865
+ getId
866
+ });
867
+ const wrappedEstimateSize = draggable2 ? (index) => index % 2 === 0 ? 0 : estimateSize(Math.floor(index / 2)) : estimateSize;
868
+ const virtualizer = useVirtualizer({
869
+ // NOTE: When draggable we double the number of items to allow for placeholders.
870
+ count: draggable2 ? visibleItems.length * 2 + 1 : visibleItems.length,
871
+ estimateSize: wrappedEstimateSize,
872
+ gap,
873
+ // Key measurements by stable item ID so the size cache survives scrolling;
874
+ // without this, measurements are indexed by position and are lost when items reorder.
875
+ getItemKey: draggable2 ? (index) => index % 2 === 0 ? `ph-${index}` : getId(visibleItems[Math.floor(index / 2)]) : (index) => getId(visibleItems[index]),
876
+ getScrollElement,
877
+ overscan,
878
+ onChange
879
+ });
880
+ const scrollToId = useCallback3((targetId) => {
881
+ const itemIndex = visibleItems.findIndex((item) => getId(item) === targetId);
882
+ if (itemIndex >= 0) {
883
+ const virtualIndex = draggable2 ? itemIndex * 2 + 1 : itemIndex;
884
+ virtualizer.scrollToIndex(virtualIndex, {
885
+ align: "start",
886
+ behavior: "smooth"
887
+ });
888
+ }
889
+ }, [
890
+ visibleItems,
891
+ getId,
892
+ draggable2,
893
+ virtualizer
894
+ ]);
895
+ useEffect3(() => {
896
+ registerScrollTo(scrollToId);
897
+ return () => registerScrollTo(void 0);
898
+ }, [
899
+ registerScrollTo,
900
+ scrollToId
901
+ ]);
902
+ const virtualItems = virtualizer.getVirtualItems();
903
+ const getData = (index) => {
904
+ if (draggable2) {
905
+ if (index % 2 === 0) {
906
+ return {
907
+ location: Math.floor(index / 2) + 0.5
908
+ };
909
+ } else {
910
+ return {
911
+ data: visibleItems[Math.floor(index / 2)],
912
+ location: Math.floor(index / 2) + 1
913
+ };
914
+ }
915
+ } else {
916
+ return {
917
+ data: visibleItems[index],
918
+ location: index + 1
919
+ };
920
+ }
921
+ };
922
+ return /* @__PURE__ */ React5.createElement("div", {
923
+ ...composableProps3(props, {
924
+ role: "list",
925
+ classNames: [
926
+ // shrink-0 is required: this div sets an explicit height via inline style (getTotalSize).
927
+ // Without it, a parent flex container (e.g. ScrollArea.Viewport) would shrink this div
928
+ // to the viewport height, collapsing the scroll content and causing scrollbar drift.
929
+ "flex shrink-0",
930
+ orientation === "horizontal" && "h-full [&>*]:shrink-0",
931
+ orientation === "vertical" && "flex-col"
932
+ ]
933
+ }),
934
+ style: {
935
+ position: "relative",
936
+ ...orientation === "vertical" ? {
937
+ width: "100%",
938
+ height: virtualizer.getTotalSize()
939
+ } : {
940
+ width: virtualizer.getTotalSize(),
941
+ height: "100%"
942
+ }
943
+ },
944
+ ref: forwardedRef
945
+ }, virtualItems.map(({ key, index, start }) => {
946
+ const { data, location } = getData(index);
947
+ return /* @__PURE__ */ React5.createElement("div", {
948
+ key,
949
+ "data-index": index,
950
+ style: {
951
+ position: "absolute",
952
+ top: 0,
953
+ left: 0,
954
+ ...orientation === "vertical" ? {
955
+ width: "100%",
956
+ transform: `translateY(${start}px)`
957
+ } : {
958
+ height: "100%",
959
+ transform: `translateX(${start}px)`
960
+ }
961
+ },
962
+ ref: virtualizer.measureElement
963
+ }, data ? /* @__PURE__ */ React5.createElement(Tile, {
964
+ id: getId(data),
965
+ data,
966
+ location,
967
+ draggable: draggable2,
968
+ current: getId(data) === currentId,
969
+ debug
970
+ }) : /* @__PURE__ */ React5.createElement(InternalPlaceholder, {
971
+ orientation,
972
+ location
973
+ }));
974
+ }));
975
+ });
976
+ MosaicVirtualStackInner.displayName = MOSAIC_VIRTUAL_STACK_NAME;
977
+ var MosaicVirtualStack = MosaicVirtualStackInner;
978
+ MosaicVirtualStack[/* @__PURE__ */ Symbol.for("dxos.composable")] = true;
979
+ var InternalPlaceholder = (props) => {
980
+ return /* @__PURE__ */ React5.createElement(MosaicPlaceholder, {
981
+ ...props,
982
+ classNames: styles.placeholder.root
983
+ }, /* @__PURE__ */ React5.createElement("div", {
984
+ className: mx4("flex h-full bg-base-surface border border-dashed border-separator rounded-xs", styles.placeholder.content)
985
+ }));
986
+ };
987
+ InternalPlaceholder.displayName = "InternalPlaceholder";
988
+
989
+ // src/components/Mosaic/Mosaic.tsx
990
+ var Mosaic = {
991
+ Root: MosaicRoot,
992
+ Container: MosaicContainer,
993
+ Tile: MosaicTile,
994
+ Placeholder: MosaicPlaceholder,
995
+ DropIndicator: MosaicDropIndicator,
996
+ Stack: MosaicStack,
997
+ VirtualStack: MosaicVirtualStack
998
+ };
999
+
1000
+ export {
1001
+ useVisibleItems,
1002
+ Focus,
1003
+ useFocus,
1004
+ styles,
1005
+ getSourceData,
1006
+ useMosaicRootContext,
1007
+ useMosaicContainerContext,
1008
+ useMosaicTileContext,
1009
+ Mosaic
1010
+ };
1011
+ //# sourceMappingURL=chunk-5K56GSJL.mjs.map