@dxos/react-ui-stack 0.8.4-main.f5c0578 → 0.8.4-main.fcfe5033a5

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