@dxos/react-ui-stack 0.8.4-main.c1de068 → 0.8.4-main.c85a9c8dae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +743 -57
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/playwright/index.mjs +4 -0
- package/dist/lib/browser/playwright/index.mjs.map +2 -2
- package/dist/lib/node-esm/index.mjs +744 -57
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/playwright/index.mjs +4 -0
- package/dist/lib/node-esm/playwright/index.mjs.map +2 -2
- package/dist/types/src/components/Stack/Stack.d.ts +17 -9
- package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
- package/dist/types/src/components/Stack/Stack.stories.d.ts +12 -3
- package/dist/types/src/components/Stack/Stack.stories.d.ts.map +1 -1
- package/dist/types/src/components/StackContext.d.ts +3 -2
- package/dist/types/src/components/StackContext.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/MenuSignifier.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItem.d.ts +10 -13
- package/dist/types/src/components/StackItem/StackItem.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItem.stories.d.ts +13 -5
- package/dist/types/src/components/StackItem/StackItem.stories.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItemContent.d.ts +4 -37
- package/dist/types/src/components/StackItem/StackItemContent.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItemDragHandle.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItemHeading.d.ts +1 -1
- package/dist/types/src/components/StackItem/StackItemHeading.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts +1 -1
- package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItemSigil.d.ts +2 -2
- package/dist/types/src/components/StackItem/StackItemSigil.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +1 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/components/{defs.d.ts → types.d.ts} +1 -1
- package/dist/types/src/components/types.d.ts.map +1 -0
- package/dist/types/src/hooks/useStackDropForElements.d.ts +9 -7
- package/dist/types/src/hooks/useStackDropForElements.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +2 -2
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +41 -38
- package/src/components/Stack/Stack.stories.tsx +8 -9
- package/src/components/Stack/Stack.tsx +230 -31
- package/src/components/StackContext.tsx +3 -2
- package/src/components/StackItem/MenuSignifier.tsx +2 -9
- package/src/components/StackItem/StackItem.stories.tsx +21 -17
- package/src/components/StackItem/StackItem.tsx +51 -31
- package/src/components/StackItem/StackItemContent.tsx +25 -44
- package/src/components/StackItem/StackItemDragHandle.tsx +4 -3
- package/src/components/StackItem/StackItemHeading.tsx +15 -18
- package/src/components/StackItem/StackItemResizeHandle.tsx +3 -2
- package/src/components/StackItem/StackItemSigil.tsx +10 -6
- package/src/components/index.ts +2 -1
- package/src/hooks/useStackDropForElements.ts +59 -45
- package/src/index.ts +0 -3
- package/src/playwright/playwright.config.ts +1 -1
- package/src/translations.ts +1 -1
- package/dist/lib/browser/chunk-P3TQV4BA.mjs +0 -1198
- package/dist/lib/browser/chunk-P3TQV4BA.mjs.map +0 -7
- package/dist/lib/browser/testing/index.mjs +0 -31
- package/dist/lib/browser/testing/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-3WVEPAJ4.mjs +0 -1200
- package/dist/lib/node-esm/chunk-3WVEPAJ4.mjs.map +0 -7
- package/dist/lib/node-esm/testing/index.mjs +0 -32
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/components/defs.d.ts.map +0 -1
- package/dist/types/src/components/deprecated/LayoutControls.d.ts +0 -19
- package/dist/types/src/components/deprecated/LayoutControls.d.ts.map +0 -1
- package/dist/types/src/exemplars/Card/Card.d.ts +0 -58
- package/dist/types/src/exemplars/Card/Card.d.ts.map +0 -1
- package/dist/types/src/exemplars/Card/Card.stories.d.ts +0 -13
- package/dist/types/src/exemplars/Card/Card.stories.d.ts.map +0 -1
- package/dist/types/src/exemplars/Card/CardDragPreview.d.ts +0 -6
- package/dist/types/src/exemplars/Card/CardDragPreview.d.ts.map +0 -1
- package/dist/types/src/exemplars/Card/fragments.d.ts +0 -12
- package/dist/types/src/exemplars/Card/fragments.d.ts.map +0 -1
- package/dist/types/src/exemplars/Card/index.d.ts +0 -4
- package/dist/types/src/exemplars/Card/index.d.ts.map +0 -1
- package/dist/types/src/exemplars/CardStack/CardStack.d.ts +0 -40
- package/dist/types/src/exemplars/CardStack/CardStack.d.ts.map +0 -1
- package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts +0 -9
- package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts.map +0 -1
- package/dist/types/src/exemplars/CardStack/CardStackDragPreview.d.ts +0 -9
- package/dist/types/src/exemplars/CardStack/CardStackDragPreview.d.ts.map +0 -1
- package/dist/types/src/exemplars/CardStack/index.d.ts +0 -3
- package/dist/types/src/exemplars/CardStack/index.d.ts.map +0 -1
- package/dist/types/src/exemplars/index.d.ts +0 -3
- package/dist/types/src/exemplars/index.d.ts.map +0 -1
- package/dist/types/src/testing/CardContainer.d.ts +0 -6
- package/dist/types/src/testing/CardContainer.d.ts.map +0 -1
- package/dist/types/src/testing/index.d.ts +0 -2
- package/dist/types/src/testing/index.d.ts.map +0 -1
- package/src/components/deprecated/LayoutControls.tsx +0 -109
- package/src/exemplars/Card/Card.stories.tsx +0 -78
- package/src/exemplars/Card/Card.tsx +0 -186
- package/src/exemplars/Card/CardDragPreview.tsx +0 -22
- package/src/exemplars/Card/fragments.ts +0 -23
- package/src/exemplars/Card/index.ts +0 -7
- package/src/exemplars/CardStack/CardStack.stories.tsx +0 -172
- package/src/exemplars/CardStack/CardStack.tsx +0 -136
- package/src/exemplars/CardStack/CardStackDragPreview.tsx +0 -61
- package/src/exemplars/CardStack/index.ts +0 -6
- package/src/exemplars/index.ts +0 -6
- package/src/testing/CardContainer.tsx +0 -34
- package/src/testing/index.ts +0 -5
- /package/src/components/{defs.ts → types.ts} +0 -0
|
@@ -7,52 +7,57 @@ import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-d
|
|
|
7
7
|
import { preserveOffsetOnSource } from '@atlaskit/pragmatic-drag-and-drop/element/preserve-offset-on-source';
|
|
8
8
|
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
9
9
|
import {
|
|
10
|
+
type Edge,
|
|
10
11
|
attachClosestEdge,
|
|
11
12
|
extractClosestEdge,
|
|
12
|
-
type Edge,
|
|
13
13
|
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
14
14
|
import { useFocusableGroup } from '@fluentui/react-tabster';
|
|
15
15
|
import { composeRefs } from '@radix-ui/react-compose-refs';
|
|
16
16
|
import React, {
|
|
17
|
-
forwardRef,
|
|
18
|
-
useLayoutEffect,
|
|
19
|
-
useState,
|
|
20
17
|
type ComponentPropsWithRef,
|
|
21
|
-
useCallback,
|
|
22
18
|
type ReactNode,
|
|
19
|
+
forwardRef,
|
|
20
|
+
useCallback,
|
|
21
|
+
useLayoutEffect,
|
|
23
22
|
useMemo,
|
|
23
|
+
useState,
|
|
24
24
|
} from 'react';
|
|
25
25
|
import { createPortal } from 'react-dom';
|
|
26
26
|
|
|
27
|
-
import { type ThemedClassName
|
|
27
|
+
import { ListItem, type ThemedClassName } from '@dxos/react-ui';
|
|
28
28
|
import { resizeAttributes, sizeStyle } from '@dxos/react-ui-dnd';
|
|
29
|
-
import { mx } from '@dxos/
|
|
29
|
+
import { mx } from '@dxos/ui-theme';
|
|
30
|
+
|
|
31
|
+
import { type ItemDragState, StackItemContext, idle, useStack, useStackItem } from '../StackContext';
|
|
32
|
+
import { type StackItemData, type StackItemSize } from '../types';
|
|
30
33
|
|
|
31
34
|
import { StackItemContent, type StackItemContentProps } from './StackItemContent';
|
|
32
35
|
import { StackItemDragHandle, type StackItemDragHandleProps } from './StackItemDragHandle';
|
|
33
36
|
import {
|
|
34
37
|
StackItemHeading,
|
|
35
38
|
StackItemHeadingLabel,
|
|
36
|
-
type StackItemHeadingProps,
|
|
37
39
|
type StackItemHeadingLabelProps,
|
|
40
|
+
type StackItemHeadingProps,
|
|
38
41
|
StackItemHeadingStickyContent,
|
|
39
42
|
} from './StackItemHeading';
|
|
40
43
|
import { StackItemResizeHandle, type StackItemResizeHandleProps } from './StackItemResizeHandle';
|
|
41
44
|
import {
|
|
42
45
|
StackItemSigil,
|
|
43
|
-
type StackItemSigilProps,
|
|
44
46
|
type StackItemSigilAction,
|
|
45
|
-
type StackItemSigilButtonProps,
|
|
46
47
|
StackItemSigilButton,
|
|
48
|
+
type StackItemSigilButtonProps,
|
|
49
|
+
type StackItemSigilProps,
|
|
47
50
|
} from './StackItemSigil';
|
|
48
|
-
import { useStack, StackItemContext, idle, type ItemDragState, useStackItem } from '../StackContext';
|
|
49
|
-
import { type StackItemSize, type StackItemData } from '../defs';
|
|
50
51
|
|
|
51
52
|
// NOTE: 48rem fills the screen on a MacbookPro with the sidebars closed.
|
|
52
53
|
export const DEFAULT_HORIZONTAL_SIZE = 48 satisfies StackItemSize;
|
|
53
54
|
export const DEFAULT_VERTICAL_SIZE = 'min-content' satisfies StackItemSize;
|
|
54
55
|
export const DEFAULT_EXTRINSIC_SIZE = DEFAULT_HORIZONTAL_SIZE satisfies StackItemSize;
|
|
55
56
|
|
|
57
|
+
//
|
|
58
|
+
// StackItemRoot
|
|
59
|
+
//
|
|
60
|
+
|
|
56
61
|
type StackItemRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {
|
|
57
62
|
item: Omit<StackItemData, 'type'>;
|
|
58
63
|
order?: number;
|
|
@@ -62,7 +67,7 @@ type StackItemRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {
|
|
|
62
67
|
onSizeChange?: (nextSize: StackItemSize) => void;
|
|
63
68
|
role?: 'article' | 'section';
|
|
64
69
|
disableRearrange?: boolean;
|
|
65
|
-
focusIndicatorVariant?: 'over-all' | 'group';
|
|
70
|
+
focusIndicatorVariant?: 'over-all' | 'group' | 'over-all-always' | 'group-always';
|
|
66
71
|
};
|
|
67
72
|
|
|
68
73
|
const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
@@ -85,18 +90,17 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
85
90
|
forwardedRef,
|
|
86
91
|
) => {
|
|
87
92
|
const [itemElement, itemRef] = useState<HTMLDivElement | null>(null);
|
|
93
|
+
const composedItemRef = composeRefs<HTMLDivElement>(itemRef, forwardedRef);
|
|
88
94
|
const [selfDragHandleElement, selfDragHandleRef] = useState<HTMLDivElement | null>(null);
|
|
89
95
|
const [closestEdge, setEdge] = useState<Edge | null>(null);
|
|
90
96
|
const [sourceId, setSourceId] = useState<string | null>(null);
|
|
91
97
|
const [dragState, setDragState] = useState<ItemDragState>(idle);
|
|
92
|
-
const { orientation, rail, onRearrange } = useStack();
|
|
98
|
+
const { orientation, rail, onRearrange, size: stackSize, stackId } = useStack();
|
|
93
99
|
const [size = orientation === 'horizontal' ? DEFAULT_HORIZONTAL_SIZE : DEFAULT_VERTICAL_SIZE, setInternalSize] =
|
|
94
100
|
useState(propsSize);
|
|
95
101
|
|
|
96
102
|
const Root = role ?? 'div';
|
|
97
103
|
|
|
98
|
-
const composedItemRef = composeRefs<HTMLDivElement>(itemRef, forwardedRef);
|
|
99
|
-
|
|
100
104
|
const setSize = useCallback(
|
|
101
105
|
(nextSize: StackItemSize, commit?: boolean) => {
|
|
102
106
|
setInternalSize(nextSize);
|
|
@@ -109,6 +113,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
109
113
|
|
|
110
114
|
const type = orientation === 'horizontal' ? 'column' : 'card';
|
|
111
115
|
|
|
116
|
+
// TODO(burdon): Factor out?
|
|
112
117
|
useLayoutEffect(() => {
|
|
113
118
|
if (!itemElement || !onRearrange || disableRearrange) {
|
|
114
119
|
return;
|
|
@@ -138,7 +143,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
138
143
|
onDragStart: () => {
|
|
139
144
|
document.body.removeAttribute('data-drag-preview');
|
|
140
145
|
itemElement?.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'active');
|
|
141
|
-
setDragState({ type: '
|
|
146
|
+
setDragState({ type: 'w-dragging', item });
|
|
142
147
|
},
|
|
143
148
|
onDrop: () => {
|
|
144
149
|
itemElement?.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'idle');
|
|
@@ -182,18 +187,18 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
182
187
|
|
|
183
188
|
const focusableGroupAttrs = useFocusableGroup({ tabBehavior: 'limited' });
|
|
184
189
|
|
|
185
|
-
// Determine if the drop would result in any changes
|
|
190
|
+
// Determine if the drop would result in any changes.
|
|
186
191
|
const shouldShowDropIndicator = () => {
|
|
187
192
|
if (!closestEdge || !sourceId) {
|
|
188
193
|
return false;
|
|
189
194
|
}
|
|
190
195
|
|
|
191
|
-
// Don't show indicator when dragged item is over itself
|
|
196
|
+
// Don't show indicator when dragged item is over itself.
|
|
192
197
|
if (sourceId === item.id) {
|
|
193
198
|
return false;
|
|
194
199
|
}
|
|
195
200
|
|
|
196
|
-
// Don't show indicator when dragged item is over the trailing edge of its previous sibling
|
|
201
|
+
// Don't show indicator when dragged item is over the trailing edge of its previous sibling.
|
|
197
202
|
const isTrailingEdgeOfPrevSibling =
|
|
198
203
|
prevSiblingId !== undefined &&
|
|
199
204
|
sourceId === prevSiblingId &&
|
|
@@ -231,18 +236,25 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
231
236
|
'group/stack-item grid relative',
|
|
232
237
|
focusIndicatorVariant === 'over-all'
|
|
233
238
|
? 'dx-focus-ring-inset-over-all'
|
|
234
|
-
:
|
|
235
|
-
? 'dx-focus-ring-
|
|
236
|
-
: '
|
|
239
|
+
: focusIndicatorVariant === 'over-all-always'
|
|
240
|
+
? 'dx-focus-ring-inset-over-all-always'
|
|
241
|
+
: orientation === 'horizontal'
|
|
242
|
+
? focusIndicatorVariant === 'group-always'
|
|
243
|
+
? 'dx-focus-ring-group-x-always'
|
|
244
|
+
: 'dx-focus-ring-group-x'
|
|
245
|
+
: focusIndicatorVariant === 'group-always'
|
|
246
|
+
? 'dx-focus-ring-group-y-always'
|
|
247
|
+
: 'dx-focus-ring-group-y',
|
|
237
248
|
orientation === 'horizontal' ? 'grid-rows-subgrid' : 'grid-cols-subgrid',
|
|
238
249
|
rail && (orientation === 'horizontal' ? 'row-span-2' : 'col-span-2'),
|
|
239
|
-
role === 'section' && orientation !== 'horizontal' && 'border-
|
|
250
|
+
role === 'section' && orientation !== 'horizontal' && 'border-b border-subdued-separator',
|
|
240
251
|
classNames,
|
|
241
252
|
)}
|
|
242
|
-
data-dx-stack-item
|
|
253
|
+
data-dx-stack-item={stackId}
|
|
254
|
+
data-dx-item-id={item.id}
|
|
243
255
|
{...resizeAttributes}
|
|
244
256
|
style={{
|
|
245
|
-
...sizeStyle(size, orientation),
|
|
257
|
+
...(stackSize !== 'split' && sizeStyle(size, orientation)),
|
|
246
258
|
...(Number.isFinite(order) && {
|
|
247
259
|
[orientation === 'horizontal' ? 'gridColumn' : 'gridRow']: `${order}`,
|
|
248
260
|
}),
|
|
@@ -260,37 +272,45 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
260
272
|
},
|
|
261
273
|
);
|
|
262
274
|
|
|
275
|
+
//
|
|
276
|
+
// StackItemDragPreview
|
|
277
|
+
//
|
|
278
|
+
|
|
263
279
|
type StackItemDragPreviewProps = {
|
|
264
280
|
children: ({ item }: { item: any }) => ReactNode;
|
|
265
281
|
};
|
|
266
282
|
|
|
267
|
-
|
|
283
|
+
const StackItemDragPreview = ({ children }: StackItemDragPreviewProps) => {
|
|
268
284
|
const { state } = useStackItem();
|
|
269
285
|
return state?.type === 'preview' ? createPortal(children({ item: state.item }), state.container) : null;
|
|
270
286
|
};
|
|
271
287
|
|
|
288
|
+
//
|
|
289
|
+
// StackItem
|
|
290
|
+
//
|
|
291
|
+
|
|
272
292
|
export const StackItem = {
|
|
273
293
|
Root: StackItemRoot,
|
|
274
294
|
Content: StackItemContent,
|
|
295
|
+
DragHandle: StackItemDragHandle,
|
|
296
|
+
DragPreview: StackItemDragPreview,
|
|
275
297
|
Heading: StackItemHeading,
|
|
276
298
|
HeadingLabel: StackItemHeadingLabel,
|
|
277
299
|
HeadingStickyContent: StackItemHeadingStickyContent,
|
|
278
300
|
ResizeHandle: StackItemResizeHandle,
|
|
279
|
-
DragHandle: StackItemDragHandle,
|
|
280
301
|
Sigil: StackItemSigil,
|
|
281
302
|
SigilButton: StackItemSigilButton,
|
|
282
|
-
DragPreview: StackItemDragPreview,
|
|
283
303
|
};
|
|
284
304
|
|
|
285
305
|
export type {
|
|
286
306
|
StackItemRootProps,
|
|
287
307
|
StackItemContentProps,
|
|
308
|
+
StackItemDragHandleProps,
|
|
309
|
+
StackItemDragPreviewProps,
|
|
288
310
|
StackItemHeadingProps,
|
|
289
311
|
StackItemHeadingLabelProps,
|
|
290
312
|
StackItemResizeHandleProps,
|
|
291
|
-
StackItemDragHandleProps,
|
|
292
313
|
StackItemSigilProps,
|
|
293
314
|
StackItemSigilButtonProps,
|
|
294
315
|
StackItemSigilAction,
|
|
295
|
-
StackItemDragPreviewProps,
|
|
296
316
|
};
|
|
@@ -5,70 +5,49 @@
|
|
|
5
5
|
import React, { type ComponentPropsWithoutRef, forwardRef, useMemo } from 'react';
|
|
6
6
|
|
|
7
7
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
8
|
-
import { mx } from '@dxos/
|
|
8
|
+
import { mx } from '@dxos/ui-theme';
|
|
9
9
|
|
|
10
10
|
import { useStack, useStackItem } from '../StackContext';
|
|
11
11
|
|
|
12
|
-
export type StackItemContentProps = ThemedClassName<Omit<ComponentPropsWithoutRef<'div'>, 'role'>> & {
|
|
13
|
-
/**
|
|
14
|
-
* This flag is required in order to clarify a developer experience that seemed like it needed extra boilerplate
|
|
15
|
-
* (`row-span-2`) or was buggy. See the description of the StackItem.Content component itself for more information.
|
|
16
|
-
*/
|
|
12
|
+
export type StackItemContentProps = ThemedClassName<Omit<ComponentPropsWithoutRef<'div'>, 'role' | 'scrollable'>> & {
|
|
17
13
|
toolbar?: boolean;
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Whether to provide for the layout of a statusbar after the content.
|
|
21
|
-
*/
|
|
22
14
|
statusbar?: boolean;
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Whether the consumer intends to do something custom and typical affordances should not apply
|
|
26
|
-
*/
|
|
27
|
-
layoutManaged?: boolean;
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Whether to set a certain aspect ratio on the content, including the toolbar and statusbar. This is provided for
|
|
31
|
-
* convenience and consistency; it can instead be specified by the `classNames` or `style` props as needed.
|
|
32
|
-
*/
|
|
33
|
-
size?: 'intrinsic' | 'video' | 'square';
|
|
34
15
|
};
|
|
35
16
|
|
|
36
17
|
/**
|
|
37
|
-
* This component should be used by plugins for rendering content within a stack item
|
|
38
|
-
* The `toolbar` flag must be provided since this component provides for the layout of content with the toolbar.
|
|
18
|
+
* This component should be used by plugins for rendering content within a stack item (i.e., a “plank” or “section”).
|
|
39
19
|
*/
|
|
40
20
|
export const StackItemContent = forwardRef<HTMLDivElement, StackItemContentProps>(
|
|
41
|
-
({ children, toolbar, statusbar,
|
|
21
|
+
({ classNames, children, toolbar, statusbar, ...props }, forwardedRef) => {
|
|
42
22
|
const { size: stackItemSize } = useStack();
|
|
43
23
|
const { role } = useStackItem();
|
|
44
24
|
const style = useMemo(
|
|
45
|
-
() =>
|
|
46
|
-
|
|
47
|
-
?
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
[toolbar, statusbar, layoutManaged],
|
|
25
|
+
() => ({
|
|
26
|
+
gridTemplateRows: [
|
|
27
|
+
toolbar && role === 'section' ? 'calc(var(--dx-toolbar-size) - 1px)' : 'var(--dx-toolbar-size)',
|
|
28
|
+
'1fr',
|
|
29
|
+
statusbar && 'var(--dx-statusbar-size)',
|
|
30
|
+
]
|
|
31
|
+
.filter(Boolean)
|
|
32
|
+
.join(' '),
|
|
33
|
+
}),
|
|
34
|
+
[toolbar, statusbar],
|
|
56
35
|
);
|
|
36
|
+
|
|
57
37
|
return (
|
|
58
38
|
<div
|
|
59
|
-
role='none'
|
|
60
39
|
{...props}
|
|
40
|
+
role='none'
|
|
41
|
+
style={style}
|
|
61
42
|
className={mx(
|
|
62
|
-
'group grid grid-cols-[100%] density-coarse',
|
|
63
|
-
stackItemSize === 'contain' && 'min-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
'[&_.dx-toolbar]:sticky [&_.dx-toolbar]:z-[1] [&_.dx-toolbar]:block-start-0 [&_.dx-toolbar]:-mbe-px [&_.dx-toolbar]:min-is-0',
|
|
43
|
+
'group grid grid-cols-[100%] dx-density-coarse',
|
|
44
|
+
stackItemSize === 'contain' && 'min-h-0 overflow-hidden',
|
|
45
|
+
toolbar &&
|
|
46
|
+
role === 'section' &&
|
|
47
|
+
'[&_.dx-toolbar]:sticky [&_.dx-toolbar]:z-[1] [&_.dx-toolbar]:top-0 [&_.dx-toolbar]:-mb-px [&_.dx-toolbar]:min-w-0',
|
|
48
|
+
toolbar && '[&>.dx-toolbar]:relative [&>.dx-toolbar]:border-b [&>.dx-toolbar]:border-subdued-separator',
|
|
69
49
|
classNames,
|
|
70
50
|
)}
|
|
71
|
-
style={style}
|
|
72
51
|
data-popover-collision-boundary={true}
|
|
73
52
|
ref={forwardedRef}
|
|
74
53
|
>
|
|
@@ -77,3 +56,5 @@ export const StackItemContent = forwardRef<HTMLDivElement, StackItemContentProps
|
|
|
77
56
|
);
|
|
78
57
|
},
|
|
79
58
|
);
|
|
59
|
+
|
|
60
|
+
StackItemContent.displayName = 'StackItemContent';
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Primitive } from '@radix-ui/react-primitive';
|
|
5
6
|
import { Slot } from '@radix-ui/react-slot';
|
|
6
7
|
import React, { type ComponentPropsWithoutRef } from 'react';
|
|
7
8
|
|
|
@@ -12,11 +13,11 @@ export type StackItemDragHandleProps = ComponentPropsWithoutRef<'button'> & { as
|
|
|
12
13
|
export const StackItemDragHandle = ({ asChild, children }: StackItemDragHandleProps) => {
|
|
13
14
|
const { selfDragHandleRef } = useStackItem();
|
|
14
15
|
|
|
15
|
-
const
|
|
16
|
+
const Comp = asChild ? Slot : Primitive.div;
|
|
16
17
|
|
|
17
18
|
return (
|
|
18
|
-
<
|
|
19
|
+
<Comp ref={selfDragHandleRef} role='button'>
|
|
19
20
|
{children}
|
|
20
|
-
</
|
|
21
|
+
</Comp>
|
|
21
22
|
);
|
|
22
23
|
};
|
|
@@ -2,18 +2,18 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Primitive } from '@radix-ui/react-primitive';
|
|
6
6
|
import { Slot } from '@radix-ui/react-slot';
|
|
7
7
|
import React, {
|
|
8
|
-
type ComponentPropsWithoutRef,
|
|
9
8
|
type ComponentPropsWithRef,
|
|
10
|
-
|
|
9
|
+
type ComponentPropsWithoutRef,
|
|
11
10
|
type PropsWithChildren,
|
|
11
|
+
forwardRef,
|
|
12
12
|
} from 'react';
|
|
13
13
|
|
|
14
14
|
import { type ThemedClassName } from '@dxos/react-ui';
|
|
15
|
-
import {
|
|
16
|
-
import { mx } from '@dxos/
|
|
15
|
+
import { type AttendableId, type Related, useAttention } from '@dxos/react-ui-attention';
|
|
16
|
+
import { mx } from '@dxos/ui-theme';
|
|
17
17
|
|
|
18
18
|
import { useStack } from '../StackContext';
|
|
19
19
|
|
|
@@ -30,34 +30,31 @@ export const StackItemHeading = ({
|
|
|
30
30
|
...props
|
|
31
31
|
}: StackItemHeadingProps) => {
|
|
32
32
|
const { orientation } = useStack();
|
|
33
|
-
const focusableGroupAttrs = useFocusableGroup({ tabBehavior: 'limited' });
|
|
34
33
|
|
|
35
|
-
const
|
|
34
|
+
const Comp = asChild ? Slot : Primitive.div;
|
|
36
35
|
|
|
37
36
|
return (
|
|
38
|
-
<
|
|
37
|
+
<Comp
|
|
39
38
|
role='heading'
|
|
40
39
|
{...props}
|
|
41
|
-
tabIndex={0}
|
|
42
|
-
{...focusableGroupAttrs}
|
|
43
40
|
className={mx(
|
|
44
|
-
'flex items-center
|
|
41
|
+
'flex items-center border-x-0! bg-header-surface',
|
|
45
42
|
separateOnScroll
|
|
46
|
-
? 'border-transparent [[data-scroll-separator="true"]_&]:border-
|
|
47
|
-
: 'border-
|
|
48
|
-
orientation === 'horizontal' ? '
|
|
49
|
-
orientation === 'horizontal' ? 'border-
|
|
43
|
+
? 'border-transparent [[data-scroll-separator="true"]_&]:border-subdued-separator'
|
|
44
|
+
: 'border-subdued-separator',
|
|
45
|
+
orientation === 'horizontal' ? 'h-(--dx-rail-size)' : 'w-(--dx-rail-size) flex-col',
|
|
46
|
+
orientation === 'horizontal' ? 'border-b' : 'border-e',
|
|
50
47
|
classNames,
|
|
51
48
|
)}
|
|
52
49
|
>
|
|
53
50
|
{children}
|
|
54
|
-
</
|
|
51
|
+
</Comp>
|
|
55
52
|
);
|
|
56
53
|
};
|
|
57
54
|
|
|
58
55
|
export const StackItemHeadingStickyContent = ({ children }: PropsWithChildren<{}>) => {
|
|
59
56
|
return (
|
|
60
|
-
<div role='none' className='sticky
|
|
57
|
+
<div role='none' className='sticky top-0 bg-(--sticky-bg) p-1 w-full'>
|
|
61
58
|
{children}
|
|
62
59
|
</div>
|
|
63
60
|
);
|
|
@@ -74,7 +71,7 @@ export const StackItemHeadingLabel = forwardRef<HTMLHeadingElement, StackItemHea
|
|
|
74
71
|
{...props}
|
|
75
72
|
data-attention={((related && isRelated) || hasAttention || isAncestor).toString()}
|
|
76
73
|
className={mx(
|
|
77
|
-
'
|
|
74
|
+
'px-1 min-w-0 w-0 grow truncate font-medium text-base-surface-text data-[attention=true]:text-accent-text self-center',
|
|
78
75
|
classNames,
|
|
79
76
|
)}
|
|
80
77
|
ref={forwardedRef}
|
|
@@ -6,15 +6,16 @@ import React from 'react';
|
|
|
6
6
|
|
|
7
7
|
import { ResizeHandle } from '@dxos/react-ui-dnd';
|
|
8
8
|
|
|
9
|
-
import { DEFAULT_EXTRINSIC_SIZE } from './StackItem';
|
|
10
9
|
import { useStack, useStackItem } from '../StackContext';
|
|
11
10
|
|
|
11
|
+
import { DEFAULT_EXTRINSIC_SIZE } from './StackItem';
|
|
12
|
+
|
|
12
13
|
const MIN_WIDTH = 20;
|
|
13
14
|
const MIN_HEIGHT = 3;
|
|
14
15
|
|
|
15
16
|
export type StackItemResizeHandleProps = {};
|
|
16
17
|
|
|
17
|
-
export const StackItemResizeHandle = () => {
|
|
18
|
+
export const StackItemResizeHandle = (_: StackItemResizeHandleProps) => {
|
|
18
19
|
const { orientation } = useStack();
|
|
19
20
|
const { setSize, size } = useStackItem();
|
|
20
21
|
|
|
@@ -4,16 +4,17 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { Fragment, type PropsWithChildren, forwardRef, useState } from 'react';
|
|
6
6
|
|
|
7
|
-
import { type
|
|
7
|
+
import { type Node } from '@dxos/app-graph';
|
|
8
8
|
import { keySymbols } from '@dxos/keyboard';
|
|
9
9
|
import { Button, type ButtonProps, DropdownMenu, Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
10
10
|
import { type AttendableId, type Related, useAttention } from '@dxos/react-ui-attention';
|
|
11
|
-
import {
|
|
11
|
+
import { mx } from '@dxos/ui-theme';
|
|
12
12
|
import { getHostPlatform } from '@dxos/util';
|
|
13
13
|
|
|
14
|
-
import { MenuSignifierHorizontal } from './MenuSignifier';
|
|
15
14
|
import { translationKey } from '../../translations';
|
|
16
15
|
|
|
16
|
+
import { MenuSignifierHorizontal } from './MenuSignifier';
|
|
17
|
+
|
|
17
18
|
export type KeyBinding = {
|
|
18
19
|
windows?: string;
|
|
19
20
|
macos?: string;
|
|
@@ -22,7 +23,7 @@ export type KeyBinding = {
|
|
|
22
23
|
unknown?: string;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
|
-
export type StackItemSigilAction = Pick<ActionLike, 'id' | 'properties' | 'data'>;
|
|
26
|
+
export type StackItemSigilAction = Pick<Node.ActionLike, 'id' | 'properties' | 'data'>;
|
|
26
27
|
|
|
27
28
|
export type StackItemSigilButtonProps = Omit<ButtonProps, 'variant'> &
|
|
28
29
|
AttendableId &
|
|
@@ -39,7 +40,10 @@ export const StackItemSigilButton = forwardRef<HTMLButtonElement, StackItemSigil
|
|
|
39
40
|
<Button
|
|
40
41
|
{...props}
|
|
41
42
|
variant={variant}
|
|
42
|
-
classNames={[
|
|
43
|
+
classNames={[
|
|
44
|
+
'shrink-0 px-0 min-h-0 w-(--dx-rail-action) h-(--dx-rail-action) relative dx-app-no-drag',
|
|
45
|
+
classNames,
|
|
46
|
+
]}
|
|
43
47
|
ref={forwardedRef}
|
|
44
48
|
>
|
|
45
49
|
{isMenu && <MenuSignifierHorizontal />}
|
|
@@ -132,7 +136,7 @@ export const StackItemSigil = forwardRef<HTMLButtonElement, StackItemSigilProps>
|
|
|
132
136
|
</DropdownMenu.ItemIndicator>
|
|
133
137
|
)}
|
|
134
138
|
{shortcut && (
|
|
135
|
-
<span className={mx('shrink-0',
|
|
139
|
+
<span className={mx('shrink-0', 'text-description')}>{keySymbols(shortcut).join('')}</span>
|
|
136
140
|
)}
|
|
137
141
|
</Root>
|
|
138
142
|
);
|
package/src/components/index.ts
CHANGED
|
@@ -8,70 +8,84 @@ import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-sc
|
|
|
8
8
|
import { attachClosestEdge, extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
9
9
|
import { useLayoutEffect, useState } from 'react';
|
|
10
10
|
|
|
11
|
-
import { type
|
|
11
|
+
import { type Orientation, type StackItemData, type StackItemRearrangeHandler } from '../components';
|
|
12
|
+
|
|
13
|
+
const noop = () => {};
|
|
14
|
+
|
|
15
|
+
export type UseStackDropForElementsProps = {
|
|
16
|
+
id?: string;
|
|
17
|
+
element: HTMLDivElement | null;
|
|
18
|
+
scrollElement?: HTMLDivElement | null;
|
|
19
|
+
orientation: Orientation;
|
|
20
|
+
selfDroppable: boolean;
|
|
21
|
+
onRearrange?: StackItemRearrangeHandler;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export type UseStackDropForElements = {
|
|
25
|
+
dropping: boolean;
|
|
26
|
+
};
|
|
12
27
|
|
|
13
28
|
/**
|
|
14
|
-
* Hook to handle drag
|
|
29
|
+
* Hook to handle drag-and-drop functionality for Stack components.
|
|
15
30
|
*/
|
|
16
31
|
export const useStackDropForElements = ({
|
|
17
32
|
id,
|
|
18
33
|
element,
|
|
19
34
|
scrollElement = element,
|
|
20
|
-
selfDroppable,
|
|
21
35
|
orientation,
|
|
36
|
+
selfDroppable,
|
|
22
37
|
onRearrange,
|
|
23
|
-
}: {
|
|
24
|
-
id?: string;
|
|
25
|
-
element: HTMLDivElement | null;
|
|
26
|
-
scrollElement?: HTMLDivElement | null;
|
|
27
|
-
selfDroppable: boolean;
|
|
28
|
-
orientation: Orientation;
|
|
29
|
-
onRearrange?: StackItemRearrangeHandler;
|
|
30
|
-
}) => {
|
|
38
|
+
}: UseStackDropForElementsProps): UseStackDropForElements => {
|
|
31
39
|
const [dropping, setDropping] = useState(false);
|
|
32
40
|
|
|
33
41
|
useLayoutEffect(() => {
|
|
34
|
-
if (!element
|
|
42
|
+
if (!element) {
|
|
35
43
|
return;
|
|
36
44
|
}
|
|
37
45
|
|
|
38
46
|
const acceptSourceType = orientation === 'horizontal' ? 'column' : 'card';
|
|
39
47
|
|
|
48
|
+
// TODO(burdon): Use monitor?
|
|
40
49
|
return combine(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
50
|
+
selfDroppable
|
|
51
|
+
? dropTargetForElements({
|
|
52
|
+
element,
|
|
53
|
+
getData: ({ input, element }) => {
|
|
54
|
+
return attachClosestEdge(
|
|
55
|
+
{ id, type: orientation === 'horizontal' ? 'card' : 'column' },
|
|
56
|
+
{ input, element, allowedEdges: [orientation === 'horizontal' ? 'left' : 'top'] },
|
|
57
|
+
);
|
|
58
|
+
},
|
|
59
|
+
onDragEnter: ({ source }) => {
|
|
60
|
+
if (source.data.type === acceptSourceType) {
|
|
61
|
+
setDropping(true);
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
onDrag: ({ source }) => {
|
|
65
|
+
if (source.data.type === acceptSourceType) {
|
|
66
|
+
setDropping(true);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
onDragLeave: () => {
|
|
70
|
+
return setDropping(false);
|
|
71
|
+
},
|
|
72
|
+
onDrop: ({ self, source }) => {
|
|
73
|
+
setDropping(false);
|
|
74
|
+
if (source.data.type === acceptSourceType && selfDroppable && onRearrange) {
|
|
75
|
+
onRearrange(source.data as StackItemData, self.data as StackItemData, extractClosestEdge(self.data));
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
})
|
|
79
|
+
: noop,
|
|
80
|
+
|
|
81
|
+
scrollElement
|
|
82
|
+
? autoScrollForElements({
|
|
83
|
+
element: scrollElement,
|
|
84
|
+
getAllowedAxis: () => orientation,
|
|
85
|
+
})
|
|
86
|
+
: noop,
|
|
73
87
|
);
|
|
74
|
-
}, [element, scrollElement, selfDroppable, orientation,
|
|
88
|
+
}, [id, element, scrollElement, selfDroppable, orientation, onRearrange]);
|
|
75
89
|
|
|
76
90
|
return { dropping };
|
|
77
91
|
};
|
package/src/index.ts
CHANGED
|
@@ -10,7 +10,7 @@ export default defineConfig({
|
|
|
10
10
|
...e2ePreset(import.meta.dirname),
|
|
11
11
|
// TODO(wittjosiah): Avoid hard-coding ports.
|
|
12
12
|
webServer: {
|
|
13
|
-
command: '
|
|
13
|
+
command: 'pnpm storybook dev --ci --quiet --port=9003 --config-dir=.storybook',
|
|
14
14
|
port: 9003,
|
|
15
15
|
reuseExistingServer: false,
|
|
16
16
|
},
|