@dxos/react-ui-mosaic 0.8.4-main.2244d791bb → 0.8.4-main.422d1c7879

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 (114) hide show
  1. package/dist/lib/browser/{chunk-XNANTBOP.mjs → chunk-33NNDFD6.mjs} +242 -615
  2. package/dist/lib/browser/chunk-33NNDFD6.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +174 -154
  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 +57 -34
  9. package/dist/lib/browser/testing/index.mjs.map +3 -3
  10. package/dist/lib/node-esm/{chunk-LWXG4JVG.mjs → chunk-Y4LG7O67.mjs} +242 -615
  11. package/dist/lib/node-esm/chunk-Y4LG7O67.mjs.map +7 -0
  12. package/dist/lib/node-esm/index.mjs +174 -154
  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 +57 -34
  18. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  19. package/dist/types/src/components/Board/Board.d.ts +10 -12
  20. package/dist/types/src/components/Board/Board.d.ts.map +1 -1
  21. package/dist/types/src/components/Board/Board.stories.d.ts +9 -5
  22. package/dist/types/src/components/Board/Board.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/Board/Column.d.ts +20 -15
  24. package/dist/types/src/components/Board/Column.d.ts.map +1 -1
  25. package/dist/types/src/components/Board/Item.d.ts +3 -0
  26. package/dist/types/src/components/Board/Item.d.ts.map +1 -1
  27. package/dist/types/src/components/Focus/Focus.d.ts +1 -25
  28. package/dist/types/src/components/Focus/Focus.d.ts.map +1 -1
  29. package/dist/types/src/components/Focus/index.d.ts +0 -1
  30. package/dist/types/src/components/Focus/index.d.ts.map +1 -1
  31. package/dist/types/src/components/Mosaic/Container.d.ts +16 -13
  32. package/dist/types/src/components/Mosaic/Container.d.ts.map +1 -1
  33. package/dist/types/src/components/Mosaic/Mosaic.d.ts +12 -27
  34. package/dist/types/src/components/Mosaic/Mosaic.d.ts.map +1 -1
  35. package/dist/types/src/components/Mosaic/Placeholder.d.ts +2 -2
  36. package/dist/types/src/components/Mosaic/Placeholder.d.ts.map +1 -1
  37. package/dist/types/src/components/Mosaic/Root.d.ts +5 -6
  38. package/dist/types/src/components/Mosaic/Root.d.ts.map +1 -1
  39. package/dist/types/src/components/Mosaic/Stack.d.ts +6 -5
  40. package/dist/types/src/components/Mosaic/Stack.d.ts.map +1 -1
  41. package/dist/types/src/components/Mosaic/Stack.stories.d.ts +11 -0
  42. package/dist/types/src/components/Mosaic/Stack.stories.d.ts.map +1 -1
  43. package/dist/types/src/components/Mosaic/Tile.d.ts +14 -9
  44. package/dist/types/src/components/Mosaic/Tile.d.ts.map +1 -1
  45. package/dist/types/src/components/index.d.ts +0 -2
  46. package/dist/types/src/components/index.d.ts.map +1 -1
  47. package/dist/types/src/hooks/useDefaultColumnEventHandler.d.ts.map +1 -1
  48. package/dist/types/src/playwright/board-manager.d.ts.map +1 -1
  49. package/dist/types/src/playwright/index.d.ts +9 -0
  50. package/dist/types/src/playwright/index.d.ts.map +1 -0
  51. package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
  52. package/dist/types/src/testing/CardContainer.d.ts +4 -3
  53. package/dist/types/src/testing/CardContainer.d.ts.map +1 -1
  54. package/dist/types/src/testing/DefaultStackTile.d.ts.map +1 -1
  55. package/dist/types/src/testing/types.d.ts.map +1 -1
  56. package/dist/types/src/translations.d.ts +3 -2
  57. package/dist/types/src/translations.d.ts.map +1 -1
  58. package/dist/types/tsconfig.tsbuildinfo +1 -1
  59. package/package.json +33 -29
  60. package/src/AUDIT.md +106 -0
  61. package/src/components/Board/Board.stories.tsx +43 -36
  62. package/src/components/Board/Board.tsx +11 -14
  63. package/src/components/Board/Column.tsx +144 -113
  64. package/src/components/Board/Item.tsx +72 -41
  65. package/src/components/Focus/Focus.tsx +2 -91
  66. package/src/components/Focus/index.ts +0 -2
  67. package/src/components/Mosaic/Container.tsx +53 -27
  68. package/src/components/Mosaic/Placeholder.tsx +8 -8
  69. package/src/components/Mosaic/Root.tsx +199 -205
  70. package/src/components/Mosaic/Stack.stories.tsx +125 -69
  71. package/src/components/Mosaic/Stack.tsx +150 -55
  72. package/src/components/Mosaic/Tile.tsx +46 -39
  73. package/src/components/Mosaic/extension.ts +1 -1
  74. package/src/components/Mosaic/styles.ts +8 -8
  75. package/src/components/index.ts +0 -2
  76. package/src/hooks/useContainerDebug.tsx +2 -2
  77. package/src/hooks/useDefaultColumnEventHandler.ts +0 -1
  78. package/src/playwright/board-manager.ts +32 -17
  79. package/src/playwright/index.ts +13 -0
  80. package/src/playwright/playwright.config.ts +2 -1
  81. package/src/playwright/smoke.spec.ts +12 -7
  82. package/src/testing/CardContainer.tsx +23 -16
  83. package/src/testing/DefaultStackTile.tsx +36 -22
  84. package/src/testing/types.ts +4 -4
  85. package/src/translations.ts +3 -2
  86. package/dist/lib/browser/chunk-XNANTBOP.mjs.map +0 -7
  87. package/dist/lib/node-esm/chunk-LWXG4JVG.mjs.map +0 -7
  88. package/dist/types/src/components/Card/Card.d.ts +0 -123
  89. package/dist/types/src/components/Card/Card.d.ts.map +0 -1
  90. package/dist/types/src/components/Card/Card.stories.d.ts +0 -21
  91. package/dist/types/src/components/Card/Card.stories.d.ts.map +0 -1
  92. package/dist/types/src/components/Card/CardDragPreview.d.ts +0 -6
  93. package/dist/types/src/components/Card/CardDragPreview.d.ts.map +0 -1
  94. package/dist/types/src/components/Card/index.d.ts +0 -4
  95. package/dist/types/src/components/Card/index.d.ts.map +0 -1
  96. package/dist/types/src/components/Card/styles.d.ts +0 -13
  97. package/dist/types/src/components/Card/styles.d.ts.map +0 -1
  98. package/dist/types/src/components/Focus/styles.d.ts +0 -6
  99. package/dist/types/src/components/Focus/styles.d.ts.map +0 -1
  100. package/dist/types/src/components/Image/Image.d.ts +0 -14
  101. package/dist/types/src/components/Image/Image.d.ts.map +0 -1
  102. package/dist/types/src/components/Image/Image.stories.d.ts +0 -33
  103. package/dist/types/src/components/Image/Image.stories.d.ts.map +0 -1
  104. package/dist/types/src/components/Image/index.d.ts +0 -2
  105. package/dist/types/src/components/Image/index.d.ts.map +0 -1
  106. package/src/components/Card/Card.stories.tsx +0 -148
  107. package/src/components/Card/Card.tsx +0 -458
  108. package/src/components/Card/CardDragPreview.tsx +0 -23
  109. package/src/components/Card/index.ts +0 -8
  110. package/src/components/Card/styles.ts +0 -23
  111. package/src/components/Focus/styles.ts +0 -21
  112. package/src/components/Image/Image.stories.tsx +0 -86
  113. package/src/components/Image/Image.tsx +0 -223
  114. package/src/components/Image/index.ts +0 -5
@@ -21,66 +21,11 @@ var useVisibleItems = ({ id, items, dragging, getId }) => {
21
21
  return visibleItems;
22
22
  };
23
23
 
24
- // src/components/Focus/styles.ts
25
- var styles = {
26
- container: {
27
- root: [
28
- // TODO(burdon): Option for border/rounded; ring/outline vs border?
29
- "outline-none border border-separator md:rounded-sm",
30
- // Focus (e.g., via tabster).
31
- "focus:!border-accentSurface",
32
- // Active (e.g., drop target).
33
- "data-[focus-state=active]:border-neutralFocusIndicator",
34
- // Error
35
- "data-[focus-state=error]:border-rose-500"
36
- ]
37
- }
38
- };
39
-
40
24
  // src/components/Focus/Focus.tsx
41
- import { useArrowNavigationGroup, useFocusableGroup, useMergedTabsterAttributes_unstable } from "@fluentui/react-tabster";
42
- import { useComposedRefs } from "@radix-ui/react-compose-refs";
43
- import { Primitive } from "@radix-ui/react-primitive";
44
- import { Slot } from "@radix-ui/react-slot";
45
- import React, { createContext, forwardRef, useContext, useRef, useState } from "react";
46
- import { mx } from "@dxos/ui-theme";
47
- var FOCUS_STATE_ATTR = "focus-state";
48
- var FocusContext = /* @__PURE__ */ createContext({});
49
- var useFocus = () => useContext(FocusContext);
50
- var Group = /* @__PURE__ */ forwardRef(({ classNames, className, children, asChild, orientation = "vertical", ...props }, forwardedRef) => {
51
- const rootRef = useRef(null);
52
- const composedRef = useComposedRefs(rootRef, forwardedRef);
53
- const Root = asChild ? Slot : Primitive.div;
54
- const focusableGroupAttrs = useFocusableGroup({
55
- tabBehavior: "limited-trap-focus"
56
- });
57
- const arrowNavigationAttrs = useArrowNavigationGroup({
58
- axis: orientation,
59
- memorizeCurrent: true
60
- });
61
- const tabsterAttrs = useMergedTabsterAttributes_unstable(focusableGroupAttrs, arrowNavigationAttrs);
62
- const [state, setState] = useState();
63
- return /* @__PURE__ */ React.createElement(FocusContext.Provider, {
64
- value: {
65
- setFocus: setState
66
- }
67
- }, /* @__PURE__ */ React.createElement(Root, {
68
- tabIndex: 0,
69
- className: mx(styles.container.root, className, classNames),
70
- ...tabsterAttrs,
71
- ...state && {
72
- [`data-${FOCUS_STATE_ATTR}`]: state
73
- },
74
- ...props,
75
- ref: composedRef
76
- }, children));
77
- });
78
- var Focus = {
79
- Group
80
- };
25
+ import { Focus, useFocus } from "@dxos/react-ui";
81
26
 
82
27
  // src/components/Mosaic/styles.ts
83
- var styles2 = {
28
+ var styles = {
84
29
  placeholder: {
85
30
  root: [
86
31
  "group opacity-0",
@@ -88,10 +33,10 @@ var styles2 = {
88
33
  'group-data-[mosaic-debug="true"]:bg-orange-500',
89
34
  "data-[mosaic-placeholder-state=active]:opacity-100",
90
35
  "data-[mosaic-placeholder-orientation=vertical]:snap-start",
91
- "data-[mosaic-placeholder-orientation=vertical]:plb-1",
92
- "data-[mosaic-placeholder-orientation=vertical]:data-[mosaic-placeholder-state=active]:plb-2.5",
93
- "data-[mosaic-placeholder-orientation=horizontal]:pli-1",
94
- "data-[mosaic-placeholder-orientation=horizontal]:data-[mosaic-placeholder-state=active]:pli-2.5"
36
+ "data-[mosaic-placeholder-orientation=vertical]:py-1",
37
+ "data-[mosaic-placeholder-orientation=vertical]:data-[mosaic-placeholder-state=active]:py-2.5",
38
+ "data-[mosaic-placeholder-orientation=horizontal]:px-1",
39
+ "data-[mosaic-placeholder-orientation=horizontal]:data-[mosaic-placeholder-state=active]:px-2.5"
95
40
  ],
96
41
  content: [
97
42
  "transition-all duration-0",
@@ -99,10 +44,10 @@ var styles2 = {
99
44
  // TODO(burdon): Flickers when start to drag since source is removed and then the placeholder shows up.
100
45
  // - Use absolute positioning?
101
46
  // 'group-data-[mosaic-placeholder-state=active]:duration-200',
102
- "group-data-[mosaic-placeholder-orientation=vertical]:bs-0",
103
- "group-data-[mosaic-placeholder-orientation=vertical]:group-data-[mosaic-placeholder-state=active]:bs-[var(--mosaic-placeholder-height)]",
104
- "group-data-[mosaic-placeholder-orientation=horizontal]:is-0",
105
- "group-data-[mosaic-placeholder-orientation=horizontal]:group-data-[mosaic-placeholder-state=active]:is-[var(--mosaic-placeholder-width)]"
47
+ "group-data-[mosaic-placeholder-orientation=vertical]:h-0",
48
+ "group-data-[mosaic-placeholder-orientation=vertical]:group-data-[mosaic-placeholder-state=active]:h-[var(--mosaic-placeholder-height)]",
49
+ "group-data-[mosaic-placeholder-orientation=horizontal]:w-0",
50
+ "group-data-[mosaic-placeholder-orientation=horizontal]:group-data-[mosaic-placeholder-state=active]:w-[var(--mosaic-placeholder-width)]"
106
51
  ]
107
52
  }
108
53
  };
@@ -115,23 +60,22 @@ var getSourceData = (source) => {
115
60
  // src/components/Mosaic/Root.tsx
116
61
  import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
117
62
  import { monitorForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
118
- import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
119
- import { createContext as createContext2 } from "@radix-ui/react-context";
120
- import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
121
- import { Slot as Slot2 } from "@radix-ui/react-slot";
122
- import React2, { forwardRef as forwardRef2, useCallback, useEffect, useRef as useRef2, useState as useState2 } from "react";
63
+ import { useComposedRefs } from "@radix-ui/react-compose-refs";
64
+ import { createContext } from "@radix-ui/react-context";
65
+ import { Primitive } from "@radix-ui/react-primitive";
66
+ import { Slot } from "@radix-ui/react-slot";
67
+ import React, { forwardRef, useCallback, useEffect, useRef, useState } from "react";
123
68
  import { log } from "@dxos/log";
124
- import { mx as mx2 } from "@dxos/ui-theme";
125
69
  var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-mosaic/src/components/Mosaic/Root.tsx";
126
- var [MosaicRootContextProvider, useMosaicRootContext] = createContext2("MosaicRoot");
70
+ var [MosaicRootContextProvider, useMosaicRootContext] = createContext("MosaicRoot");
127
71
  var MOSAIC_ROOT_NAME = "Mosaic.Root";
128
72
  var MOSAIC_ROOT_DEBUG_ATTR = "mosaic-debug";
129
- var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, debug }, forwardedRef) => {
130
- const rootRef = useRef2(null);
131
- const composedRef = useComposedRefs2(rootRef, forwardedRef);
132
- const Root = asChild ? Slot2 : Primitive2.div;
133
- const [handlers, setHandlers] = useState2({});
134
- const [dragging, setDragging] = useState2();
73
+ var MosaicRoot = /* @__PURE__ */ forwardRef(({ children, asChild, debug }, forwardedRef) => {
74
+ const rootRef = useRef(null);
75
+ const composedRef = useComposedRefs(rootRef, forwardedRef);
76
+ const Comp = asChild ? Slot : Primitive.div;
77
+ const [handlers, setHandlers] = useState({});
78
+ const [dragging, setDragging] = useState();
135
79
  const getSourceHandler = useCallback((source) => {
136
80
  const data = source.data;
137
81
  return {
@@ -176,7 +120,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
176
120
  source: {
177
121
  data: sourceData,
178
122
  handler: handlers[sourceData.containerId],
179
- // TOOD(burdon): Check id matches.
123
+ // TODO(burdon): Check id matches.
180
124
  container: location.initial.dropTargets.find((target) => target.data.type === "container")?.element
181
125
  },
182
126
  target: targetData && {
@@ -208,7 +152,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
208
152
  location: location.current.dropTargets.map((target) => target.data)
209
153
  }, {
210
154
  F: __dxlog_file,
211
- L: 149,
155
+ L: 144,
212
156
  S: void 0,
213
157
  C: (f, a) => f(...a)
214
158
  });
@@ -227,7 +171,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
227
171
  location: location.current.dropTargets.map((target) => target.data)
228
172
  }, {
229
173
  F: __dxlog_file,
230
- L: 162,
174
+ L: 157,
231
175
  S: void 0,
232
176
  C: (f, a) => f(...a)
233
177
  });
@@ -266,7 +210,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
266
210
  location: location.current.dropTargets.map((target) => target.data)
267
211
  }, {
268
212
  F: __dxlog_file,
269
- L: 191,
213
+ L: 186,
270
214
  S: void 0,
271
215
  C: (f, a) => f(...a)
272
216
  });
@@ -277,7 +221,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
277
221
  handlers: Object.keys(handlers)
278
222
  }, {
279
223
  F: __dxlog_file,
280
- L: 199,
224
+ L: 194,
281
225
  S: void 0,
282
226
  C: (f, a) => f(...a)
283
227
  });
@@ -287,7 +231,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
287
231
  if (location.current.dropTargets.length === 0) {
288
232
  log.info("cancelled", void 0, {
289
233
  F: __dxlog_file,
290
- L: 214,
234
+ L: 209,
291
235
  S: void 0,
292
236
  C: (f, a) => f(...a)
293
237
  });
@@ -300,7 +244,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
300
244
  handlers: Object.keys(handlers)
301
245
  }, {
302
246
  F: __dxlog_file,
303
- L: 219,
247
+ L: 214,
304
248
  S: void 0,
305
249
  C: (f, a) => f(...a)
306
250
  });
@@ -317,7 +261,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
317
261
  source: sourceData
318
262
  }, {
319
263
  F: __dxlog_file,
320
- L: 235,
264
+ L: 230,
321
265
  S: void 0,
322
266
  C: (f, a) => f(...a)
323
267
  });
@@ -347,7 +291,7 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
347
291
  getSourceHandler,
348
292
  getTargetHandler
349
293
  ]);
350
- return /* @__PURE__ */ React2.createElement(MosaicRootContextProvider, {
294
+ return /* @__PURE__ */ React.createElement(MosaicRootContextProvider, {
351
295
  containers: handlers,
352
296
  addContainer: (container) => setHandlers((containers) => ({
353
297
  ...containers,
@@ -360,8 +304,8 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
360
304
  };
361
305
  }),
362
306
  dragging
363
- }, /* @__PURE__ */ React2.createElement(Root, {
364
- className: mx2("group", classNames),
307
+ }, /* @__PURE__ */ React.createElement(Comp, {
308
+ className: "contents group",
365
309
  [`data-${MOSAIC_ROOT_DEBUG_ATTR}`]: debug,
366
310
  ref: composedRef
367
311
  }, children));
@@ -369,38 +313,52 @@ var MosaicRoot = /* @__PURE__ */ forwardRef2(({ classNames, children, asChild, d
369
313
  MosaicRoot.displayName = MOSAIC_ROOT_NAME;
370
314
 
371
315
  // src/components/Mosaic/Container.tsx
316
+ import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
372
317
  import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
373
318
  import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
374
- import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
375
- import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
376
- import { createContext as createContext3 } from "@radix-ui/react-context";
377
- import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
378
- import { Slot as Slot3 } from "@radix-ui/react-slot";
319
+ import { useComposedRefs as useComposedRefs2 } from "@radix-ui/react-compose-refs";
320
+ import { createContext as createContext2 } from "@radix-ui/react-context";
321
+ import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
322
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
379
323
  import { bind } from "bind-event-listener";
380
- import React3, { forwardRef as forwardRef3, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef3, useState as useState3 } from "react";
381
- import { mx as mx3 } from "@dxos/ui-theme";
324
+ import React2, { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
325
+ import { composable, composableProps } from "@dxos/ui-theme";
382
326
  import { isTruthy } from "@dxos/util";
383
327
  var MOSAIC_CONTAINER_NAME = "Mosaic.Container";
384
- var [MosaicContainerContextProvider, useMosaicContainerContext] = createContext3("MosaicContainer");
328
+ var [MosaicContainerContextProvider, useMosaicContainerContext] = createContext2("MosaicContainer");
385
329
  var MOSAIC_CONTAINER_STATE_ATTR = "mosaic-container-state";
386
330
  var MOSAIC_CONTAINER_PLACEHOLDER_WIDTH = "--mosaic-placeholder-width";
387
331
  var MOSAIC_CONTAINER_PLACEHOLDER_HEIGHT = "--mosaic-placeholder-height";
388
332
  var counter = 0;
389
- var MosaicContainer = /* @__PURE__ */ forwardRef3(({ classNames, className, children, eventHandler: eventHandlerProp, orientation = "vertical", asChild, autoScroll: autoscrollElement, withFocus, debug, ...props }, forwardedRef) => {
390
- const rootRef = useRef3(null);
391
- const composedRef = useComposedRefs3(rootRef, forwardedRef);
392
- const Root = asChild ? Slot3 : Primitive3.div;
333
+ var MosaicContainer = composable(({ children, eventHandler: eventHandlerProp, orientation = "vertical", asChild, autoScroll: autoscrollElement, withFocus, currentId, onCurrentChange, debug, ...props }, forwardedRef) => {
334
+ const Comp = asChild ? Slot2 : Primitive2.div;
335
+ const rootRef = useRef2(null);
336
+ const composedRef = useComposedRefs2(rootRef, forwardedRef);
393
337
  const eventHandler = useMemo2(() => eventHandlerProp ?? {
394
338
  id: `mosaic-container-${counter++}`
395
339
  }, [
396
340
  eventHandlerProp
397
341
  ]);
398
342
  const { dragging } = useMosaicRootContext(MOSAIC_CONTAINER_NAME);
399
- const [state, setState] = useState3({
343
+ const [state, setState] = useState2({
400
344
  type: "idle"
401
345
  });
402
- const [activeLocation, setActiveLocation] = useState3();
403
- const [scrolling, setScrolling] = useState3(false);
346
+ const [activeLocation, setActiveLocation] = useState2();
347
+ const [scrolling, setScrolling] = useState2(false);
348
+ const setCurrentId = useCallback2((id) => onCurrentChange?.(id), [
349
+ onCurrentChange
350
+ ]);
351
+ const scrollToRef = useRef2(void 0);
352
+ const registerScrollTo = useCallback2((fn) => {
353
+ scrollToRef.current = fn;
354
+ }, []);
355
+ useEffect2(() => {
356
+ if (currentId) {
357
+ scrollToRef.current?.(currentId);
358
+ }
359
+ }, [
360
+ currentId
361
+ ]);
404
362
  const { setFocus } = useFocus();
405
363
  useEffect2(() => {
406
364
  if (withFocus) {
@@ -535,7 +493,7 @@ var MosaicContainer = /* @__PURE__ */ forwardRef3(({ classNames, className, chil
535
493
  data,
536
494
  autoscrollElement
537
495
  ]);
538
- return /* @__PURE__ */ React3.createElement(MosaicContainerContextProvider, {
496
+ return /* @__PURE__ */ React2.createElement(MosaicContainerContextProvider, {
539
497
  id: eventHandler.id,
540
498
  eventHandler,
541
499
  orientation,
@@ -543,14 +501,18 @@ var MosaicContainer = /* @__PURE__ */ forwardRef3(({ classNames, className, chil
543
501
  dragging: state.type === "active" ? dragging : void 0,
544
502
  scrolling,
545
503
  activeLocation,
546
- setActiveLocation
547
- }, /* @__PURE__ */ React3.createElement(Root, {
548
- className: mx3("bs-full", className, classNames),
549
- style: {
550
- [MOSAIC_CONTAINER_PLACEHOLDER_WIDTH]: state.type === "active" && state.bounds ? `${state.bounds.width}px` : "0px",
551
- [MOSAIC_CONTAINER_PLACEHOLDER_HEIGHT]: state.type === "active" && state.bounds ? `${state.bounds.height}px` : "0px"
552
- },
553
- ...props,
504
+ setActiveLocation,
505
+ currentId,
506
+ setCurrentId,
507
+ registerScrollTo
508
+ }, /* @__PURE__ */ React2.createElement(Comp, {
509
+ ...composableProps(props, {
510
+ classNames: "h-full",
511
+ style: {
512
+ [MOSAIC_CONTAINER_PLACEHOLDER_WIDTH]: state.type === "active" && state.bounds ? `${state.bounds.width}px` : "0px",
513
+ [MOSAIC_CONTAINER_PLACEHOLDER_HEIGHT]: state.type === "active" && state.bounds ? `${state.bounds.height}px` : "0px"
514
+ }
515
+ }),
554
516
  [`data-${MOSAIC_CONTAINER_STATE_ATTR}`]: state.type,
555
517
  ref: composedRef
556
518
  }, children), debug?.());
@@ -558,27 +520,27 @@ var MosaicContainer = /* @__PURE__ */ forwardRef3(({ classNames, className, chil
558
520
  MosaicContainer.displayName = MOSAIC_CONTAINER_NAME;
559
521
 
560
522
  // src/components/Mosaic/Tile.tsx
523
+ import { attachClosestEdge, extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
561
524
  import { combine as combine3 } from "@atlaskit/pragmatic-drag-and-drop/combine";
562
525
  import { draggable, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
563
526
  import { preserveOffsetOnSource } from "@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source";
564
527
  import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
565
- import { attachClosestEdge, extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
566
528
  import { composeRefs } from "@radix-ui/react-compose-refs";
567
- import { createContext as createContext4 } from "@radix-ui/react-context";
568
- import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
569
- import { Slot as Slot4 } from "@radix-ui/react-slot";
570
- import React4, { forwardRef as forwardRef4, useLayoutEffect, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
529
+ import { createContext as createContext3 } from "@radix-ui/react-context";
530
+ import { Primitive as Primitive3 } from "@radix-ui/react-primitive";
531
+ import { Slot as Slot3 } from "@radix-ui/react-slot";
532
+ import React3, { useLayoutEffect, useMemo as useMemo3, useRef as useRef3, useState as useState3 } from "react";
571
533
  import { createPortal } from "react-dom";
572
- import { mx as mx4 } from "@dxos/ui-theme";
534
+ import { composableProps as composableProps2, slottable } from "@dxos/ui-theme";
573
535
  var MOSAIC_TILE_NAME = "Mosaic.Tile";
574
- var [MosaicTileContextProvider, useMosaicTileContext] = createContext4("MosaicTile");
536
+ var [MosaicTileContextProvider, useMosaicTileContext] = createContext3("MosaicTile");
575
537
  var MOSAIC_TILE_STATE_ATTR = "mosaic-tile-state";
576
- var MosaicTile = /* @__PURE__ */ forwardRef4(({ classNames, className, children, asChild, dragHandle, allowedEdges: allowedEdgesProp, location, id, data: dataProp, debug: _ }, forwardedRef) => {
577
- const rootRef = useRef4(null);
538
+ var MosaicTile = slottable(({ children, asChild, dragHandle, allowedEdges: allowedEdgesProp, location, id, data: dataProp, draggable: draggableProp, current: _current, debug: _, ...props }, forwardedRef) => {
539
+ const Comp = asChild ? Slot3 : Primitive3.div;
540
+ const rootRef = useRef3(null);
578
541
  const composedRef = composeRefs(rootRef, forwardedRef);
579
- const Root = asChild ? Slot4 : Primitive4.div;
580
542
  const { id: containerId, eventHandler, orientation, scrolling, setActiveLocation } = useMosaicContainerContext(MOSAIC_TILE_NAME);
581
- const [state, setState] = useState4({
543
+ const [state, setState] = useState3({
582
544
  type: "idle"
583
545
  });
584
546
  const allowedEdges = useMemo3(() => allowedEdgesProp || (orientation === "vertical" ? [
@@ -604,7 +566,7 @@ var MosaicTile = /* @__PURE__ */ forwardRef4(({ classNames, className, children,
604
566
  ]);
605
567
  useLayoutEffect(() => {
606
568
  const root = rootRef.current;
607
- if (!root || !containerId || scrolling) {
569
+ if (!draggableProp || !root || !containerId || scrolling) {
608
570
  return;
609
571
  }
610
572
  const handleChange = ({ self, source }) => {
@@ -698,6 +660,8 @@ var MosaicTile = /* @__PURE__ */ forwardRef4(({ classNames, className, children,
698
660
  );
699
661
  }, [
700
662
  rootRef,
663
+ forwardedRef,
664
+ containerId,
701
665
  dragHandle,
702
666
  eventHandler,
703
667
  data,
@@ -705,18 +669,22 @@ var MosaicTile = /* @__PURE__ */ forwardRef4(({ classNames, className, children,
705
669
  allowedEdges,
706
670
  setActiveLocation
707
671
  ]);
708
- return /* @__PURE__ */ React4.createElement(MosaicTileContextProvider, {
672
+ const { className, ...rest } = composableProps2(props, {
673
+ classNames: "relative outline-none"
674
+ });
675
+ return /* @__PURE__ */ React3.createElement(MosaicTileContextProvider, {
709
676
  state
710
- }, /* @__PURE__ */ React4.createElement(Root, {
677
+ }, /* @__PURE__ */ React3.createElement(Comp, {
678
+ ...rest,
679
+ "data-object-id": id,
711
680
  [`data-${MOSAIC_TILE_STATE_ATTR}`]: state.type,
712
681
  role: "listitem",
713
- className: mx4("relative", className, classNames),
682
+ className,
714
683
  ref: composedRef
715
- }, children), state.type === "preview" && /* @__PURE__ */ createPortal(/* @__PURE__ */ React4.createElement(Root, {
684
+ }, children), state.type === "preview" && /* @__PURE__ */ createPortal(/* @__PURE__ */ React3.createElement(Comp, {
716
685
  // NOTE: Use to control appearance while dragging.
717
686
  [`data-${MOSAIC_TILE_STATE_ATTR}`]: state.type,
718
- // TODO(burdon): Configure drop animation.
719
- className: mx4("relative", className, classNames),
687
+ className,
720
688
  style: {
721
689
  width: `${state.rect.width}px`,
722
690
  height: `${state.rect.height}px`
@@ -726,18 +694,18 @@ var MosaicTile = /* @__PURE__ */ forwardRef4(({ classNames, className, children,
726
694
  MosaicTile.displayName = MOSAIC_TILE_NAME;
727
695
 
728
696
  // src/components/Mosaic/Placeholder.tsx
697
+ import { DropIndicator as NaturalDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box";
729
698
  import { dropTargetForElements as dropTargetForElements3 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
730
- import { DropIndicator as NativeDropIndicator } from "@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box";
731
- import { Primitive as Primitive5 } from "@radix-ui/react-primitive";
732
- import { Slot as Slot5 } from "@radix-ui/react-slot";
733
- import React5, { useLayoutEffect as useLayoutEffect2, useMemo as useMemo4, useRef as useRef5 } from "react";
734
- import { mx as mx5 } from "@dxos/ui-theme";
699
+ import { Primitive as Primitive4 } from "@radix-ui/react-primitive";
700
+ import { Slot as Slot4 } from "@radix-ui/react-slot";
701
+ import React4, { useLayoutEffect as useLayoutEffect2, useMemo as useMemo4, useRef as useRef4 } from "react";
702
+ import { mx } from "@dxos/ui-theme";
735
703
  var MOSAIC_PLACEHOLDER_NAME = "Mosaic.Placeholder";
736
704
  var MOSAIC_PLACEHOLDER_ORIENTATION_ATTR = "mosaic-placeholder-orientation";
737
705
  var MOSAIC_PLACEHOLDER_STATE_ATTR = "mosaic-placeholder-state";
738
706
  var MosaicPlaceholder = ({ classNames, children, asChild, orientation = "vertical", location }) => {
739
- const rootRef = useRef5(null);
740
- const Root = asChild ? Slot5 : Primitive5.div;
707
+ const rootRef = useRef4(null);
708
+ const Comp = asChild ? Slot4 : Primitive4.div;
741
709
  const { id: containerId, eventHandler, scrolling, activeLocation, setActiveLocation } = useMosaicContainerContext(MOSAIC_PLACEHOLDER_NAME);
742
710
  const data = useMemo4(() => ({
743
711
  type: "placeholder",
@@ -777,11 +745,11 @@ var MosaicPlaceholder = ({ classNames, children, asChild, orientation = "vertica
777
745
  scrolling,
778
746
  setActiveLocation
779
747
  ]);
780
- return /* @__PURE__ */ React5.createElement(Root, {
748
+ return /* @__PURE__ */ React4.createElement(Comp, {
781
749
  [`data-${MOSAIC_PLACEHOLDER_ORIENTATION_ATTR}`]: orientation,
782
750
  [`data-${MOSAIC_PLACEHOLDER_STATE_ATTR}`]: data.location === activeLocation ? "active" : "idle",
783
751
  role: "none",
784
- className: mx5("relative", classNames),
752
+ className: mx("relative", classNames),
785
753
  ref: rootRef
786
754
  }, children);
787
755
  };
@@ -789,7 +757,7 @@ MosaicPlaceholder.displayName = MOSAIC_PLACEHOLDER_NAME;
789
757
  var DROP_INDICATOR_NAME = "Mosaic.DropIndicator";
790
758
  var MosaicDropIndicator = (props) => {
791
759
  const { state } = useMosaicTileContext(DROP_INDICATOR_NAME);
792
- return state.type === "target" && state.closestEdge ? /* @__PURE__ */ React5.createElement(NativeDropIndicator, {
760
+ return state.type === "target" && state.closestEdge ? /* @__PURE__ */ React4.createElement(NaturalDropIndicator, {
793
761
  ...props,
794
762
  edge: state.closestEdge
795
763
  }) : null;
@@ -797,440 +765,15 @@ var MosaicDropIndicator = (props) => {
797
765
  MosaicDropIndicator.displayName = DROP_INDICATOR_NAME;
798
766
 
799
767
  // src/components/Mosaic/Stack.tsx
768
+ import { useComposedRefs as useComposedRefs3 } from "@radix-ui/react-compose-refs";
800
769
  import { useVirtualizer } from "@tanstack/react-virtual";
801
- import React8, { Fragment, forwardRef as forwardRef6 } from "react";
770
+ import React5, { forwardRef as forwardRef2, Fragment, useCallback as useCallback3, useEffect as useEffect3, useRef as useRef5 } from "react";
802
771
  import { invariant } from "@dxos/invariant";
803
- import { mx as mx8 } from "@dxos/ui-theme";
804
-
805
- // src/translations.ts
806
- var translationKey = "@dxos/react-ui-mosaic";
807
- var translations = [
808
- {
809
- "en-US": {
810
- [translationKey]: {
811
- "add item label": "Add item",
812
- "delete menu label": "Delete"
813
- }
814
- }
815
- }
816
- ];
817
-
818
- // src/components/Card/styles.ts
819
- var styles3 = {
820
- root: "group/card relative min-bs-[--rail-item] is-full card-min-width overflow-hidden",
821
- border: "bg-cardSurface border border-separator dark:border-subduedSeparator rounded-sm dx-focus-ring-group-y-indicator",
822
- /**
823
- * Row grid.
824
- * NOTE: Rows should provide their own line padding (since they may need to encapsulate buttons, etc.)
825
- */
826
- grid_3: "grid grid-cols-[var(--rail-item)_minmax(0,1fr)_var(--rail-item)] gap-x-1",
827
- grid_2: "grid grid-cols-[var(--rail-item)_minmax(0,1fr)] gap-x-1",
828
- // TODO(burdon): Address density.
829
- grid_3_coarse: "grid grid-cols-[var(--l0-avatar-size)_minmax(0,1fr)_var(--rail-item)] gap-x-1",
830
- poster: "max-bs-[200px]"
831
- };
832
-
833
- // src/components/Card/Card.tsx
834
- import { Slot as Slot6 } from "@radix-ui/react-slot";
835
- import React7, { createContext as createContext5, forwardRef as forwardRef5, useContext as useContext2 } from "react";
836
- import { Button, DropdownMenu, Icon, Toolbar, useTranslation } from "@dxos/react-ui";
837
- import { mx as mx7 } from "@dxos/ui-theme";
838
-
839
- // src/components/Image/Image.tsx
840
- import React6, { useCallback as useCallback2, useRef as useRef6, useState as useState5 } from "react";
841
- import { mx as mx6 } from "@dxos/ui-theme";
842
- var cache = /* @__PURE__ */ new Map();
843
- var Image = ({ classNames, src, alt = "", crossOrigin = "anonymous", sampleSize = 64, contrast = 0.9 }) => {
844
- const [crossOriginState, setCrossOriginState] = useState5(crossOrigin);
845
- const [dominantColor, setDominantColor] = useState5(void 0);
846
- const [imageLoaded, setImageLoaded] = useState5(false);
847
- const canvasRef = useRef6(null);
848
- const handleImageError = () => {
849
- setCrossOriginState(void 0);
850
- };
851
- const handleImageLoad = useCallback2(({ target }) => {
852
- const rgb = cache.get(src);
853
- if (rgb) {
854
- setDominantColor(rgb);
855
- setImageLoaded(true);
856
- return;
857
- }
858
- const img = target;
859
- if (!canvasRef.current) {
860
- return;
861
- }
862
- try {
863
- const color = extractDominantColor(canvasRef.current, img, {
864
- sampleSize,
865
- contrast
866
- });
867
- if (color) {
868
- const rgb2 = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
869
- cache.set(src, rgb2);
870
- setDominantColor(rgb2);
871
- }
872
- } catch {
873
- setCrossOriginState(void 0);
874
- }
875
- setImageLoaded(true);
876
- }, [
877
- sampleSize,
878
- contrast,
879
- src
880
- ]);
881
- return /* @__PURE__ */ React6.createElement("div", {
882
- className: mx6(`relative flex is-full justify-center overflow-hidden transition-all duration-700`, classNames),
883
- style: {
884
- backgroundColor: dominantColor
885
- }
886
- }, /* @__PURE__ */ React6.createElement("canvas", {
887
- ref: canvasRef,
888
- style: {
889
- display: "none"
890
- },
891
- "aria-hidden": "true"
892
- }), /* @__PURE__ */ React6.createElement("div", {
893
- className: "absolute inset-0 pointer-events-none",
894
- style: {
895
- background: dominantColor ? `radial-gradient(circle at center, transparent 30%, ${dominantColor} 100%)` : void 0,
896
- transition: "opacity 0.7s ease-in-out",
897
- opacity: 0.5
898
- }
899
- }), /* @__PURE__ */ React6.createElement("img", {
900
- src,
901
- alt,
902
- crossOrigin: crossOriginState,
903
- onError: handleImageError,
904
- onLoad: handleImageLoad,
905
- className: mx6("z-10 object-contain transition-opacity duration-500", classNames),
906
- style: {
907
- opacity: imageLoaded ? 1 : 0
908
- }
909
- }));
910
- };
911
- var extractDominantColor = (canvas, img, { sampleSize = 64, contrast = 0.95 }) => {
912
- const ctx = canvas.getContext("2d");
913
- if (!ctx) {
914
- return null;
915
- }
916
- canvas.width = sampleSize;
917
- canvas.height = sampleSize;
918
- ctx.drawImage(img, 0, 0, sampleSize, sampleSize);
919
- const imageData = ctx.getImageData(0, 0, sampleSize, sampleSize);
920
- const pixels = imageData.data;
921
- if (isTransparent(pixels, sampleSize)) {
922
- return null;
923
- }
924
- let r = 0;
925
- let g = 0;
926
- let b = 0;
927
- let totalWeight = 0;
928
- const cornerSize = Math.floor(sampleSize * 0.125);
929
- for (let y = 0; y < sampleSize; y++) {
930
- for (let x = 0; x < sampleSize; x++) {
931
- const isInTopLeft = x < cornerSize && y < cornerSize;
932
- const isInTopRight = x >= sampleSize - cornerSize && y < cornerSize;
933
- const isInBottomLeft = x < cornerSize && y >= sampleSize - cornerSize;
934
- const isInBottomRight = x >= sampleSize - cornerSize && y >= sampleSize - cornerSize;
935
- if (!isInTopLeft && !isInTopRight && !isInBottomLeft && !isInBottomRight) {
936
- continue;
937
- }
938
- const i = (y * sampleSize + x) * 4;
939
- const red = pixels[i];
940
- const green = pixels[i + 1];
941
- const blue = pixels[i + 2];
942
- const alpha = pixels[i + 3];
943
- if (alpha === 0) continue;
944
- const max = Math.max(red, green, blue);
945
- const min = Math.min(red, green, blue);
946
- const saturation = max === 0 ? 0 : (max - min) / max;
947
- const weight = 1 + saturation * 2;
948
- r += red * weight;
949
- g += green * weight;
950
- b += blue * weight;
951
- totalWeight += weight;
952
- }
953
- }
954
- if (totalWeight > 0) {
955
- r = Math.round(Math.round(r / totalWeight) * contrast);
956
- g = Math.round(Math.round(g / totalWeight) * contrast);
957
- b = Math.round(Math.round(b / totalWeight) * contrast);
958
- return [
959
- r,
960
- g,
961
- b
962
- ];
963
- }
964
- return null;
965
- };
966
- var isTransparent = (pixels, sampleSize, threshold = 0.5) => {
967
- let edgeTransparentPixels = 0;
968
- const edgePixels = sampleSize * 4 - 4;
969
- for (let x = 0; x < sampleSize; x++) {
970
- const topIndex = x * 4;
971
- if (pixels[topIndex + 3] === 0) edgeTransparentPixels++;
972
- const bottomIndex = ((sampleSize - 1) * sampleSize + x) * 4;
973
- if (pixels[bottomIndex + 3] === 0) edgeTransparentPixels++;
974
- }
975
- for (let y = 1; y < sampleSize - 1; y++) {
976
- const leftIndex = y * sampleSize * 4;
977
- if (pixels[leftIndex + 3] === 0) edgeTransparentPixels++;
978
- const rightIndex = (y * sampleSize + sampleSize - 1) * 4;
979
- if (pixels[rightIndex + 3] === 0) edgeTransparentPixels++;
980
- }
981
- return edgeTransparentPixels / edgePixels > threshold;
982
- };
983
-
984
- // src/components/Card/Card.tsx
985
- var CardContext = /* @__PURE__ */ createContext5({});
986
- var CardRoot = /* @__PURE__ */ forwardRef5(({ children, classNames, className, id, asChild, role = "group", border = true, fullWidth, ...props }, forwardedRef) => {
987
- const Root = asChild ? Slot6 : "div";
988
- return /* @__PURE__ */ React7.createElement(Root, {
989
- ...id && {
990
- "data-object-id": id
991
- },
992
- ...props,
993
- role,
994
- className: mx7(styles3.root, border && styles3.border, fullWidth && "!max-is-none", className, classNames),
995
- ref: forwardedRef
996
- }, children);
997
- });
998
- var CardToolbar = /* @__PURE__ */ forwardRef5(({ children, classNames, density = "fine", ...props }, forwardedRef) => {
999
- return /* @__PURE__ */ React7.createElement(Toolbar.Root, {
1000
- ...props,
1001
- classNames: [
1002
- "density-fine bg-transparent",
1003
- density === "fine" ? styles3.grid_3 : styles3.grid_3_coarse,
1004
- classNames
1005
- ],
1006
- ref: forwardedRef
1007
- }, children);
1008
- });
1009
- var CardToolbarIconButton = Toolbar.IconButton;
1010
- var CardToolbarSeparator = Toolbar.Separator;
1011
- var CardDragHandle = /* @__PURE__ */ forwardRef5((_, forwardedRef) => {
1012
- const { t } = useTranslation(translationKey);
1013
- return /* @__PURE__ */ React7.createElement(Toolbar.IconButton, {
1014
- "data-testid": "card-drag-handle",
1015
- noTooltip: true,
1016
- iconOnly: true,
1017
- icon: "ph--dots-six-vertical--regular",
1018
- variant: "ghost",
1019
- label: t("drag handle label"),
1020
- classNames: "cursor-pointer",
1021
- size: 5,
1022
- disabled: !forwardedRef,
1023
- ref: forwardedRef
1024
- });
1025
- });
1026
- var CardClose = /* @__PURE__ */ forwardRef5(({ onClick }, forwardedRef) => {
1027
- const { t } = useTranslation(translationKey);
1028
- return /* @__PURE__ */ React7.createElement(Toolbar.IconButton, {
1029
- iconOnly: true,
1030
- icon: "ph--x--regular",
1031
- variant: "ghost",
1032
- label: t("card close label"),
1033
- classNames: "cursor-pointer",
1034
- size: 5,
1035
- onClick,
1036
- ref: forwardedRef
1037
- });
1038
- });
1039
- var CardMenu = ({ context, items }) => {
1040
- const { t } = useTranslation(translationKey);
1041
- const { menuItems } = useContext2(CardContext) ?? {};
1042
- const combinedItems = [
1043
- ...items ?? [],
1044
- ...menuItems ?? []
1045
- ];
1046
- return /* @__PURE__ */ React7.createElement(DropdownMenu.Root, null, /* @__PURE__ */ React7.createElement(DropdownMenu.Trigger, {
1047
- disabled: !combinedItems.length,
1048
- asChild: true
1049
- }, /* @__PURE__ */ React7.createElement(Card.ToolbarIconButton, {
1050
- iconOnly: true,
1051
- variant: "ghost",
1052
- icon: "ph--dots-three-vertical--regular",
1053
- label: t("action menu label")
1054
- })), (combinedItems?.length ?? 0) > 0 && /* @__PURE__ */ React7.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React7.createElement(DropdownMenu.Content, null, /* @__PURE__ */ React7.createElement(DropdownMenu.Viewport, null, combinedItems?.map(({ label, onClick: onSelect }, i) => /* @__PURE__ */ React7.createElement(DropdownMenu.Item, {
1055
- key: i,
1056
- onSelect: () => onSelect(context)
1057
- }, label))), /* @__PURE__ */ React7.createElement(DropdownMenu.Arrow, null))));
1058
- };
1059
- var CardTitle = /* @__PURE__ */ forwardRef5(({ children, classNames, className, asChild, role = "heading", ...props }, forwardedRef) => {
1060
- const Root = asChild ? Slot6 : "div";
1061
- return /* @__PURE__ */ React7.createElement(Root, {
1062
- ...props,
1063
- role,
1064
- className: mx7("grow truncate", classNames, className),
1065
- ref: forwardedRef
1066
- }, children);
1067
- });
1068
- var CardContent = /* @__PURE__ */ forwardRef5(({ children, ...props }, forwardedRef) => {
1069
- return /* @__PURE__ */ React7.createElement("div", {
1070
- role: "none",
1071
- className: "contents [&>:last-child]:pbe-1",
1072
- ...props,
1073
- ref: forwardedRef
1074
- }, children);
1075
- });
1076
- var CardRow = /* @__PURE__ */ forwardRef5(({ children, classNames, className, role = "none", icon, ...props }, forwardedRef) => {
1077
- return /* @__PURE__ */ React7.createElement("div", {
1078
- ...props,
1079
- role,
1080
- className: mx7(styles3.grid_2, "pli-1", classNames, className),
1081
- ref: forwardedRef
1082
- }, icon && /* @__PURE__ */ React7.createElement(CardIcon, {
1083
- classNames: "text-subdued",
1084
- icon
1085
- }) || /* @__PURE__ */ React7.createElement("div", null), children);
1086
- });
1087
- var CardHeading = /* @__PURE__ */ forwardRef5(({ children, classNames, className, asChild, role = "heading", variant = "default", ...props }, forwardedRef) => {
1088
- const Root = asChild ? Slot6 : "div";
1089
- const variantClassNames = {
1090
- default: "plb-1",
1091
- subtitle: "plb-2 text-xs text-description font-medium uppercase"
1092
- };
1093
- return /* @__PURE__ */ React7.createElement(Root, {
1094
- ...props,
1095
- role,
1096
- className: mx7(variantClassNames[variant], classNames, className),
1097
- ref: forwardedRef
1098
- }, children);
1099
- });
1100
- var CardText = /* @__PURE__ */ forwardRef5(({ children, classNames, className, asChild, role = "none", truncate, variant = "default", ...props }, forwardedRef) => {
1101
- const Root = asChild ? Slot6 : "div";
1102
- const variantClassNames = {
1103
- default: {
1104
- root: "plb-1"
1105
- },
1106
- description: {
1107
- root: "plb-1.5",
1108
- span: "text-sm text-description line-clamp-3"
1109
- }
1110
- };
1111
- return /* @__PURE__ */ React7.createElement(Root, {
1112
- ...props,
1113
- role,
1114
- className: mx7("flex overflow-hidden", variantClassNames[variant].root, classNames, className),
1115
- ref: forwardedRef
1116
- }, /* @__PURE__ */ React7.createElement("span", {
1117
- className: mx7(variantClassNames[variant].span, truncate && "truncate")
1118
- }, children));
1119
- });
1120
- var CardPoster = (props) => {
1121
- const aspect = props.aspect === "auto" ? "aspect-auto" : "aspect-video";
1122
- if (props.image) {
1123
- return /* @__PURE__ */ React7.createElement("div", {
1124
- role: "none",
1125
- className: "mbe-1"
1126
- }, /* @__PURE__ */ React7.createElement(Image, {
1127
- classNames: [
1128
- styles3.poster,
1129
- aspect,
1130
- props.classNames
1131
- ],
1132
- src: props.image,
1133
- alt: props.alt
1134
- }));
1135
- }
1136
- if (props.icon) {
1137
- return /* @__PURE__ */ React7.createElement("div", {
1138
- role: "image",
1139
- className: mx7("grid place-items-center bg-inputSurface text-subdued", styles3.poster, aspect, props.classNames),
1140
- "aria-label": props.alt
1141
- }, /* @__PURE__ */ React7.createElement(Icon, {
1142
- icon: props.icon,
1143
- size: 10
1144
- }));
1145
- }
1146
- };
1147
- var CardAction = ({ icon, actionIcon = "ph--arrow-right--regular", label, onClick }) => {
1148
- return /* @__PURE__ */ React7.createElement("div", {
1149
- role: "none",
1150
- className: "is-full pli-1"
1151
- }, /* @__PURE__ */ React7.createElement(Button, {
1152
- variant: "ghost",
1153
- classNames: mx7(styles3.grid_3, "!p-0 is-full text-start overflow-hidden"),
1154
- onClick
1155
- }, icon ? /* @__PURE__ */ React7.createElement(CardIcon, {
1156
- classNames: "text-subdued",
1157
- icon
1158
- }) : /* @__PURE__ */ React7.createElement("div", null), /* @__PURE__ */ React7.createElement("span", {
1159
- className: mx7("min-is-0 flex-1 truncate", !actionIcon && "col-span-2")
1160
- }, label), actionIcon && /* @__PURE__ */ React7.createElement(CardIcon, {
1161
- icon: actionIcon
1162
- })));
1163
- };
1164
- var CardLink = ({ label, href }) => {
1165
- return /* @__PURE__ */ React7.createElement("div", {
1166
- role: "none",
1167
- className: "is-full pli-1"
1168
- }, /* @__PURE__ */ React7.createElement("a", {
1169
- className: mx7(styles3.grid_3, "group !p-0 dx-button dx-focus-ring !min-bs-1"),
1170
- "data-variant": "ghost",
1171
- href,
1172
- target: "_blank",
1173
- rel: "noreferrer"
1174
- }, /* @__PURE__ */ React7.createElement(CardIcon, {
1175
- classNames: "text-subdued",
1176
- icon: "ph--link--regular"
1177
- }), /* @__PURE__ */ React7.createElement("span", {
1178
- className: mx7("min-is-0 flex-1 truncate")
1179
- }, label), /* @__PURE__ */ React7.createElement(CardIcon, {
1180
- classNames: "invisible group-hover:visible",
1181
- icon: "ph--arrow-square-out--regular"
1182
- })));
1183
- };
1184
- var CardIconBlock = ({ classNames, children, role = "none", ...props }) => {
1185
- return /* @__PURE__ */ React7.createElement("div", {
1186
- ...props,
1187
- role,
1188
- className: mx7("grid bs-[var(--rail-item)] is-[var(--rail-item)] place-items-center", classNames)
1189
- }, children);
1190
- };
1191
- var CardIcon = ({ toolbar, ...props }) => {
1192
- return /* @__PURE__ */ React7.createElement(CardIconBlock, null, /* @__PURE__ */ React7.createElement(Icon, {
1193
- ...props,
1194
- size: toolbar ? 5 : 4
1195
- }));
1196
- };
1197
- var Card = {
1198
- Context: CardContext,
1199
- Root: CardRoot,
1200
- // Toolbar
1201
- Toolbar: CardToolbar,
1202
- ToolbarIconButton: CardToolbarIconButton,
1203
- ToolbarSeparator: CardToolbarSeparator,
1204
- DragHandle: CardDragHandle,
1205
- Title: CardTitle,
1206
- Close: CardClose,
1207
- Menu: CardMenu,
1208
- Icon: CardIcon,
1209
- IconBlock: CardIconBlock,
1210
- // Content
1211
- Content: CardContent,
1212
- Row: CardRow,
1213
- Heading: CardHeading,
1214
- Text: CardText,
1215
- Poster: CardPoster,
1216
- Action: CardAction,
1217
- Link: CardLink
1218
- };
1219
-
1220
- // src/components/Mosaic/Stack.tsx
772
+ import { composable as composable2, composableProps as composableProps3, mx as mx2 } from "@dxos/ui-theme";
1221
773
  var __dxlog_file2 = "/__w/dxos/dxos/packages/ui/react-ui-mosaic/src/components/Mosaic/Stack.tsx";
1222
774
  var MOSAIC_STACK_NAME = "MosaicStack";
1223
- var MosaicStackInner = /* @__PURE__ */ forwardRef6(({ classNames, className, role = "list", orientation: orientationProp = "vertical", draggable: draggable2 = true, items, getId, Tile, debug, ...props }, forwardedRef) => {
1224
- invariant(Tile, void 0, {
1225
- F: __dxlog_file2,
1226
- L: 75,
1227
- S: void 0,
1228
- A: [
1229
- "Tile",
1230
- ""
1231
- ]
1232
- });
1233
- const { id, orientation = orientationProp, dragging } = useMosaicContainerContext(MOSAIC_STACK_NAME);
775
+ var MosaicStackInner = composable2(({ orientation: orientationProp = "vertical", getId, items, scrollIntoView = true, Tile, draggable: draggable2 = true, debug, ...props }, forwardedRef) => {
776
+ const { id, orientation = orientationProp, dragging, currentId, registerScrollTo } = useMosaicContainerContext(MOSAIC_STACK_NAME);
1234
777
  const visibleItems = useVisibleItems({
1235
778
  id,
1236
779
  items,
@@ -1239,30 +782,57 @@ var MosaicStackInner = /* @__PURE__ */ forwardRef6(({ classNames, className, rol
1239
782
  });
1240
783
  invariant(orientation === "vertical" || orientation === "horizontal", `Invalid orientation: ${orientation}`, {
1241
784
  F: __dxlog_file2,
1242
- L: 78,
785
+ L: 91,
1243
786
  S: void 0,
1244
787
  A: [
1245
788
  "orientation === 'vertical' || orientation === 'horizontal'",
1246
789
  "`Invalid orientation: ${orientation}`"
1247
790
  ]
1248
791
  });
1249
- return /* @__PURE__ */ React8.createElement("div", {
1250
- ...props,
1251
- role,
1252
- className: mx8("flex", orientation === "horizontal" && "bs-full [&>*]:shrink-0", orientation === "vertical" && "flex-col", classNames, className),
1253
- ref: forwardedRef
1254
- }, /* @__PURE__ */ React8.createElement(InternalPlaceholder, {
792
+ const rootRef = useRef5(null);
793
+ const scrollToId = useCallback3((targetId) => {
794
+ if (!scrollIntoView) {
795
+ return;
796
+ }
797
+ const el = rootRef.current?.querySelector(`[data-object-id="${CSS.escape(targetId)}"]`);
798
+ el?.scrollIntoView({
799
+ block: "nearest",
800
+ behavior: "smooth"
801
+ });
802
+ }, [
803
+ scrollIntoView
804
+ ]);
805
+ useEffect3(() => {
806
+ registerScrollTo(scrollToId);
807
+ return () => registerScrollTo(void 0);
808
+ }, [
809
+ registerScrollTo,
810
+ scrollToId
811
+ ]);
812
+ const composedRef = useComposedRefs3(rootRef, forwardedRef);
813
+ return /* @__PURE__ */ React5.createElement("div", {
814
+ ...composableProps3(props, {
815
+ role: "list",
816
+ classNames: [
817
+ "flex",
818
+ orientation === "horizontal" && "h-full [&>*]:shrink-0",
819
+ orientation === "vertical" && "flex-col"
820
+ ]
821
+ }),
822
+ ref: composedRef
823
+ }, draggable2 && /* @__PURE__ */ React5.createElement(InternalPlaceholder, {
1255
824
  orientation,
1256
825
  location: 0.5
1257
- }), visibleItems?.map((item, index) => /* @__PURE__ */ React8.createElement(Fragment, {
826
+ }), visibleItems?.map((item, index) => /* @__PURE__ */ React5.createElement(Fragment, {
1258
827
  key: getId(item)
1259
- }, /* @__PURE__ */ React8.createElement(Tile, {
828
+ }, /* @__PURE__ */ React5.createElement(Tile, {
1260
829
  id: getId(item),
1261
830
  data: item,
1262
831
  location: index + 1,
1263
832
  draggable: draggable2,
833
+ current: getId(item) === currentId,
1264
834
  debug
1265
- }), /* @__PURE__ */ React8.createElement(InternalPlaceholder, {
835
+ }), draggable2 && /* @__PURE__ */ React5.createElement(InternalPlaceholder, {
1266
836
  orientation,
1267
837
  location: index + 1.5
1268
838
  }))));
@@ -1270,35 +840,94 @@ var MosaicStackInner = /* @__PURE__ */ forwardRef6(({ classNames, className, rol
1270
840
  MosaicStackInner.displayName = MOSAIC_STACK_NAME;
1271
841
  var MosaicStack = MosaicStackInner;
1272
842
  var MOSAIC_VIRTUAL_STACK_NAME = "MosaicVirtualStack";
1273
- var MosaicVirtualStackInner = /* @__PURE__ */ forwardRef6(({ classNames, className, role = "list", orientation = "vertical", items, getId, Tile, estimateSize, getScrollElement, overscan = 8, onChange, debug, ...props }, forwardedRef) => {
843
+ var MosaicVirtualStackInner = /* @__PURE__ */ forwardRef2(({ orientation = "vertical", getId, items, scrollIntoView = true, Tile, estimateSize, getScrollElement, overscan = 8, gap, onChange, draggable: draggable2 = true, debug, ...props }, forwardedRef) => {
1274
844
  invariant(Tile, void 0, {
1275
845
  F: __dxlog_file2,
1276
- L: 142,
846
+ L: 180,
1277
847
  S: void 0,
1278
848
  A: [
1279
849
  "Tile",
1280
850
  ""
1281
851
  ]
1282
852
  });
1283
- const { id, dragging } = useMosaicContainerContext(MOSAIC_VIRTUAL_STACK_NAME);
853
+ const { id, dragging, currentId, registerScrollTo } = useMosaicContainerContext(MOSAIC_VIRTUAL_STACK_NAME);
1284
854
  const visibleItems = useVisibleItems({
1285
855
  id,
1286
856
  items,
1287
857
  dragging: dragging?.source.data,
1288
858
  getId
1289
859
  });
860
+ const wrappedEstimateSize = draggable2 ? (index) => index % 2 === 0 ? 0 : estimateSize(Math.floor(index / 2)) : estimateSize;
1290
861
  const virtualizer = useVirtualizer({
1291
- count: visibleItems.length * 2 + 1,
1292
- estimateSize,
862
+ // NOTE: When draggable we double the number of items to allow for placeholders.
863
+ count: draggable2 ? visibleItems.length * 2 + 1 : visibleItems.length,
864
+ estimateSize: wrappedEstimateSize,
865
+ gap,
866
+ // Key measurements by stable item ID so the size cache survives scrolling;
867
+ // without this, measurements are indexed by position and are lost when items reorder.
868
+ getItemKey: draggable2 ? (index) => index % 2 === 0 ? `ph-${index}` : getId(visibleItems[Math.floor(index / 2)]) : (index) => getId(visibleItems[index]),
1293
869
  getScrollElement,
1294
870
  overscan,
1295
871
  onChange
1296
872
  });
873
+ const scrollToId = useCallback3((targetId) => {
874
+ const itemIndex = visibleItems.findIndex((item) => getId(item) === targetId);
875
+ if (itemIndex >= 0) {
876
+ if (!scrollIntoView) {
877
+ return;
878
+ }
879
+ const virtualIndex = draggable2 ? itemIndex * 2 + 1 : itemIndex;
880
+ virtualizer.scrollToIndex(virtualIndex, {
881
+ align: "start",
882
+ behavior: "smooth"
883
+ });
884
+ }
885
+ }, [
886
+ visibleItems,
887
+ getId,
888
+ draggable2,
889
+ virtualizer,
890
+ scrollIntoView
891
+ ]);
892
+ useEffect3(() => {
893
+ registerScrollTo(scrollToId);
894
+ return () => registerScrollTo(void 0);
895
+ }, [
896
+ registerScrollTo,
897
+ scrollToId
898
+ ]);
1297
899
  const virtualItems = virtualizer.getVirtualItems();
1298
- return /* @__PURE__ */ React8.createElement("div", {
1299
- ...props,
1300
- role,
1301
- className: mx8("flex", orientation === "horizontal" && "bs-full [&>*]:shrink-0", orientation === "vertical" && "flex-col", classNames, className),
900
+ const getData = (index) => {
901
+ if (draggable2) {
902
+ if (index % 2 === 0) {
903
+ return {
904
+ location: Math.floor(index / 2) + 0.5
905
+ };
906
+ } else {
907
+ return {
908
+ data: visibleItems[Math.floor(index / 2)],
909
+ location: Math.floor(index / 2) + 1
910
+ };
911
+ }
912
+ } else {
913
+ return {
914
+ data: visibleItems[index],
915
+ location: index + 1
916
+ };
917
+ }
918
+ };
919
+ return /* @__PURE__ */ React5.createElement("div", {
920
+ ...composableProps3(props, {
921
+ role: "list",
922
+ classNames: [
923
+ // shrink-0 is required: this div sets an explicit height via inline style (getTotalSize).
924
+ // Without it, a parent flex container (e.g. ScrollArea.Viewport) would shrink this div
925
+ // to the viewport height, collapsing the scroll content and causing scrollbar drift.
926
+ "flex shrink-0",
927
+ orientation === "horizontal" && "h-full [&>*]:shrink-0",
928
+ orientation === "vertical" && "flex-col"
929
+ ]
930
+ }),
1302
931
  style: {
1303
932
  position: "relative",
1304
933
  ...orientation === "vertical" ? {
@@ -1310,43 +939,46 @@ var MosaicVirtualStackInner = /* @__PURE__ */ forwardRef6(({ classNames, classNa
1310
939
  }
1311
940
  },
1312
941
  ref: forwardedRef
1313
- }, virtualItems.map((virtualItem) => {
1314
- const data = visibleItems[Math.floor(virtualItem.index / 2)];
1315
- return /* @__PURE__ */ React8.createElement("div", {
1316
- key: virtualItem.key,
1317
- "data-index": virtualItem.index,
942
+ }, virtualItems.map(({ key, index, start }) => {
943
+ const { data, location } = getData(index);
944
+ return /* @__PURE__ */ React5.createElement("div", {
945
+ key,
946
+ "data-index": index,
1318
947
  style: {
1319
948
  position: "absolute",
1320
949
  top: 0,
1321
950
  left: 0,
1322
951
  ...orientation === "vertical" ? {
1323
952
  width: "100%",
1324
- transform: `translateY(${virtualItem.start}px)`
953
+ transform: `translateY(${start}px)`
1325
954
  } : {
1326
955
  height: "100%",
1327
- transform: `translateX(${virtualItem.start}px)`
956
+ transform: `translateX(${start}px)`
1328
957
  }
1329
958
  },
1330
959
  ref: virtualizer.measureElement
1331
- }, virtualItem.index % 2 === 0 ? /* @__PURE__ */ React8.createElement(InternalPlaceholder, {
1332
- orientation,
1333
- location: Math.floor(virtualItem.index / 2) + 0.5
1334
- }) : /* @__PURE__ */ React8.createElement(Tile, {
960
+ }, data ? /* @__PURE__ */ React5.createElement(Tile, {
1335
961
  id: getId(data),
1336
962
  data,
1337
- location: Math.floor(virtualItem.index / 2) + 1,
963
+ location,
964
+ draggable: draggable2,
965
+ current: getId(data) === currentId,
1338
966
  debug
967
+ }) : /* @__PURE__ */ React5.createElement(InternalPlaceholder, {
968
+ orientation,
969
+ location
1339
970
  }));
1340
971
  }));
1341
972
  });
1342
973
  MosaicVirtualStackInner.displayName = MOSAIC_VIRTUAL_STACK_NAME;
1343
974
  var MosaicVirtualStack = MosaicVirtualStackInner;
975
+ MosaicVirtualStack[/* @__PURE__ */ Symbol.for("dxos.composable")] = true;
1344
976
  var InternalPlaceholder = (props) => {
1345
- return /* @__PURE__ */ React8.createElement(MosaicPlaceholder, {
977
+ return /* @__PURE__ */ React5.createElement(MosaicPlaceholder, {
1346
978
  ...props,
1347
- classNames: styles2.placeholder.root
1348
- }, /* @__PURE__ */ React8.createElement("div", {
1349
- className: mx8("flex bs-full bg-baseSurface border border-dashed border-separator rounded-sm", styles2.placeholder.content)
979
+ classNames: styles.placeholder.root
980
+ }, /* @__PURE__ */ React5.createElement("div", {
981
+ className: mx2("flex h-full bg-base-surface border border-dashed border-separator rounded-xs", styles.placeholder.content)
1350
982
  }));
1351
983
  };
1352
984
  InternalPlaceholder.displayName = "InternalPlaceholder";
@@ -1364,18 +996,13 @@ var Mosaic = {
1364
996
 
1365
997
  export {
1366
998
  useVisibleItems,
1367
- styles,
1368
- useFocus,
1369
999
  Focus,
1370
- styles2,
1000
+ useFocus,
1001
+ styles,
1371
1002
  getSourceData,
1372
1003
  useMosaicRootContext,
1373
1004
  useMosaicContainerContext,
1374
1005
  useMosaicTileContext,
1375
- Mosaic,
1376
- translationKey,
1377
- styles3,
1378
- Image,
1379
- Card
1006
+ Mosaic
1380
1007
  };
1381
- //# sourceMappingURL=chunk-XNANTBOP.mjs.map
1008
+ //# sourceMappingURL=chunk-33NNDFD6.mjs.map