@dxos/react-ui-stack 0.8.4-main.dedc0f3 → 0.8.4-main.dfabb4ec29

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