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

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