@dxos/react-ui-mosaic 0.7.5-main.ff8607b → 0.8.4-main.69d29f4

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 (282) hide show
  1. package/README.md +2 -44
  2. package/dist/lib/browser/chunk-4VDZJ3HV.mjs +1639 -0
  3. package/dist/lib/browser/chunk-4VDZJ3HV.mjs.map +7 -0
  4. package/dist/lib/browser/index.css +13 -0
  5. package/dist/lib/browser/index.css.map +7 -0
  6. package/dist/lib/browser/index.mjs +85 -689
  7. package/dist/lib/browser/index.mjs.map +4 -4
  8. package/dist/lib/browser/meta.json +1 -1
  9. package/dist/lib/browser/testing/index.css +13 -0
  10. package/dist/lib/browser/testing/index.css.map +7 -0
  11. package/dist/lib/browser/testing/index.mjs +306 -0
  12. package/dist/lib/browser/testing/index.mjs.map +7 -0
  13. package/dist/lib/node-esm/chunk-KONKDEUD.mjs +1641 -0
  14. package/dist/lib/node-esm/chunk-KONKDEUD.mjs.map +7 -0
  15. package/dist/lib/node-esm/index.css +13 -0
  16. package/dist/lib/node-esm/index.css.map +7 -0
  17. package/dist/lib/node-esm/index.mjs +85 -690
  18. package/dist/lib/node-esm/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/lib/node-esm/testing/index.css +13 -0
  21. package/dist/lib/node-esm/testing/index.css.map +7 -0
  22. package/dist/lib/node-esm/testing/index.mjs +307 -0
  23. package/dist/lib/node-esm/testing/index.mjs.map +7 -0
  24. package/dist/types/src/components/Card/Card.d.ts +120 -0
  25. package/dist/types/src/components/Card/Card.d.ts.map +1 -0
  26. package/dist/types/src/components/Card/Card.stories.d.ts +21 -0
  27. package/dist/types/src/components/Card/Card.stories.d.ts.map +1 -0
  28. package/dist/types/src/components/Card/CardDragPreview.d.ts +6 -0
  29. package/dist/types/src/components/Card/CardDragPreview.d.ts.map +1 -0
  30. package/dist/types/src/components/Card/index.d.ts +4 -0
  31. package/dist/types/src/components/Card/index.d.ts.map +1 -0
  32. package/dist/types/src/components/Card/styles.d.ts +13 -0
  33. package/dist/types/src/components/Card/styles.d.ts.map +1 -0
  34. package/dist/types/src/components/Focus/Focus.d.ts +25 -0
  35. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -0
  36. package/dist/types/src/components/Focus/index.d.ts +3 -0
  37. package/dist/types/src/components/Focus/index.d.ts.map +1 -0
  38. package/dist/types/src/components/Focus/styles.d.ts +6 -0
  39. package/dist/types/src/components/Focus/styles.d.ts.map +1 -0
  40. package/dist/types/src/components/Image/Image.d.ts +14 -0
  41. package/dist/types/src/components/Image/Image.d.ts.map +1 -0
  42. package/dist/types/src/components/Image/Image.stories.d.ts +33 -0
  43. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -0
  44. package/dist/types/src/components/Image/index.d.ts +2 -0
  45. package/dist/types/src/components/Image/index.d.ts.map +1 -0
  46. package/dist/types/src/components/Layout/Layout.d.ts +33 -0
  47. package/dist/types/src/components/Layout/Layout.d.ts.map +1 -0
  48. package/dist/types/src/components/Layout/Layout.stories.d.ts +10 -0
  49. package/dist/types/src/components/Layout/Layout.stories.d.ts.map +1 -0
  50. package/dist/types/src/components/Layout/index.d.ts +2 -0
  51. package/dist/types/src/components/Layout/index.d.ts.map +1 -0
  52. package/dist/types/src/components/Mosaic/Mosaic.d.ts +141 -0
  53. package/dist/types/src/components/Mosaic/Mosaic.d.ts.map +1 -0
  54. package/dist/types/src/components/Mosaic/Mosaic.stories.d.ts +27 -0
  55. package/dist/types/src/components/Mosaic/Mosaic.stories.d.ts.map +1 -0
  56. package/dist/types/src/components/Mosaic/extension.d.ts +20 -0
  57. package/dist/types/src/components/Mosaic/extension.d.ts.map +1 -0
  58. package/dist/types/src/components/Mosaic/index.d.ts +5 -0
  59. package/dist/types/src/components/Mosaic/index.d.ts.map +1 -0
  60. package/dist/types/src/components/Mosaic/styles.d.ts +7 -0
  61. package/dist/types/src/components/Mosaic/styles.d.ts.map +1 -0
  62. package/dist/types/src/components/Mosaic/types.d.ts +79 -0
  63. package/dist/types/src/components/Mosaic/types.d.ts.map +1 -0
  64. package/dist/types/src/components/Scrollable/Scrollable.d.ts +17 -0
  65. package/dist/types/src/components/Scrollable/Scrollable.d.ts.map +1 -0
  66. package/dist/types/src/components/Scrollable/Scrollable.stories.d.ts +8 -0
  67. package/dist/types/src/components/Scrollable/Scrollable.stories.d.ts.map +1 -0
  68. package/dist/types/src/components/Scrollable/index.d.ts +2 -0
  69. package/dist/types/src/components/Scrollable/index.d.ts.map +1 -0
  70. package/dist/types/src/components/Stack/Stack.d.ts +24 -0
  71. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -0
  72. package/dist/types/src/components/Stack/Stack.stories.d.ts +9 -0
  73. package/dist/types/src/components/Stack/Stack.stories.d.ts.map +1 -0
  74. package/dist/types/src/components/Stack/index.d.ts.map +1 -0
  75. package/dist/types/src/components/index.d.ts +7 -0
  76. package/dist/types/src/components/index.d.ts.map +1 -0
  77. package/dist/types/src/hooks/index.d.ts +4 -0
  78. package/dist/types/src/hooks/index.d.ts.map +1 -0
  79. package/dist/types/src/hooks/useContainerDebug.d.ts +9 -0
  80. package/dist/types/src/hooks/useContainerDebug.d.ts.map +1 -0
  81. package/dist/types/src/hooks/useEventHandlerAdapter.d.ts +32 -0
  82. package/dist/types/src/hooks/useEventHandlerAdapter.d.ts.map +1 -0
  83. package/dist/types/src/hooks/useVisibleItems.d.ts +16 -0
  84. package/dist/types/src/hooks/useVisibleItems.d.ts.map +1 -0
  85. package/dist/types/src/index.d.ts +2 -1
  86. package/dist/types/src/index.d.ts.map +1 -1
  87. package/dist/types/src/testing/Board.d.ts +45 -0
  88. package/dist/types/src/testing/Board.d.ts.map +1 -0
  89. package/dist/types/src/testing/CardContainer.d.ts +17 -0
  90. package/dist/types/src/testing/CardContainer.d.ts.map +1 -0
  91. package/dist/types/src/testing/DefaultStackTile.d.ts +4 -0
  92. package/dist/types/src/testing/DefaultStackTile.d.ts.map +1 -0
  93. package/dist/types/src/testing/Slot.stories.d.ts +14 -0
  94. package/dist/types/src/testing/Slot.stories.d.ts.map +1 -0
  95. package/dist/types/src/testing/Virtualizer.stories.d.ts +12 -0
  96. package/dist/types/src/testing/Virtualizer.stories.d.ts.map +1 -0
  97. package/dist/types/src/testing/decorator.d.ts +3 -0
  98. package/dist/types/src/testing/decorator.d.ts.map +1 -0
  99. package/dist/types/src/testing/index.d.ts +4 -2
  100. package/dist/types/src/testing/index.d.ts.map +1 -1
  101. package/dist/types/src/translations.d.ts +7 -0
  102. package/dist/types/src/translations.d.ts.map +1 -0
  103. package/dist/types/tsconfig.tsbuildinfo +1 -1
  104. package/package.json +63 -40
  105. package/src/components/Card/Card.stories.tsx +148 -0
  106. package/src/components/Card/Card.tsx +435 -0
  107. package/src/components/Card/CardDragPreview.tsx +23 -0
  108. package/src/components/Card/index.ts +8 -0
  109. package/src/components/Card/styles.ts +23 -0
  110. package/src/components/Focus/Focus.tsx +95 -0
  111. package/src/components/Focus/index.ts +7 -0
  112. package/src/components/Focus/styles.ts +24 -0
  113. package/src/components/Image/Image.stories.tsx +86 -0
  114. package/src/components/Image/Image.tsx +223 -0
  115. package/src/components/Image/index.ts +5 -0
  116. package/src/components/Layout/Layout.stories.tsx +59 -0
  117. package/src/components/Layout/Layout.tsx +108 -0
  118. package/src/components/Layout/index.ts +5 -0
  119. package/src/components/Mosaic/Mosaic.stories.tsx +113 -0
  120. package/src/components/Mosaic/Mosaic.tsx +930 -0
  121. package/src/components/Mosaic/extension.ts +141 -0
  122. package/src/components/Mosaic/index.ts +10 -0
  123. package/src/components/Mosaic/styles.ts +31 -0
  124. package/src/components/Mosaic/types.ts +82 -0
  125. package/src/components/Scrollable/Scrollable.stories.tsx +33 -0
  126. package/src/components/Scrollable/Scrollable.tsx +99 -0
  127. package/src/components/Scrollable/index.ts +5 -0
  128. package/src/components/Scrollable/scrollable.css +20 -0
  129. package/src/components/Stack/Stack.stories.tsx +115 -0
  130. package/src/components/Stack/Stack.tsx +210 -0
  131. package/src/{views → components}/Stack/index.ts +1 -1
  132. package/src/components/index.ts +10 -0
  133. package/src/hooks/index.ts +7 -0
  134. package/src/hooks/useContainerDebug.tsx +46 -0
  135. package/src/hooks/useEventHandlerAdapter.ts +99 -0
  136. package/src/hooks/useVisibleItems.ts +43 -0
  137. package/src/index.ts +3 -2
  138. package/src/testing/Board.tsx +278 -0
  139. package/src/testing/CardContainer.tsx +88 -0
  140. package/src/testing/DefaultStackTile.tsx +38 -0
  141. package/src/testing/Slot.stories.tsx +101 -0
  142. package/src/testing/Virtualizer.stories.tsx +133 -0
  143. package/src/testing/decorator.tsx +16 -0
  144. package/src/testing/index.ts +5 -3
  145. package/src/translations.ts +15 -0
  146. package/dist/lib/node/index.cjs +0 -705
  147. package/dist/lib/node/index.cjs.map +0 -7
  148. package/dist/lib/node/meta.json +0 -1
  149. package/dist/types/src/mosaic/Container.d.ts +0 -94
  150. package/dist/types/src/mosaic/Container.d.ts.map +0 -1
  151. package/dist/types/src/mosaic/Debug.d.ts +0 -9
  152. package/dist/types/src/mosaic/Debug.d.ts.map +0 -1
  153. package/dist/types/src/mosaic/DefaultComponent.d.ts +0 -4
  154. package/dist/types/src/mosaic/DefaultComponent.d.ts.map +0 -1
  155. package/dist/types/src/mosaic/DragOverlay.d.ts +0 -11
  156. package/dist/types/src/mosaic/DragOverlay.d.ts.map +0 -1
  157. package/dist/types/src/mosaic/Mosaic.d.ts +0 -34
  158. package/dist/types/src/mosaic/Mosaic.d.ts.map +0 -1
  159. package/dist/types/src/mosaic/Root.d.ts +0 -28
  160. package/dist/types/src/mosaic/Root.d.ts.map +0 -1
  161. package/dist/types/src/mosaic/SortableContext.d.ts +0 -14
  162. package/dist/types/src/mosaic/SortableContext.d.ts.map +0 -1
  163. package/dist/types/src/mosaic/Tile.d.ts +0 -74
  164. package/dist/types/src/mosaic/Tile.d.ts.map +0 -1
  165. package/dist/types/src/mosaic/hooks/index.d.ts +0 -5
  166. package/dist/types/src/mosaic/hooks/index.d.ts.map +0 -1
  167. package/dist/types/src/mosaic/hooks/useContainer.d.ts +0 -4
  168. package/dist/types/src/mosaic/hooks/useContainer.d.ts.map +0 -1
  169. package/dist/types/src/mosaic/hooks/useItemsWithOrigin.d.ts +0 -3
  170. package/dist/types/src/mosaic/hooks/useItemsWithOrigin.d.ts.map +0 -1
  171. package/dist/types/src/mosaic/hooks/useItemsWithPreview.d.ts +0 -10
  172. package/dist/types/src/mosaic/hooks/useItemsWithPreview.d.ts.map +0 -1
  173. package/dist/types/src/mosaic/hooks/useMosaic.d.ts +0 -2
  174. package/dist/types/src/mosaic/hooks/useMosaic.d.ts.map +0 -1
  175. package/dist/types/src/mosaic/index.d.ts +0 -5
  176. package/dist/types/src/mosaic/index.d.ts.map +0 -1
  177. package/dist/types/src/mosaic/types.d.ts +0 -10
  178. package/dist/types/src/mosaic/types.d.ts.map +0 -1
  179. package/dist/types/src/mosaic/util/data.d.ts +0 -3
  180. package/dist/types/src/mosaic/util/data.d.ts.map +0 -1
  181. package/dist/types/src/mosaic/util/index.d.ts +0 -5
  182. package/dist/types/src/mosaic/util/index.d.ts.map +0 -1
  183. package/dist/types/src/mosaic/util/path.d.ts +0 -14
  184. package/dist/types/src/mosaic/util/path.d.ts.map +0 -1
  185. package/dist/types/src/mosaic/util/path.test.d.ts +0 -2
  186. package/dist/types/src/mosaic/util/path.test.d.ts.map +0 -1
  187. package/dist/types/src/mosaic/util/props.d.ts +0 -4
  188. package/dist/types/src/mosaic/util/props.d.ts.map +0 -1
  189. package/dist/types/src/mosaic/util/styles.d.ts +0 -3
  190. package/dist/types/src/mosaic/util/styles.d.ts.map +0 -1
  191. package/dist/types/src/testing/Cards.d.ts +0 -10
  192. package/dist/types/src/testing/Cards.d.ts.map +0 -1
  193. package/dist/types/src/testing/generator.d.ts +0 -35
  194. package/dist/types/src/testing/generator.d.ts.map +0 -1
  195. package/dist/types/src/views/Demo/Demo.stories.d.ts +0 -14
  196. package/dist/types/src/views/Demo/Demo.stories.d.ts.map +0 -1
  197. package/dist/types/src/views/Demo/Echo.stories.d.ts +0 -8
  198. package/dist/types/src/views/Demo/Echo.stories.d.ts.map +0 -1
  199. package/dist/types/src/views/Grid/Grid.d.ts +0 -31
  200. package/dist/types/src/views/Grid/Grid.d.ts.map +0 -1
  201. package/dist/types/src/views/Grid/Grid.stories.d.ts +0 -14
  202. package/dist/types/src/views/Grid/Grid.stories.d.ts.map +0 -1
  203. package/dist/types/src/views/Grid/index.d.ts +0 -3
  204. package/dist/types/src/views/Grid/index.d.ts.map +0 -1
  205. package/dist/types/src/views/Grid/layout.d.ts +0 -27
  206. package/dist/types/src/views/Grid/layout.d.ts.map +0 -1
  207. package/dist/types/src/views/Grid/testing.d.ts +0 -11
  208. package/dist/types/src/views/Grid/testing.d.ts.map +0 -1
  209. package/dist/types/src/views/Kanban/Kanban.d.ts +0 -12
  210. package/dist/types/src/views/Kanban/Kanban.d.ts.map +0 -1
  211. package/dist/types/src/views/Kanban/Kanban.stories.d.ts +0 -29
  212. package/dist/types/src/views/Kanban/Kanban.stories.d.ts.map +0 -1
  213. package/dist/types/src/views/Kanban/index.d.ts +0 -2
  214. package/dist/types/src/views/Kanban/index.d.ts.map +0 -1
  215. package/dist/types/src/views/Kanban/testing.d.ts +0 -12
  216. package/dist/types/src/views/Kanban/testing.d.ts.map +0 -1
  217. package/dist/types/src/views/Stack/Columns.stories.d.ts +0 -34
  218. package/dist/types/src/views/Stack/Columns.stories.d.ts.map +0 -1
  219. package/dist/types/src/views/Stack/Stack.d.ts +0 -10
  220. package/dist/types/src/views/Stack/Stack.d.ts.map +0 -1
  221. package/dist/types/src/views/Stack/Stack.stories.d.ts +0 -40
  222. package/dist/types/src/views/Stack/Stack.stories.d.ts.map +0 -1
  223. package/dist/types/src/views/Stack/index.d.ts.map +0 -1
  224. package/dist/types/src/views/Stack/testing.d.ts +0 -10
  225. package/dist/types/src/views/Stack/testing.d.ts.map +0 -1
  226. package/dist/types/src/views/Tree/Graph.stories.d.ts +0 -11
  227. package/dist/types/src/views/Tree/Graph.stories.d.ts.map +0 -1
  228. package/dist/types/src/views/Tree/Tree.d.ts +0 -13
  229. package/dist/types/src/views/Tree/Tree.d.ts.map +0 -1
  230. package/dist/types/src/views/Tree/Tree.stories.d.ts +0 -42
  231. package/dist/types/src/views/Tree/Tree.stories.d.ts.map +0 -1
  232. package/dist/types/src/views/Tree/index.d.ts +0 -2
  233. package/dist/types/src/views/Tree/index.d.ts.map +0 -1
  234. package/dist/types/src/views/Tree/testing.d.ts +0 -11
  235. package/dist/types/src/views/Tree/testing.d.ts.map +0 -1
  236. package/dist/types/src/views/index.d.ts +0 -5
  237. package/dist/types/src/views/index.d.ts.map +0 -1
  238. package/src/mosaic/Container.tsx +0 -190
  239. package/src/mosaic/Debug.tsx +0 -24
  240. package/src/mosaic/DefaultComponent.tsx +0 -26
  241. package/src/mosaic/DragOverlay.tsx +0 -150
  242. package/src/mosaic/Mosaic.ts +0 -100
  243. package/src/mosaic/Root.tsx +0 -320
  244. package/src/mosaic/SortableContext.tsx +0 -61
  245. package/src/mosaic/Tile.tsx +0 -207
  246. package/src/mosaic/hooks/index.ts +0 -8
  247. package/src/mosaic/hooks/useContainer.ts +0 -13
  248. package/src/mosaic/hooks/useItemsWithOrigin.ts +0 -33
  249. package/src/mosaic/hooks/useItemsWithPreview.ts +0 -69
  250. package/src/mosaic/hooks/useMosaic.ts +0 -11
  251. package/src/mosaic/index.ts +0 -9
  252. package/src/mosaic/types.ts +0 -15
  253. package/src/mosaic/util/data.ts +0 -19
  254. package/src/mosaic/util/index.ts +0 -8
  255. package/src/mosaic/util/path.test.ts +0 -24
  256. package/src/mosaic/util/path.ts +0 -21
  257. package/src/mosaic/util/props.ts +0 -14
  258. package/src/mosaic/util/styles.ts +0 -10
  259. package/src/testing/Cards.tsx +0 -88
  260. package/src/testing/generator.ts +0 -131
  261. package/src/views/Demo/Demo.stories.tsx +0 -81
  262. package/src/views/Demo/Echo.stories.tsx +0 -75
  263. package/src/views/Grid/Grid.stories.tsx +0 -51
  264. package/src/views/Grid/Grid.tsx +0 -265
  265. package/src/views/Grid/index.ts +0 -7
  266. package/src/views/Grid/layout.ts +0 -42
  267. package/src/views/Grid/testing.tsx +0 -92
  268. package/src/views/Kanban/Kanban.stories.tsx +0 -51
  269. package/src/views/Kanban/Kanban.tsx +0 -139
  270. package/src/views/Kanban/index.ts +0 -5
  271. package/src/views/Kanban/testing.tsx +0 -234
  272. package/src/views/Stack/Columns.stories.tsx +0 -63
  273. package/src/views/Stack/Stack.stories.tsx +0 -65
  274. package/src/views/Stack/Stack.tsx +0 -58
  275. package/src/views/Stack/testing.tsx +0 -77
  276. package/src/views/Tree/Graph.stories.tsx +0 -37
  277. package/src/views/Tree/Tree.stories.tsx +0 -95
  278. package/src/views/Tree/Tree.tsx +0 -126
  279. package/src/views/Tree/index.ts +0 -5
  280. package/src/views/Tree/testing.tsx +0 -142
  281. package/src/views/index.ts +0 -8
  282. /package/dist/types/src/{views → components}/Stack/index.d.ts +0 -0
@@ -0,0 +1,1639 @@
1
+ // src/components/Card/styles.ts
2
+ var styles = {
3
+ root: "group/card relative min-bs-[--rail-item] overflow-hidden is-full card-min-width __card-max-width",
4
+ border: "bg-cardSurface border border-separator dark:border-subduedSeparator rounded-sm dx-focus-ring-group-y-indicator",
5
+ /**
6
+ * Row grid.
7
+ * NOTE: Rows should provide their own line padding (since they may need to encapsulate buttons, etc.)
8
+ */
9
+ grid_3: "grid grid-cols-[var(--rail-item)_minmax(0,1fr)_var(--rail-item)] gap-x-1",
10
+ grid_2: "grid grid-cols-[var(--rail-item)_minmax(0,1fr)] gap-x-1",
11
+ // TODO(burdon): Address density.
12
+ grid_3_coarse: "grid grid-cols-[var(--l0-avatar-size)_minmax(0,1fr)_var(--rail-item)] gap-x-1",
13
+ poster: "max-bs-[200px]"
14
+ };
15
+
16
+ // src/components/Image/Image.tsx
17
+ import React, { useCallback, useRef, useState } from "react";
18
+ import { mx } from "@dxos/ui-theme";
19
+ var cache = /* @__PURE__ */ new Map();
20
+ var Image = ({ classNames, src, alt = "", crossOrigin = "anonymous", sampleSize = 64, contrast = 0.9 }) => {
21
+ const [crossOriginState, setCrossOriginState] = useState(crossOrigin);
22
+ const [dominantColor, setDominantColor] = useState(void 0);
23
+ const [imageLoaded, setImageLoaded] = useState(false);
24
+ const canvasRef = useRef(null);
25
+ const handleImageError = () => {
26
+ setCrossOriginState(void 0);
27
+ };
28
+ const handleImageLoad = useCallback(({ target }) => {
29
+ const rgb = cache.get(src);
30
+ if (rgb) {
31
+ setDominantColor(rgb);
32
+ setImageLoaded(true);
33
+ return;
34
+ }
35
+ const img = target;
36
+ if (!canvasRef.current) {
37
+ return;
38
+ }
39
+ try {
40
+ const color = extractDominantColor(canvasRef.current, img, {
41
+ sampleSize,
42
+ contrast
43
+ });
44
+ if (color) {
45
+ const rgb2 = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
46
+ cache.set(src, rgb2);
47
+ setDominantColor(rgb2);
48
+ }
49
+ } catch {
50
+ setCrossOriginState(void 0);
51
+ }
52
+ setImageLoaded(true);
53
+ }, [
54
+ sampleSize,
55
+ contrast,
56
+ src
57
+ ]);
58
+ return /* @__PURE__ */ React.createElement("div", {
59
+ className: mx(`relative flex is-full justify-center overflow-hidden transition-all duration-700`, classNames),
60
+ style: {
61
+ backgroundColor: dominantColor
62
+ }
63
+ }, /* @__PURE__ */ React.createElement("canvas", {
64
+ ref: canvasRef,
65
+ style: {
66
+ display: "none"
67
+ },
68
+ "aria-hidden": "true"
69
+ }), /* @__PURE__ */ React.createElement("div", {
70
+ className: "absolute inset-0 pointer-events-none",
71
+ style: {
72
+ background: dominantColor ? `radial-gradient(circle at center, transparent 30%, ${dominantColor} 100%)` : void 0,
73
+ transition: "opacity 0.7s ease-in-out",
74
+ opacity: 0.5
75
+ }
76
+ }), /* @__PURE__ */ React.createElement("img", {
77
+ src,
78
+ alt,
79
+ crossOrigin: crossOriginState,
80
+ onError: handleImageError,
81
+ onLoad: handleImageLoad,
82
+ className: mx("z-10 object-contain transition-opacity duration-500", classNames),
83
+ style: {
84
+ opacity: imageLoaded ? 1 : 0
85
+ }
86
+ }));
87
+ };
88
+ var extractDominantColor = (canvas, img, { sampleSize = 64, contrast = 0.95 }) => {
89
+ const ctx = canvas.getContext("2d");
90
+ if (!ctx) {
91
+ return null;
92
+ }
93
+ canvas.width = sampleSize;
94
+ canvas.height = sampleSize;
95
+ ctx.drawImage(img, 0, 0, sampleSize, sampleSize);
96
+ const imageData = ctx.getImageData(0, 0, sampleSize, sampleSize);
97
+ const pixels = imageData.data;
98
+ if (isTransparent(pixels, sampleSize)) {
99
+ return null;
100
+ }
101
+ let r = 0;
102
+ let g = 0;
103
+ let b = 0;
104
+ let totalWeight = 0;
105
+ const cornerSize = Math.floor(sampleSize * 0.125);
106
+ for (let y = 0; y < sampleSize; y++) {
107
+ for (let x = 0; x < sampleSize; x++) {
108
+ const isInTopLeft = x < cornerSize && y < cornerSize;
109
+ const isInTopRight = x >= sampleSize - cornerSize && y < cornerSize;
110
+ const isInBottomLeft = x < cornerSize && y >= sampleSize - cornerSize;
111
+ const isInBottomRight = x >= sampleSize - cornerSize && y >= sampleSize - cornerSize;
112
+ if (!isInTopLeft && !isInTopRight && !isInBottomLeft && !isInBottomRight) {
113
+ continue;
114
+ }
115
+ const i = (y * sampleSize + x) * 4;
116
+ const red = pixels[i];
117
+ const green = pixels[i + 1];
118
+ const blue = pixels[i + 2];
119
+ const alpha = pixels[i + 3];
120
+ if (alpha === 0) continue;
121
+ const max = Math.max(red, green, blue);
122
+ const min = Math.min(red, green, blue);
123
+ const saturation = max === 0 ? 0 : (max - min) / max;
124
+ const weight = 1 + saturation * 2;
125
+ r += red * weight;
126
+ g += green * weight;
127
+ b += blue * weight;
128
+ totalWeight += weight;
129
+ }
130
+ }
131
+ if (totalWeight > 0) {
132
+ r = Math.round(Math.round(r / totalWeight) * contrast);
133
+ g = Math.round(Math.round(g / totalWeight) * contrast);
134
+ b = Math.round(Math.round(b / totalWeight) * contrast);
135
+ return [
136
+ r,
137
+ g,
138
+ b
139
+ ];
140
+ }
141
+ return null;
142
+ };
143
+ var isTransparent = (pixels, sampleSize, threshold = 0.5) => {
144
+ let edgeTransparentPixels = 0;
145
+ const edgePixels = sampleSize * 4 - 4;
146
+ for (let x = 0; x < sampleSize; x++) {
147
+ const topIndex = x * 4;
148
+ if (pixels[topIndex + 3] === 0) edgeTransparentPixels++;
149
+ const bottomIndex = ((sampleSize - 1) * sampleSize + x) * 4;
150
+ if (pixels[bottomIndex + 3] === 0) edgeTransparentPixels++;
151
+ }
152
+ for (let y = 1; y < sampleSize - 1; y++) {
153
+ const leftIndex = y * sampleSize * 4;
154
+ if (pixels[leftIndex + 3] === 0) edgeTransparentPixels++;
155
+ const rightIndex = (y * sampleSize + sampleSize - 1) * 4;
156
+ if (pixels[rightIndex + 3] === 0) edgeTransparentPixels++;
157
+ }
158
+ return edgeTransparentPixels / edgePixels > threshold;
159
+ };
160
+
161
+ // src/components/Card/Card.tsx
162
+ import { Slot } from "@radix-ui/react-slot";
163
+ import React2, { createContext, forwardRef, useContext } from "react";
164
+ import { Button, DropdownMenu, Icon, Toolbar, useTranslation } from "@dxos/react-ui";
165
+ import { mx as mx2 } from "@dxos/ui-theme";
166
+
167
+ // src/translations.ts
168
+ var translationKey = "@dxos/react-ui-mosaic";
169
+ var translations = [
170
+ {
171
+ "en-US": {
172
+ [translationKey]: {}
173
+ }
174
+ }
175
+ ];
176
+
177
+ // src/components/Card/Card.tsx
178
+ var CardContext = /* @__PURE__ */ createContext({});
179
+ var CardRoot = /* @__PURE__ */ forwardRef(({ children, classNames, className, id, asChild, role = "group", border = true, fullWidth, ...props }, forwardedRef) => {
180
+ const Root2 = asChild ? Slot : "div";
181
+ return /* @__PURE__ */ React2.createElement(Root2, {
182
+ ...id && {
183
+ "data-object-id": id
184
+ },
185
+ ...props,
186
+ role,
187
+ className: mx2(styles.root, border && styles.border, fullWidth && "!max-is-none", className, classNames),
188
+ ref: forwardedRef
189
+ }, children);
190
+ });
191
+ var CardToolbar = /* @__PURE__ */ forwardRef(({ children, classNames, density = "fine", ...props }, forwardedRef) => {
192
+ return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
193
+ ...props,
194
+ classNames: [
195
+ "density-fine bg-transparent",
196
+ density === "fine" ? styles.grid_3 : styles.grid_3_coarse,
197
+ classNames
198
+ ],
199
+ ref: forwardedRef
200
+ }, children);
201
+ });
202
+ var CardToolbarIconButton = Toolbar.IconButton;
203
+ var CardToolbarSeparator = Toolbar.Separator;
204
+ var CardDragHandle = /* @__PURE__ */ forwardRef((_, forwardedRef) => {
205
+ const { t } = useTranslation(translationKey);
206
+ return /* @__PURE__ */ React2.createElement(Toolbar.IconButton, {
207
+ "data-testid": "card-drag-handle",
208
+ noTooltip: true,
209
+ iconOnly: true,
210
+ icon: "ph--dots-six-vertical--regular",
211
+ variant: "ghost",
212
+ label: t("drag handle label"),
213
+ classNames: "cursor-pointer",
214
+ size: 5,
215
+ disabled: !forwardedRef,
216
+ ref: forwardedRef
217
+ });
218
+ });
219
+ var CardClose = /* @__PURE__ */ forwardRef(({ onClick }, forwardedRef) => {
220
+ const { t } = useTranslation(translationKey);
221
+ return /* @__PURE__ */ React2.createElement(Toolbar.IconButton, {
222
+ iconOnly: true,
223
+ icon: "ph--x--regular",
224
+ variant: "ghost",
225
+ label: t("card close label"),
226
+ classNames: "cursor-pointer",
227
+ size: 5,
228
+ onClick,
229
+ ref: forwardedRef
230
+ });
231
+ });
232
+ var CardMenu = ({ context, items }) => {
233
+ const { t } = useTranslation(translationKey);
234
+ const { menuItems } = useContext(CardContext) ?? {};
235
+ const combinedItems = [
236
+ ...items ?? [],
237
+ ...menuItems ?? []
238
+ ];
239
+ return /* @__PURE__ */ React2.createElement(DropdownMenu.Root, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Trigger, {
240
+ disabled: !combinedItems.length,
241
+ asChild: true
242
+ }, /* @__PURE__ */ React2.createElement(Card.ToolbarIconButton, {
243
+ iconOnly: true,
244
+ variant: "ghost",
245
+ icon: "ph--dots-three-vertical--regular",
246
+ label: t("action menu label")
247
+ })), (combinedItems?.length ?? 0) > 0 && /* @__PURE__ */ React2.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Content, null, /* @__PURE__ */ React2.createElement(DropdownMenu.Viewport, null, combinedItems?.map(({ label, onClick: onSelect }, i) => /* @__PURE__ */ React2.createElement(DropdownMenu.Item, {
248
+ key: i,
249
+ onSelect: () => onSelect(context)
250
+ }, label))), /* @__PURE__ */ React2.createElement(DropdownMenu.Arrow, null))));
251
+ };
252
+ var CardTitle = /* @__PURE__ */ forwardRef(({ children, classNames, className, asChild, role = "heading", ...props }, forwardedRef) => {
253
+ const Root2 = asChild ? Slot : "div";
254
+ return /* @__PURE__ */ React2.createElement(Root2, {
255
+ ...props,
256
+ role,
257
+ className: mx2("grow truncate", classNames, className),
258
+ ref: forwardedRef
259
+ }, children);
260
+ });
261
+ var CardContent = /* @__PURE__ */ forwardRef(({ children, ...props }, forwardedRef) => {
262
+ return /* @__PURE__ */ React2.createElement("div", {
263
+ role: "none",
264
+ className: "contents [&>:last-child]:pbe-1",
265
+ ...props,
266
+ ref: forwardedRef
267
+ }, children);
268
+ });
269
+ var CardRow = /* @__PURE__ */ forwardRef(({ children, classNames, className, role = "none", icon, ...props }, forwardedRef) => {
270
+ return /* @__PURE__ */ React2.createElement("div", {
271
+ ...props,
272
+ role,
273
+ className: mx2(styles.grid_2, "pli-1", classNames, className),
274
+ ref: forwardedRef
275
+ }, icon && /* @__PURE__ */ React2.createElement(CardIcon, {
276
+ classNames: "text-subdued",
277
+ icon
278
+ }) || /* @__PURE__ */ React2.createElement("div", null), children);
279
+ });
280
+ var CardHeading = /* @__PURE__ */ forwardRef(({ children, classNames, className, asChild, role = "heading", variant = "default", ...props }, forwardedRef) => {
281
+ const Root2 = asChild ? Slot : "div";
282
+ const variantClassNames = {
283
+ default: "plb-1",
284
+ subtitle: "plb-2 text-xs text-description font-medium uppercase"
285
+ };
286
+ return /* @__PURE__ */ React2.createElement(Root2, {
287
+ ...props,
288
+ role,
289
+ className: mx2(variantClassNames[variant], classNames, className),
290
+ ref: forwardedRef
291
+ }, children);
292
+ });
293
+ var CardText = /* @__PURE__ */ forwardRef(({ children, classNames, className, asChild, role = "none", truncate, variant = "default", ...props }, forwardedRef) => {
294
+ const Root2 = asChild ? Slot : "div";
295
+ const variantClassNames = {
296
+ default: {
297
+ root: "plb-1"
298
+ },
299
+ description: {
300
+ root: "plb-1.5",
301
+ span: "text-sm text-description line-clamp-3"
302
+ }
303
+ };
304
+ return /* @__PURE__ */ React2.createElement(Root2, {
305
+ ...props,
306
+ role,
307
+ className: mx2("flex overflow-hidden", variantClassNames[variant].root, classNames, className),
308
+ ref: forwardedRef
309
+ }, /* @__PURE__ */ React2.createElement("span", {
310
+ className: mx2(variantClassNames[variant].span, truncate && "truncate")
311
+ }, children));
312
+ });
313
+ var CardPoster = (props) => {
314
+ const aspect = props.aspect === "auto" ? "aspect-auto" : "aspect-video";
315
+ if (props.image) {
316
+ return /* @__PURE__ */ React2.createElement("div", {
317
+ role: "none",
318
+ className: "mbe-1"
319
+ }, /* @__PURE__ */ React2.createElement(Image, {
320
+ classNames: [
321
+ styles.poster,
322
+ aspect,
323
+ props.classNames
324
+ ],
325
+ src: props.image,
326
+ alt: props.alt
327
+ }));
328
+ }
329
+ if (props.icon) {
330
+ return /* @__PURE__ */ React2.createElement("div", {
331
+ role: "image",
332
+ className: mx2("grid place-items-center bg-inputSurface text-subdued", styles.poster, aspect, props.classNames),
333
+ "aria-label": props.alt
334
+ }, /* @__PURE__ */ React2.createElement(Icon, {
335
+ icon: props.icon,
336
+ size: 10
337
+ }));
338
+ }
339
+ };
340
+ var CardAction = ({ icon, actionIcon = "ph--arrow-right--regular", label, onClick }) => {
341
+ return /* @__PURE__ */ React2.createElement("div", {
342
+ role: "none",
343
+ className: "is-full pli-1"
344
+ }, /* @__PURE__ */ React2.createElement(Button, {
345
+ variant: "ghost",
346
+ classNames: mx2(styles.grid_3, "!p-0 is-full text-start overflow-hidden"),
347
+ onClick
348
+ }, icon ? /* @__PURE__ */ React2.createElement(CardIcon, {
349
+ classNames: "text-subdued",
350
+ icon
351
+ }) : /* @__PURE__ */ React2.createElement("div", null), /* @__PURE__ */ React2.createElement("span", {
352
+ className: mx2("min-is-0 flex-1 truncate", !actionIcon && "col-span-2")
353
+ }, label), actionIcon && /* @__PURE__ */ React2.createElement(CardIcon, {
354
+ icon: actionIcon
355
+ })));
356
+ };
357
+ var CardLink = ({ label, href }) => {
358
+ return /* @__PURE__ */ React2.createElement("div", {
359
+ role: "none",
360
+ className: "is-full pli-1"
361
+ }, /* @__PURE__ */ React2.createElement("a", {
362
+ className: mx2(styles.grid_3, "group !p-0 dx-button dx-focus-ring !min-bs-1"),
363
+ "data-variant": "ghost",
364
+ href,
365
+ target: "_blank",
366
+ rel: "noreferrer"
367
+ }, /* @__PURE__ */ React2.createElement(CardIcon, {
368
+ classNames: "text-subdued",
369
+ icon: "ph--link--regular"
370
+ }), /* @__PURE__ */ React2.createElement("span", {
371
+ className: mx2("min-is-0 flex-1 truncate")
372
+ }, label), /* @__PURE__ */ React2.createElement(CardIcon, {
373
+ classNames: "invisible group-hover:visible",
374
+ icon: "ph--arrow-square-out--regular"
375
+ })));
376
+ };
377
+ var CardIcon = ({ toolbar, ...props }) => {
378
+ return /* @__PURE__ */ React2.createElement("div", {
379
+ role: "none",
380
+ className: "grid bs-[var(--rail-item)] is-[var(--rail-item)] place-items-center"
381
+ }, /* @__PURE__ */ React2.createElement(Icon, {
382
+ ...props,
383
+ size: toolbar ? 5 : 4
384
+ }));
385
+ };
386
+ var Card = {
387
+ Context: CardContext,
388
+ Root: CardRoot,
389
+ // Toolbar
390
+ Toolbar: CardToolbar,
391
+ ToolbarIconButton: CardToolbarIconButton,
392
+ ToolbarSeparator: CardToolbarSeparator,
393
+ DragHandle: CardDragHandle,
394
+ Title: CardTitle,
395
+ Close: CardClose,
396
+ Menu: CardMenu,
397
+ Icon: CardIcon,
398
+ // Content
399
+ Content: CardContent,
400
+ Row: CardRow,
401
+ Heading: CardHeading,
402
+ Text: CardText,
403
+ Poster: CardPoster,
404
+ Action: CardAction,
405
+ Link: CardLink
406
+ };
407
+
408
+ // src/components/Focus/styles.ts
409
+ var styles2 = {
410
+ container: {
411
+ // TODO(burdon): Handle selection (aria-current?)
412
+ // TODO(burdon): Use ring instead of border?
413
+ root: [
414
+ "outline-none border border-separator rounded-sm",
415
+ // Focus (e.g., via tabster).
416
+ // TODO(burdon): Why is ! required?
417
+ "focus:!border-accentSurface",
418
+ // Active (e.g., drop target).
419
+ "data-[focus-state=active]:border-neutralFocusIndicator",
420
+ // Error
421
+ // TODO(burdon): Error token.
422
+ "data-[focus-state=error]:border-rose-500"
423
+ ]
424
+ }
425
+ };
426
+
427
+ // src/components/Focus/Focus.tsx
428
+ import { useArrowNavigationGroup, useFocusableGroup, useMergedTabsterAttributes_unstable } from "@fluentui/react-tabster";
429
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
430
+ import { Primitive } from "@radix-ui/react-primitive";
431
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
432
+ import React3, { createContext as createContext2, forwardRef as forwardRef2, useContext as useContext2, useRef as useRef2, useState as useState2 } from "react";
433
+ import { mx as mx3 } from "@dxos/ui-theme";
434
+ var FOCUS_STATE_ATTR = "focus-state";
435
+ var FocusContext = /* @__PURE__ */ createContext2({});
436
+ var useFocus = () => useContext2(FocusContext);
437
+ var Group = /* @__PURE__ */ forwardRef2(({ classNames, className, children, asChild, axis = "vertical", ...props }, forwardedRef) => {
438
+ const rootRef = useRef2(null);
439
+ const composedRef = useComposedRefs(rootRef, forwardedRef);
440
+ const Root2 = asChild ? Slot2 : Primitive.div;
441
+ const focusableGroupAttrs = useFocusableGroup({
442
+ tabBehavior: "limited-trap-focus"
443
+ });
444
+ const arrowNavigationAttrs = useArrowNavigationGroup({
445
+ axis,
446
+ memorizeCurrent: true
447
+ });
448
+ const tabsterAttrs = useMergedTabsterAttributes_unstable(focusableGroupAttrs, arrowNavigationAttrs);
449
+ const [state, setState] = useState2();
450
+ return /* @__PURE__ */ React3.createElement(FocusContext.Provider, {
451
+ value: {
452
+ setFocus: setState
453
+ }
454
+ }, /* @__PURE__ */ React3.createElement(Root2, {
455
+ tabIndex: 0,
456
+ className: mx3(styles2.container.root, className, classNames),
457
+ ...tabsterAttrs,
458
+ ...state && {
459
+ [`data-${FOCUS_STATE_ATTR}`]: state
460
+ },
461
+ ...props,
462
+ ref: composedRef
463
+ }, children));
464
+ });
465
+ var Focus = {
466
+ Group
467
+ };
468
+
469
+ // src/components/Mosaic/styles.ts
470
+ var styles3 = {
471
+ placeholder: {
472
+ root: [
473
+ "group opacity-0",
474
+ 'group-data-[mosaic-debug="true"]:opacity-100',
475
+ 'group-data-[mosaic-debug="true"]:bg-orange-500',
476
+ "data-[mosaic-placeholder-state=active]:opacity-100",
477
+ "data-[mosaic-placeholder-axis=vertical]:plb-1",
478
+ "data-[mosaic-placeholder-axis=vertical]:data-[mosaic-placeholder-state=active]:plb-2.5",
479
+ "data-[mosaic-placeholder-axis=horizontal]:pli-1",
480
+ "data-[mosaic-placeholder-axis=horizontal]:data-[mosaic-placeholder-state=active]:pli-2.5"
481
+ ],
482
+ content: [
483
+ "transition-all duration-0",
484
+ // TODO(burdon): Don't animate open if placeholder is the source.
485
+ // TODO(burdon): Flickers when start to drag since source is removed and then the placeholder shows up.
486
+ // - Use absolute positioning?
487
+ // 'group-data-[mosaic-placeholder-state=active]:duration-200',
488
+ "group-data-[mosaic-placeholder-axis=vertical]:bs-0",
489
+ "group-data-[mosaic-placeholder-axis=horizontal]:is-0",
490
+ "group-data-[mosaic-placeholder-axis=vertical]:group-data-[mosaic-placeholder-state=active]:bs-[var(--mosaic-placeholder-height)]",
491
+ "group-data-[mosaic-placeholder-axis=horizontal]:group-data-[mosaic-placeholder-state=active]:is-[var(--mosaic-placeholder-width)]"
492
+ ]
493
+ }
494
+ };
495
+
496
+ // src/components/Mosaic/extension.ts
497
+ import { StateEffect, StateField } from "@codemirror/state";
498
+ import { Decoration, EditorView, ViewPlugin, WidgetType } from "@codemirror/view";
499
+ var dropHandler = ({ onDrop = handleDrop } = {}) => {
500
+ const views = /* @__PURE__ */ new Set();
501
+ let state = null;
502
+ const reset = () => {
503
+ views.forEach((view) => view.dispatch({
504
+ effects: setDrop.of(null)
505
+ }));
506
+ state = null;
507
+ };
508
+ const extension = [
509
+ dropField,
510
+ ViewPlugin.fromClass(class {
511
+ _view;
512
+ constructor(_view) {
513
+ this._view = _view;
514
+ views.add(_view);
515
+ }
516
+ destroy() {
517
+ views.delete(this._view);
518
+ }
519
+ })
520
+ ];
521
+ return {
522
+ extension,
523
+ update: (position) => {
524
+ if (!position) {
525
+ reset();
526
+ return;
527
+ }
528
+ views.forEach((view) => {
529
+ const rect = view.dom.getBoundingClientRect();
530
+ if (position.x >= rect.left && position.x <= rect.right && position.y >= rect.top && position.y <= rect.bottom) {
531
+ let pos = view.posAtCoords(position);
532
+ if (pos !== null) {
533
+ const word = view.state.wordAt(pos);
534
+ if (word) {
535
+ const startDist = Math.abs(pos - word.from);
536
+ const endDist = Math.abs(pos - word.to);
537
+ pos = startDist < endDist ? word.from : word.to;
538
+ }
539
+ view.dispatch({
540
+ effects: setDrop.of(pos)
541
+ });
542
+ state = {
543
+ view,
544
+ pos
545
+ };
546
+ return;
547
+ }
548
+ }
549
+ view.dispatch({
550
+ effects: setDrop.of(null)
551
+ });
552
+ });
553
+ },
554
+ cancel: () => {
555
+ reset();
556
+ },
557
+ drop: ({ text, url }) => {
558
+ if (state) {
559
+ onDrop(state.view, state.pos, {
560
+ text,
561
+ url
562
+ });
563
+ }
564
+ reset();
565
+ }
566
+ };
567
+ };
568
+ var handleDrop = (view, pos, event) => {
569
+ const line = view.state.doc.lineAt(pos);
570
+ if (line.text.trim() === "") {
571
+ view.dispatch({
572
+ changes: {
573
+ from: pos,
574
+ insert: `
575
+ ![${event.text}](${event.url})
576
+ `
577
+ },
578
+ effects: setDrop.of(null)
579
+ });
580
+ } else {
581
+ view.dispatch({
582
+ changes: {
583
+ from: pos,
584
+ insert: ` [${event.text}](${event.url})`
585
+ },
586
+ effects: setDrop.of(null)
587
+ });
588
+ }
589
+ };
590
+ var setDrop = StateEffect.define();
591
+ var dropField = StateField.define({
592
+ create: () => Decoration.none,
593
+ update: (decorations, tr) => {
594
+ for (const effect of tr.effects) {
595
+ if (effect.is(setDrop)) {
596
+ if (effect.value === null) {
597
+ return Decoration.none;
598
+ }
599
+ return Decoration.set([
600
+ Decoration.widget({
601
+ widget: new class extends WidgetType {
602
+ toDOM() {
603
+ const dom = document.createElement("span");
604
+ dom.className = "cm-drop-cursor";
605
+ dom.style.borderLeft = "2px solid var(--dx-accentSurface)";
606
+ dom.style.display = "inline-block";
607
+ dom.style.height = "1em";
608
+ dom.style.verticalAlign = "middle";
609
+ return dom;
610
+ }
611
+ }(),
612
+ side: 0
613
+ }).range(effect.value)
614
+ ]);
615
+ }
616
+ }
617
+ return decorations.map(tr.changes);
618
+ },
619
+ provide: (field) => EditorView.decorations.from(field)
620
+ });
621
+
622
+ // src/hooks/useContainerDebug.tsx
623
+ import React7, { forwardRef as forwardRef6, useMemo as useMemo5, useRef as useRef5 } from "react";
624
+ import { createPortal as createPortal2 } from "react-dom";
625
+ import { Json } from "@dxos/react-ui-syntax-highlighter";
626
+ import { mx as mx7 } from "@dxos/ui-theme";
627
+
628
+ // src/components/Mosaic/Mosaic.tsx
629
+ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
630
+ import { draggable, dropTargetForElements, monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
631
+ import { preserveOffsetOnSource } from "@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source";
632
+ import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
633
+ import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
634
+ import { attachClosestEdge, extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
635
+ import { DropIndicator as NativeDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box";
636
+ import { composeRefs, useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
637
+ import { createContext as createContext3 } from "@radix-ui/react-context";
638
+ import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
639
+ import { Slot as Slot3 } from "@radix-ui/react-slot";
640
+ import { bind } from "bind-event-listener";
641
+ import React6, { forwardRef as forwardRef5, useCallback as useCallback2, useEffect as useEffect2, useLayoutEffect, useMemo as useMemo4, useRef as useRef4, useState as useState3 } from "react";
642
+ import { createPortal } from "react-dom";
643
+ import { log as log2 } from "@dxos/log";
644
+ import { mx as mx6 } from "@dxos/ui-theme";
645
+ import { isTruthy } from "@dxos/util";
646
+
647
+ // src/components/Scrollable/Scrollable.tsx
648
+ import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
649
+ import React4, { forwardRef as forwardRef3, useEffect, useMemo, useRef as useRef3 } from "react";
650
+ import { mx as mx4 } from "@dxos/ui-theme";
651
+ import "overlayscrollbars/styles/overlayscrollbars.css";
652
+ var defaultOptions = {
653
+ scrollbars: {
654
+ autoHide: "leave",
655
+ autoHideDelay: 1e3,
656
+ autoHideSuspend: true
657
+ }
658
+ };
659
+ var Scrollable = /* @__PURE__ */ forwardRef3(({ classNames, axis = "vertical", padding, options: optionsProp = defaultOptions, onScroll, viewportRef, ...props }, forwardedRef) => {
660
+ const osRef = useRef3(null);
661
+ const options = useMemo(() => {
662
+ const options2 = {
663
+ ...optionsProp
664
+ };
665
+ if (axis) {
666
+ options2.overflow = {
667
+ x: axis === "horizontal" ? "scroll" : "hidden",
668
+ y: axis === "vertical" ? "scroll" : "hidden"
669
+ };
670
+ }
671
+ return options2;
672
+ }, [
673
+ axis,
674
+ optionsProp
675
+ ]);
676
+ useEffect(() => {
677
+ const hostElement = osRef.current?.getElement();
678
+ if (forwardedRef) {
679
+ if (typeof forwardedRef === "function") {
680
+ forwardedRef(hostElement ?? null);
681
+ } else {
682
+ forwardedRef.current = hostElement ?? null;
683
+ }
684
+ }
685
+ });
686
+ useEffect(() => {
687
+ const instance = osRef.current?.osInstance();
688
+ if (viewportRef) {
689
+ viewportRef.current = instance?.elements().viewport ?? null;
690
+ }
691
+ }, [
692
+ osRef,
693
+ viewportRef
694
+ ]);
695
+ const events = useMemo(() => {
696
+ if (!onScroll) {
697
+ return null;
698
+ }
699
+ return {
700
+ scroll: (_, event) => {
701
+ onScroll(event);
702
+ }
703
+ };
704
+ }, [
705
+ onScroll
706
+ ]);
707
+ return /* @__PURE__ */ React4.createElement(OverlayScrollbarsComponent, {
708
+ ...props,
709
+ className: mx4(padding && axis === "vertical" ? "pli-3" : "pbe-3", classNames),
710
+ options,
711
+ events,
712
+ ref: osRef
713
+ });
714
+ });
715
+
716
+ // src/components/Stack/Stack.tsx
717
+ import { useVirtualizer } from "@tanstack/react-virtual";
718
+ import React5, { Fragment, forwardRef as forwardRef4 } from "react";
719
+ import { invariant } from "@dxos/invariant";
720
+ import { mx as mx5 } from "@dxos/ui-theme";
721
+
722
+ // src/hooks/useEventHandlerAdapter.ts
723
+ import { useMemo as useMemo2 } from "react";
724
+ import { log } from "@dxos/log";
725
+ import { arrayMove } from "@dxos/util";
726
+ var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-mosaic/src/hooks/useEventHandlerAdapter.ts";
727
+ var useEventHandlerAdapter = ({ items, getId, get, make, onChange, ...props }) => {
728
+ return useMemo2(() => ({
729
+ ...props,
730
+ onTake: ({ source }, cb) => {
731
+ log.info("onTake", {
732
+ source
733
+ }, {
734
+ F: __dxlog_file,
735
+ L: 58,
736
+ S: void 0,
737
+ C: (f, a) => f(...a)
738
+ });
739
+ const mutate = (items2) => {
740
+ const from = items2.findIndex((item) => getId(item) === source.id);
741
+ if (from !== -1) {
742
+ items2.splice(from, 1);
743
+ }
744
+ };
745
+ if (onChange) {
746
+ onChange(mutate);
747
+ } else {
748
+ mutate(items);
749
+ }
750
+ void cb(source.data);
751
+ },
752
+ onDrop: ({ source, target }) => {
753
+ const to = target?.type === "tile" || target?.type === "placeholder" ? target.location : -1;
754
+ log.info("onDrop", {
755
+ source,
756
+ target,
757
+ to
758
+ }, {
759
+ F: __dxlog_file,
760
+ L: 76,
761
+ S: void 0,
762
+ C: (f, a) => f(...a)
763
+ });
764
+ const mutate = (items2) => {
765
+ const from = items2.findIndex((item) => getId(item) === source.id);
766
+ if (to !== -1) {
767
+ if (from !== -1) {
768
+ arrayMove(items2, from, to);
769
+ } else {
770
+ items2.splice(to, 0, make(get(source.data)));
771
+ }
772
+ }
773
+ };
774
+ if (onChange) {
775
+ onChange(mutate);
776
+ } else {
777
+ mutate(items);
778
+ }
779
+ }
780
+ }), [
781
+ items,
782
+ onChange
783
+ ]);
784
+ };
785
+
786
+ // src/hooks/useVisibleItems.ts
787
+ import { useMemo as useMemo3 } from "react";
788
+ var useVisibleItems = ({ id, items, dragging, getId }) => {
789
+ const visibleItems = useMemo3(() => {
790
+ if (!items || !dragging || id !== dragging.containerId) {
791
+ return items ?? [];
792
+ }
793
+ const idx = items.findIndex((item) => getId(item) === dragging.id);
794
+ if (idx === -1) {
795
+ return items;
796
+ }
797
+ const visibleItems2 = items.slice();
798
+ visibleItems2.splice(idx, 1);
799
+ return visibleItems2;
800
+ }, [
801
+ id,
802
+ items,
803
+ dragging,
804
+ getId
805
+ ]);
806
+ return visibleItems;
807
+ };
808
+
809
+ // src/components/Stack/Stack.tsx
810
+ var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-mosaic/src/components/Stack/Stack.tsx";
811
+ var StackInner = /* @__PURE__ */ forwardRef4(({ className, classNames, role = "list", axis = "vertical", draggable: draggable2 = true, items, getId, Tile: Tile2, debug, ...props }, forwardedRef) => {
812
+ invariant(Tile2, void 0, {
813
+ F: __dxlog_file2,
814
+ L: 44,
815
+ S: void 0,
816
+ A: [
817
+ "Tile",
818
+ ""
819
+ ]
820
+ });
821
+ const { id, dragging } = useContainerContext(StackInner.displayName);
822
+ const visibleItems = useVisibleItems({
823
+ id,
824
+ items,
825
+ dragging: dragging?.source.data,
826
+ getId
827
+ });
828
+ return /* @__PURE__ */ React5.createElement("div", {
829
+ ...props,
830
+ role,
831
+ className: mx5("flex", axis === "horizontal" && "bs-full [&>*]:shrink-0", axis === "vertical" && "flex-col", classNames, className),
832
+ ref: forwardedRef
833
+ }, /* @__PURE__ */ React5.createElement(Placeholder, {
834
+ axis,
835
+ location: 0.5
836
+ }), visibleItems?.map((item, index) => /* @__PURE__ */ React5.createElement(Fragment, {
837
+ key: getId(item)
838
+ }, /* @__PURE__ */ React5.createElement(Tile2, {
839
+ id: getId(item),
840
+ data: item,
841
+ location: index + 1,
842
+ draggable: draggable2,
843
+ debug
844
+ }), /* @__PURE__ */ React5.createElement(Placeholder, {
845
+ axis,
846
+ location: index + 1.5
847
+ }))));
848
+ });
849
+ StackInner.displayName = "Stack";
850
+ var Stack = StackInner;
851
+ var VirtualStackInner = /* @__PURE__ */ forwardRef4(({ className, classNames, role = "list", axis = "vertical", items, getId, Tile: Tile2, estimateSize, getScrollElement, overscan = 8, onChange, debug, ...props }, forwardedRef) => {
852
+ invariant(Tile2, void 0, {
853
+ F: __dxlog_file2,
854
+ L: 106,
855
+ S: void 0,
856
+ A: [
857
+ "Tile",
858
+ ""
859
+ ]
860
+ });
861
+ const { id, dragging } = useContainerContext(VirtualStackInner.displayName);
862
+ const visibleItems = useVisibleItems({
863
+ id,
864
+ items,
865
+ dragging: dragging?.source.data,
866
+ getId
867
+ });
868
+ const virtualizer = useVirtualizer({
869
+ count: visibleItems.length * 2 + 1,
870
+ estimateSize,
871
+ getScrollElement,
872
+ overscan,
873
+ onChange
874
+ });
875
+ const virtualItems = virtualizer.getVirtualItems();
876
+ return /* @__PURE__ */ React5.createElement("div", {
877
+ ...props,
878
+ role,
879
+ className: mx5("flex", axis === "horizontal" && "bs-full [&>*]:shrink-0", axis === "vertical" && "flex-col", classNames, className),
880
+ style: {
881
+ position: "relative",
882
+ ...axis === "vertical" ? {
883
+ width: "100%",
884
+ height: virtualizer.getTotalSize()
885
+ } : {
886
+ width: virtualizer.getTotalSize(),
887
+ height: "100%"
888
+ }
889
+ },
890
+ ref: forwardedRef
891
+ }, virtualItems.map((virtualItem) => {
892
+ const data = visibleItems[Math.floor(virtualItem.index / 2)];
893
+ return /* @__PURE__ */ React5.createElement("div", {
894
+ key: virtualItem.key,
895
+ "data-index": virtualItem.index,
896
+ style: {
897
+ position: "absolute",
898
+ top: 0,
899
+ left: 0,
900
+ ...axis === "vertical" ? {
901
+ width: "100%",
902
+ transform: `translateY(${virtualItem.start}px)`
903
+ } : {
904
+ height: "100%",
905
+ transform: `translateX(${virtualItem.start}px)`
906
+ }
907
+ },
908
+ ref: virtualizer.measureElement
909
+ }, virtualItem.index % 2 === 0 ? /* @__PURE__ */ React5.createElement(Placeholder, {
910
+ axis,
911
+ location: Math.floor(virtualItem.index / 2) + 0.5
912
+ }) : /* @__PURE__ */ React5.createElement(Tile2, {
913
+ id: getId(data),
914
+ data,
915
+ location: Math.floor(virtualItem.index / 2) + 1,
916
+ debug
917
+ }));
918
+ }));
919
+ });
920
+ VirtualStackInner.displayName = "VirtualStackInner";
921
+ var VirtualStack = VirtualStackInner;
922
+ var Placeholder = (props) => {
923
+ return /* @__PURE__ */ React5.createElement(Mosaic.Placeholder, {
924
+ ...props,
925
+ classNames: styles3.placeholder.root
926
+ }, /* @__PURE__ */ React5.createElement("div", {
927
+ className: mx5("flex bs-full bg-baseSurface border border-dashed border-separator rounded-sm", styles3.placeholder.content)
928
+ }));
929
+ };
930
+ Placeholder.displayName = "Placeholder";
931
+
932
+ // src/components/Mosaic/Mosaic.tsx
933
+ var __dxlog_file3 = "/__w/dxos/dxos/packages/ui/react-ui-mosaic/src/components/Mosaic/Mosaic.tsx";
934
+ var getSourceData = (source) => {
935
+ return source.data.type === "tile" ? source.data : null;
936
+ };
937
+ var [RootContextProvider, useRootContext] = createContext3("MosaicRoot");
938
+ var ROOT_DEBUG_ATTR = "mosaic-debug";
939
+ var Root = /* @__PURE__ */ forwardRef5(({ classNames, children, asChild, debug }, forwardedRef) => {
940
+ const rootRef = useRef4(null);
941
+ const composedRef = useComposedRefs2(rootRef, forwardedRef);
942
+ const Root2 = asChild ? Slot3 : Primitive2.div;
943
+ const [handlers, setHandlers] = useState3({});
944
+ const [dragging, setDragging] = useState3();
945
+ const getSourceHandler = useCallback2((source) => {
946
+ const data = source.data;
947
+ return {
948
+ data,
949
+ handler: handlers[data.containerId]
950
+ };
951
+ }, [
952
+ handlers
953
+ ]);
954
+ const getTargetHandler = useCallback2((location) => {
955
+ for (const target of location.current.dropTargets) {
956
+ const data = target.data;
957
+ let containerId;
958
+ switch (data.type) {
959
+ case "tile":
960
+ case "placeholder":
961
+ containerId = data.containerId;
962
+ break;
963
+ case "container":
964
+ containerId = data.id;
965
+ break;
966
+ }
967
+ const handler = handlers[containerId];
968
+ if (handler) {
969
+ return {
970
+ data,
971
+ handler
972
+ };
973
+ }
974
+ }
975
+ return {};
976
+ }, [
977
+ handlers
978
+ ]);
979
+ useEffect2(() => {
980
+ const handleChange = ({ source, location }) => {
981
+ const { data: sourceData } = getSourceHandler(source);
982
+ const { data: targetData, handler } = getTargetHandler(location);
983
+ setDragging((dragging2) => {
984
+ dragging2?.target?.handler?.onCancel?.();
985
+ return {
986
+ source: {
987
+ data: sourceData,
988
+ handler: handlers[sourceData.containerId],
989
+ // TOOD(burdon): Check id matches.
990
+ container: location.initial.dropTargets.find((target) => target.data.type === "container")?.element
991
+ },
992
+ target: targetData && {
993
+ data: targetData,
994
+ handler
995
+ }
996
+ };
997
+ });
998
+ };
999
+ const handleCancel = () => {
1000
+ setDragging((dragging2) => {
1001
+ requestAnimationFrame(() => {
1002
+ dragging2?.target?.handler?.onCancel?.();
1003
+ dragging2?.source?.container?.dispatchEvent(new CustomEvent("dnd:cancel", {
1004
+ bubbles: true
1005
+ }));
1006
+ });
1007
+ return void 0;
1008
+ });
1009
+ };
1010
+ let noTargetTimeout;
1011
+ return combine(monitorForElements({
1012
+ /**
1013
+ * Dragging started within any container.
1014
+ */
1015
+ onDragStart: ({ source, location }) => {
1016
+ log2("Root.onDragStart", {
1017
+ source: source.data,
1018
+ location: location.current.dropTargets.map((target) => target.data)
1019
+ }, {
1020
+ F: __dxlog_file3,
1021
+ L: 215,
1022
+ S: void 0,
1023
+ C: (f, a) => f(...a)
1024
+ });
1025
+ handleChange({
1026
+ source,
1027
+ location
1028
+ });
1029
+ },
1030
+ /**
1031
+ * Dragging entered a new container.
1032
+ */
1033
+ onDropTargetChange: ({ source, location }) => {
1034
+ clearTimeout(noTargetTimeout);
1035
+ log2("Root.onDropTargetChange", {
1036
+ source: source.data,
1037
+ location: location.current.dropTargets.map((target) => target.data)
1038
+ }, {
1039
+ F: __dxlog_file3,
1040
+ L: 228,
1041
+ S: void 0,
1042
+ C: (f, a) => f(...a)
1043
+ });
1044
+ if (location.current.dropTargets.length === 0) {
1045
+ noTargetTimeout = setTimeout(() => setDragging(void 0), 1e3);
1046
+ } else {
1047
+ handleChange({
1048
+ source,
1049
+ location
1050
+ });
1051
+ }
1052
+ },
1053
+ /**
1054
+ * Dragging within any container.
1055
+ */
1056
+ onDrag: ({ source, location }) => {
1057
+ const { data } = getSourceHandler(source);
1058
+ const { handler } = getTargetHandler(location);
1059
+ if (handler) {
1060
+ const { clientX: x, clientY: y } = location.current.input;
1061
+ handler.onDrag?.({
1062
+ source: data,
1063
+ position: {
1064
+ x,
1065
+ y
1066
+ }
1067
+ });
1068
+ }
1069
+ },
1070
+ /**
1071
+ * Dragging ended.
1072
+ */
1073
+ onDrop: ({ source, location }) => {
1074
+ log2.info("Root.onDrop", {
1075
+ source: source.data,
1076
+ location: location.current.dropTargets.map((target) => target.data)
1077
+ }, {
1078
+ F: __dxlog_file3,
1079
+ L: 257,
1080
+ S: void 0,
1081
+ C: (f, a) => f(...a)
1082
+ });
1083
+ const { data: sourceData, handler: sourceHandler } = getSourceHandler(source);
1084
+ if (!sourceHandler) {
1085
+ log2.warn("invalid source", {
1086
+ source: sourceData,
1087
+ handlers: Object.keys(handlers)
1088
+ }, {
1089
+ F: __dxlog_file3,
1090
+ L: 265,
1091
+ S: void 0,
1092
+ C: (f, a) => f(...a)
1093
+ });
1094
+ return;
1095
+ }
1096
+ try {
1097
+ if (location.current.dropTargets.length === 0) {
1098
+ log2.info("cancelled", void 0, {
1099
+ F: __dxlog_file3,
1100
+ L: 280,
1101
+ S: void 0,
1102
+ C: (f, a) => f(...a)
1103
+ });
1104
+ } else {
1105
+ const { data: targetData, handler: targetHandler } = getTargetHandler(location);
1106
+ if (!targetHandler) {
1107
+ log2.warn("invalid target", {
1108
+ source: sourceData,
1109
+ location,
1110
+ handlers: Object.keys(handlers)
1111
+ }, {
1112
+ F: __dxlog_file3,
1113
+ L: 285,
1114
+ S: void 0,
1115
+ C: (f, a) => f(...a)
1116
+ });
1117
+ return;
1118
+ }
1119
+ if (sourceHandler === targetHandler) {
1120
+ targetHandler.onDrop?.({
1121
+ source: sourceData,
1122
+ target: targetData
1123
+ });
1124
+ } else {
1125
+ if (!sourceHandler.onTake) {
1126
+ log2.warn("invalid source", {
1127
+ source: sourceData
1128
+ }, {
1129
+ F: __dxlog_file3,
1130
+ L: 301,
1131
+ S: void 0,
1132
+ C: (f, a) => f(...a)
1133
+ });
1134
+ return;
1135
+ }
1136
+ sourceHandler.onTake?.({
1137
+ source: sourceData
1138
+ }, async (object) => {
1139
+ targetHandler.onDrop?.({
1140
+ // TODO(burdon): Change source!!!
1141
+ source: {
1142
+ ...sourceData,
1143
+ data: object
1144
+ },
1145
+ target: targetData
1146
+ });
1147
+ return true;
1148
+ });
1149
+ }
1150
+ }
1151
+ } finally {
1152
+ handleCancel();
1153
+ }
1154
+ }
1155
+ }));
1156
+ }, [
1157
+ handlers,
1158
+ getSourceHandler,
1159
+ getTargetHandler
1160
+ ]);
1161
+ return /* @__PURE__ */ React6.createElement(RootContextProvider, {
1162
+ containers: handlers,
1163
+ addContainer: (container) => setHandlers((containers) => ({
1164
+ ...containers,
1165
+ [container.id]: container
1166
+ })),
1167
+ removeContainer: (id) => setHandlers((containers) => {
1168
+ delete containers[id];
1169
+ return {
1170
+ ...containers
1171
+ };
1172
+ }),
1173
+ dragging
1174
+ }, /* @__PURE__ */ React6.createElement(Root2, {
1175
+ className: mx6("group overflow-hidden", classNames),
1176
+ [`data-${ROOT_DEBUG_ATTR}`]: debug,
1177
+ ref: composedRef
1178
+ }, children));
1179
+ });
1180
+ var [ContainerContextProvider, useContainerContext] = createContext3("MosaicContainer");
1181
+ var CONTAINER_STATE_ATTR = "mosaic-container-state";
1182
+ var CONTAINER_PLACEHOLDER_WIDTH = "--mosaic-placeholder-width";
1183
+ var CONTAINER_PLACEHOLDER_HEIGHT = "--mosaic-placeholder-height";
1184
+ var counter = 0;
1185
+ var Container = /* @__PURE__ */ forwardRef5(({ className, classNames, children, eventHandler: eventHandlerProp, axis = "vertical", asChild, autoScroll: autoscrollElement, withFocus, debug, ...props }, forwardedRef) => {
1186
+ const rootRef = useRef4(null);
1187
+ const composedRef = useComposedRefs2(rootRef, forwardedRef);
1188
+ const Root2 = asChild ? Slot3 : Primitive2.div;
1189
+ const eventHandler = useMemo4(() => eventHandlerProp ?? {
1190
+ id: `mosaic-container-${counter++}`
1191
+ }, [
1192
+ eventHandlerProp
1193
+ ]);
1194
+ const { dragging } = useRootContext(Container.displayName);
1195
+ const [state, setState] = useState3({
1196
+ type: "idle"
1197
+ });
1198
+ const [activeLocation, setActiveLocation] = useState3();
1199
+ const [scrolling, setScrolling] = useState3(false);
1200
+ const { setFocus } = useFocus();
1201
+ useEffect2(() => {
1202
+ if (withFocus) {
1203
+ setFocus?.(state.type === "active" ? "active" : void 0);
1204
+ }
1205
+ }, [
1206
+ setFocus,
1207
+ withFocus,
1208
+ state
1209
+ ]);
1210
+ const { addContainer, removeContainer } = useRootContext(eventHandler.id);
1211
+ useEffect2(() => {
1212
+ addContainer(eventHandler);
1213
+ return () => removeContainer(eventHandler.id);
1214
+ }, [
1215
+ eventHandler
1216
+ ]);
1217
+ const data = useMemo4(() => ({
1218
+ type: "container",
1219
+ id: eventHandler.id
1220
+ }), [
1221
+ eventHandler.id
1222
+ ]);
1223
+ useEffect2(() => {
1224
+ if (!rootRef.current) {
1225
+ return;
1226
+ }
1227
+ let timeout;
1228
+ const handleScroll = () => {
1229
+ setScrolling(true);
1230
+ clearTimeout(timeout);
1231
+ timeout = setTimeout(() => {
1232
+ setScrolling(false);
1233
+ }, 500);
1234
+ };
1235
+ return combine(...[
1236
+ // Autoscroll.
1237
+ // TODO(burdon): Autoscroll doesn't work well horizontally.
1238
+ autoscrollElement && [
1239
+ autoScrollForElements({
1240
+ element: autoscrollElement,
1241
+ canScroll: ({ element: _ }) => {
1242
+ return true;
1243
+ },
1244
+ getAllowedAxis: () => axis,
1245
+ getConfiguration: () => ({
1246
+ maxScrollSpeed: "fast"
1247
+ })
1248
+ }),
1249
+ bind(autoscrollElement, {
1250
+ type: "scroll",
1251
+ listener: handleScroll
1252
+ }),
1253
+ () => setScrolling(false)
1254
+ ],
1255
+ // Target.
1256
+ dropTargetForElements({
1257
+ element: rootRef.current,
1258
+ getData: () => data,
1259
+ /**
1260
+ * Test if permitted to drop here.
1261
+ * NOTE: Contained Tile and Placeholder elements do the same.
1262
+ */
1263
+ canDrop: ({ source }) => {
1264
+ const data2 = getSourceData(source);
1265
+ return data2 && eventHandler.canDrop?.({
1266
+ source: data2
1267
+ }) || false;
1268
+ },
1269
+ // TODO(burdon): Provide semantic intent to onDrop.
1270
+ // getDropEffect: () => {
1271
+ // return 'move';
1272
+ // },
1273
+ /**
1274
+ * Dragging started in this container.
1275
+ */
1276
+ onDragStart: ({ source }) => {
1277
+ const sourceData = source.data;
1278
+ setState({
1279
+ type: "active",
1280
+ bounds: sourceData.bounds
1281
+ });
1282
+ },
1283
+ /**
1284
+ * Dragging entered this container.
1285
+ */
1286
+ onDragEnter: ({ source }) => {
1287
+ const sourceData = source.data;
1288
+ setState({
1289
+ type: "active",
1290
+ bounds: sourceData.bounds
1291
+ });
1292
+ },
1293
+ /**
1294
+ * Dragging left this container.
1295
+ * NOTE: If the container isn't full-height, then when the dragged item is temporarily removed the container will shrink,
1296
+ * triggering `onDragLeave`, which then causes the item to be added and removed continually (flickering).
1297
+ */
1298
+ onDragLeave: ({ source }) => {
1299
+ const sourceData = source.data;
1300
+ if (sourceData.containerId !== eventHandler.id) {
1301
+ setState({
1302
+ type: "idle"
1303
+ });
1304
+ }
1305
+ },
1306
+ /**
1307
+ * Dropped in this container.
1308
+ */
1309
+ onDrop: () => {
1310
+ setState({
1311
+ type: "idle"
1312
+ });
1313
+ }
1314
+ }),
1315
+ /**
1316
+ * Custom event for dragging cancellation.
1317
+ */
1318
+ bind(rootRef.current, {
1319
+ type: "dnd:cancel",
1320
+ listener: () => {
1321
+ setState({
1322
+ type: "idle"
1323
+ });
1324
+ }
1325
+ })
1326
+ ].filter(isTruthy).flatMap((x) => x));
1327
+ }, [
1328
+ rootRef,
1329
+ eventHandler,
1330
+ data,
1331
+ autoscrollElement
1332
+ ]);
1333
+ return /* @__PURE__ */ React6.createElement(ContainerContextProvider, {
1334
+ id: eventHandler.id,
1335
+ eventHandler,
1336
+ axis,
1337
+ state,
1338
+ dragging: state.type === "active" ? dragging : void 0,
1339
+ scrolling,
1340
+ activeLocation,
1341
+ setActiveLocation
1342
+ }, /* @__PURE__ */ React6.createElement(Root2, {
1343
+ className: mx6("bs-full", className, classNames),
1344
+ style: {
1345
+ [CONTAINER_PLACEHOLDER_WIDTH]: state.type === "active" && state.bounds ? `${state.bounds.width}px` : "0px",
1346
+ [CONTAINER_PLACEHOLDER_HEIGHT]: state.type === "active" && state.bounds ? `${state.bounds.height}px` : "0px"
1347
+ },
1348
+ ...props,
1349
+ [`data-${CONTAINER_STATE_ATTR}`]: state.type,
1350
+ ref: composedRef
1351
+ }, children), debug?.());
1352
+ });
1353
+ Container.displayName = "MosaicContainer";
1354
+ var [TileContextProvider, useTileContext] = createContext3("MosaicTile");
1355
+ var TILE_STATE_ATTR = "mosaic-tile-state";
1356
+ var Tile = /* @__PURE__ */ forwardRef5(({ className, classNames, children, asChild, dragHandle, allowedEdges: allowedEdgesProp, location, id, data: dataProp, debug: _ }, forwardedRef) => {
1357
+ const rootRef = useRef4(null);
1358
+ const composedRef = composeRefs(rootRef, forwardedRef);
1359
+ const Root2 = asChild ? Slot3 : Primitive2.div;
1360
+ const { id: containerId, eventHandler, axis, scrolling, setActiveLocation } = useContainerContext(Tile.displayName);
1361
+ const [state, setState] = useState3({
1362
+ type: "idle"
1363
+ });
1364
+ const allowedEdges = useMemo4(() => allowedEdgesProp || (axis === "vertical" ? [
1365
+ "top",
1366
+ "bottom"
1367
+ ] : [
1368
+ "left",
1369
+ "right"
1370
+ ]), [
1371
+ allowedEdgesProp,
1372
+ axis
1373
+ ]);
1374
+ const data = useMemo4(() => ({
1375
+ type: "tile",
1376
+ id,
1377
+ containerId,
1378
+ data: dataProp,
1379
+ location
1380
+ }), [
1381
+ containerId,
1382
+ location,
1383
+ dataProp
1384
+ ]);
1385
+ useLayoutEffect(() => {
1386
+ const root = rootRef.current;
1387
+ if (!root || !containerId || scrolling) {
1388
+ return;
1389
+ }
1390
+ const handleChange = ({ self, source }) => {
1391
+ if (source.data.id !== dataProp.id) {
1392
+ const closestEdge = extractClosestEdge(self.data);
1393
+ const location2 = data.location + (closestEdge === "top" || closestEdge === "left" ? -0.5 : 0.5);
1394
+ setActiveLocation(location2);
1395
+ setState({
1396
+ type: "target",
1397
+ closestEdge
1398
+ });
1399
+ }
1400
+ };
1401
+ return combine(
1402
+ // Source.
1403
+ draggable({
1404
+ element: root,
1405
+ dragHandle: dragHandle && state.type !== "preview" ? dragHandle : void 0,
1406
+ canDrag: () => true,
1407
+ getInitialData: () => data,
1408
+ onGenerateDragPreview: ({ location: location2, nativeSetDragImage }) => {
1409
+ setCustomNativeDragPreview({
1410
+ nativeSetDragImage,
1411
+ getOffset: preserveOffsetOnSource({
1412
+ element: root,
1413
+ input: location2.current.input
1414
+ }),
1415
+ render: ({ container }) => {
1416
+ data.bounds = root.getBoundingClientRect();
1417
+ setState({
1418
+ type: "preview",
1419
+ container,
1420
+ rect: root.getBoundingClientRect()
1421
+ });
1422
+ return () => setState({
1423
+ type: "dragging"
1424
+ });
1425
+ }
1426
+ });
1427
+ },
1428
+ onDragStart: () => {
1429
+ setState({
1430
+ type: "dragging"
1431
+ });
1432
+ },
1433
+ onDrop: () => {
1434
+ setState({
1435
+ type: "idle"
1436
+ });
1437
+ }
1438
+ }),
1439
+ // Target.
1440
+ dropTargetForElements({
1441
+ element: root,
1442
+ getData: ({ input, element }) => attachClosestEdge(data, {
1443
+ input,
1444
+ element,
1445
+ allowedEdges
1446
+ }),
1447
+ canDrop: ({ source }) => {
1448
+ const data2 = getSourceData(source);
1449
+ return data2 && eventHandler.canDrop?.({
1450
+ source: data2
1451
+ }) || false;
1452
+ },
1453
+ onDragEnter: ({ self, source }) => {
1454
+ handleChange({
1455
+ self,
1456
+ source
1457
+ });
1458
+ },
1459
+ onDragLeave: () => {
1460
+ setState({
1461
+ type: "idle"
1462
+ });
1463
+ setActiveLocation(void 0);
1464
+ },
1465
+ onDrag: ({ self, source }) => {
1466
+ handleChange({
1467
+ self,
1468
+ source
1469
+ });
1470
+ },
1471
+ onDrop: () => {
1472
+ setState({
1473
+ type: "idle"
1474
+ });
1475
+ setActiveLocation(void 0);
1476
+ }
1477
+ })
1478
+ );
1479
+ }, [
1480
+ rootRef,
1481
+ dragHandle,
1482
+ eventHandler,
1483
+ data,
1484
+ scrolling,
1485
+ allowedEdges,
1486
+ setActiveLocation
1487
+ ]);
1488
+ return /* @__PURE__ */ React6.createElement(TileContextProvider, {
1489
+ state
1490
+ }, /* @__PURE__ */ React6.createElement(Root2, {
1491
+ [`data-${TILE_STATE_ATTR}`]: state.type,
1492
+ role: "listitem",
1493
+ className: mx6("relative", className, classNames),
1494
+ ref: composedRef
1495
+ }, children), state.type === "preview" && /* @__PURE__ */ createPortal(/* @__PURE__ */ React6.createElement(Root2, {
1496
+ // NOTE: Use to control appearance while dragging.
1497
+ [`data-${TILE_STATE_ATTR}`]: state.type,
1498
+ // TODO(burdon): Configure drop animation.
1499
+ className: mx6("relative", className, classNames),
1500
+ style: {
1501
+ width: `${state.rect.width}px`,
1502
+ height: `${state.rect.height}px`
1503
+ }
1504
+ }, children), state.container));
1505
+ });
1506
+ Tile.displayName = "MosaicTile";
1507
+ var PLACEHOLDER_AXIS_ATTR = "mosaic-placeholder-axis";
1508
+ var PLACEHOLDER_STATE_ATTR = "mosaic-placeholder-state";
1509
+ var Placeholder2 = ({ classNames, children, asChild, axis = "vertical", location }) => {
1510
+ const rootRef = useRef4(null);
1511
+ const Root2 = asChild ? Slot3 : Primitive2.div;
1512
+ const { id: containerId, eventHandler, scrolling, activeLocation, setActiveLocation } = useContainerContext(Placeholder2.displayName);
1513
+ const data = useMemo4(() => ({
1514
+ type: "placeholder",
1515
+ containerId,
1516
+ location
1517
+ }), [
1518
+ containerId,
1519
+ location
1520
+ ]);
1521
+ useLayoutEffect(() => {
1522
+ const root = rootRef.current;
1523
+ if (!root || scrolling) {
1524
+ return;
1525
+ }
1526
+ return dropTargetForElements({
1527
+ element: root,
1528
+ getData: () => data,
1529
+ canDrop: ({ source }) => {
1530
+ const data2 = getSourceData(source);
1531
+ return data2 && eventHandler.canDrop?.({
1532
+ source: data2
1533
+ }) || false;
1534
+ },
1535
+ onDragEnter: () => {
1536
+ setActiveLocation(data.location);
1537
+ },
1538
+ onDragLeave: () => {
1539
+ setActiveLocation(void 0);
1540
+ },
1541
+ onDrop: () => {
1542
+ setActiveLocation(void 0);
1543
+ }
1544
+ });
1545
+ }, [
1546
+ rootRef,
1547
+ data,
1548
+ scrolling,
1549
+ setActiveLocation
1550
+ ]);
1551
+ return /* @__PURE__ */ React6.createElement(Root2, {
1552
+ [`data-${PLACEHOLDER_AXIS_ATTR}`]: axis,
1553
+ [`data-${PLACEHOLDER_STATE_ATTR}`]: data.location === activeLocation ? "active" : "idle",
1554
+ role: "none",
1555
+ className: mx6("relative", classNames),
1556
+ ref: rootRef
1557
+ }, children);
1558
+ };
1559
+ Placeholder2.displayName = "MosaicPlaceholder";
1560
+ var DropIndicator = (props) => {
1561
+ const { state } = useTileContext(DropIndicator.displayName);
1562
+ return state.type === "target" && state.closestEdge ? /* @__PURE__ */ React6.createElement(NativeDropIndicator, {
1563
+ ...props,
1564
+ edge: state.closestEdge
1565
+ }) : null;
1566
+ };
1567
+ DropIndicator.displayName = "MosaicDropIndicator";
1568
+ var Mosaic = {
1569
+ Root,
1570
+ Container,
1571
+ Tile,
1572
+ Placeholder: Placeholder2,
1573
+ DropIndicator,
1574
+ // TODO(burdon): Move out of Mosaic namespace?
1575
+ Viewport: Scrollable,
1576
+ Stack,
1577
+ VirtualStack
1578
+ };
1579
+
1580
+ // src/hooks/useContainerDebug.tsx
1581
+ var useContainerDebug = (debug) => {
1582
+ const debugRef = useRef5(null);
1583
+ return useMemo5(() => {
1584
+ if (!debug) {
1585
+ return [
1586
+ () => null,
1587
+ void 0
1588
+ ];
1589
+ }
1590
+ return [
1591
+ ({ classNames }) => /* @__PURE__ */ React7.createElement("div", {
1592
+ role: "none",
1593
+ className: mx7("overflow-hidden", classNames),
1594
+ ref: debugRef
1595
+ }),
1596
+ () => debugRef.current && /* @__PURE__ */ createPortal2(/* @__PURE__ */ React7.createElement(ContainerInfo, null), debugRef.current)
1597
+ ];
1598
+ }, [
1599
+ debug,
1600
+ debugRef
1601
+ ]);
1602
+ };
1603
+ var ContainerInfo = /* @__PURE__ */ forwardRef6(({ classNames }, forwardedRef) => {
1604
+ const { id, state, activeLocation, scrolling } = useContainerContext(ContainerInfo.displayName);
1605
+ const counter2 = useRef5(0);
1606
+ return /* @__PURE__ */ React7.createElement(Json, {
1607
+ data: {
1608
+ id,
1609
+ activeLocation,
1610
+ scrolling,
1611
+ state,
1612
+ count: counter2.current++
1613
+ },
1614
+ classNames: mx7("text-xs", classNames),
1615
+ ref: forwardedRef
1616
+ });
1617
+ });
1618
+ ContainerInfo.displayName = "ContainerInfo";
1619
+
1620
+ export {
1621
+ styles,
1622
+ Image,
1623
+ Card,
1624
+ styles2,
1625
+ useFocus,
1626
+ Focus,
1627
+ styles3,
1628
+ dropHandler,
1629
+ useContainerDebug,
1630
+ useEventHandlerAdapter,
1631
+ useVisibleItems,
1632
+ Stack,
1633
+ VirtualStack,
1634
+ useRootContext,
1635
+ useContainerContext,
1636
+ useTileContext,
1637
+ Mosaic
1638
+ };
1639
+ //# sourceMappingURL=chunk-4VDZJ3HV.mjs.map