@dxos/react-ui-stack 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae

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 (112) hide show
  1. package/dist/lib/browser/index.mjs +743 -65
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/playwright/index.mjs +10 -23
  5. package/dist/lib/browser/playwright/index.mjs.map +2 -2
  6. package/dist/lib/node-esm/index.mjs +744 -65
  7. package/dist/lib/node-esm/index.mjs.map +4 -4
  8. package/dist/lib/node-esm/meta.json +1 -1
  9. package/dist/lib/node-esm/playwright/index.mjs +10 -23
  10. package/dist/lib/node-esm/playwright/index.mjs.map +2 -2
  11. package/dist/types/src/components/Stack/Stack.d.ts +8 -8
  12. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
  13. package/dist/types/src/components/StackContext.d.ts +2 -2
  14. package/dist/types/src/components/StackContext.d.ts.map +1 -1
  15. package/dist/types/src/components/StackItem/MenuSignifier.d.ts.map +1 -1
  16. package/dist/types/src/components/StackItem/StackItem.d.ts +6 -10
  17. package/dist/types/src/components/StackItem/StackItem.d.ts.map +1 -1
  18. package/dist/types/src/components/StackItem/StackItem.stories.d.ts.map +1 -1
  19. package/dist/types/src/components/StackItem/StackItemContent.d.ts +2 -43
  20. package/dist/types/src/components/StackItem/StackItemContent.d.ts.map +1 -1
  21. package/dist/types/src/components/StackItem/StackItemDragHandle.d.ts.map +1 -1
  22. package/dist/types/src/components/StackItem/StackItemHeading.d.ts.map +1 -1
  23. package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts +1 -1
  24. package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts.map +1 -1
  25. package/dist/types/src/components/StackItem/StackItemSigil.d.ts +2 -2
  26. package/dist/types/src/components/StackItem/StackItemSigil.d.ts.map +1 -1
  27. package/dist/types/src/components/index.d.ts +1 -2
  28. package/dist/types/src/components/index.d.ts.map +1 -1
  29. package/dist/types/src/components/{defs.d.ts → types.d.ts} +1 -1
  30. package/dist/types/src/components/types.d.ts.map +1 -0
  31. package/dist/types/src/hooks/useStackDropForElements.d.ts +8 -6
  32. package/dist/types/src/hooks/useStackDropForElements.d.ts.map +1 -1
  33. package/dist/types/src/index.d.ts +0 -1
  34. package/dist/types/src/index.d.ts.map +1 -1
  35. package/dist/types/src/translations.d.ts +2 -2
  36. package/dist/types/src/translations.d.ts.map +1 -1
  37. package/dist/types/tsconfig.tsbuildinfo +1 -1
  38. package/package.json +41 -38
  39. package/src/components/Stack/Stack.stories.tsx +2 -2
  40. package/src/components/Stack/Stack.tsx +27 -25
  41. package/src/components/StackContext.tsx +2 -2
  42. package/src/components/StackItem/MenuSignifier.tsx +2 -9
  43. package/src/components/StackItem/StackItem.stories.tsx +6 -4
  44. package/src/components/StackItem/StackItem.tsx +26 -14
  45. package/src/components/StackItem/StackItemContent.tsx +23 -54
  46. package/src/components/StackItem/StackItemDragHandle.tsx +4 -3
  47. package/src/components/StackItem/StackItemHeading.tsx +12 -11
  48. package/src/components/StackItem/StackItemResizeHandle.tsx +1 -1
  49. package/src/components/StackItem/StackItemSigil.tsx +8 -5
  50. package/src/components/index.ts +2 -2
  51. package/src/hooks/useStackDropForElements.ts +58 -44
  52. package/src/index.ts +0 -3
  53. package/src/playwright/playwright.config.ts +1 -1
  54. package/src/translations.ts +1 -1
  55. package/dist/lib/browser/chunk-SM27YTH3.mjs +0 -1418
  56. package/dist/lib/browser/chunk-SM27YTH3.mjs.map +0 -7
  57. package/dist/lib/browser/testing/index.mjs +0 -31
  58. package/dist/lib/browser/testing/index.mjs.map +0 -7
  59. package/dist/lib/node-esm/chunk-MMAOXKOM.mjs +0 -1420
  60. package/dist/lib/node-esm/chunk-MMAOXKOM.mjs.map +0 -7
  61. package/dist/lib/node-esm/testing/index.mjs +0 -32
  62. package/dist/lib/node-esm/testing/index.mjs.map +0 -7
  63. package/dist/types/src/components/Image/Image.d.ts +0 -11
  64. package/dist/types/src/components/Image/Image.d.ts.map +0 -1
  65. package/dist/types/src/components/Image/Image.stories.d.ts +0 -30
  66. package/dist/types/src/components/Image/Image.stories.d.ts.map +0 -1
  67. package/dist/types/src/components/Image/index.d.ts +0 -2
  68. package/dist/types/src/components/Image/index.d.ts.map +0 -1
  69. package/dist/types/src/components/defs.d.ts.map +0 -1
  70. package/dist/types/src/components/deprecated/LayoutControls.d.ts +0 -19
  71. package/dist/types/src/components/deprecated/LayoutControls.d.ts.map +0 -1
  72. package/dist/types/src/exemplars/Card/Card.d.ts +0 -65
  73. package/dist/types/src/exemplars/Card/Card.d.ts.map +0 -1
  74. package/dist/types/src/exemplars/Card/Card.stories.d.ts +0 -21
  75. package/dist/types/src/exemplars/Card/Card.stories.d.ts.map +0 -1
  76. package/dist/types/src/exemplars/Card/CardDragPreview.d.ts +0 -6
  77. package/dist/types/src/exemplars/Card/CardDragPreview.d.ts.map +0 -1
  78. package/dist/types/src/exemplars/Card/fragments.d.ts +0 -13
  79. package/dist/types/src/exemplars/Card/fragments.d.ts.map +0 -1
  80. package/dist/types/src/exemplars/Card/index.d.ts +0 -4
  81. package/dist/types/src/exemplars/Card/index.d.ts.map +0 -1
  82. package/dist/types/src/exemplars/CardStack/CardStack.d.ts +0 -42
  83. package/dist/types/src/exemplars/CardStack/CardStack.d.ts.map +0 -1
  84. package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts +0 -15
  85. package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts.map +0 -1
  86. package/dist/types/src/exemplars/CardStack/CardStackDragPreview.d.ts +0 -9
  87. package/dist/types/src/exemplars/CardStack/CardStackDragPreview.d.ts.map +0 -1
  88. package/dist/types/src/exemplars/CardStack/index.d.ts +0 -3
  89. package/dist/types/src/exemplars/CardStack/index.d.ts.map +0 -1
  90. package/dist/types/src/exemplars/index.d.ts +0 -3
  91. package/dist/types/src/exemplars/index.d.ts.map +0 -1
  92. package/dist/types/src/testing/CardContainer.d.ts +0 -6
  93. package/dist/types/src/testing/CardContainer.d.ts.map +0 -1
  94. package/dist/types/src/testing/index.d.ts +0 -2
  95. package/dist/types/src/testing/index.d.ts.map +0 -1
  96. package/src/components/Image/Image.stories.tsx +0 -56
  97. package/src/components/Image/Image.tsx +0 -137
  98. package/src/components/Image/index.ts +0 -5
  99. package/src/components/deprecated/LayoutControls.tsx +0 -109
  100. package/src/exemplars/Card/Card.stories.tsx +0 -64
  101. package/src/exemplars/Card/Card.tsx +0 -204
  102. package/src/exemplars/Card/CardDragPreview.tsx +0 -22
  103. package/src/exemplars/Card/fragments.ts +0 -24
  104. package/src/exemplars/Card/index.ts +0 -7
  105. package/src/exemplars/CardStack/CardStack.stories.tsx +0 -173
  106. package/src/exemplars/CardStack/CardStack.tsx +0 -139
  107. package/src/exemplars/CardStack/CardStackDragPreview.tsx +0 -61
  108. package/src/exemplars/CardStack/index.ts +0 -6
  109. package/src/exemplars/index.ts +0 -6
  110. package/src/testing/CardContainer.tsx +0 -37
  111. package/src/testing/index.ts +0 -5
  112. /package/src/components/{defs.ts → types.ts} +0 -0
@@ -1,77 +1,756 @@
1
1
  import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
2
- import {
3
- Card,
4
- CardDragPreview,
5
- CardStack,
6
- CardStackDragPreview,
7
- DEFAULT_EXTRINSIC_SIZE,
8
- DEFAULT_HORIZONTAL_SIZE,
9
- DEFAULT_VERTICAL_SIZE,
10
- Image,
11
- Stack,
12
- StackContext,
13
- StackItem,
14
- StackItemDragPreview,
15
- autoScrollRootAttributes,
16
- cardChrome,
17
- cardDefaultInlineSize,
18
- cardDialogContent,
19
- cardDialogHeader,
20
- cardDialogOverflow,
21
- cardDialogPaddedOverflow,
22
- cardDialogSearchListRoot,
23
- cardHeading,
24
- cardNoSpacing,
25
- cardRoot,
26
- cardSpacing,
27
- cardStackContent,
28
- cardStackDefaultInlineSizeRem,
29
- cardStackFooter,
30
- cardStackHeading,
31
- cardStackItem,
32
- cardStackRoot,
33
- cardText,
34
- labelSpacing,
35
- railGridHorizontal,
36
- railGridHorizontalContainFitContent,
37
- railGridVertical,
38
- railGridVerticalContainFitContent,
39
- translationKey,
40
- translations
41
- } from "./chunk-MMAOXKOM.mjs";
2
+
3
+ // src/components/Stack/Stack.tsx
4
+ import { composeRefs } from "@radix-ui/react-compose-refs";
5
+ import React, { Children, forwardRef, useCallback, useEffect, useMemo, useState as useState2 } from "react";
6
+ import { ListItem, useId } from "@dxos/react-ui";
7
+ import { mx } from "@dxos/ui-theme";
8
+
9
+ // src/hooks/useStackDropForElements.ts
10
+ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
11
+ import { dropTargetForElements } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
12
+ import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
13
+ import { attachClosestEdge, extractClosestEdge } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
14
+ import { useLayoutEffect, useState } from "react";
15
+ var noop = () => {
16
+ };
17
+ var useStackDropForElements = ({ id, element, scrollElement = element, orientation, selfDroppable, onRearrange }) => {
18
+ const [dropping, setDropping] = useState(false);
19
+ useLayoutEffect(() => {
20
+ if (!element) {
21
+ return;
22
+ }
23
+ const acceptSourceType = orientation === "horizontal" ? "column" : "card";
24
+ return combine(selfDroppable ? dropTargetForElements({
25
+ element,
26
+ getData: ({ input, element: element2 }) => {
27
+ return attachClosestEdge({
28
+ id,
29
+ type: orientation === "horizontal" ? "card" : "column"
30
+ }, {
31
+ input,
32
+ element: element2,
33
+ allowedEdges: [
34
+ orientation === "horizontal" ? "left" : "top"
35
+ ]
36
+ });
37
+ },
38
+ onDragEnter: ({ source }) => {
39
+ if (source.data.type === acceptSourceType) {
40
+ setDropping(true);
41
+ }
42
+ },
43
+ onDrag: ({ source }) => {
44
+ if (source.data.type === acceptSourceType) {
45
+ setDropping(true);
46
+ }
47
+ },
48
+ onDragLeave: () => {
49
+ return setDropping(false);
50
+ },
51
+ onDrop: ({ self, source }) => {
52
+ setDropping(false);
53
+ if (source.data.type === acceptSourceType && selfDroppable && onRearrange) {
54
+ onRearrange(source.data, self.data, extractClosestEdge(self.data));
55
+ }
56
+ }
57
+ }) : noop, scrollElement ? autoScrollForElements({
58
+ element: scrollElement,
59
+ getAllowedAxis: () => orientation
60
+ }) : noop);
61
+ }, [
62
+ id,
63
+ element,
64
+ scrollElement,
65
+ selfDroppable,
66
+ orientation,
67
+ onRearrange
68
+ ]);
69
+ return {
70
+ dropping
71
+ };
72
+ };
73
+
74
+ // src/components/StackContext.tsx
75
+ import { createContext, useContext } from "react";
76
+ var StackContext = /* @__PURE__ */ createContext({
77
+ orientation: "vertical",
78
+ rail: true,
79
+ size: "intrinsic"
80
+ });
81
+ var useStack = () => useContext(StackContext);
82
+ var idle = {
83
+ type: "idle"
84
+ };
85
+ var StackItemContext = /* @__PURE__ */ createContext({
86
+ selfDragHandleRef: () => {
87
+ },
88
+ size: "min-content",
89
+ setSize: () => {
90
+ },
91
+ state: idle,
92
+ setState: () => {
93
+ }
94
+ });
95
+ var useStackItem = () => useContext(StackItemContext);
96
+
97
+ // src/components/Stack/Stack.tsx
98
+ var railGridHorizontal = "grid-rows-[[rail-start]_var(--dx-rail-size)_[content-start]_1fr_[content-end]]";
99
+ var railGridVertical = "grid-cols-[[rail-start]_var(--dx-rail-size)_[content-start]_1fr_[content-end]]";
100
+ var railGridHorizontalContainFitContent = "grid-rows-[[rail-start]_var(--dx-rail-size)_[content-start]_fit-content(calc(100%-var(--dx-rail-size)*2+2px))_[content-end]]";
101
+ var railGridVerticalContainFitContent = "grid-cols-[[rail-start]_var(--dx-rail-size)_[content-start]_fit-content(calc(100%-var(--dx-rail-size)*2+2px))_[content-end]]";
102
+ var autoScrollRootAttributes = {
103
+ "data-drag-autoscroll": "idle"
104
+ };
105
+ var PERPENDICULAR_FOCUS_THRESHHOLD = 128;
106
+ var scrollIntoViewAndFocus = (el, orientation) => {
107
+ el.scrollIntoView({
108
+ behavior: "instant",
109
+ [orientation === "vertical" ? "block" : "inline"]: "center"
110
+ });
111
+ return el.focus();
112
+ };
113
+ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientation = "vertical", rail = true, size = "intrinsic", onRearrange, itemsCount = Children.count(children), getDropElement, separatorOnScroll, circularFocus, ...props }, forwardedRef) => {
114
+ const stackId = useId("stack", props.id);
115
+ const [stackElement, stackRef] = useState2(null);
116
+ const [lastFocusedItem, setLastFocusedItem] = useState2();
117
+ const composedItemRef = composeRefs(stackRef, forwardedRef);
118
+ const styles = {
119
+ [orientation === "horizontal" ? "gridTemplateColumns" : "gridTemplateRows"]: size === "split" ? `repeat(${itemsCount}, 1fr)` : `repeat(${itemsCount}, min-content) [tabster-dummies] 0`,
120
+ ...style
121
+ };
122
+ const selfDroppable = !!(itemsCount < 1 && onRearrange && props.id);
123
+ const { dropping } = useStackDropForElements({
124
+ id: props.id,
125
+ element: getDropElement && stackElement ? getDropElement(stackElement) : stackElement,
126
+ scrollElement: stackElement,
127
+ selfDroppable,
128
+ orientation,
129
+ onRearrange
130
+ });
131
+ const handleScroll = useCallback(() => {
132
+ if (stackElement && Number.isFinite(separatorOnScroll)) {
133
+ const scrollPosition = orientation === "horizontal" ? stackElement.scrollLeft : stackElement.scrollTop;
134
+ const scrollSize = orientation === "horizontal" ? stackElement.scrollWidth : stackElement.scrollHeight;
135
+ const clientSize = orientation === "horizontal" ? stackElement.clientWidth : stackElement.clientHeight;
136
+ const separatorHost = stackElement.closest("[data-scroll-separator]");
137
+ if (separatorHost) {
138
+ separatorHost.setAttribute("data-scroll-separator", String(scrollPosition > separatorOnScroll));
139
+ separatorHost.setAttribute("data-scroll-separator-end", String(scrollSize - (scrollPosition + clientSize) > separatorOnScroll));
140
+ }
141
+ }
142
+ }, [
143
+ stackElement,
144
+ separatorOnScroll,
145
+ orientation
146
+ ]);
147
+ const handleBlur = useCallback((event) => {
148
+ if (event.target) {
149
+ const target = event.target;
150
+ const closestStackItem = target.closest(`[data-dx-item-id]`);
151
+ if (closestStackItem?.closest(`[data-dx-stack="${stackId}"]`)) {
152
+ setLastFocusedItem(closestStackItem?.getAttribute("data-dx-item-id") ?? void 0);
153
+ }
154
+ }
155
+ props.onBlur?.(event);
156
+ }, [
157
+ stackId,
158
+ props.onBlur
159
+ ]);
160
+ const handleKeyDown = useCallback((event) => {
161
+ const target = event.target;
162
+ 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)}"]`)) {
163
+ const closestOwnedItem = target.closest(`[data-dx-stack-item="${stackId}"]`);
164
+ const closestStack = target.closest("[data-dx-stack]");
165
+ const closestStackItems = Array.from(closestStack?.querySelectorAll(`[data-dx-stack-item="${stackId}"]`) ?? []);
166
+ const closestStackOrientation = closestStack?.getAttribute("aria-orientation");
167
+ const ancestorStack = closestStack?.parentElement?.closest("[data-dx-stack]");
168
+ if (closestOwnedItem && closestStack) {
169
+ const ancestorOrientation = ancestorStack?.getAttribute("aria-orientation");
170
+ const parallelDelta = (closestStackOrientation === "vertical" ? event.key === "ArrowUp" : event.key === "ArrowLeft") ? -1 : (closestStackOrientation === "vertical" ? event.key === "ArrowDown" : event.key === "ArrowRight") ? 1 : 0;
171
+ const perpendicularDelta = (closestStackOrientation === "vertical" ? event.key === "ArrowLeft" : event.key === "ArrowUp") ? -1 : (closestStackOrientation === "vertical" ? event.key === "ArrowRight" : event.key === "ArrowDown") ? 1 : 0;
172
+ if (parallelDelta !== 0) {
173
+ const currentIndex = closestStackItems.indexOf(closestOwnedItem);
174
+ const nextIndex = currentIndex + parallelDelta;
175
+ let adjacentItem;
176
+ if (circularFocus) {
177
+ adjacentItem = closestStackItems[(nextIndex + closestStackItems.length) % closestStackItems.length];
178
+ } else {
179
+ if (nextIndex >= 0 && nextIndex < closestStackItems.length) {
180
+ adjacentItem = closestStackItems[nextIndex];
181
+ }
182
+ }
183
+ if (adjacentItem) {
184
+ event.preventDefault();
185
+ scrollIntoViewAndFocus(adjacentItem, closestStackOrientation);
186
+ }
187
+ }
188
+ if (perpendicularDelta !== 0) {
189
+ if (ancestorStack && ancestorOrientation !== closestStackOrientation) {
190
+ const siblingStacks = Array.from(ancestorStack.querySelectorAll(`[data-dx-stack-item="${ancestorStack.getAttribute("data-dx-stack")}"] [data-dx-stack]`));
191
+ const currentStackIndex = siblingStacks.indexOf(closestStack);
192
+ const nextStackIndex = currentStackIndex + perpendicularDelta;
193
+ let adjacentStack;
194
+ if (ancestorStack.getAttribute("data-dx-stack-circular-focus") === "true") {
195
+ adjacentStack = siblingStacks[(nextStackIndex + siblingStacks.length) % siblingStacks.length];
196
+ } else {
197
+ if (nextStackIndex >= 0 && nextStackIndex < siblingStacks.length) {
198
+ adjacentStack = siblingStacks[nextStackIndex];
199
+ }
200
+ }
201
+ const adjacentStackSelfItem = adjacentStack?.closest(`[data-dx-stack-item=${ancestorStack.getAttribute("data-dx-stack")}]`);
202
+ const adjacentStackItems = adjacentStack ? Array.from(adjacentStack.querySelectorAll(`[data-dx-stack-item="${adjacentStack.getAttribute("data-dx-stack")}"]`)) : [];
203
+ if (adjacentStack && adjacentStackItems.length > 0) {
204
+ let closestItem = adjacentStackItems[0];
205
+ const lastFocusedItem2 = adjacentStack.querySelector(`[data-dx-item-id="${adjacentStack.getAttribute("data-dx-last-focused-item") ?? "never"}"]`);
206
+ if (lastFocusedItem2) {
207
+ closestItem = lastFocusedItem2;
208
+ } else {
209
+ const ownedItemRect = closestOwnedItem.getBoundingClientRect();
210
+ const targetPosition = closestStackOrientation === "vertical" ? ownedItemRect.top : ownedItemRect.left;
211
+ let closestDistance = Infinity;
212
+ for (const item of adjacentStackItems) {
213
+ const itemRect = item.getBoundingClientRect();
214
+ const itemPosition = closestStackOrientation === "vertical" ? itemRect.top : itemRect.left;
215
+ const distance = Math.abs(itemPosition - targetPosition);
216
+ if (distance < closestDistance) {
217
+ closestDistance = distance;
218
+ closestItem = item;
219
+ }
220
+ if (closestDistance <= PERPENDICULAR_FOCUS_THRESHHOLD) {
221
+ break;
222
+ }
223
+ }
224
+ }
225
+ event.preventDefault();
226
+ scrollIntoViewAndFocus(closestItem, closestStackOrientation);
227
+ } else if (adjacentStackSelfItem) {
228
+ event.preventDefault();
229
+ scrollIntoViewAndFocus(adjacentStackSelfItem, ancestorOrientation);
230
+ }
231
+ } else if (closestOwnedItem) {
232
+ const closestOwnedItemStack = closestOwnedItem.querySelector("[data-dx-stack]");
233
+ const closestOwnedItemStackItems = closestOwnedItemStack ? Array.from(closestOwnedItemStack.querySelectorAll(`[data-dx-stack-item="${closestOwnedItemStack.getAttribute("data-dx-stack")}"]`)) : [];
234
+ if (closestOwnedItemStackItems.length > 0) {
235
+ event.preventDefault();
236
+ scrollIntoViewAndFocus(closestOwnedItemStackItems[[
237
+ "ArrowUp",
238
+ "ArrowLeft"
239
+ ].includes(event.key) ? closestOwnedItemStackItems.length - 1 : 0], closestOwnedItemStack?.getAttribute("aria-orientation"));
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+ props.onKeyDown?.(event);
246
+ }, [
247
+ props.onKeyDown,
248
+ stackId,
249
+ circularFocus
250
+ ]);
251
+ const gridClasses = useMemo(() => {
252
+ if (!rail) {
253
+ return orientation === "horizontal" ? "grid-rows-1 px-(--stack-gap)" : "grid-cols-1 py-(--stack-gap)";
254
+ }
255
+ if (orientation === "horizontal") {
256
+ return railGridHorizontal;
257
+ } else {
258
+ return railGridVertical;
259
+ }
260
+ }, [
261
+ rail,
262
+ orientation,
263
+ size
264
+ ]);
265
+ useEffect(() => {
266
+ if (!(stackElement && Number.isFinite(separatorOnScroll))) {
267
+ return;
268
+ }
269
+ const observer = new MutationObserver(() => {
270
+ handleScroll();
271
+ });
272
+ observer.observe(stackElement, {
273
+ childList: true,
274
+ subtree: true
275
+ });
276
+ return () => {
277
+ observer.disconnect();
278
+ };
279
+ }, [
280
+ stackElement,
281
+ handleScroll
282
+ ]);
283
+ return /* @__PURE__ */ React.createElement(StackContext.Provider, {
284
+ value: {
285
+ orientation,
286
+ rail,
287
+ size,
288
+ onRearrange,
289
+ stackId
290
+ }
291
+ }, /* @__PURE__ */ React.createElement("div", {
292
+ ...props,
293
+ className: mx("grid relative [--stack-gap:var(--spacing-trim-xs)]", gridClasses, size === "contain" && (orientation === "horizontal" ? "overflow-x-auto overscroll-x-contain min-h-0 max-h-full h-full" : "overflow-y-auto min-w-0 max-w-full w-full"), classNames),
294
+ onKeyDown: handleKeyDown,
295
+ onBlur: handleBlur,
296
+ "data-dx-stack": stackId,
297
+ "data-dx-stack-circular-focus": circularFocus,
298
+ "data-dx-last-focused-item": lastFocusedItem,
299
+ "data-rail": rail,
300
+ "aria-orientation": orientation,
301
+ style: styles,
302
+ ref: composedItemRef,
303
+ ...Number.isFinite(separatorOnScroll) && {
304
+ onScroll: handleScroll
305
+ }
306
+ }, children, selfDroppable && dropping && /* @__PURE__ */ React.createElement(ListItem.DropIndicator, {
307
+ lineInset: 8,
308
+ terminalInset: -8,
309
+ gap: -8,
310
+ edge: orientation === "horizontal" ? "left" : "top"
311
+ })));
312
+ });
313
+
314
+ // src/components/StackItem/StackItem.tsx
315
+ import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
316
+ import { draggable, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
317
+ import { preserveOffsetOnSource } from "@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source";
318
+ import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
319
+ import { attachClosestEdge as attachClosestEdge2, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
320
+ import { useFocusableGroup } from "@fluentui/react-tabster";
321
+ import { composeRefs as composeRefs2 } from "@radix-ui/react-compose-refs";
322
+ import React8, { forwardRef as forwardRef5, useCallback as useCallback2, useLayoutEffect as useLayoutEffect2, useMemo as useMemo3, useState as useState4 } from "react";
323
+ import { createPortal } from "react-dom";
324
+ import { ListItem as ListItem2 } from "@dxos/react-ui";
325
+ import { resizeAttributes, sizeStyle } from "@dxos/react-ui-dnd";
326
+ import { mx as mx5 } from "@dxos/ui-theme";
327
+
328
+ // src/components/StackItem/StackItemContent.tsx
329
+ import React2, { forwardRef as forwardRef2, useMemo as useMemo2 } from "react";
330
+ import { mx as mx2 } from "@dxos/ui-theme";
331
+ var StackItemContent = /* @__PURE__ */ forwardRef2(({ classNames, children, toolbar, statusbar, ...props }, forwardedRef) => {
332
+ const { size: stackItemSize } = useStack();
333
+ const { role } = useStackItem();
334
+ const style = useMemo2(() => ({
335
+ gridTemplateRows: [
336
+ toolbar && role === "section" ? "calc(var(--dx-toolbar-size) - 1px)" : "var(--dx-toolbar-size)",
337
+ "1fr",
338
+ statusbar && "var(--dx-statusbar-size)"
339
+ ].filter(Boolean).join(" ")
340
+ }), [
341
+ toolbar,
342
+ statusbar
343
+ ]);
344
+ return /* @__PURE__ */ React2.createElement("div", {
345
+ ...props,
346
+ role: "none",
347
+ style,
348
+ className: mx2("group grid grid-cols-[100%] dx-density-coarse", stackItemSize === "contain" && "min-h-0 overflow-hidden", toolbar && role === "section" && "[&_.dx-toolbar]:sticky [&_.dx-toolbar]:z-[1] [&_.dx-toolbar]:top-0 [&_.dx-toolbar]:-mb-px [&_.dx-toolbar]:min-w-0", toolbar && "[&>.dx-toolbar]:relative [&>.dx-toolbar]:border-b [&>.dx-toolbar]:border-subdued-separator", classNames),
349
+ "data-popover-collision-boundary": true,
350
+ ref: forwardedRef
351
+ }, children);
352
+ });
353
+ StackItemContent.displayName = "StackItemContent";
354
+
355
+ // src/components/StackItem/StackItemDragHandle.tsx
356
+ import { Primitive } from "@radix-ui/react-primitive";
357
+ import { Slot } from "@radix-ui/react-slot";
358
+ import React3 from "react";
359
+ var StackItemDragHandle = ({ asChild, children }) => {
360
+ const { selfDragHandleRef } = useStackItem();
361
+ const Comp = asChild ? Slot : Primitive.div;
362
+ return /* @__PURE__ */ React3.createElement(Comp, {
363
+ ref: selfDragHandleRef,
364
+ role: "button"
365
+ }, children);
366
+ };
367
+
368
+ // src/components/StackItem/StackItemHeading.tsx
369
+ import { Primitive as Primitive2 } from "@radix-ui/react-primitive";
370
+ import { Slot as Slot2 } from "@radix-ui/react-slot";
371
+ import React4, { forwardRef as forwardRef3 } from "react";
372
+ import { useAttention } from "@dxos/react-ui-attention";
373
+ import { mx as mx3 } from "@dxos/ui-theme";
374
+ var StackItemHeading = ({ children, classNames, asChild, separateOnScroll, ...props }) => {
375
+ const { orientation } = useStack();
376
+ const Comp = asChild ? Slot2 : Primitive2.div;
377
+ return /* @__PURE__ */ React4.createElement(Comp, {
378
+ role: "heading",
379
+ ...props,
380
+ className: mx3("flex items-center border-x-0! bg-header-surface", separateOnScroll ? 'border-transparent [[data-scroll-separator="true"]_&]:border-subdued-separator' : "border-subdued-separator", orientation === "horizontal" ? "h-(--dx-rail-size)" : "w-(--dx-rail-size) flex-col", orientation === "horizontal" ? "border-b" : "border-e", classNames)
381
+ }, children);
382
+ };
383
+ var StackItemHeadingStickyContent = ({ children }) => {
384
+ return /* @__PURE__ */ React4.createElement("div", {
385
+ role: "none",
386
+ className: "sticky top-0 bg-(--sticky-bg) p-1 w-full"
387
+ }, children);
388
+ };
389
+ var StackItemHeadingLabel = /* @__PURE__ */ forwardRef3(({ attendableId, related, classNames, ...props }, forwardedRef) => {
390
+ const { hasAttention, isAncestor, isRelated } = useAttention(attendableId);
391
+ return /* @__PURE__ */ React4.createElement("h1", {
392
+ ...props,
393
+ "data-attention": (related && isRelated || hasAttention || isAncestor).toString(),
394
+ className: mx3("px-1 min-w-0 w-0 grow truncate font-medium text-base-surface-text data-[attention=true]:text-accent-text self-center", classNames),
395
+ ref: forwardedRef
396
+ });
397
+ });
398
+
399
+ // src/components/StackItem/StackItemResizeHandle.tsx
400
+ import React5 from "react";
401
+ import { ResizeHandle } from "@dxos/react-ui-dnd";
402
+ var MIN_WIDTH = 20;
403
+ var MIN_HEIGHT = 3;
404
+ var StackItemResizeHandle = (_) => {
405
+ const { orientation } = useStack();
406
+ const { setSize, size } = useStackItem();
407
+ return /* @__PURE__ */ React5.createElement(ResizeHandle, {
408
+ side: orientation === "horizontal" ? "inline-end" : "block-end",
409
+ fallbackSize: DEFAULT_EXTRINSIC_SIZE,
410
+ minSize: orientation === "horizontal" ? MIN_WIDTH : MIN_HEIGHT,
411
+ size,
412
+ onSizeChange: setSize
413
+ });
414
+ };
415
+
416
+ // src/components/StackItem/StackItemSigil.tsx
417
+ import React7, { Fragment, forwardRef as forwardRef4, useState as useState3 } from "react";
418
+ import { keySymbols } from "@dxos/keyboard";
419
+ import { Button, DropdownMenu, Icon, toLocalizedString, useTranslation } from "@dxos/react-ui";
420
+ import { useAttention as useAttention2 } from "@dxos/react-ui-attention";
421
+ import { mx as mx4 } from "@dxos/ui-theme";
422
+ import { getHostPlatform } from "@dxos/util";
423
+
424
+ // src/translations.ts
425
+ var translationKey = "@dxos/react-ui-stack";
426
+ var translations = [
427
+ {
428
+ "en-US": {
429
+ [translationKey]: {
430
+ "resize label": "Drag to resize",
431
+ "drag handle label": "Drag to rearrange",
432
+ "pin start label": "Pin to the left sidebar",
433
+ "pin end label": "Pin to the right sidebar",
434
+ "increment start label": "Move to the left",
435
+ "increment end label": "Move to the right",
436
+ "close label": "Close",
437
+ "minify label": "Minify"
438
+ }
439
+ }
440
+ }
441
+ ];
442
+
443
+ // src/components/StackItem/MenuSignifier.tsx
444
+ import React6 from "react";
445
+ var MenuSignifierHorizontal = () => /* @__PURE__ */ React6.createElement("svg", {
446
+ className: "absolute bottom-[7px]",
447
+ width: 20,
448
+ height: 2,
449
+ viewBox: "0 0 20 2",
450
+ stroke: "currentColor",
451
+ opacity: 0.5
452
+ }, /* @__PURE__ */ React6.createElement("line", {
453
+ x1: 0.5,
454
+ y1: 0.75,
455
+ x2: 19,
456
+ y2: 0.75,
457
+ strokeWidth: 1.25,
458
+ strokeLinecap: "round",
459
+ strokeDasharray: "6 20",
460
+ strokeDashoffset: "-6.5"
461
+ }));
462
+
463
+ // src/components/StackItem/StackItemSigil.tsx
464
+ var StackItemSigilButton = /* @__PURE__ */ forwardRef4(({ attendableId, classNames, related, isMenu = true, children, ...props }, forwardedRef) => {
465
+ const { hasAttention, isAncestor, isRelated } = useAttention2(attendableId);
466
+ const variant = related && isRelated || hasAttention || isAncestor ? "primary" : "ghost";
467
+ return /* @__PURE__ */ React7.createElement(Button, {
468
+ ...props,
469
+ variant,
470
+ classNames: [
471
+ "shrink-0 px-0 min-h-0 w-(--dx-rail-action) h-(--dx-rail-action) relative dx-app-no-drag",
472
+ classNames
473
+ ],
474
+ ref: forwardedRef
475
+ }, isMenu && /* @__PURE__ */ React7.createElement(MenuSignifierHorizontal, null), children);
476
+ });
477
+ var StackItemSigil = /* @__PURE__ */ forwardRef4(({ actions: actionGroups, onAction, triggerLabel, attendableId, icon, related, children }, forwardedRef) => {
478
+ const { t } = useTranslation(translationKey);
479
+ const [optionsMenuOpen, setOptionsMenuOpen] = useState3(false);
480
+ const hasActions = actionGroups && actionGroups.length > 0;
481
+ const button = /* @__PURE__ */ React7.createElement(StackItemSigilButton, {
482
+ attendableId,
483
+ related,
484
+ isMenu: hasActions,
485
+ // TODO(wittjosiah): Better disabling of interactive styles when no action are available.
486
+ // Remove underscore icon when no actions are available?
487
+ classNames: !hasActions && "cursor-default"
488
+ }, /* @__PURE__ */ React7.createElement("span", {
489
+ className: "sr-only"
490
+ }, triggerLabel), /* @__PURE__ */ React7.createElement(Icon, {
491
+ icon,
492
+ size: 5
493
+ }));
494
+ if (!hasActions) {
495
+ return button;
496
+ }
497
+ return /* @__PURE__ */ React7.createElement(DropdownMenu.Root, {
498
+ open: optionsMenuOpen,
499
+ onOpenChange: setOptionsMenuOpen
500
+ }, /* @__PURE__ */ React7.createElement(DropdownMenu.Trigger, {
501
+ asChild: true,
502
+ ref: forwardedRef
503
+ }, button), /* @__PURE__ */ React7.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React7.createElement(DropdownMenu.Content, {
504
+ classNames: "z-[31]"
505
+ }, /* @__PURE__ */ React7.createElement(DropdownMenu.Viewport, null, actionGroups?.map((actions, index) => {
506
+ const separator = index > 0 ? /* @__PURE__ */ React7.createElement(DropdownMenu.Separator, null) : null;
507
+ return /* @__PURE__ */ React7.createElement(Fragment, {
508
+ key: index
509
+ }, separator, actions.map((action) => {
510
+ const shortcut = typeof action.properties.keyBinding === "string" ? action.properties.keyBinding : action.properties.keyBinding?.[getHostPlatform()];
511
+ const menuItemType = action.properties.menuItemType;
512
+ const Root = menuItemType === "toggle" ? DropdownMenu.CheckboxItem : DropdownMenu.Item;
513
+ return /* @__PURE__ */ React7.createElement(Root, {
514
+ key: action.id,
515
+ onClick: (event) => {
516
+ if (action.properties.disabled) {
517
+ return;
518
+ }
519
+ event.stopPropagation();
520
+ setOptionsMenuOpen(false);
521
+ onAction?.(action);
522
+ },
523
+ classNames: "gap-2",
524
+ disabled: action.properties.disabled,
525
+ checked: menuItemType === "toggle" ? action.properties.isChecked : void 0,
526
+ ...action.properties?.testId && {
527
+ "data-testid": action.properties.testId
528
+ }
529
+ }, /* @__PURE__ */ React7.createElement(Icon, {
530
+ icon: action.properties.icon ?? "ph--placeholder--regular",
531
+ size: 4
532
+ }), /* @__PURE__ */ React7.createElement("span", {
533
+ className: "grow truncate"
534
+ }, toLocalizedString(action.properties.label ?? "", t)), menuItemType === "toggle" && /* @__PURE__ */ React7.createElement(DropdownMenu.ItemIndicator, {
535
+ asChild: true
536
+ }, /* @__PURE__ */ React7.createElement(Icon, {
537
+ icon: "ph--check--regular",
538
+ size: 4
539
+ })), shortcut && /* @__PURE__ */ React7.createElement("span", {
540
+ className: mx4("shrink-0", "text-description")
541
+ }, keySymbols(shortcut).join("")));
542
+ }));
543
+ }), children), /* @__PURE__ */ React7.createElement(DropdownMenu.Arrow, null))));
544
+ });
545
+
546
+ // src/components/StackItem/StackItem.tsx
547
+ var DEFAULT_HORIZONTAL_SIZE = 48;
548
+ var DEFAULT_VERTICAL_SIZE = "min-content";
549
+ var DEFAULT_EXTRINSIC_SIZE = DEFAULT_HORIZONTAL_SIZE;
550
+ var StackItemRoot = /* @__PURE__ */ forwardRef5(({ item, children, classNames, size: propsSize, onSizeChange, role, order, prevSiblingId, nextSiblingId, style, disableRearrange, focusIndicatorVariant = "over-all", ...props }, forwardedRef) => {
551
+ const [itemElement, itemRef] = useState4(null);
552
+ const composedItemRef = composeRefs2(itemRef, forwardedRef);
553
+ const [selfDragHandleElement, selfDragHandleRef] = useState4(null);
554
+ const [closestEdge, setEdge] = useState4(null);
555
+ const [sourceId, setSourceId] = useState4(null);
556
+ const [dragState, setDragState] = useState4(idle);
557
+ const { orientation, rail, onRearrange, size: stackSize, stackId } = useStack();
558
+ const [size = orientation === "horizontal" ? DEFAULT_HORIZONTAL_SIZE : DEFAULT_VERTICAL_SIZE, setInternalSize] = useState4(propsSize);
559
+ const Root = role ?? "div";
560
+ const setSize = useCallback2((nextSize, commit) => {
561
+ setInternalSize(nextSize);
562
+ if (commit) {
563
+ onSizeChange?.(nextSize);
564
+ }
565
+ }, [
566
+ onSizeChange
567
+ ]);
568
+ const type = orientation === "horizontal" ? "column" : "card";
569
+ useLayoutEffect2(() => {
570
+ if (!itemElement || !onRearrange || disableRearrange) {
571
+ return;
572
+ }
573
+ return combine2(draggable({
574
+ element: itemElement,
575
+ ...selfDragHandleElement && {
576
+ dragHandle: selfDragHandleElement
577
+ },
578
+ getInitialData: () => ({
579
+ id: item.id,
580
+ type
581
+ }),
582
+ onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
583
+ document.body.setAttribute("data-drag-preview", "true");
584
+ const offsetFn = preserveOffsetOnSource({
585
+ element: source.element,
586
+ input: location.current.input
587
+ });
588
+ const rect = source.element.getBoundingClientRect();
589
+ setCustomNativeDragPreview({
590
+ nativeSetDragImage,
591
+ getOffset: ({ container }) => {
592
+ return offsetFn({
593
+ container
594
+ });
595
+ },
596
+ render: ({ container }) => {
597
+ container.style.width = rect.width + "px";
598
+ setDragState({
599
+ type: "preview",
600
+ container,
601
+ item
602
+ });
603
+ return () => {
604
+ };
605
+ }
606
+ });
607
+ },
608
+ onDragStart: () => {
609
+ document.body.removeAttribute("data-drag-preview");
610
+ itemElement?.closest("[data-drag-autoscroll]")?.setAttribute("data-drag-autoscroll", "active");
611
+ setDragState({
612
+ type: "w-dragging",
613
+ item
614
+ });
615
+ },
616
+ onDrop: () => {
617
+ itemElement?.closest("[data-drag-autoscroll]")?.setAttribute("data-drag-autoscroll", "idle");
618
+ setDragState(idle);
619
+ }
620
+ }), dropTargetForElements2({
621
+ element: itemElement,
622
+ getData: ({ input, element }) => {
623
+ return attachClosestEdge2({
624
+ id: item.id,
625
+ type
626
+ }, {
627
+ input,
628
+ element,
629
+ allowedEdges: orientation === "horizontal" ? [
630
+ "left",
631
+ "right"
632
+ ] : [
633
+ "top",
634
+ "bottom"
635
+ ]
636
+ });
637
+ },
638
+ onDragEnter: ({ self, source }) => {
639
+ if (source.data.type === self.data.type) {
640
+ setEdge(extractClosestEdge2(self.data));
641
+ setSourceId(source.data.id);
642
+ }
643
+ },
644
+ onDrag: ({ self, source }) => {
645
+ if (source.data.type === self.data.type) {
646
+ setEdge(extractClosestEdge2(self.data));
647
+ setSourceId(source.data.id);
648
+ }
649
+ },
650
+ onDragLeave: () => {
651
+ setEdge(null);
652
+ setSourceId(null);
653
+ },
654
+ onDrop: ({ self, source }) => {
655
+ setEdge(null);
656
+ setSourceId(null);
657
+ if (source.data.type === self.data.type) {
658
+ onRearrange(source.data, self.data, extractClosestEdge2(self.data));
659
+ }
660
+ }
661
+ }));
662
+ }, [
663
+ orientation,
664
+ item,
665
+ onRearrange,
666
+ selfDragHandleElement,
667
+ itemElement
668
+ ]);
669
+ const focusableGroupAttrs = useFocusableGroup({
670
+ tabBehavior: "limited"
671
+ });
672
+ const shouldShowDropIndicator = () => {
673
+ if (!closestEdge || !sourceId) {
674
+ return false;
675
+ }
676
+ if (sourceId === item.id) {
677
+ return false;
678
+ }
679
+ const isTrailingEdgeOfPrevSibling = prevSiblingId !== void 0 && sourceId === prevSiblingId && (orientation === "horizontal" && closestEdge === "left" || orientation === "vertical" && closestEdge === "top");
680
+ if (isTrailingEdgeOfPrevSibling) {
681
+ return false;
682
+ }
683
+ const isLeadingEdgeOfNextSibling = nextSiblingId !== void 0 && sourceId === nextSiblingId && (orientation === "horizontal" && closestEdge === "right" || orientation === "vertical" && closestEdge === "bottom");
684
+ if (isLeadingEdgeOfNextSibling) {
685
+ return false;
686
+ }
687
+ return true;
688
+ };
689
+ const stackItemContextValue = useMemo3(() => ({
690
+ selfDragHandleRef,
691
+ size,
692
+ setSize,
693
+ state: dragState,
694
+ setState: setDragState,
695
+ role
696
+ }), [
697
+ selfDragHandleRef,
698
+ size,
699
+ setSize,
700
+ dragState,
701
+ setDragState,
702
+ role
703
+ ]);
704
+ return /* @__PURE__ */ React8.createElement(StackItemContext.Provider, {
705
+ value: stackItemContextValue
706
+ }, /* @__PURE__ */ React8.createElement(Root, {
707
+ ...props,
708
+ tabIndex: 0,
709
+ ...focusableGroupAttrs,
710
+ className: mx5("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-b border-subdued-separator", classNames),
711
+ "data-dx-stack-item": stackId,
712
+ "data-dx-item-id": item.id,
713
+ ...resizeAttributes,
714
+ style: {
715
+ ...stackSize !== "split" && sizeStyle(size, orientation),
716
+ ...Number.isFinite(order) && {
717
+ [orientation === "horizontal" ? "gridColumn" : "gridRow"]: `${order}`
718
+ },
719
+ ...style
720
+ },
721
+ ref: composedItemRef
722
+ }, children, shouldShowDropIndicator() && closestEdge && /* @__PURE__ */ React8.createElement(ListItem2.DropIndicator, {
723
+ lineInset: 8,
724
+ terminalInset: -8,
725
+ edge: closestEdge
726
+ })));
727
+ });
728
+ var StackItemDragPreview = ({ children }) => {
729
+ const { state } = useStackItem();
730
+ return state?.type === "preview" ? /* @__PURE__ */ createPortal(children({
731
+ item: state.item
732
+ }), state.container) : null;
733
+ };
734
+ var StackItem = {
735
+ Root: StackItemRoot,
736
+ Content: StackItemContent,
737
+ DragHandle: StackItemDragHandle,
738
+ DragPreview: StackItemDragPreview,
739
+ Heading: StackItemHeading,
740
+ HeadingLabel: StackItemHeadingLabel,
741
+ HeadingStickyContent: StackItemHeadingStickyContent,
742
+ ResizeHandle: StackItemResizeHandle,
743
+ Sigil: StackItemSigil,
744
+ SigilButton: StackItemSigilButton
745
+ };
42
746
  export {
43
- Card,
44
- CardDragPreview,
45
- CardStack,
46
- CardStackDragPreview,
47
747
  DEFAULT_EXTRINSIC_SIZE,
48
748
  DEFAULT_HORIZONTAL_SIZE,
49
749
  DEFAULT_VERTICAL_SIZE,
50
- Image,
51
750
  Stack,
52
751
  StackContext,
53
752
  StackItem,
54
- StackItemDragPreview,
55
753
  autoScrollRootAttributes,
56
- cardChrome,
57
- cardDefaultInlineSize,
58
- cardDialogContent,
59
- cardDialogHeader,
60
- cardDialogOverflow,
61
- cardDialogPaddedOverflow,
62
- cardDialogSearchListRoot,
63
- cardHeading,
64
- cardNoSpacing,
65
- cardRoot,
66
- cardSpacing,
67
- cardStackContent,
68
- cardStackDefaultInlineSizeRem,
69
- cardStackFooter,
70
- cardStackHeading,
71
- cardStackItem,
72
- cardStackRoot,
73
- cardText,
74
- labelSpacing,
75
754
  railGridHorizontal,
76
755
  railGridHorizontalContainFitContent,
77
756
  railGridVertical,