@dxos/react-ui-stack 0.8.4-main.e098934 → 0.8.4-main.e8ec1fe

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 (59) hide show
  1. package/dist/lib/browser/{chunk-3V2YUQK5.mjs → chunk-3F2KBXLP.mjs} +208 -101
  2. package/dist/lib/browser/chunk-3F2KBXLP.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +5 -1
  4. package/dist/lib/browser/meta.json +1 -1
  5. package/dist/lib/browser/playwright/index.mjs +10 -23
  6. package/dist/lib/browser/playwright/index.mjs.map +2 -2
  7. package/dist/lib/browser/testing/index.mjs +1 -1
  8. package/dist/lib/node-esm/{chunk-HE3BRF7A.mjs → chunk-SYKFLQGK.mjs} +208 -101
  9. package/dist/lib/node-esm/chunk-SYKFLQGK.mjs.map +7 -0
  10. package/dist/lib/node-esm/index.mjs +5 -1
  11. package/dist/lib/node-esm/meta.json +1 -1
  12. package/dist/lib/node-esm/playwright/index.mjs +10 -23
  13. package/dist/lib/node-esm/playwright/index.mjs.map +2 -2
  14. package/dist/lib/node-esm/testing/index.mjs +1 -1
  15. package/dist/types/src/components/Image/Image.d.ts +5 -2
  16. package/dist/types/src/components/Image/Image.d.ts.map +1 -1
  17. package/dist/types/src/components/Image/Image.stories.d.ts +3 -1
  18. package/dist/types/src/components/Image/Image.stories.d.ts.map +1 -1
  19. package/dist/types/src/components/Stack/Stack.d.ts +6 -5
  20. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
  21. package/dist/types/src/components/Stack/Stack.stories.d.ts +1 -2
  22. package/dist/types/src/components/Stack/Stack.stories.d.ts.map +1 -1
  23. package/dist/types/src/components/StackItem/StackItem.d.ts +4 -3
  24. package/dist/types/src/components/StackItem/StackItem.d.ts.map +1 -1
  25. package/dist/types/src/components/StackItem/StackItem.stories.d.ts +0 -1
  26. package/dist/types/src/components/StackItem/StackItem.stories.d.ts.map +1 -1
  27. package/dist/types/src/components/StackItem/StackItemContent.d.ts +20 -10
  28. package/dist/types/src/components/StackItem/StackItemContent.d.ts.map +1 -1
  29. package/dist/types/src/components/StackItem/StackItemHeading.d.ts.map +1 -1
  30. package/dist/types/src/exemplars/Card/Card.d.ts +21 -10
  31. package/dist/types/src/exemplars/Card/Card.d.ts.map +1 -1
  32. package/dist/types/src/exemplars/Card/Card.stories.d.ts +0 -23
  33. package/dist/types/src/exemplars/Card/Card.stories.d.ts.map +1 -1
  34. package/dist/types/src/exemplars/Card/fragments.d.ts +1 -1
  35. package/dist/types/src/exemplars/Card/fragments.d.ts.map +1 -1
  36. package/dist/types/src/exemplars/CardStack/CardStack.d.ts +3 -1
  37. package/dist/types/src/exemplars/CardStack/CardStack.d.ts.map +1 -1
  38. package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts +3 -1
  39. package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts.map +1 -1
  40. package/dist/types/src/hooks/useStackDropForElements.d.ts +2 -2
  41. package/dist/types/src/hooks/useStackDropForElements.d.ts.map +1 -1
  42. package/dist/types/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +27 -27
  44. package/src/components/Image/Image.stories.tsx +34 -8
  45. package/src/components/Image/Image.tsx +158 -73
  46. package/src/components/Stack/Stack.stories.tsx +2 -4
  47. package/src/components/Stack/Stack.tsx +93 -38
  48. package/src/components/StackItem/StackItem.stories.tsx +3 -5
  49. package/src/components/StackItem/StackItem.tsx +11 -4
  50. package/src/components/StackItem/StackItemContent.tsx +19 -8
  51. package/src/components/StackItem/StackItemHeading.tsx +1 -5
  52. package/src/exemplars/Card/Card.stories.tsx +1 -25
  53. package/src/exemplars/Card/Card.tsx +39 -15
  54. package/src/exemplars/Card/fragments.ts +1 -1
  55. package/src/exemplars/CardStack/CardStack.stories.tsx +5 -4
  56. package/src/exemplars/CardStack/CardStack.tsx +11 -8
  57. package/src/hooks/useStackDropForElements.ts +42 -35
  58. package/dist/lib/browser/chunk-3V2YUQK5.mjs.map +0 -7
  59. package/dist/lib/node-esm/chunk-HE3BRF7A.mjs.map +0 -7
@@ -2,67 +2,49 @@ import { createRequire } from 'node:module';const require = createRequire(import
2
2
 
3
3
  // src/components/Image/Image.tsx
4
4
  import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
5
- import React, { useRef, useState } from "react";
5
+ import React, { useCallback, useRef, useState } from "react";
6
6
  import { mx } from "@dxos/react-ui-theme";
7
- var Image = ({ classNames, src, alt = "", crossOrigin = "anonymous", sampleSize = 64, contrast = 0.95 }) => {
7
+ var cache = /* @__PURE__ */ new Map();
8
+ var Image = ({ classNames, src, alt = "", crossOrigin = "anonymous", sampleSize = 64, contrast = 0.9 }) => {
8
9
  var _effect = _useSignals();
9
10
  try {
10
11
  const [crossOriginState, setCrossOriginState] = useState(crossOrigin);
11
12
  const [dominantColor, setDominantColor] = useState(void 0);
12
13
  const [imageLoaded, setImageLoaded] = useState(false);
13
14
  const canvasRef = useRef(null);
14
- const extractDominantColor = (img) => {
15
- const canvas = canvasRef.current;
16
- const ctx = canvas?.getContext("2d");
17
- if (!canvas || !ctx) {
15
+ const handleImageError = () => {
16
+ setCrossOriginState(void 0);
17
+ };
18
+ const handleImageLoad = useCallback(({ target }) => {
19
+ const rgb = cache.get(src);
20
+ if (rgb) {
21
+ setDominantColor(rgb);
22
+ setImageLoaded(true);
23
+ return;
24
+ }
25
+ const img = target;
26
+ if (!canvasRef.current) {
18
27
  return;
19
28
  }
20
- canvas.width = sampleSize;
21
- canvas.height = sampleSize;
22
- ctx.drawImage(img, 0, 0, sampleSize, sampleSize);
23
29
  try {
24
- const imageData = ctx.getImageData(0, 0, sampleSize, sampleSize);
25
- const pixels = imageData.data;
26
- let r = 0;
27
- let g = 0;
28
- let b = 0;
29
- let totalWeight = 0;
30
- for (let i = 0; i < pixels.length; i += 4) {
31
- const red = pixels[i];
32
- const green = pixels[i + 1];
33
- const blue = pixels[i + 2];
34
- const alpha = pixels[i + 3];
35
- if (alpha === 0) continue;
36
- const max = Math.max(red, green, blue);
37
- const min = Math.min(red, green, blue);
38
- const saturation = max === 0 ? 0 : (max - min) / max;
39
- const weight = 1 + saturation * 2;
40
- r += red * weight;
41
- g += green * weight;
42
- b += blue * weight;
43
- totalWeight += weight;
44
- }
45
- if (totalWeight > 0) {
46
- r = Math.round(r / totalWeight);
47
- g = Math.round(g / totalWeight);
48
- b = Math.round(b / totalWeight);
49
- r = Math.round(r * contrast);
50
- g = Math.round(g * contrast);
51
- b = Math.round(b * contrast);
52
- setDominantColor(`rgb(${r}, ${g}, ${b})`);
30
+ const color = extractDominantColor(canvasRef.current, img, {
31
+ sampleSize,
32
+ contrast
33
+ });
34
+ if (color) {
35
+ const rgb2 = `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
36
+ cache.set(src, rgb2);
37
+ setDominantColor(rgb2);
53
38
  }
54
39
  } catch {
55
40
  setCrossOriginState(void 0);
56
41
  }
57
- };
58
- const handleImageError = () => {
59
- setCrossOriginState(void 0);
60
- };
61
- const handleImageLoad = (ev) => {
62
- const img = ev.target;
63
- extractDominantColor(img);
64
42
  setImageLoaded(true);
65
- };
43
+ }, [
44
+ sampleSize,
45
+ contrast,
46
+ src
47
+ ]);
66
48
  return /* @__PURE__ */ React.createElement("div", {
67
49
  className: mx(`relative flex is-full justify-center overflow-hidden transition-all duration-700`, classNames),
68
50
  style: {
@@ -96,6 +78,78 @@ var Image = ({ classNames, src, alt = "", crossOrigin = "anonymous", sampleSize
96
78
  _effect.f();
97
79
  }
98
80
  };
81
+ var extractDominantColor = (canvas, img, { sampleSize = 64, contrast = 0.95 }) => {
82
+ const ctx = canvas.getContext("2d");
83
+ if (!ctx) {
84
+ return null;
85
+ }
86
+ canvas.width = sampleSize;
87
+ canvas.height = sampleSize;
88
+ ctx.drawImage(img, 0, 0, sampleSize, sampleSize);
89
+ const imageData = ctx.getImageData(0, 0, sampleSize, sampleSize);
90
+ const pixels = imageData.data;
91
+ if (isTransparent(pixels, sampleSize)) {
92
+ return null;
93
+ }
94
+ let r = 0;
95
+ let g = 0;
96
+ let b = 0;
97
+ let totalWeight = 0;
98
+ const cornerSize = Math.floor(sampleSize * 0.125);
99
+ for (let y = 0; y < sampleSize; y++) {
100
+ for (let x = 0; x < sampleSize; x++) {
101
+ const isInTopLeft = x < cornerSize && y < cornerSize;
102
+ const isInTopRight = x >= sampleSize - cornerSize && y < cornerSize;
103
+ const isInBottomLeft = x < cornerSize && y >= sampleSize - cornerSize;
104
+ const isInBottomRight = x >= sampleSize - cornerSize && y >= sampleSize - cornerSize;
105
+ if (!isInTopLeft && !isInTopRight && !isInBottomLeft && !isInBottomRight) {
106
+ continue;
107
+ }
108
+ const i = (y * sampleSize + x) * 4;
109
+ const red = pixels[i];
110
+ const green = pixels[i + 1];
111
+ const blue = pixels[i + 2];
112
+ const alpha = pixels[i + 3];
113
+ if (alpha === 0) continue;
114
+ const max = Math.max(red, green, blue);
115
+ const min = Math.min(red, green, blue);
116
+ const saturation = max === 0 ? 0 : (max - min) / max;
117
+ const weight = 1 + saturation * 2;
118
+ r += red * weight;
119
+ g += green * weight;
120
+ b += blue * weight;
121
+ totalWeight += weight;
122
+ }
123
+ }
124
+ if (totalWeight > 0) {
125
+ r = Math.round(Math.round(r / totalWeight) * contrast);
126
+ g = Math.round(Math.round(g / totalWeight) * contrast);
127
+ b = Math.round(Math.round(b / totalWeight) * contrast);
128
+ return [
129
+ r,
130
+ g,
131
+ b
132
+ ];
133
+ }
134
+ return null;
135
+ };
136
+ var isTransparent = (pixels, sampleSize, threshold = 0.5) => {
137
+ let edgeTransparentPixels = 0;
138
+ const edgePixels = sampleSize * 4 - 4;
139
+ for (let x = 0; x < sampleSize; x++) {
140
+ const topIndex = x * 4;
141
+ if (pixels[topIndex + 3] === 0) edgeTransparentPixels++;
142
+ const bottomIndex = ((sampleSize - 1) * sampleSize + x) * 4;
143
+ if (pixels[bottomIndex + 3] === 0) edgeTransparentPixels++;
144
+ }
145
+ for (let y = 1; y < sampleSize - 1; y++) {
146
+ const leftIndex = y * sampleSize * 4;
147
+ if (pixels[leftIndex + 3] === 0) edgeTransparentPixels++;
148
+ const rightIndex = (y * sampleSize + sampleSize - 1) * 4;
149
+ if (pixels[rightIndex + 3] === 0) edgeTransparentPixels++;
150
+ }
151
+ return edgeTransparentPixels / edgePixels > threshold;
152
+ };
99
153
 
100
154
  // src/components/StackContext.tsx
101
155
  import { createContext, useContext } from "react";
@@ -123,7 +177,7 @@ var useStackItem = () => useContext(StackItemContext);
123
177
  // src/components/Stack/Stack.tsx
124
178
  import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
125
179
  import { composeRefs } from "@radix-ui/react-compose-refs";
126
- import React2, { Children, forwardRef, useCallback, useEffect, useMemo, useState as useState3 } from "react";
180
+ import React2, { Children, forwardRef, useCallback as useCallback2, useEffect, useMemo, useState as useState3 } from "react";
127
181
  import { ListItem, useId } from "@dxos/react-ui";
128
182
  import { mx as mx2 } from "@dxos/react-ui-theme";
129
183
 
@@ -133,14 +187,16 @@ import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element
133
187
  import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
134
188
  import { attachClosestEdge, extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
135
189
  import { useLayoutEffect, useState as useState2 } from "react";
136
- var useStackDropForElements = ({ id, element, scrollElement = element, selfDroppable, orientation, onRearrange }) => {
190
+ var noop = () => {
191
+ };
192
+ var useStackDropForElements = ({ id, element, scrollElement = element, orientation, selfDroppable, onRearrange }) => {
137
193
  const [dropping, setDropping] = useState2(false);
138
194
  useLayoutEffect(() => {
139
- if (!element || !selfDroppable) {
195
+ if (!element) {
140
196
  return;
141
197
  }
142
198
  const acceptSourceType = orientation === "horizontal" ? "column" : "card";
143
- return combine(dropTargetForElements({
199
+ return combine(selfDroppable ? dropTargetForElements({
144
200
  element,
145
201
  getData: ({ input, element: element2 }) => {
146
202
  return attachClosestEdge({
@@ -173,10 +229,10 @@ var useStackDropForElements = ({ id, element, scrollElement = element, selfDropp
173
229
  onRearrange(source.data, self.data, extractClosestEdge(self.data));
174
230
  }
175
231
  }
176
- }), autoScrollForElements({
232
+ }) : noop, scrollElement ? autoScrollForElements({
177
233
  element: scrollElement,
178
234
  getAllowedAxis: () => orientation
179
- }));
235
+ }) : noop);
180
236
  }, [
181
237
  element,
182
238
  scrollElement,
@@ -206,11 +262,12 @@ var scrollIntoViewAndFocus = (el, orientation) => {
206
262
  });
207
263
  return el.focus();
208
264
  };
209
- var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientation = "vertical", rail = true, size = "intrinsic", onRearrange, itemsCount = Children.count(children), getDropElement, separatorOnScroll, ...props }, forwardedRef) => {
265
+ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientation = "vertical", rail = true, size = "intrinsic", onRearrange, itemsCount = Children.count(children), getDropElement, separatorOnScroll, circularFocus, ...props }, forwardedRef) => {
210
266
  var _effect = _useSignals2();
211
267
  try {
212
268
  const stackId = useId("stack", props.id);
213
269
  const [stackElement, stackRef] = useState3(null);
270
+ const [lastFocusedItem, setLastFocusedItem] = useState3();
214
271
  const composedItemRef = composeRefs(stackRef, forwardedRef);
215
272
  const styles = {
216
273
  [orientation === "horizontal" ? "gridTemplateColumns" : "gridTemplateRows"]: size === "split" ? `repeat(${itemsCount}, 1fr)` : `repeat(${itemsCount}, min-content) [tabster-dummies] 0`,
@@ -225,7 +282,7 @@ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientati
225
282
  orientation,
226
283
  onRearrange
227
284
  });
228
- const handleScroll = useCallback(() => {
285
+ const handleScroll = useCallback2(() => {
229
286
  if (stackElement && Number.isFinite(separatorOnScroll)) {
230
287
  const scrollPosition = orientation === "horizontal" ? stackElement.scrollLeft : stackElement.scrollTop;
231
288
  const scrollSize = orientation === "horizontal" ? stackElement.scrollWidth : stackElement.scrollHeight;
@@ -241,7 +298,20 @@ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientati
241
298
  separatorOnScroll,
242
299
  orientation
243
300
  ]);
244
- const handleKeyDown = useCallback((event) => {
301
+ const handleBlur = useCallback2((event) => {
302
+ if (event.target) {
303
+ const target = event.target;
304
+ const closestStackItem = target.closest(`[data-dx-item-id]`);
305
+ if (closestStackItem?.closest(`[data-dx-stack="${stackId}"]`)) {
306
+ setLastFocusedItem(closestStackItem?.getAttribute("data-dx-item-id") ?? void 0);
307
+ }
308
+ }
309
+ props.onBlur?.(event);
310
+ }, [
311
+ stackId,
312
+ props.onBlur
313
+ ]);
314
+ const handleKeyDown = useCallback2((event) => {
245
315
  const target = event.target;
246
316
  if (event.key.startsWith("Arrow") && !target.closest(`input, textarea, [role="textbox"], [data-tabster*="mover"], [data-arrow-keys="all"], [data-arrow-keys~="${event.key.toLowerCase().slice(5)}"]`)) {
247
317
  const closestOwnedItem = target.closest(`[data-dx-stack-item="${stackId}"]`);
@@ -254,7 +324,16 @@ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientati
254
324
  const parallelDelta = (closestStackOrientation === "vertical" ? event.key === "ArrowUp" : event.key === "ArrowLeft") ? -1 : (closestStackOrientation === "vertical" ? event.key === "ArrowDown" : event.key === "ArrowRight") ? 1 : 0;
255
325
  const perpendicularDelta = (closestStackOrientation === "vertical" ? event.key === "ArrowLeft" : event.key === "ArrowUp") ? -1 : (closestStackOrientation === "vertical" ? event.key === "ArrowRight" : event.key === "ArrowDown") ? 1 : 0;
256
326
  if (parallelDelta !== 0) {
257
- const adjacentItem = closestStackItems[(closestStackItems.indexOf(closestOwnedItem) + parallelDelta + closestStackItems.length) % closestStackItems.length];
327
+ const currentIndex = closestStackItems.indexOf(closestOwnedItem);
328
+ const nextIndex = currentIndex + parallelDelta;
329
+ let adjacentItem;
330
+ if (circularFocus) {
331
+ adjacentItem = closestStackItems[(nextIndex + closestStackItems.length) % closestStackItems.length];
332
+ } else {
333
+ if (nextIndex >= 0 && nextIndex < closestStackItems.length) {
334
+ adjacentItem = closestStackItems[nextIndex];
335
+ }
336
+ }
258
337
  if (adjacentItem) {
259
338
  event.preventDefault();
260
339
  scrollIntoViewAndFocus(adjacentItem, closestStackOrientation);
@@ -263,24 +342,38 @@ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientati
263
342
  if (perpendicularDelta !== 0) {
264
343
  if (ancestorStack && ancestorOrientation !== closestStackOrientation) {
265
344
  const siblingStacks = Array.from(ancestorStack.querySelectorAll(`[data-dx-stack-item="${ancestorStack.getAttribute("data-dx-stack")}"] [data-dx-stack]`));
266
- const adjacentStack = siblingStacks[(siblingStacks.indexOf(closestStack) + perpendicularDelta + siblingStacks.length) % siblingStacks.length];
345
+ const currentStackIndex = siblingStacks.indexOf(closestStack);
346
+ const nextStackIndex = currentStackIndex + perpendicularDelta;
347
+ let adjacentStack;
348
+ if (ancestorStack.getAttribute("data-dx-stack-circular-focus") === "true") {
349
+ adjacentStack = siblingStacks[(nextStackIndex + siblingStacks.length) % siblingStacks.length];
350
+ } else {
351
+ if (nextStackIndex >= 0 && nextStackIndex < siblingStacks.length) {
352
+ adjacentStack = siblingStacks[nextStackIndex];
353
+ }
354
+ }
267
355
  const adjacentStackSelfItem = adjacentStack?.closest(`[data-dx-stack-item=${ancestorStack.getAttribute("data-dx-stack")}]`);
268
356
  const adjacentStackItems = adjacentStack ? Array.from(adjacentStack.querySelectorAll(`[data-dx-stack-item="${adjacentStack.getAttribute("data-dx-stack")}"]`)) : [];
269
- if (adjacentStackItems.length > 0) {
270
- const ownedItemRect = closestOwnedItem.getBoundingClientRect();
271
- const targetPosition = closestStackOrientation === "vertical" ? ownedItemRect.top : ownedItemRect.left;
357
+ if (adjacentStack && adjacentStackItems.length > 0) {
272
358
  let closestItem = adjacentStackItems[0];
273
- let closestDistance = Infinity;
274
- for (const item of adjacentStackItems) {
275
- const itemRect = item.getBoundingClientRect();
276
- const itemPosition = closestStackOrientation === "vertical" ? itemRect.top : itemRect.left;
277
- const distance = Math.abs(itemPosition - targetPosition);
278
- if (distance < closestDistance) {
279
- closestDistance = distance;
280
- closestItem = item;
281
- }
282
- if (closestDistance <= PERPENDICULAR_FOCUS_THRESHHOLD) {
283
- break;
359
+ const lastFocusedItem2 = adjacentStack.querySelector(`[data-dx-item-id="${adjacentStack.getAttribute("data-dx-last-focused-item") ?? "never"}"]`);
360
+ if (lastFocusedItem2) {
361
+ closestItem = lastFocusedItem2;
362
+ } else {
363
+ const ownedItemRect = closestOwnedItem.getBoundingClientRect();
364
+ const targetPosition = closestStackOrientation === "vertical" ? ownedItemRect.top : ownedItemRect.left;
365
+ let closestDistance = Infinity;
366
+ for (const item of adjacentStackItems) {
367
+ const itemRect = item.getBoundingClientRect();
368
+ const itemPosition = closestStackOrientation === "vertical" ? itemRect.top : itemRect.left;
369
+ const distance = Math.abs(itemPosition - targetPosition);
370
+ if (distance < closestDistance) {
371
+ closestDistance = distance;
372
+ closestItem = item;
373
+ }
374
+ if (closestDistance <= PERPENDICULAR_FOCUS_THRESHHOLD) {
375
+ break;
376
+ }
284
377
  }
285
378
  }
286
379
  event.preventDefault();
@@ -306,7 +399,8 @@ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientati
306
399
  props.onKeyDown?.(event);
307
400
  }, [
308
401
  props.onKeyDown,
309
- stackId
402
+ stackId,
403
+ circularFocus
310
404
  ]);
311
405
  const gridClasses = useMemo(() => {
312
406
  if (!rail) {
@@ -352,7 +446,10 @@ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientati
352
446
  ...props,
353
447
  className: mx2("grid relative [--stack-gap:var(--dx-trimXs)]", gridClasses, size === "contain" && (orientation === "horizontal" ? "overflow-x-auto overscroll-x-contain min-bs-0 max-bs-full bs-full" : "overflow-y-auto min-is-0 max-is-full is-full"), classNames),
354
448
  onKeyDown: handleKeyDown,
449
+ onBlur: handleBlur,
355
450
  "data-dx-stack": stackId,
451
+ "data-dx-stack-circular-focus": circularFocus,
452
+ "data-dx-last-focused-item": lastFocusedItem,
356
453
  "data-rail": rail,
357
454
  "aria-orientation": orientation,
358
455
  style: styles,
@@ -397,9 +494,9 @@ import { draggable, dropTargetForElements as dropTargetForElements2 } from "@atl
397
494
  import { preserveOffsetOnSource } from "@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source";
398
495
  import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
399
496
  import { attachClosestEdge as attachClosestEdge2, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
400
- import { useFocusableGroup as useFocusableGroup2 } from "@fluentui/react-tabster";
497
+ import { useFocusableGroup } from "@fluentui/react-tabster";
401
498
  import { composeRefs as composeRefs2 } from "@radix-ui/react-compose-refs";
402
- import React9, { forwardRef as forwardRef5, useCallback as useCallback2, useLayoutEffect as useLayoutEffect2, useMemo as useMemo3, useState as useState5 } from "react";
499
+ import React9, { forwardRef as forwardRef5, useCallback as useCallback3, useLayoutEffect as useLayoutEffect2, useMemo as useMemo3, useState as useState5 } from "react";
403
500
  import { createPortal } from "react-dom";
404
501
  import { ListItem as ListItem2 } from "@dxos/react-ui";
405
502
  import { resizeAttributes, sizeStyle } from "@dxos/react-ui-dnd";
@@ -409,7 +506,7 @@ import { mx as mx6 } from "@dxos/react-ui-theme";
409
506
  import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
410
507
  import React3, { forwardRef as forwardRef2, useMemo as useMemo2 } from "react";
411
508
  import { mx as mx3 } from "@dxos/react-ui-theme";
412
- var StackItemContent = /* @__PURE__ */ forwardRef2(({ children, toolbar, statusbar, layoutManaged, classNames, size = "intrinsic", ...props }, forwardedRef) => {
509
+ var StackItemContent = /* @__PURE__ */ forwardRef2(({ children, toolbar, statusbar, layoutManaged, classNames, size = "intrinsic", scrollable, ...props }, forwardedRef) => {
413
510
  var _effect = _useSignals3();
414
511
  try {
415
512
  const { size: stackItemSize } = useStack();
@@ -432,7 +529,7 @@ var StackItemContent = /* @__PURE__ */ forwardRef2(({ children, toolbar, statusb
432
529
  return /* @__PURE__ */ React3.createElement("div", {
433
530
  role: "none",
434
531
  ...props,
435
- className: mx3("group grid grid-cols-[100%] density-coarse", stackItemSize === "contain" && "min-bs-0 overflow-hidden", size === "video" ? "aspect-video" : size === "square" && "aspect-square", toolbar && "[&>.dx-toolbar]:relative [&>.dx-toolbar]:border-be [&>.dx-toolbar]:border-subduedSeparator", role === "section" && toolbar && "[&_.dx-toolbar]:sticky [&_.dx-toolbar]:z-[1] [&_.dx-toolbar]:block-start-0 [&_.dx-toolbar]:-mbe-px [&_.dx-toolbar]:min-is-0", classNames),
532
+ className: mx3("group grid grid-cols-[100%] density-coarse", size === "video" ? "aspect-video" : size === "square" && "aspect-square", stackItemSize === "contain" && "min-bs-0 overflow-hidden", scrollable ? "min-bs-0 overflow-y-auto scrollbar-thin contain-layout" : "overflow-hidden", role === "section" && toolbar && "[&_.dx-toolbar]:sticky [&_.dx-toolbar]:z-[1] [&_.dx-toolbar]:block-start-0 [&_.dx-toolbar]:-mbe-px [&_.dx-toolbar]:min-is-0", toolbar && "[&>.dx-toolbar]:relative [&>.dx-toolbar]:border-be [&>.dx-toolbar]:border-subduedSeparator", classNames),
436
533
  style,
437
534
  "data-popover-collision-boundary": true,
438
535
  ref: forwardedRef
@@ -462,7 +559,6 @@ var StackItemDragHandle = ({ asChild, children }) => {
462
559
 
463
560
  // src/components/StackItem/StackItemHeading.tsx
464
561
  import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
465
- import { useFocusableGroup } from "@fluentui/react-tabster";
466
562
  import { Slot as Slot2 } from "@radix-ui/react-slot";
467
563
  import React5, { forwardRef as forwardRef3 } from "react";
468
564
  import { useAttention } from "@dxos/react-ui-attention";
@@ -471,16 +567,11 @@ var StackItemHeading = ({ children, classNames, asChild, separateOnScroll, ...pr
471
567
  var _effect = _useSignals5();
472
568
  try {
473
569
  const { orientation } = useStack();
474
- const focusableGroupAttrs = useFocusableGroup({
475
- tabBehavior: "limited"
476
- });
477
570
  const Root = asChild ? Slot2 : "div";
478
571
  return /* @__PURE__ */ React5.createElement(Root, {
479
572
  role: "heading",
480
573
  ...props,
481
- tabIndex: 0,
482
- ...focusableGroupAttrs,
483
- className: mx4("flex items-center dx-focus-ring-inset-over-all relative !border-is-0 bg-headerSurface", separateOnScroll ? 'border-transparent [[data-scroll-separator="true"]_&]:border-subduedSeparator' : "border-subduedSeparator", orientation === "horizontal" ? "bs-[--rail-size]" : "is-[--rail-size] flex-col", orientation === "horizontal" ? "border-be" : "border-ie", classNames)
574
+ className: mx4("flex items-center !border-is-0 bg-headerSurface", separateOnScroll ? 'border-transparent [[data-scroll-separator="true"]_&]:border-subduedSeparator' : "border-subduedSeparator", orientation === "horizontal" ? "bs-[--rail-size]" : "is-[--rail-size] flex-col", orientation === "horizontal" ? "border-be" : "border-ie", classNames)
484
575
  }, children);
485
576
  } finally {
486
577
  _effect.f();
@@ -681,7 +772,7 @@ var StackItemRoot = /* @__PURE__ */ forwardRef5(({ item, children, classNames, s
681
772
  const [size = orientation === "horizontal" ? DEFAULT_HORIZONTAL_SIZE : DEFAULT_VERTICAL_SIZE, setInternalSize] = useState5(propsSize);
682
773
  const Root = role ?? "div";
683
774
  const composedItemRef = composeRefs2(itemRef, forwardedRef);
684
- const setSize = useCallback2((nextSize, commit) => {
775
+ const setSize = useCallback3((nextSize, commit) => {
685
776
  setInternalSize(nextSize);
686
777
  if (commit) {
687
778
  onSizeChange?.(nextSize);
@@ -790,7 +881,7 @@ var StackItemRoot = /* @__PURE__ */ forwardRef5(({ item, children, classNames, s
790
881
  selfDragHandleElement,
791
882
  itemElement
792
883
  ]);
793
- const focusableGroupAttrs = useFocusableGroup2({
884
+ const focusableGroupAttrs = useFocusableGroup({
794
885
  tabBehavior: "limited"
795
886
  });
796
887
  const shouldShowDropIndicator = () => {
@@ -831,8 +922,9 @@ var StackItemRoot = /* @__PURE__ */ forwardRef5(({ item, children, classNames, s
831
922
  ...props,
832
923
  tabIndex: 0,
833
924
  ...focusableGroupAttrs,
834
- className: mx6("group/stack-item grid relative", focusIndicatorVariant === "over-all" ? "dx-focus-ring-inset-over-all" : orientation === "horizontal" ? "dx-focus-ring-group-x" : "dx-focus-ring-group-y", orientation === "horizontal" ? "grid-rows-subgrid" : "grid-cols-subgrid", rail && (orientation === "horizontal" ? "row-span-2" : "col-span-2"), role === "section" && orientation !== "horizontal" && "border-be border-subduedSeparator", classNames),
925
+ className: mx6("group/stack-item grid relative", focusIndicatorVariant === "over-all" ? "dx-focus-ring-inset-over-all" : focusIndicatorVariant === "over-all-always" ? "dx-focus-ring-inset-over-all-always" : orientation === "horizontal" ? focusIndicatorVariant === "group-always" ? "dx-focus-ring-group-x-always" : "dx-focus-ring-group-x" : focusIndicatorVariant === "group-always" ? "dx-focus-ring-group-y-always" : "dx-focus-ring-group-y", orientation === "horizontal" ? "grid-rows-subgrid" : "grid-cols-subgrid", rail && (orientation === "horizontal" ? "row-span-2" : "col-span-2"), role === "section" && orientation !== "horizontal" && "border-be border-subduedSeparator", classNames),
835
926
  "data-dx-stack-item": stackId,
927
+ "data-dx-item-id": item.id,
836
928
  ...resizeAttributes,
837
929
  style: {
838
930
  ...stackSize !== "split" && sizeStyle(size, orientation),
@@ -882,7 +974,7 @@ var cardDialogPaddedOverflow = `${cardDialogOverflow} plb-cardSpacingBlock`;
882
974
  var cardDialogSearchListRoot = "pli-cardSpacingInline pbs-cardSpacingBlock [&>input]:mbe-0 min-bs-0 flex-1 flex flex-col";
883
975
  var cardText = cardSpacing;
884
976
  var cardHeading = "text-lg font-medium line-clamp-2 grow";
885
- var cardChrome = "pli-[--dx-cardSpacingChrome] mlb-[--dx-cardSpacingChrome] [&_.dx-button]:text-start [&_.dx-button]:is-full";
977
+ var cardChrome = "pli-[--dx-cardSpacingChrome] mlb-[--dx-cardSpacingChrome] [&_.dx-button]:text-start [&_.dx-button]:is-full [&_.dx-button]:pis-[calc(var(--dx-cardSpacingInline)-var(--dx-cardSpacingChrome))]";
886
978
 
887
979
  // src/exemplars/Card/Card.tsx
888
980
  import { useSignals as _useSignals10 } from "@preact-signals/safe-react/tracking";
@@ -890,8 +982,10 @@ import { Primitive } from "@radix-ui/react-primitive";
890
982
  import { Slot as Slot3 } from "@radix-ui/react-slot";
891
983
  import React10, { forwardRef as forwardRef6 } from "react";
892
984
  import { Icon as Icon2, IconButton, Toolbar, useTranslation as useTranslation2 } from "@dxos/react-ui";
893
- import { hoverableControls, mx as mx7 } from "@dxos/react-ui-theme";
894
- var CardStaticRoot = /* @__PURE__ */ forwardRef6(({ children, classNames, asChild, role = "group", ...props }, forwardedRef) => {
985
+ import { cardMinInlineSize, hoverableControls, mx as mx7 } from "@dxos/react-ui-theme";
986
+ var cardDefaultInlineSize = cardMinInlineSize;
987
+ var cardStackDefaultInlineSizeRem = cardDefaultInlineSize + 2.125;
988
+ var CardStaticRoot = /* @__PURE__ */ forwardRef6(({ children, classNames, id, asChild, role = "group", ...props }, forwardedRef) => {
895
989
  var _effect = _useSignals10();
896
990
  try {
897
991
  const Root = asChild ? Slot3 : "div";
@@ -905,6 +999,9 @@ var CardStaticRoot = /* @__PURE__ */ forwardRef6(({ children, classNames, asChil
905
999
  role
906
1000
  };
907
1001
  return /* @__PURE__ */ React10.createElement(Root, {
1002
+ ...id && {
1003
+ "data-object-id": id
1004
+ },
908
1005
  ...props,
909
1006
  ...rootProps,
910
1007
  ref: forwardedRef
@@ -913,7 +1010,7 @@ var CardStaticRoot = /* @__PURE__ */ forwardRef6(({ children, classNames, asChil
913
1010
  _effect.f();
914
1011
  }
915
1012
  });
916
- var CardSurfaceRoot = ({ role = "never", children, classNames }) => {
1013
+ var CardSurfaceRoot = ({ id, role = "never", children, classNames }) => {
917
1014
  var _effect = _useSignals10();
918
1015
  try {
919
1016
  if ([
@@ -922,6 +1019,9 @@ var CardSurfaceRoot = ({ role = "never", children, classNames }) => {
922
1019
  "card--extrinsic"
923
1020
  ].includes(role)) {
924
1021
  return /* @__PURE__ */ React10.createElement("div", {
1022
+ ...id && {
1023
+ "data-object-id": id
1024
+ },
925
1025
  className: mx7(role === "card--popover" ? "popover-card-width" : [
926
1026
  "card--intrinsic",
927
1027
  "card--extrinsic"
@@ -929,6 +1029,7 @@ var CardSurfaceRoot = ({ role = "never", children, classNames }) => {
929
1029
  }, children);
930
1030
  } else {
931
1031
  return /* @__PURE__ */ React10.createElement(CardStaticRoot, {
1032
+ id,
932
1033
  classNames: [
933
1034
  role === "card--transclusion" && "mlb-1",
934
1035
  role === "card--transclusion" && hoverableControls,
@@ -1006,8 +1107,9 @@ var CardPoster = (props) => {
1006
1107
  if (props.image) {
1007
1108
  return /* @__PURE__ */ React10.createElement(Image, {
1008
1109
  classNames: [
1009
- `dx-card__poster is-full __bs-auto`,
1010
- aspect
1110
+ `dx-card__poster is-full`,
1111
+ aspect,
1112
+ props.classNames
1011
1113
  ],
1012
1114
  src: props.image,
1013
1115
  alt: props.alt
@@ -1016,7 +1118,7 @@ var CardPoster = (props) => {
1016
1118
  if (props.icon) {
1017
1119
  return /* @__PURE__ */ React10.createElement("div", {
1018
1120
  role: "image",
1019
- className: mx7(`dx-card__poster grid place-items-center bg-inputSurface text-subdued`, aspect),
1121
+ className: mx7(`dx-card__poster grid place-items-center bg-inputSurface text-subdued`, aspect, props.classNames),
1020
1122
  "aria-label": props.alt
1021
1123
  }, /* @__PURE__ */ React10.createElement(Icon2, {
1022
1124
  icon: props.icon,
@@ -1192,21 +1294,24 @@ var CardStackFooter = /* @__PURE__ */ forwardRef7(({ children, classNames, asChi
1192
1294
  _effect.f();
1193
1295
  }
1194
1296
  });
1195
- var cardStackContent = [
1196
- "shrink min-bs-0 bg-baseSurface border border-separator rounded-md grid dx-focus-ring-group-x-indicator kanban-drop",
1197
- railGridHorizontalContainFitContent
1198
- ];
1199
- var CardStackContent = /* @__PURE__ */ forwardRef7(({ children, classNames, asChild, role = "none", ...props }, forwardedRef) => {
1297
+ var cardStackContent = "shrink min-bs-0 bg-baseSurface border border-separator rounded-md grid dx-focus-ring-group-x-indicator kanban-drop";
1298
+ var CardStackContent = /* @__PURE__ */ forwardRef7(({ children, classNames, asChild, role = "none", footer = true, ...props }, forwardedRef) => {
1200
1299
  var _effect = _useSignals12();
1201
1300
  try {
1202
1301
  const Root = asChild ? Slot4 : "div";
1302
+ const baseClassNames = footer ? [
1303
+ cardStackContent,
1304
+ railGridHorizontalContainFitContent
1305
+ ] : [
1306
+ cardStackContent
1307
+ ];
1203
1308
  const rootProps = asChild ? {
1204
1309
  classNames: [
1205
- ...cardStackContent,
1310
+ ...baseClassNames,
1206
1311
  classNames
1207
1312
  ]
1208
1313
  } : {
1209
- className: mx9(...cardStackContent, classNames),
1314
+ className: mx9(...baseClassNames, classNames),
1210
1315
  role
1211
1316
  };
1212
1317
  return /* @__PURE__ */ React12.createElement(Root, {
@@ -1364,6 +1469,8 @@ export {
1364
1469
  cardText,
1365
1470
  cardHeading,
1366
1471
  cardChrome,
1472
+ cardDefaultInlineSize,
1473
+ cardStackDefaultInlineSizeRem,
1367
1474
  Card,
1368
1475
  CardDragPreview2 as CardDragPreview,
1369
1476
  cardStackHeading,
@@ -1374,4 +1481,4 @@ export {
1374
1481
  CardStack,
1375
1482
  CardStackDragPreview
1376
1483
  };
1377
- //# sourceMappingURL=chunk-HE3BRF7A.mjs.map
1484
+ //# sourceMappingURL=chunk-SYKFLQGK.mjs.map