@dxos/react-ui-stack 0.8.2-main.fbd8ed0 → 0.8.2-staging.42af850

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 (30) hide show
  1. package/dist/lib/browser/index.mjs +454 -322
  2. package/dist/lib/browser/index.mjs.map +3 -3
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/testing/index.mjs.map +3 -3
  5. package/dist/lib/node/index.cjs +452 -319
  6. package/dist/lib/node/index.cjs.map +3 -3
  7. package/dist/lib/node/meta.json +1 -1
  8. package/dist/lib/node/testing/index.cjs.map +3 -3
  9. package/dist/lib/node-esm/index.mjs +454 -322
  10. package/dist/lib/node-esm/index.mjs.map +3 -3
  11. package/dist/lib/node-esm/meta.json +1 -1
  12. package/dist/lib/node-esm/testing/index.mjs.map +3 -3
  13. package/dist/types/src/components/Stack/Stack.d.ts +2 -0
  14. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
  15. package/dist/types/src/components/Stack/Stack.stories.d.ts.map +1 -1
  16. package/dist/types/src/components/StackContext.d.ts +13 -0
  17. package/dist/types/src/components/StackContext.d.ts.map +1 -1
  18. package/dist/types/src/components/StackItem/StackItem.d.ts +12 -3
  19. package/dist/types/src/components/StackItem/StackItem.d.ts.map +1 -1
  20. package/dist/types/src/components/StackItem/StackItemHeading.d.ts.map +1 -1
  21. package/dist/types/src/components/StackItem/StackItemSigil.d.ts.map +1 -1
  22. package/dist/types/src/testing/stack-manager.d.ts.map +1 -1
  23. package/package.json +21 -20
  24. package/src/components/Stack/Stack.stories.tsx +14 -4
  25. package/src/components/Stack/Stack.tsx +34 -3
  26. package/src/components/StackContext.tsx +20 -0
  27. package/src/components/StackItem/StackItem.tsx +87 -10
  28. package/src/components/StackItem/StackItemHeading.tsx +2 -1
  29. package/src/components/StackItem/StackItemSigil.tsx +2 -14
  30. package/src/testing/stack-manager.ts +6 -6
@@ -1,7 +1,8 @@
1
1
  // packages/ui/react-ui-stack/src/components/Stack/Stack.tsx
2
+ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
2
3
  import { useArrowNavigationGroup } from "@fluentui/react-tabster";
3
4
  import { composeRefs } from "@radix-ui/react-compose-refs";
4
- import React, { Children, forwardRef, useState as useState2, useMemo } from "react";
5
+ import React, { Children, forwardRef, useState as useState2, useMemo, useCallback } from "react";
5
6
  import { ListItem } from "@dxos/react-ui";
6
7
  import { mx } from "@dxos/react-ui-theme";
7
8
 
@@ -75,11 +76,17 @@ var StackContext = /* @__PURE__ */ createContext({
75
76
  size: "intrinsic"
76
77
  });
77
78
  var useStack = () => useContext(StackContext);
79
+ var idle = {
80
+ type: "idle"
81
+ };
78
82
  var StackItemContext = /* @__PURE__ */ createContext({
79
83
  selfDragHandleRef: () => {
80
84
  },
81
85
  size: "min-content",
82
86
  setSize: () => {
87
+ },
88
+ state: idle,
89
+ setState: () => {
83
90
  }
84
91
  });
85
92
  var useStackItem = () => useContext(StackItemContext);
@@ -92,158 +99,214 @@ var railGridVerticalContainFitContent = "grid-cols-[[rail-start]_var(--rail-size
92
99
  var autoScrollRootAttributes = {
93
100
  "data-drag-autoscroll": "idle"
94
101
  };
95
- var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientation = "vertical", rail = true, size = "intrinsic", onRearrange, itemsCount = Children.count(children), ...props }, forwardedRef) => {
96
- const [stackElement, stackRef] = useState2(null);
97
- const composedItemRef = composeRefs(stackRef, forwardedRef);
98
- const arrowNavigationAttrs = useArrowNavigationGroup({
99
- axis: orientation
100
- });
101
- const styles = {
102
- [orientation === "horizontal" ? "gridTemplateColumns" : "gridTemplateRows"]: `repeat(${itemsCount}, min-content) [tabster-dummies] 0`,
103
- ...style
104
- };
105
- const selfDroppable = !!(itemsCount < 1 && onRearrange && props.id);
106
- const { dropping } = useStackDropForElements({
107
- id: props.id,
108
- element: stackElement,
109
- selfDroppable,
110
- orientation,
111
- onRearrange
112
- });
113
- const gridClasses = useMemo(() => {
114
- if (!rail) {
115
- return orientation === "horizontal" ? "grid-rows-1 pli-1" : "grid-cols-1 plb-1";
116
- }
117
- if (orientation === "horizontal") {
118
- return size === "contain-fit-content" ? railGridHorizontalContainFitContent : railGridHorizontal;
119
- } else {
120
- return size === "contain-fit-content" ? railGridVerticalContainFitContent : railGridVertical;
121
- }
122
- }, [
123
- rail,
124
- orientation,
125
- size
126
- ]);
127
- return /* @__PURE__ */ React.createElement(StackContext.Provider, {
128
- value: {
102
+ var Stack = /* @__PURE__ */ forwardRef(({ children, classNames, style, orientation = "vertical", rail = true, size = "intrinsic", onRearrange, itemsCount = Children.count(children), getDropElement, separatorOnScroll, ...props }, forwardedRef) => {
103
+ var _effect = _useSignals();
104
+ try {
105
+ const [stackElement, stackRef] = useState2(null);
106
+ const composedItemRef = composeRefs(stackRef, forwardedRef);
107
+ const arrowNavigationAttrs = useArrowNavigationGroup({
108
+ axis: orientation
109
+ });
110
+ const styles = {
111
+ [orientation === "horizontal" ? "gridTemplateColumns" : "gridTemplateRows"]: `repeat(${itemsCount}, min-content) [tabster-dummies] 0`,
112
+ ...style
113
+ };
114
+ const selfDroppable = !!(itemsCount < 1 && onRearrange && props.id);
115
+ const { dropping } = useStackDropForElements({
116
+ id: props.id,
117
+ element: getDropElement && stackElement ? getDropElement(stackElement) : stackElement,
118
+ selfDroppable,
129
119
  orientation,
130
- rail,
131
- size,
132
120
  onRearrange
133
- }
134
- }, /* @__PURE__ */ React.createElement("div", {
135
- ...props,
136
- ...arrowNavigationAttrs,
137
- className: mx("grid relative", gridClasses, (size === "contain" || size === "contain-fit-content") && (orientation === "horizontal" ? "overflow-x-auto min-bs-0 max-bs-full bs-full" : "overflow-y-auto min-is-0 max-is-full is-full"), classNames),
138
- "data-rail": rail,
139
- "aria-orientation": orientation,
140
- style: styles,
141
- ref: composedItemRef
142
- }, children, selfDroppable && dropping && /* @__PURE__ */ React.createElement(ListItem.DropIndicator, {
143
- lineInset: 8,
144
- terminalInset: -8,
145
- gap: -8,
146
- edge: orientation === "horizontal" ? "left" : "top"
147
- })));
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 gridClasses = useMemo(() => {
139
+ if (!rail) {
140
+ return orientation === "horizontal" ? "grid-rows-1 pli-1" : "grid-cols-1 plb-1";
141
+ }
142
+ if (orientation === "horizontal") {
143
+ return size === "contain-fit-content" ? railGridHorizontalContainFitContent : railGridHorizontal;
144
+ } else {
145
+ return size === "contain-fit-content" ? railGridVerticalContainFitContent : railGridVertical;
146
+ }
147
+ }, [
148
+ rail,
149
+ orientation,
150
+ size
151
+ ]);
152
+ return /* @__PURE__ */ React.createElement(StackContext.Provider, {
153
+ value: {
154
+ orientation,
155
+ rail,
156
+ size,
157
+ onRearrange
158
+ }
159
+ }, /* @__PURE__ */ React.createElement("div", {
160
+ ...props,
161
+ ...arrowNavigationAttrs,
162
+ className: mx("grid relative", gridClasses, (size === "contain" || size === "contain-fit-content") && (orientation === "horizontal" ? "overflow-x-auto min-bs-0 max-bs-full bs-full" : "overflow-y-auto min-is-0 max-is-full is-full"), classNames),
163
+ "data-rail": rail,
164
+ "aria-orientation": orientation,
165
+ style: styles,
166
+ ref: composedItemRef,
167
+ ...Number.isFinite(separatorOnScroll) && {
168
+ onScroll: handleScroll
169
+ }
170
+ }, children, selfDroppable && dropping && /* @__PURE__ */ React.createElement(ListItem.DropIndicator, {
171
+ lineInset: 8,
172
+ terminalInset: -8,
173
+ gap: -8,
174
+ edge: orientation === "horizontal" ? "left" : "top"
175
+ })));
176
+ } finally {
177
+ _effect.f();
178
+ }
148
179
  });
149
180
 
150
181
  // packages/ui/react-ui-stack/src/components/StackItem/StackItem.tsx
182
+ import { useSignals as _useSignals8 } from "@preact-signals/safe-react/tracking";
151
183
  import { combine as combine2 } from "@atlaskit/pragmatic-drag-and-drop/combine";
152
184
  import { draggable, dropTargetForElements as dropTargetForElements2 } from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
153
185
  import { preserveOffsetOnSource } from "@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source";
154
- import { scrollJustEnoughIntoView } from "@atlaskit/pragmatic-drag-and-drop/element/scroll-just-enough-into-view";
186
+ import { setCustomNativeDragPreview } from "@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview";
155
187
  import { attachClosestEdge as attachClosestEdge2, extractClosestEdge as extractClosestEdge2 } from "@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge";
156
188
  import { useFocusableGroup as useFocusableGroup2 } from "@fluentui/react-tabster";
157
189
  import { composeRefs as composeRefs2 } from "@radix-ui/react-compose-refs";
158
- import React8, { forwardRef as forwardRef5, useLayoutEffect as useLayoutEffect2, useState as useState4, useCallback } from "react";
190
+ import React8, { forwardRef as forwardRef5, useLayoutEffect as useLayoutEffect2, useState as useState4, useCallback as useCallback2 } from "react";
191
+ import { createPortal } from "react-dom";
159
192
  import { ListItem as ListItem2 } from "@dxos/react-ui";
160
193
  import { resizeAttributes, sizeStyle } from "@dxos/react-ui-dnd";
161
194
  import { mx as mx5 } from "@dxos/react-ui-theme";
162
195
 
163
196
  // packages/ui/react-ui-stack/src/components/StackItem/StackItemContent.tsx
197
+ import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
164
198
  import React2, { forwardRef as forwardRef2 } from "react";
165
199
  import { mx as mx2 } from "@dxos/react-ui-theme";
166
200
  var StackItemContent = /* @__PURE__ */ forwardRef2(({ children, toolbar, statusbar, classNames, size = "intrinsic", ...props }, forwardedRef) => {
167
- const { size: stackItemSize } = useStack();
168
- return /* @__PURE__ */ React2.createElement("div", {
169
- role: "none",
170
- ...props,
171
- className: mx2("group grid grid-cols-[100%]", stackItemSize === "contain" && "min-bs-0 overflow-hidden", size === "video" ? "aspect-video" : size === "square" && "aspect-square", classNames),
172
- style: {
173
- gridTemplateRows: [
174
- ...toolbar ? [
175
- "var(--rail-action)"
176
- ] : [],
177
- "1fr",
178
- ...statusbar ? [
179
- "var(--statusbar-size)"
180
- ] : []
181
- ].join(" ")
182
- },
183
- "data-popover-collision-boundary": true,
184
- ref: forwardedRef
185
- }, children);
201
+ var _effect = _useSignals2();
202
+ try {
203
+ const { size: stackItemSize } = useStack();
204
+ return /* @__PURE__ */ React2.createElement("div", {
205
+ role: "none",
206
+ ...props,
207
+ className: mx2("group grid grid-cols-[100%]", stackItemSize === "contain" && "min-bs-0 overflow-hidden", size === "video" ? "aspect-video" : size === "square" && "aspect-square", classNames),
208
+ style: {
209
+ gridTemplateRows: [
210
+ ...toolbar ? [
211
+ "var(--rail-action)"
212
+ ] : [],
213
+ "1fr",
214
+ ...statusbar ? [
215
+ "var(--statusbar-size)"
216
+ ] : []
217
+ ].join(" ")
218
+ },
219
+ "data-popover-collision-boundary": true,
220
+ ref: forwardedRef
221
+ }, children);
222
+ } finally {
223
+ _effect.f();
224
+ }
186
225
  });
187
226
 
188
227
  // packages/ui/react-ui-stack/src/components/StackItem/StackItemDragHandle.tsx
228
+ import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
189
229
  import { Slot } from "@radix-ui/react-slot";
190
230
  import React3 from "react";
191
231
  var StackItemDragHandle = ({ asChild, children }) => {
192
- const { selfDragHandleRef } = useStackItem();
193
- const Root = asChild ? Slot : "div";
194
- return /* @__PURE__ */ React3.createElement(Root, {
195
- ref: selfDragHandleRef,
196
- role: "button"
197
- }, children);
232
+ var _effect = _useSignals3();
233
+ try {
234
+ const { selfDragHandleRef } = useStackItem();
235
+ const Root = asChild ? Slot : "div";
236
+ return /* @__PURE__ */ React3.createElement(Root, {
237
+ ref: selfDragHandleRef,
238
+ role: "button"
239
+ }, children);
240
+ } finally {
241
+ _effect.f();
242
+ }
198
243
  };
199
244
 
200
245
  // packages/ui/react-ui-stack/src/components/StackItem/StackItemHeading.tsx
246
+ import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
201
247
  import { useFocusableGroup } from "@fluentui/react-tabster";
202
248
  import React4, { forwardRef as forwardRef3 } from "react";
203
249
  import { useAttention } from "@dxos/react-ui-attention";
204
250
  import { mx as mx3 } from "@dxos/react-ui-theme";
205
251
  var StackItemHeading = ({ children, classNames, ...props }) => {
206
- const { orientation } = useStack();
207
- const focusableGroupAttrs = useFocusableGroup({
208
- tabBehavior: "limited"
209
- });
210
- return /* @__PURE__ */ React4.createElement("div", {
211
- role: "heading",
212
- ...props,
213
- tabIndex: 0,
214
- ...focusableGroupAttrs,
215
- className: mx3("flex items-center dx-focus-ring-inset-over-all relative !border-is-0 bg-headerSurface", orientation === "horizontal" ? "bs-[--rail-size]" : "is-[--rail-size] flex-col", classNames)
216
- }, children);
252
+ var _effect = _useSignals4();
253
+ try {
254
+ const { orientation } = useStack();
255
+ const focusableGroupAttrs = useFocusableGroup({
256
+ tabBehavior: "limited"
257
+ });
258
+ return /* @__PURE__ */ React4.createElement("div", {
259
+ role: "heading",
260
+ ...props,
261
+ tabIndex: 0,
262
+ ...focusableGroupAttrs,
263
+ className: mx3('flex items-center dx-focus-ring-inset-over-all relative !border-is-0 bg-headerSurface border-transparent [[data-scroll-separator="true"]_&]:border-subduedSeparator', orientation === "horizontal" ? "bs-[--rail-size]" : "is-[--rail-size] flex-col", orientation === "horizontal" ? "border-be" : "border-ie", classNames)
264
+ }, children);
265
+ } finally {
266
+ _effect.f();
267
+ }
217
268
  };
218
269
  var StackItemHeadingLabel = /* @__PURE__ */ forwardRef3(({ attendableId, related, classNames, ...props }, forwardedRef) => {
219
- const { hasAttention, isAncestor, isRelated } = useAttention(attendableId);
220
- return /* @__PURE__ */ React4.createElement("h1", {
221
- ...props,
222
- "data-attention": (related && isRelated || hasAttention || isAncestor).toString(),
223
- className: mx3("pli-1 min-is-0 is-0 grow truncate font-medium text-baseText data-[attention=true]:text-accentText self-center", classNames),
224
- ref: forwardedRef
225
- });
270
+ var _effect = _useSignals4();
271
+ try {
272
+ const { hasAttention, isAncestor, isRelated } = useAttention(attendableId);
273
+ return /* @__PURE__ */ React4.createElement("h1", {
274
+ ...props,
275
+ "data-attention": (related && isRelated || hasAttention || isAncestor).toString(),
276
+ className: mx3("pli-1 min-is-0 is-0 grow truncate font-medium text-baseText data-[attention=true]:text-accentText self-center", classNames),
277
+ ref: forwardedRef
278
+ });
279
+ } finally {
280
+ _effect.f();
281
+ }
226
282
  });
227
283
 
228
284
  // packages/ui/react-ui-stack/src/components/StackItem/StackItemResizeHandle.tsx
285
+ import { useSignals as _useSignals5 } from "@preact-signals/safe-react/tracking";
229
286
  import React5 from "react";
230
287
  import { ResizeHandle } from "@dxos/react-ui-dnd";
231
288
  var MIN_WIDTH = 20;
232
289
  var MIN_HEIGHT = 3;
233
290
  var StackItemResizeHandle = () => {
234
- const { orientation } = useStack();
235
- const { setSize, size } = useStackItem();
236
- return /* @__PURE__ */ React5.createElement(ResizeHandle, {
237
- side: orientation === "horizontal" ? "inline-end" : "block-end",
238
- fallbackSize: DEFAULT_EXTRINSIC_SIZE,
239
- minSize: orientation === "horizontal" ? MIN_WIDTH : MIN_HEIGHT,
240
- size,
241
- onSizeChange: setSize
242
- });
291
+ var _effect = _useSignals5();
292
+ try {
293
+ const { orientation } = useStack();
294
+ const { setSize, size } = useStackItem();
295
+ return /* @__PURE__ */ React5.createElement(ResizeHandle, {
296
+ side: orientation === "horizontal" ? "inline-end" : "block-end",
297
+ fallbackSize: DEFAULT_EXTRINSIC_SIZE,
298
+ minSize: orientation === "horizontal" ? MIN_WIDTH : MIN_HEIGHT,
299
+ size,
300
+ onSizeChange: setSize
301
+ });
302
+ } finally {
303
+ _effect.f();
304
+ }
243
305
  };
244
306
 
245
307
  // packages/ui/react-ui-stack/src/components/StackItem/StackItemSigil.tsx
246
- import React7, { Fragment, forwardRef as forwardRef4, useRef, useState as useState3 } from "react";
308
+ import { useSignals as _useSignals7 } from "@preact-signals/safe-react/tracking";
309
+ import React7, { Fragment, forwardRef as forwardRef4, useState as useState3 } from "react";
247
310
  import { keySymbols } from "@dxos/keyboard";
248
311
  import { Button, DropdownMenu, Icon, toLocalizedString, useTranslation } from "@dxos/react-ui";
249
312
  import { useAttention as useAttention2 } from "@dxos/react-ui-attention";
@@ -251,24 +314,32 @@ import { descriptionText, mx as mx4 } from "@dxos/react-ui-theme";
251
314
  import { getHostPlatform } from "@dxos/util";
252
315
 
253
316
  // packages/ui/react-ui-stack/src/components/StackItem/MenuSignifier.tsx
317
+ import { useSignals as _useSignals6 } from "@preact-signals/safe-react/tracking";
254
318
  import React6 from "react";
255
- var MenuSignifierHorizontal = () => /* @__PURE__ */ React6.createElement("svg", {
256
- className: "absolute block-end-[7px]",
257
- width: 20,
258
- height: 2,
259
- viewBox: "0 0 20 2",
260
- stroke: "currentColor",
261
- opacity: 0.5
262
- }, /* @__PURE__ */ React6.createElement("line", {
263
- x1: 0.5,
264
- y1: 0.75,
265
- x2: 19,
266
- y2: 0.75,
267
- strokeWidth: 1.25,
268
- strokeLinecap: "round",
269
- strokeDasharray: "6 20",
270
- strokeDashoffset: "-6.5"
271
- }));
319
+ var MenuSignifierHorizontal = () => {
320
+ var _effect = _useSignals6();
321
+ try {
322
+ return /* @__PURE__ */ React6.createElement("svg", {
323
+ className: "absolute block-end-[7px]",
324
+ width: 20,
325
+ height: 2,
326
+ viewBox: "0 0 20 2",
327
+ stroke: "currentColor",
328
+ opacity: 0.5
329
+ }, /* @__PURE__ */ React6.createElement("line", {
330
+ x1: 0.5,
331
+ y1: 0.75,
332
+ x2: 19,
333
+ y2: 0.75,
334
+ strokeWidth: 1.25,
335
+ strokeLinecap: "round",
336
+ strokeDasharray: "6 20",
337
+ strokeDashoffset: "-6.5"
338
+ }));
339
+ } finally {
340
+ _effect.f();
341
+ }
342
+ };
272
343
 
273
344
  // packages/ui/react-ui-stack/src/translations.ts
274
345
  var translationKey = "stack";
@@ -290,221 +361,280 @@ var translations_default = [
290
361
 
291
362
  // packages/ui/react-ui-stack/src/components/StackItem/StackItemSigil.tsx
292
363
  var StackItemSigilButton = /* @__PURE__ */ forwardRef4(({ attendableId, classNames, related, isMenu = true, children, ...props }, forwardedRef) => {
293
- const { hasAttention, isAncestor, isRelated } = useAttention2(attendableId);
294
- const variant = related && isRelated || hasAttention || isAncestor ? "primary" : "ghost";
295
- return /* @__PURE__ */ React7.createElement(Button, {
296
- ...props,
297
- variant,
298
- classNames: [
299
- "shrink-0 pli-0 min-bs-0 is-[--rail-action] bs-[--rail-action] relative app-no-drag",
300
- classNames
301
- ],
302
- ref: forwardedRef
303
- }, isMenu && /* @__PURE__ */ React7.createElement(MenuSignifierHorizontal, null), children);
364
+ var _effect = _useSignals7();
365
+ try {
366
+ const { hasAttention, isAncestor, isRelated } = useAttention2(attendableId);
367
+ const variant = related && isRelated || hasAttention || isAncestor ? "primary" : "ghost";
368
+ return /* @__PURE__ */ React7.createElement(Button, {
369
+ ...props,
370
+ variant,
371
+ classNames: [
372
+ "shrink-0 pli-0 min-bs-0 is-[--rail-action] bs-[--rail-action] relative app-no-drag",
373
+ classNames
374
+ ],
375
+ ref: forwardedRef
376
+ }, isMenu && /* @__PURE__ */ React7.createElement(MenuSignifierHorizontal, null), children);
377
+ } finally {
378
+ _effect.f();
379
+ }
304
380
  });
305
381
  var StackItemSigil = /* @__PURE__ */ forwardRef4(({ actions: actionGroups, onAction, triggerLabel, attendableId, icon, related, children }, forwardedRef) => {
306
- const { t } = useTranslation(translationKey);
307
- const suppressNextTooltip = useRef(false);
308
- const [optionsMenuOpen, setOptionsMenuOpen] = useState3(false);
309
- const hasActions = actionGroups && actionGroups.length > 0;
310
- const button = /* @__PURE__ */ React7.createElement(StackItemSigilButton, {
311
- attendableId,
312
- related,
313
- isMenu: hasActions,
314
- // TODO(wittjosiah): Better disabling of interactive styles when no action are available.
315
- // Remove underscore icon when no actions are available?
316
- classNames: !hasActions && "cursor-default"
317
- }, /* @__PURE__ */ React7.createElement("span", {
318
- className: "sr-only"
319
- }, triggerLabel), /* @__PURE__ */ React7.createElement(Icon, {
320
- icon,
321
- size: 5
322
- }));
323
- if (!hasActions) {
324
- return button;
325
- }
326
- return /* @__PURE__ */ React7.createElement(DropdownMenu.Root, {
327
- open: optionsMenuOpen,
328
- onOpenChange: (nextOpen) => {
329
- if (!nextOpen) {
330
- suppressNextTooltip.current = true;
331
- }
332
- return setOptionsMenuOpen(nextOpen);
382
+ var _effect = _useSignals7();
383
+ try {
384
+ const { t } = useTranslation(translationKey);
385
+ const [optionsMenuOpen, setOptionsMenuOpen] = useState3(false);
386
+ const hasActions = actionGroups && actionGroups.length > 0;
387
+ const button = /* @__PURE__ */ React7.createElement(StackItemSigilButton, {
388
+ attendableId,
389
+ related,
390
+ isMenu: hasActions,
391
+ // TODO(wittjosiah): Better disabling of interactive styles when no action are available.
392
+ // Remove underscore icon when no actions are available?
393
+ classNames: !hasActions && "cursor-default"
394
+ }, /* @__PURE__ */ React7.createElement("span", {
395
+ className: "sr-only"
396
+ }, triggerLabel), /* @__PURE__ */ React7.createElement(Icon, {
397
+ icon,
398
+ size: 5
399
+ }));
400
+ if (!hasActions) {
401
+ return button;
333
402
  }
334
- }, /* @__PURE__ */ React7.createElement(DropdownMenu.Trigger, {
335
- asChild: true,
336
- ref: forwardedRef
337
- }, button), /* @__PURE__ */ React7.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React7.createElement(DropdownMenu.Content, {
338
- classNames: "z-[31]"
339
- }, /* @__PURE__ */ React7.createElement(DropdownMenu.Viewport, null, actionGroups?.map((actions, index) => {
340
- const separator = index > 0 ? /* @__PURE__ */ React7.createElement(DropdownMenu.Separator, null) : null;
341
- return /* @__PURE__ */ React7.createElement(Fragment, {
342
- key: index
343
- }, separator, actions.map((action) => {
344
- const shortcut = typeof action.properties.keyBinding === "string" ? action.properties.keyBinding : action.properties.keyBinding?.[getHostPlatform()];
345
- const menuItemType = action.properties.menuItemType;
346
- const Root = menuItemType === "toggle" ? DropdownMenu.CheckboxItem : DropdownMenu.Item;
347
- return /* @__PURE__ */ React7.createElement(Root, {
348
- key: action.id,
349
- onClick: (event) => {
350
- if (action.properties.disabled) {
351
- return;
403
+ return /* @__PURE__ */ React7.createElement(DropdownMenu.Root, {
404
+ open: optionsMenuOpen,
405
+ onOpenChange: setOptionsMenuOpen
406
+ }, /* @__PURE__ */ React7.createElement(DropdownMenu.Trigger, {
407
+ asChild: true,
408
+ ref: forwardedRef
409
+ }, button), /* @__PURE__ */ React7.createElement(DropdownMenu.Portal, null, /* @__PURE__ */ React7.createElement(DropdownMenu.Content, {
410
+ classNames: "z-[31]"
411
+ }, /* @__PURE__ */ React7.createElement(DropdownMenu.Viewport, null, actionGroups?.map((actions, index) => {
412
+ const separator = index > 0 ? /* @__PURE__ */ React7.createElement(DropdownMenu.Separator, null) : null;
413
+ return /* @__PURE__ */ React7.createElement(Fragment, {
414
+ key: index
415
+ }, separator, actions.map((action) => {
416
+ const shortcut = typeof action.properties.keyBinding === "string" ? action.properties.keyBinding : action.properties.keyBinding?.[getHostPlatform()];
417
+ const menuItemType = action.properties.menuItemType;
418
+ const Root = menuItemType === "toggle" ? DropdownMenu.CheckboxItem : DropdownMenu.Item;
419
+ return /* @__PURE__ */ React7.createElement(Root, {
420
+ key: action.id,
421
+ onClick: (event) => {
422
+ if (action.properties.disabled) {
423
+ return;
424
+ }
425
+ event.stopPropagation();
426
+ setOptionsMenuOpen(false);
427
+ onAction?.(action);
428
+ },
429
+ classNames: "gap-2",
430
+ disabled: action.properties.disabled,
431
+ checked: menuItemType === "toggle" ? action.properties.isChecked : void 0,
432
+ ...action.properties?.testId && {
433
+ "data-testid": action.properties.testId
352
434
  }
353
- event.stopPropagation();
354
- suppressNextTooltip.current = true;
355
- setOptionsMenuOpen(false);
356
- onAction?.(action);
357
- },
358
- classNames: "gap-2",
359
- disabled: action.properties.disabled,
360
- checked: menuItemType === "toggle" ? action.properties.isChecked : void 0,
361
- ...action.properties?.testId && {
362
- "data-testid": action.properties.testId
363
- }
364
- }, /* @__PURE__ */ React7.createElement(Icon, {
365
- icon: action.properties.icon ?? "ph--placeholder--regular",
366
- size: 4
367
- }), /* @__PURE__ */ React7.createElement("span", {
368
- className: "grow truncate"
369
- }, toLocalizedString(action.properties.label ?? "", t)), menuItemType === "toggle" && /* @__PURE__ */ React7.createElement(DropdownMenu.ItemIndicator, {
370
- asChild: true
371
- }, /* @__PURE__ */ React7.createElement(Icon, {
372
- icon: "ph--check--regular",
373
- size: 4
374
- })), shortcut && /* @__PURE__ */ React7.createElement("span", {
375
- className: mx4("shrink-0", descriptionText)
376
- }, keySymbols(shortcut).join("")));
377
- }));
378
- }), children), /* @__PURE__ */ React7.createElement(DropdownMenu.Arrow, null))));
435
+ }, /* @__PURE__ */ React7.createElement(Icon, {
436
+ icon: action.properties.icon ?? "ph--placeholder--regular",
437
+ size: 4
438
+ }), /* @__PURE__ */ React7.createElement("span", {
439
+ className: "grow truncate"
440
+ }, toLocalizedString(action.properties.label ?? "", t)), menuItemType === "toggle" && /* @__PURE__ */ React7.createElement(DropdownMenu.ItemIndicator, {
441
+ asChild: true
442
+ }, /* @__PURE__ */ React7.createElement(Icon, {
443
+ icon: "ph--check--regular",
444
+ size: 4
445
+ })), shortcut && /* @__PURE__ */ React7.createElement("span", {
446
+ className: mx4("shrink-0", descriptionText)
447
+ }, keySymbols(shortcut).join("")));
448
+ }));
449
+ }), children), /* @__PURE__ */ React7.createElement(DropdownMenu.Arrow, null))));
450
+ } finally {
451
+ _effect.f();
452
+ }
379
453
  });
380
454
 
381
455
  // packages/ui/react-ui-stack/src/components/StackItem/StackItem.tsx
382
456
  var DEFAULT_HORIZONTAL_SIZE = 48;
383
457
  var DEFAULT_VERTICAL_SIZE = "min-content";
384
458
  var DEFAULT_EXTRINSIC_SIZE = DEFAULT_HORIZONTAL_SIZE;
385
- var StackItemRoot = /* @__PURE__ */ forwardRef5(({ item, children, classNames, size: propsSize, onSizeChange, role, order, style, disableRearrange, focusIndicatorVariant = "over-all", ...props }, forwardedRef) => {
386
- const [itemElement, itemRef] = useState4(null);
387
- const [selfDragHandleElement, selfDragHandleRef] = useState4(null);
388
- const [closestEdge, setEdge] = useState4(null);
389
- const { orientation, rail, onRearrange } = useStack();
390
- const [size = orientation === "horizontal" ? DEFAULT_HORIZONTAL_SIZE : DEFAULT_VERTICAL_SIZE, setInternalSize] = useState4(propsSize);
391
- const Root = role ?? "div";
392
- const composedItemRef = composeRefs2(itemRef, forwardedRef);
393
- const setSize = useCallback((nextSize, commit) => {
394
- setInternalSize(nextSize);
395
- if (commit) {
396
- onSizeChange?.(nextSize);
397
- }
398
- }, [
399
- onSizeChange
400
- ]);
401
- const type = orientation === "horizontal" ? "column" : "card";
402
- useLayoutEffect2(() => {
403
- if (!itemElement || !onRearrange || disableRearrange) {
404
- return;
405
- }
406
- return combine2(draggable({
407
- element: itemElement,
408
- ...selfDragHandleElement && {
409
- dragHandle: selfDragHandleElement
410
- },
411
- getInitialData: () => ({
412
- id: item.id,
413
- type
414
- }),
415
- onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
416
- document.body.setAttribute("data-drag-preview", "true");
417
- scrollJustEnoughIntoView({
418
- element: source.element
419
- });
420
- const { x, y } = preserveOffsetOnSource({
421
- element: source.element,
422
- input: location.current.input
423
- })({
424
- container: source.element.offsetParent ?? document.body
425
- });
426
- nativeSetDragImage?.(source.element, x, y);
427
- },
428
- onDragStart: () => {
429
- document.body.removeAttribute("data-drag-preview");
430
- itemElement?.closest("[data-drag-autoscroll]")?.setAttribute("data-drag-autoscroll", "active");
431
- },
432
- onDrop: () => {
433
- itemElement?.closest("[data-drag-autoscroll]")?.setAttribute("data-drag-autoscroll", "idle");
459
+ var StackItemRoot = /* @__PURE__ */ forwardRef5(({ item, children, classNames, size: propsSize, onSizeChange, role, order, prevSiblingId, nextSiblingId, style, disableRearrange, focusIndicatorVariant = "over-all", ...props }, forwardedRef) => {
460
+ var _effect = _useSignals8();
461
+ try {
462
+ const [itemElement, itemRef] = useState4(null);
463
+ const [selfDragHandleElement, selfDragHandleRef] = useState4(null);
464
+ const [closestEdge, setEdge] = useState4(null);
465
+ const [sourceId, setSourceId] = useState4(null);
466
+ const [dragState, setDragState] = useState4(idle);
467
+ const { orientation, rail, onRearrange } = useStack();
468
+ const [size = orientation === "horizontal" ? DEFAULT_HORIZONTAL_SIZE : DEFAULT_VERTICAL_SIZE, setInternalSize] = useState4(propsSize);
469
+ const Root = role ?? "div";
470
+ const composedItemRef = composeRefs2(itemRef, forwardedRef);
471
+ const setSize = useCallback2((nextSize, commit) => {
472
+ setInternalSize(nextSize);
473
+ if (commit) {
474
+ onSizeChange?.(nextSize);
475
+ }
476
+ }, [
477
+ onSizeChange
478
+ ]);
479
+ const type = orientation === "horizontal" ? "column" : "card";
480
+ useLayoutEffect2(() => {
481
+ if (!itemElement || !onRearrange || disableRearrange) {
482
+ return;
434
483
  }
435
- }), dropTargetForElements2({
436
- element: itemElement,
437
- getData: ({ input, element }) => {
438
- return attachClosestEdge2({
484
+ return combine2(draggable({
485
+ element: itemElement,
486
+ ...selfDragHandleElement && {
487
+ dragHandle: selfDragHandleElement
488
+ },
489
+ getInitialData: () => ({
439
490
  id: item.id,
440
491
  type
441
- }, {
442
- input,
443
- element,
444
- allowedEdges: orientation === "horizontal" ? [
445
- "left",
446
- "right"
447
- ] : [
448
- "top",
449
- "bottom"
450
- ]
451
- });
452
- },
453
- onDragEnter: ({ self, source }) => {
454
- if (source.data.type === self.data.type) {
455
- setEdge(extractClosestEdge2(self.data));
456
- }
457
- },
458
- onDrag: ({ self, source }) => {
459
- if (source.data.type === self.data.type) {
460
- setEdge(extractClosestEdge2(self.data));
492
+ }),
493
+ onGenerateDragPreview: ({ nativeSetDragImage, source, location }) => {
494
+ document.body.setAttribute("data-drag-preview", "true");
495
+ const offsetFn = preserveOffsetOnSource({
496
+ element: source.element,
497
+ input: location.current.input
498
+ });
499
+ const rect = source.element.getBoundingClientRect();
500
+ setCustomNativeDragPreview({
501
+ nativeSetDragImage,
502
+ getOffset: ({ container }) => {
503
+ return offsetFn({
504
+ container
505
+ });
506
+ },
507
+ render: ({ container }) => {
508
+ container.style.width = rect.width + "px";
509
+ setDragState({
510
+ type: "preview",
511
+ container,
512
+ item
513
+ });
514
+ return () => {
515
+ };
516
+ }
517
+ });
518
+ },
519
+ onDragStart: () => {
520
+ document.body.removeAttribute("data-drag-preview");
521
+ itemElement?.closest("[data-drag-autoscroll]")?.setAttribute("data-drag-autoscroll", "active");
522
+ setDragState({
523
+ type: "is-dragging",
524
+ item
525
+ });
526
+ },
527
+ onDrop: () => {
528
+ itemElement?.closest("[data-drag-autoscroll]")?.setAttribute("data-drag-autoscroll", "idle");
529
+ setDragState(idle);
461
530
  }
462
- },
463
- onDragLeave: () => setEdge(null),
464
- onDrop: ({ self, source }) => {
465
- setEdge(null);
466
- if (source.data.type === self.data.type) {
467
- onRearrange(source.data, self.data, extractClosestEdge2(self.data));
531
+ }), dropTargetForElements2({
532
+ element: itemElement,
533
+ getData: ({ input, element }) => {
534
+ return attachClosestEdge2({
535
+ id: item.id,
536
+ type
537
+ }, {
538
+ input,
539
+ element,
540
+ allowedEdges: orientation === "horizontal" ? [
541
+ "left",
542
+ "right"
543
+ ] : [
544
+ "top",
545
+ "bottom"
546
+ ]
547
+ });
548
+ },
549
+ onDragEnter: ({ self, source }) => {
550
+ if (source.data.type === self.data.type) {
551
+ setEdge(extractClosestEdge2(self.data));
552
+ setSourceId(source.data.id);
553
+ }
554
+ },
555
+ onDrag: ({ self, source }) => {
556
+ if (source.data.type === self.data.type) {
557
+ setEdge(extractClosestEdge2(self.data));
558
+ setSourceId(source.data.id);
559
+ }
560
+ },
561
+ onDragLeave: () => {
562
+ setEdge(null);
563
+ setSourceId(null);
564
+ },
565
+ onDrop: ({ self, source }) => {
566
+ setEdge(null);
567
+ setSourceId(null);
568
+ if (source.data.type === self.data.type) {
569
+ onRearrange(source.data, self.data, extractClosestEdge2(self.data));
570
+ }
468
571
  }
572
+ }));
573
+ }, [
574
+ orientation,
575
+ item,
576
+ onRearrange,
577
+ selfDragHandleElement,
578
+ itemElement
579
+ ]);
580
+ const focusableGroupAttrs = useFocusableGroup2({
581
+ tabBehavior: "limited"
582
+ });
583
+ const shouldShowDropIndicator = () => {
584
+ if (!closestEdge || !sourceId) {
585
+ return false;
469
586
  }
470
- }));
471
- }, [
472
- orientation,
473
- item,
474
- onRearrange,
475
- selfDragHandleElement,
476
- itemElement
477
- ]);
478
- const focusableGroupAttrs = useFocusableGroup2({
479
- tabBehavior: "limited"
480
- });
481
- return /* @__PURE__ */ React8.createElement(StackItemContext.Provider, {
482
- value: {
483
- selfDragHandleRef,
484
- size,
485
- setSize
486
- }
487
- }, /* @__PURE__ */ React8.createElement(Root, {
488
- ...props,
489
- tabIndex: 0,
490
- ...focusableGroupAttrs,
491
- className: mx5("group/stack-item grid relative", focusIndicatorVariant === "over-all" ? "dx-focus-ring-inset-over-all" : orientation === "horizontal" ? "dx-focus-ring-group-x" : "dx-focus-ring-group-y", orientation === "horizontal" ? "grid-rows-subgrid" : "grid-cols-subgrid", rail && (orientation === "horizontal" ? "row-span-2" : "col-span-2"), classNames),
492
- "data-dx-stack-item": true,
493
- ...resizeAttributes,
494
- style: {
495
- ...sizeStyle(size, orientation),
496
- ...Number.isFinite(order) && {
497
- [orientation === "horizontal" ? "gridColumn" : "gridRow"]: `${order}`
587
+ if (sourceId === item.id) {
588
+ return false;
589
+ }
590
+ const isTrailingEdgeOfPrevSibling = prevSiblingId !== void 0 && sourceId === prevSiblingId && (orientation === "horizontal" && closestEdge === "left" || orientation === "vertical" && closestEdge === "top");
591
+ if (isTrailingEdgeOfPrevSibling) {
592
+ return false;
593
+ }
594
+ const isLeadingEdgeOfNextSibling = nextSiblingId !== void 0 && sourceId === nextSiblingId && (orientation === "horizontal" && closestEdge === "right" || orientation === "vertical" && closestEdge === "bottom");
595
+ if (isLeadingEdgeOfNextSibling) {
596
+ return false;
597
+ }
598
+ return true;
599
+ };
600
+ return /* @__PURE__ */ React8.createElement(StackItemContext.Provider, {
601
+ value: {
602
+ selfDragHandleRef,
603
+ size,
604
+ setSize,
605
+ state: dragState,
606
+ setState: setDragState
607
+ }
608
+ }, /* @__PURE__ */ React8.createElement(Root, {
609
+ ...props,
610
+ tabIndex: 0,
611
+ ...focusableGroupAttrs,
612
+ className: mx5("group/stack-item grid relative", focusIndicatorVariant === "over-all" ? "dx-focus-ring-inset-over-all" : orientation === "horizontal" ? "dx-focus-ring-group-x" : "dx-focus-ring-group-y", orientation === "horizontal" ? "grid-rows-subgrid" : "grid-cols-subgrid", rail && (orientation === "horizontal" ? "row-span-2" : "col-span-2"), classNames),
613
+ "data-dx-stack-item": true,
614
+ ...resizeAttributes,
615
+ style: {
616
+ ...sizeStyle(size, orientation),
617
+ ...Number.isFinite(order) && {
618
+ [orientation === "horizontal" ? "gridColumn" : "gridRow"]: `${order}`
619
+ },
620
+ ...style
498
621
  },
499
- ...style
500
- },
501
- ref: composedItemRef
502
- }, children, closestEdge && /* @__PURE__ */ React8.createElement(ListItem2.DropIndicator, {
503
- lineInset: 8,
504
- terminalInset: -8,
505
- edge: closestEdge
506
- })));
622
+ ref: composedItemRef
623
+ }, children, shouldShowDropIndicator() && closestEdge && /* @__PURE__ */ React8.createElement(ListItem2.DropIndicator, {
624
+ lineInset: 8,
625
+ terminalInset: -8,
626
+ edge: closestEdge
627
+ })));
628
+ } finally {
629
+ _effect.f();
630
+ }
507
631
  });
632
+ var StackItemDragPreview = ({ children }) => {
633
+ const { state } = useStackItem();
634
+ return state?.type === "preview" ? /* @__PURE__ */ createPortal(children({
635
+ item: state.item
636
+ }), state.container) : null;
637
+ };
508
638
  var StackItem = {
509
639
  Root: StackItemRoot,
510
640
  Content: StackItemContent,
@@ -513,7 +643,8 @@ var StackItem = {
513
643
  ResizeHandle: StackItemResizeHandle,
514
644
  DragHandle: StackItemDragHandle,
515
645
  Sigil: StackItemSigil,
516
- SigilButton: StackItemSigilButton
646
+ SigilButton: StackItemSigilButton,
647
+ DragPreview: StackItemDragPreview
517
648
  };
518
649
  export {
519
650
  DEFAULT_EXTRINSIC_SIZE,
@@ -522,6 +653,7 @@ export {
522
653
  Stack,
523
654
  StackContext,
524
655
  StackItem,
656
+ StackItemDragPreview,
525
657
  autoScrollRootAttributes,
526
658
  railGridHorizontal,
527
659
  railGridHorizontalContainFitContent,