@dxos/react-ui-stack 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/index.mjs +743 -65
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/playwright/index.mjs +10 -23
- package/dist/lib/browser/playwright/index.mjs.map +2 -2
- package/dist/lib/node-esm/index.mjs +744 -65
- 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 +10 -23
- package/dist/lib/node-esm/playwright/index.mjs.map +2 -2
- package/dist/types/src/components/Stack/Stack.d.ts +8 -8
- package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
- package/dist/types/src/components/StackContext.d.ts +2 -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 +6 -10
- package/dist/types/src/components/StackItem/StackItem.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItem.stories.d.ts.map +1 -1
- package/dist/types/src/components/StackItem/StackItemContent.d.ts +2 -43
- 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.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 -2
- 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 +8 -6
- 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 +2 -2
- package/src/components/Stack/Stack.tsx +27 -25
- package/src/components/StackContext.tsx +2 -2
- package/src/components/StackItem/MenuSignifier.tsx +2 -9
- package/src/components/StackItem/StackItem.stories.tsx +6 -4
- package/src/components/StackItem/StackItem.tsx +26 -14
- package/src/components/StackItem/StackItemContent.tsx +23 -54
- package/src/components/StackItem/StackItemDragHandle.tsx +4 -3
- package/src/components/StackItem/StackItemHeading.tsx +12 -11
- package/src/components/StackItem/StackItemResizeHandle.tsx +1 -1
- package/src/components/StackItem/StackItemSigil.tsx +8 -5
- package/src/components/index.ts +2 -2
- package/src/hooks/useStackDropForElements.ts +58 -44
- 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-SM27YTH3.mjs +0 -1418
- package/dist/lib/browser/chunk-SM27YTH3.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-MMAOXKOM.mjs +0 -1420
- package/dist/lib/node-esm/chunk-MMAOXKOM.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/Image/Image.d.ts +0 -11
- package/dist/types/src/components/Image/Image.d.ts.map +0 -1
- package/dist/types/src/components/Image/Image.stories.d.ts +0 -30
- package/dist/types/src/components/Image/Image.stories.d.ts.map +0 -1
- package/dist/types/src/components/Image/index.d.ts +0 -2
- package/dist/types/src/components/Image/index.d.ts.map +0 -1
- 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 -65
- package/dist/types/src/exemplars/Card/Card.d.ts.map +0 -1
- package/dist/types/src/exemplars/Card/Card.stories.d.ts +0 -21
- 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 -13
- 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 -42
- package/dist/types/src/exemplars/CardStack/CardStack.d.ts.map +0 -1
- package/dist/types/src/exemplars/CardStack/CardStack.stories.d.ts +0 -15
- 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/Image/Image.stories.tsx +0 -56
- package/src/components/Image/Image.tsx +0 -137
- package/src/components/Image/index.ts +0 -5
- package/src/components/deprecated/LayoutControls.tsx +0 -109
- package/src/exemplars/Card/Card.stories.tsx +0 -64
- package/src/exemplars/Card/Card.tsx +0 -204
- package/src/exemplars/Card/CardDragPreview.tsx +0 -22
- package/src/exemplars/Card/fragments.ts +0 -24
- package/src/exemplars/Card/index.ts +0 -7
- package/src/exemplars/CardStack/CardStack.stories.tsx +0 -173
- package/src/exemplars/CardStack/CardStack.tsx +0 -139
- 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 -37
- package/src/testing/index.ts +0 -5
- /package/src/components/{defs.ts → types.ts} +0 -0
package/package.json
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-stack",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.c85a9c8dae",
|
|
4
4
|
"description": "A stack component.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/dxos/dxos"
|
|
10
|
+
},
|
|
7
11
|
"license": "MIT",
|
|
8
12
|
"author": "DXOS.org",
|
|
9
|
-
"sideEffects":
|
|
13
|
+
"sideEffects": false,
|
|
10
14
|
"type": "module",
|
|
11
15
|
"exports": {
|
|
12
16
|
".": {
|
|
@@ -18,11 +22,6 @@
|
|
|
18
22
|
"types": "./dist/types/src/playwright/index.d.ts",
|
|
19
23
|
"browser": "./dist/lib/browser/playwright/index.mjs",
|
|
20
24
|
"node": "./dist/lib/node-esm/playwright/index.mjs"
|
|
21
|
-
},
|
|
22
|
-
"./testing": {
|
|
23
|
-
"types": "./dist/types/src/testing/index.d.ts",
|
|
24
|
-
"browser": "./dist/lib/browser/testing/index.mjs",
|
|
25
|
-
"node": "./dist/lib/node-esm/testing/index.mjs"
|
|
26
25
|
}
|
|
27
26
|
},
|
|
28
27
|
"types": "dist/types/src/index.d.ts",
|
|
@@ -41,11 +40,11 @@
|
|
|
41
40
|
"src"
|
|
42
41
|
],
|
|
43
42
|
"dependencies": {
|
|
44
|
-
"@atlaskit/pragmatic-drag-and-drop": "
|
|
45
|
-
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.
|
|
46
|
-
"@atlaskit/pragmatic-drag-and-drop-hitbox": "
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
43
|
+
"@atlaskit/pragmatic-drag-and-drop": "1.7.7",
|
|
44
|
+
"@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.2",
|
|
45
|
+
"@atlaskit/pragmatic-drag-and-drop-hitbox": "1.1.0",
|
|
46
|
+
"@atlaskit/pragmatic-drag-and-drop-react-drop-indicator": "3.2.10",
|
|
47
|
+
"@fluentui/react-tabster": "9.26.11",
|
|
49
48
|
"@radix-ui/primitive": "1.1.1",
|
|
50
49
|
"@radix-ui/react-compose-refs": "1.1.1",
|
|
51
50
|
"@radix-ui/react-context": "1.1.1",
|
|
@@ -54,36 +53,40 @@
|
|
|
54
53
|
"@radix-ui/react-slot": "1.1.2",
|
|
55
54
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
56
55
|
"react-resize-detector": "^11.0.1",
|
|
57
|
-
"@dxos/echo": "0.8.4-main.
|
|
58
|
-
"@dxos/
|
|
59
|
-
"@dxos/
|
|
60
|
-
"@dxos/
|
|
61
|
-
"@dxos/
|
|
62
|
-
"@dxos/
|
|
63
|
-
"@dxos/react-ui-attention": "0.8.4-main.c4373fc"
|
|
56
|
+
"@dxos/echo": "0.8.4-main.c85a9c8dae",
|
|
57
|
+
"@dxos/react-ui-dnd": "0.8.4-main.c85a9c8dae",
|
|
58
|
+
"@dxos/react-ui-attention": "0.8.4-main.c85a9c8dae",
|
|
59
|
+
"@dxos/keyboard": "0.8.4-main.c85a9c8dae",
|
|
60
|
+
"@dxos/react-ui-mosaic": "0.8.4-main.c85a9c8dae",
|
|
61
|
+
"@dxos/util": "0.8.4-main.c85a9c8dae"
|
|
64
62
|
},
|
|
65
63
|
"devDependencies": {
|
|
66
|
-
"@types/react": "~19.2.
|
|
67
|
-
"@types/react-dom": "~19.2.
|
|
68
|
-
"react": "~19.2.
|
|
69
|
-
"react-dom": "~19.2.
|
|
70
|
-
"vite": "7.1.
|
|
71
|
-
"@dxos/app-graph": "0.8.4-main.
|
|
72
|
-
"@dxos/client": "0.8.4-main.
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/
|
|
75
|
-
"@dxos/
|
|
76
|
-
"@dxos/
|
|
77
|
-
"@dxos/
|
|
78
|
-
"@dxos/
|
|
64
|
+
"@types/react": "~19.2.7",
|
|
65
|
+
"@types/react-dom": "~19.2.3",
|
|
66
|
+
"react": "~19.2.3",
|
|
67
|
+
"react-dom": "~19.2.3",
|
|
68
|
+
"vite": "^7.1.11",
|
|
69
|
+
"@dxos/app-graph": "0.8.4-main.c85a9c8dae",
|
|
70
|
+
"@dxos/client": "0.8.4-main.c85a9c8dae",
|
|
71
|
+
"@dxos/app-framework": "0.8.4-main.c85a9c8dae",
|
|
72
|
+
"@dxos/echo": "0.8.4-main.c85a9c8dae",
|
|
73
|
+
"@dxos/echo-db": "0.8.4-main.c85a9c8dae",
|
|
74
|
+
"@dxos/random": "0.8.4-main.c85a9c8dae",
|
|
75
|
+
"@dxos/react-client": "0.8.4-main.c85a9c8dae",
|
|
76
|
+
"@dxos/react-ui": "0.8.4-main.c85a9c8dae",
|
|
77
|
+
"@dxos/storybook-utils": "0.8.4-main.c85a9c8dae",
|
|
78
|
+
"@dxos/types": "0.8.4-main.c85a9c8dae",
|
|
79
|
+
"@dxos/test-utils": "0.8.4-main.c85a9c8dae",
|
|
80
|
+
"@dxos/ui-theme": "0.8.4-main.c85a9c8dae",
|
|
81
|
+
"@dxos/schema": "0.8.4-main.c85a9c8dae"
|
|
79
82
|
},
|
|
80
83
|
"peerDependencies": {
|
|
81
|
-
"react": "
|
|
82
|
-
"react-dom": "
|
|
83
|
-
"@dxos/
|
|
84
|
-
"@dxos/
|
|
85
|
-
"@dxos/
|
|
86
|
-
"@dxos/react-ui
|
|
84
|
+
"react": "~19.2.3",
|
|
85
|
+
"react-dom": "~19.2.3",
|
|
86
|
+
"@dxos/client": "0.8.4-main.c85a9c8dae",
|
|
87
|
+
"@dxos/random": "0.8.4-main.c85a9c8dae",
|
|
88
|
+
"@dxos/ui-theme": "0.8.4-main.c85a9c8dae",
|
|
89
|
+
"@dxos/react-ui": "0.8.4-main.c85a9c8dae"
|
|
87
90
|
},
|
|
88
91
|
"publishConfig": {
|
|
89
92
|
"access": "public"
|
|
@@ -9,8 +9,8 @@ import React, { useCallback, useState } from 'react';
|
|
|
9
9
|
import { faker } from '@dxos/random';
|
|
10
10
|
import { withTheme } from '@dxos/react-ui/testing';
|
|
11
11
|
|
|
12
|
-
import { type StackItemData } from '../defs';
|
|
13
12
|
import { StackItem } from '../StackItem';
|
|
13
|
+
import { type StackItemData } from '../types';
|
|
14
14
|
|
|
15
15
|
import { Stack } from './Stack';
|
|
16
16
|
|
|
@@ -132,7 +132,7 @@ const meta = {
|
|
|
132
132
|
title: 'ui/react-ui-stack/Stack',
|
|
133
133
|
component: DefaultStory,
|
|
134
134
|
argTypes: { orientation: { control: 'radio', options: ['horizontal', 'vertical'] } },
|
|
135
|
-
decorators: [withTheme],
|
|
135
|
+
decorators: [withTheme()],
|
|
136
136
|
} satisfies Meta<typeof DefaultStory>;
|
|
137
137
|
|
|
138
138
|
export default meta;
|
|
@@ -7,6 +7,7 @@ import React, {
|
|
|
7
7
|
type CSSProperties,
|
|
8
8
|
Children,
|
|
9
9
|
type ComponentPropsWithRef,
|
|
10
|
+
type FocusEvent,
|
|
10
11
|
type KeyboardEvent,
|
|
11
12
|
forwardRef,
|
|
12
13
|
useCallback,
|
|
@@ -16,13 +17,14 @@ import React, {
|
|
|
16
17
|
} from 'react';
|
|
17
18
|
|
|
18
19
|
import { ListItem, type ThemedClassName, useId } from '@dxos/react-ui';
|
|
19
|
-
import { mx } from '@dxos/
|
|
20
|
+
import { mx } from '@dxos/ui-theme';
|
|
20
21
|
|
|
21
22
|
import { useStackDropForElements } from '../../hooks';
|
|
22
|
-
import { type StackContextValue } from '../defs';
|
|
23
23
|
import { StackContext } from '../StackContext';
|
|
24
|
+
import { type StackContextValue } from '../types';
|
|
24
25
|
|
|
25
26
|
export type Orientation = 'horizontal' | 'vertical';
|
|
27
|
+
|
|
26
28
|
/**
|
|
27
29
|
* Size is how Stack and its StackItems coordinate the dimensions of the items with the available space.
|
|
28
30
|
* - `intrinsic` signals to Stack and its StackItems to occupy their intrinsic size
|
|
@@ -32,22 +34,14 @@ export type Orientation = 'horizontal' | 'vertical';
|
|
|
32
34
|
*/
|
|
33
35
|
export type Size = 'intrinsic' | 'contain' | 'split';
|
|
34
36
|
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
itemsCount?: number;
|
|
38
|
-
getDropElement?: (stackElement: HTMLDivElement) => HTMLDivElement;
|
|
39
|
-
separatorOnScroll?: number;
|
|
40
|
-
circularFocus?: boolean;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export const railGridHorizontal = 'grid-rows-[[rail-start]_var(--rail-size)_[content-start]_1fr_[content-end]]';
|
|
44
|
-
export const railGridVertical = 'grid-cols-[[rail-start]_var(--rail-size)_[content-start]_1fr_[content-end]]';
|
|
37
|
+
export const railGridHorizontal = 'grid-rows-[[rail-start]_var(--dx-rail-size)_[content-start]_1fr_[content-end]]';
|
|
38
|
+
export const railGridVertical = 'grid-cols-[[rail-start]_var(--dx-rail-size)_[content-start]_1fr_[content-end]]';
|
|
45
39
|
|
|
46
40
|
// TODO(ZaymonFC): Magic 2px to stop overflow.
|
|
47
41
|
export const railGridHorizontalContainFitContent =
|
|
48
|
-
'grid-rows-[[rail-start]_var(--rail-size)_[content-start]_fit-content(calc(100%-var(--rail-size)*2+2px))_[content-end]]';
|
|
42
|
+
'grid-rows-[[rail-start]_var(--dx-rail-size)_[content-start]_fit-content(calc(100%-var(--dx-rail-size)*2+2px))_[content-end]]';
|
|
49
43
|
export const railGridVerticalContainFitContent =
|
|
50
|
-
'grid-cols-[[rail-start]_var(--rail-size)_[content-start]_fit-content(calc(100%-var(--rail-size)*2+2px))_[content-end]]';
|
|
44
|
+
'grid-cols-[[rail-start]_var(--dx-rail-size)_[content-start]_fit-content(calc(100%-var(--dx-rail-size)*2+2px))_[content-end]]';
|
|
51
45
|
|
|
52
46
|
export const autoScrollRootAttributes = { 'data-drag-autoscroll': 'idle' };
|
|
53
47
|
|
|
@@ -61,6 +55,14 @@ const scrollIntoViewAndFocus = (el: HTMLElement, orientation: StackProps['orient
|
|
|
61
55
|
return el.focus();
|
|
62
56
|
};
|
|
63
57
|
|
|
58
|
+
export type StackProps = Omit<ThemedClassName<ComponentPropsWithRef<'div'>>, 'aria-orientation'> &
|
|
59
|
+
Partial<StackContextValue> & {
|
|
60
|
+
itemsCount?: number;
|
|
61
|
+
getDropElement?: (stackElement: HTMLDivElement) => HTMLDivElement;
|
|
62
|
+
separatorOnScroll?: number;
|
|
63
|
+
circularFocus?: boolean;
|
|
64
|
+
};
|
|
65
|
+
|
|
64
66
|
export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
65
67
|
(
|
|
66
68
|
{
|
|
@@ -68,7 +70,7 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
|
68
70
|
classNames,
|
|
69
71
|
style,
|
|
70
72
|
orientation = 'vertical',
|
|
71
|
-
rail = true,
|
|
73
|
+
rail = true, // TODO(burdon): Change default to false.
|
|
72
74
|
size = 'intrinsic',
|
|
73
75
|
onRearrange,
|
|
74
76
|
itemsCount = Children.count(children),
|
|
@@ -121,7 +123,7 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
|
121
123
|
* Handles blur events to track the last focused item within this stack.
|
|
122
124
|
*/
|
|
123
125
|
const handleBlur = useCallback(
|
|
124
|
-
(event:
|
|
126
|
+
(event: FocusEvent<HTMLDivElement>) => {
|
|
125
127
|
if (event.target) {
|
|
126
128
|
const target = event.target as HTMLElement;
|
|
127
129
|
const closestStackItem = target.closest(`[data-dx-item-id]`) as HTMLElement | null;
|
|
@@ -135,9 +137,9 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
|
135
137
|
);
|
|
136
138
|
|
|
137
139
|
/**
|
|
138
|
-
* Handles moving focus using the arrow keys. Focus is only handled by the nearest stack;
|
|
139
|
-
* orientation, focus cycles between items, otherwise focus is passed to an adjacent stack item;
|
|
140
|
-
* such stack item, focus is passed to the adjacent empty stack if one can be found.
|
|
140
|
+
* Handles moving focus using the arrow keys. Focus is only handled by the nearest stack;
|
|
141
|
+
* if the arrow key matches the orientation, focus cycles between items, otherwise focus is passed to an adjacent stack item;
|
|
142
|
+
* or, if there is no such stack item, focus is passed to the adjacent empty stack if one can be found.
|
|
141
143
|
*/
|
|
142
144
|
const handleKeyDown = useCallback(
|
|
143
145
|
(event: KeyboardEvent<HTMLDivElement>) => {
|
|
@@ -193,6 +195,7 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
|
193
195
|
scrollIntoViewAndFocus(adjacentItem, closestStackOrientation);
|
|
194
196
|
}
|
|
195
197
|
}
|
|
198
|
+
|
|
196
199
|
if (perpendicularDelta !== 0) {
|
|
197
200
|
if (ancestorStack && ancestorOrientation !== closestStackOrientation) {
|
|
198
201
|
const siblingStacks = Array.from(
|
|
@@ -241,12 +244,10 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
|
241
244
|
closestStackOrientation === 'vertical' ? ownedItemRect.top : ownedItemRect.left;
|
|
242
245
|
|
|
243
246
|
let closestDistance = Infinity;
|
|
244
|
-
|
|
245
247
|
for (const item of adjacentStackItems) {
|
|
246
248
|
const itemRect = item.getBoundingClientRect();
|
|
247
249
|
const itemPosition = closestStackOrientation === 'vertical' ? itemRect.top : itemRect.left;
|
|
248
250
|
const distance = Math.abs(itemPosition - targetPosition);
|
|
249
|
-
|
|
250
251
|
if (distance < closestDistance) {
|
|
251
252
|
closestDistance = distance;
|
|
252
253
|
closestItem = item;
|
|
@@ -292,8 +293,9 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
|
292
293
|
|
|
293
294
|
const gridClasses = useMemo(() => {
|
|
294
295
|
if (!rail) {
|
|
295
|
-
return orientation === 'horizontal' ? 'grid-rows-1
|
|
296
|
+
return orientation === 'horizontal' ? 'grid-rows-1 px-(--stack-gap)' : 'grid-cols-1 py-(--stack-gap)';
|
|
296
297
|
}
|
|
298
|
+
|
|
297
299
|
if (orientation === 'horizontal') {
|
|
298
300
|
return railGridHorizontal;
|
|
299
301
|
} else {
|
|
@@ -322,12 +324,12 @@ export const Stack = forwardRef<HTMLDivElement, StackProps>(
|
|
|
322
324
|
<div
|
|
323
325
|
{...props}
|
|
324
326
|
className={mx(
|
|
325
|
-
'grid relative [--stack-gap:var(--
|
|
327
|
+
'grid relative [--stack-gap:var(--spacing-trim-xs)]',
|
|
326
328
|
gridClasses,
|
|
327
329
|
size === 'contain' &&
|
|
328
330
|
(orientation === 'horizontal'
|
|
329
|
-
? 'overflow-x-auto overscroll-x-contain min-
|
|
330
|
-
: 'overflow-y-auto min-
|
|
331
|
+
? 'overflow-x-auto overscroll-x-contain min-h-0 max-h-full h-full'
|
|
332
|
+
: 'overflow-y-auto min-w-0 max-w-full w-full'),
|
|
331
333
|
classNames,
|
|
332
334
|
)}
|
|
333
335
|
onKeyDown={handleKeyDown}
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import { createContext, useContext } from 'react';
|
|
6
6
|
|
|
7
|
-
import { type StackItemRearrangeHandler, type StackItemSize } from './defs';
|
|
8
7
|
import { type Orientation, type Size } from './Stack';
|
|
8
|
+
import { type StackItemRearrangeHandler, type StackItemSize } from './types';
|
|
9
9
|
|
|
10
10
|
export type StackContextValue = {
|
|
11
11
|
orientation: Orientation;
|
|
@@ -33,7 +33,7 @@ export type ItemDragState =
|
|
|
33
33
|
item: any;
|
|
34
34
|
}
|
|
35
35
|
| {
|
|
36
|
-
type: '
|
|
36
|
+
type: 'w-dragging';
|
|
37
37
|
item: any;
|
|
38
38
|
};
|
|
39
39
|
|
|
@@ -5,14 +5,7 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
7
|
export const MenuSignifierHorizontal = () => (
|
|
8
|
-
<svg
|
|
9
|
-
className='absolute block-end-[7px]'
|
|
10
|
-
width={20}
|
|
11
|
-
height={2}
|
|
12
|
-
viewBox='0 0 20 2'
|
|
13
|
-
stroke='currentColor'
|
|
14
|
-
opacity={0.5}
|
|
15
|
-
>
|
|
8
|
+
<svg className='absolute bottom-[7px]' width={20} height={2} viewBox='0 0 20 2' stroke='currentColor' opacity={0.5}>
|
|
16
9
|
<line
|
|
17
10
|
x1={0.5}
|
|
18
11
|
y1={0.75}
|
|
@@ -27,7 +20,7 @@ export const MenuSignifierHorizontal = () => (
|
|
|
27
20
|
);
|
|
28
21
|
|
|
29
22
|
export const MenuSignifierVertical = () => (
|
|
30
|
-
<svg className='absolute
|
|
23
|
+
<svg className='absolute left-1' width={2} height={18} viewBox='0 0 2 18' stroke='currentColor'>
|
|
31
24
|
<line x1={1} y1={3} x2={1} y2={18} strokeWidth={1.5} strokeLinecap='round' strokeDasharray='0 6' />
|
|
32
25
|
</svg>
|
|
33
26
|
);
|
|
@@ -13,9 +13,9 @@ import { StackItem, type StackItemRootProps } from './StackItem';
|
|
|
13
13
|
const DefaultStory = (props: StackItemRootProps) => {
|
|
14
14
|
return (
|
|
15
15
|
<StackItem.Root role='section' {...props} classNames='w-[20rem] border border-separator'>
|
|
16
|
-
<StackItem.Heading>
|
|
16
|
+
<StackItem.Heading classNames='w-full border-b border-separator'>
|
|
17
17
|
<span className='sr-only'>Title</span>
|
|
18
|
-
<div role='none' className='sticky -
|
|
18
|
+
<div role='none' className='sticky -top-px bg-(--sticky-bg) p-1 w-full'>
|
|
19
19
|
<DropdownMenu.Root>
|
|
20
20
|
<DropdownMenu.Trigger asChild>
|
|
21
21
|
<StackItem.SigilButton>
|
|
@@ -25,7 +25,9 @@ const DefaultStory = (props: StackItemRootProps) => {
|
|
|
25
25
|
</DropdownMenu.Root>
|
|
26
26
|
</div>
|
|
27
27
|
</StackItem.Heading>
|
|
28
|
-
<StackItem.Content>
|
|
28
|
+
<StackItem.Content>
|
|
29
|
+
<div className='p-4 text-center'>Content</div>
|
|
30
|
+
</StackItem.Content>
|
|
29
31
|
</StackItem.Root>
|
|
30
32
|
);
|
|
31
33
|
};
|
|
@@ -34,7 +36,7 @@ const meta = {
|
|
|
34
36
|
title: 'ui/react-ui-stack/StackItem',
|
|
35
37
|
component: StackItem.Root as any,
|
|
36
38
|
render: DefaultStory,
|
|
37
|
-
decorators: [withTheme],
|
|
39
|
+
decorators: [withTheme()],
|
|
38
40
|
parameters: {
|
|
39
41
|
layout: 'centered',
|
|
40
42
|
},
|
|
@@ -26,10 +26,10 @@ import { createPortal } from 'react-dom';
|
|
|
26
26
|
|
|
27
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
30
|
|
|
31
|
-
import { type StackItemData, type StackItemSize } from '../defs';
|
|
32
31
|
import { type ItemDragState, StackItemContext, idle, useStack, useStackItem } from '../StackContext';
|
|
32
|
+
import { type StackItemData, type StackItemSize } from '../types';
|
|
33
33
|
|
|
34
34
|
import { StackItemContent, type StackItemContentProps } from './StackItemContent';
|
|
35
35
|
import { StackItemDragHandle, type StackItemDragHandleProps } from './StackItemDragHandle';
|
|
@@ -54,6 +54,10 @@ export const DEFAULT_HORIZONTAL_SIZE = 48 satisfies StackItemSize;
|
|
|
54
54
|
export const DEFAULT_VERTICAL_SIZE = 'min-content' satisfies StackItemSize;
|
|
55
55
|
export const DEFAULT_EXTRINSIC_SIZE = DEFAULT_HORIZONTAL_SIZE satisfies StackItemSize;
|
|
56
56
|
|
|
57
|
+
//
|
|
58
|
+
// StackItemRoot
|
|
59
|
+
//
|
|
60
|
+
|
|
57
61
|
type StackItemRootProps = ThemedClassName<ComponentPropsWithRef<'div'>> & {
|
|
58
62
|
item: Omit<StackItemData, 'type'>;
|
|
59
63
|
order?: number;
|
|
@@ -86,6 +90,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
86
90
|
forwardedRef,
|
|
87
91
|
) => {
|
|
88
92
|
const [itemElement, itemRef] = useState<HTMLDivElement | null>(null);
|
|
93
|
+
const composedItemRef = composeRefs<HTMLDivElement>(itemRef, forwardedRef);
|
|
89
94
|
const [selfDragHandleElement, selfDragHandleRef] = useState<HTMLDivElement | null>(null);
|
|
90
95
|
const [closestEdge, setEdge] = useState<Edge | null>(null);
|
|
91
96
|
const [sourceId, setSourceId] = useState<string | null>(null);
|
|
@@ -96,8 +101,6 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
96
101
|
|
|
97
102
|
const Root = role ?? 'div';
|
|
98
103
|
|
|
99
|
-
const composedItemRef = composeRefs<HTMLDivElement>(itemRef, forwardedRef);
|
|
100
|
-
|
|
101
104
|
const setSize = useCallback(
|
|
102
105
|
(nextSize: StackItemSize, commit?: boolean) => {
|
|
103
106
|
setInternalSize(nextSize);
|
|
@@ -110,6 +113,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
110
113
|
|
|
111
114
|
const type = orientation === 'horizontal' ? 'column' : 'card';
|
|
112
115
|
|
|
116
|
+
// TODO(burdon): Factor out?
|
|
113
117
|
useLayoutEffect(() => {
|
|
114
118
|
if (!itemElement || !onRearrange || disableRearrange) {
|
|
115
119
|
return;
|
|
@@ -139,7 +143,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
139
143
|
onDragStart: () => {
|
|
140
144
|
document.body.removeAttribute('data-drag-preview');
|
|
141
145
|
itemElement?.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'active');
|
|
142
|
-
setDragState({ type: '
|
|
146
|
+
setDragState({ type: 'w-dragging', item });
|
|
143
147
|
},
|
|
144
148
|
onDrop: () => {
|
|
145
149
|
itemElement?.closest('[data-drag-autoscroll]')?.setAttribute('data-drag-autoscroll', 'idle');
|
|
@@ -183,18 +187,18 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
183
187
|
|
|
184
188
|
const focusableGroupAttrs = useFocusableGroup({ tabBehavior: 'limited' });
|
|
185
189
|
|
|
186
|
-
// Determine if the drop would result in any changes
|
|
190
|
+
// Determine if the drop would result in any changes.
|
|
187
191
|
const shouldShowDropIndicator = () => {
|
|
188
192
|
if (!closestEdge || !sourceId) {
|
|
189
193
|
return false;
|
|
190
194
|
}
|
|
191
195
|
|
|
192
|
-
// Don't show indicator when dragged item is over itself
|
|
196
|
+
// Don't show indicator when dragged item is over itself.
|
|
193
197
|
if (sourceId === item.id) {
|
|
194
198
|
return false;
|
|
195
199
|
}
|
|
196
200
|
|
|
197
|
-
// 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.
|
|
198
202
|
const isTrailingEdgeOfPrevSibling =
|
|
199
203
|
prevSiblingId !== undefined &&
|
|
200
204
|
sourceId === prevSiblingId &&
|
|
@@ -243,7 +247,7 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
243
247
|
: 'dx-focus-ring-group-y',
|
|
244
248
|
orientation === 'horizontal' ? 'grid-rows-subgrid' : 'grid-cols-subgrid',
|
|
245
249
|
rail && (orientation === 'horizontal' ? 'row-span-2' : 'col-span-2'),
|
|
246
|
-
role === 'section' && orientation !== 'horizontal' && 'border-
|
|
250
|
+
role === 'section' && orientation !== 'horizontal' && 'border-b border-subdued-separator',
|
|
247
251
|
classNames,
|
|
248
252
|
)}
|
|
249
253
|
data-dx-stack-item={stackId}
|
|
@@ -268,37 +272,45 @@ const StackItemRoot = forwardRef<HTMLDivElement, StackItemRootProps>(
|
|
|
268
272
|
},
|
|
269
273
|
);
|
|
270
274
|
|
|
275
|
+
//
|
|
276
|
+
// StackItemDragPreview
|
|
277
|
+
//
|
|
278
|
+
|
|
271
279
|
type StackItemDragPreviewProps = {
|
|
272
280
|
children: ({ item }: { item: any }) => ReactNode;
|
|
273
281
|
};
|
|
274
282
|
|
|
275
|
-
|
|
283
|
+
const StackItemDragPreview = ({ children }: StackItemDragPreviewProps) => {
|
|
276
284
|
const { state } = useStackItem();
|
|
277
285
|
return state?.type === 'preview' ? createPortal(children({ item: state.item }), state.container) : null;
|
|
278
286
|
};
|
|
279
287
|
|
|
288
|
+
//
|
|
289
|
+
// StackItem
|
|
290
|
+
//
|
|
291
|
+
|
|
280
292
|
export const StackItem = {
|
|
281
293
|
Root: StackItemRoot,
|
|
282
294
|
Content: StackItemContent,
|
|
295
|
+
DragHandle: StackItemDragHandle,
|
|
296
|
+
DragPreview: StackItemDragPreview,
|
|
283
297
|
Heading: StackItemHeading,
|
|
284
298
|
HeadingLabel: StackItemHeadingLabel,
|
|
285
299
|
HeadingStickyContent: StackItemHeadingStickyContent,
|
|
286
300
|
ResizeHandle: StackItemResizeHandle,
|
|
287
|
-
DragHandle: StackItemDragHandle,
|
|
288
301
|
Sigil: StackItemSigil,
|
|
289
302
|
SigilButton: StackItemSigilButton,
|
|
290
|
-
DragPreview: StackItemDragPreview,
|
|
291
303
|
};
|
|
292
304
|
|
|
293
305
|
export type {
|
|
294
306
|
StackItemRootProps,
|
|
295
307
|
StackItemContentProps,
|
|
308
|
+
StackItemDragHandleProps,
|
|
309
|
+
StackItemDragPreviewProps,
|
|
296
310
|
StackItemHeadingProps,
|
|
297
311
|
StackItemHeadingLabelProps,
|
|
298
312
|
StackItemResizeHandleProps,
|
|
299
|
-
StackItemDragHandleProps,
|
|
300
313
|
StackItemSigilProps,
|
|
301
314
|
StackItemSigilButtonProps,
|
|
302
315
|
StackItemSigilAction,
|
|
303
|
-
StackItemDragPreviewProps,
|
|
304
316
|
};
|
|
@@ -5,82 +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
|
-
// TODO(burdon): Add prop for container-max-width?
|
|
13
12
|
export type StackItemContentProps = ThemedClassName<Omit<ComponentPropsWithoutRef<'div'>, 'role' | 'scrollable'>> & {
|
|
14
|
-
/**
|
|
15
|
-
* This flag is required in order to clarify a developer experience that seemed like it needed extra boilerplate
|
|
16
|
-
* (`row-span-2`) or was buggy. See the description of the StackItem.Content component itself for more information.
|
|
17
|
-
*/
|
|
18
13
|
toolbar?: boolean;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Whether to provide for the layout of a statusbar after the content.
|
|
22
|
-
*/
|
|
23
14
|
statusbar?: boolean;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Whether to support y-axis scrolling.
|
|
27
|
-
*/
|
|
28
|
-
scrollable?: boolean;
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Whether the consumer intends to do something custom and typical affordances should not apply.
|
|
32
|
-
*/
|
|
33
|
-
// TODO(burdon): This is cryptic; can we remove (only used by plugin-inbox?) Normalize toolbar?
|
|
34
|
-
layoutManaged?: boolean;
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Whether to set a certain aspect ratio on the content, including the toolbar and statusbar.
|
|
38
|
-
* This is provided for convenience and consistency; it can instead be specified by the `classNames` or `style` props as needed.
|
|
39
|
-
*/
|
|
40
|
-
size?: 'intrinsic' | 'video' | 'square';
|
|
41
15
|
};
|
|
42
16
|
|
|
43
17
|
/**
|
|
44
|
-
* This component should be used by plugins for rendering content within a stack item
|
|
45
|
-
* 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”).
|
|
46
19
|
*/
|
|
47
20
|
export const StackItemContent = forwardRef<HTMLDivElement, StackItemContentProps>(
|
|
48
|
-
(
|
|
49
|
-
{ children, toolbar, statusbar, layoutManaged, classNames, size = 'intrinsic', scrollable, ...props },
|
|
50
|
-
forwardedRef,
|
|
51
|
-
) => {
|
|
21
|
+
({ classNames, children, toolbar, statusbar, ...props }, forwardedRef) => {
|
|
52
22
|
const { size: stackItemSize } = useStack();
|
|
53
23
|
const { role } = useStackItem();
|
|
54
24
|
const style = useMemo(
|
|
55
|
-
() =>
|
|
56
|
-
|
|
57
|
-
?
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
[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],
|
|
66
35
|
);
|
|
67
36
|
|
|
68
37
|
return (
|
|
69
38
|
<div
|
|
70
|
-
role='none'
|
|
71
39
|
{...props}
|
|
40
|
+
role='none'
|
|
41
|
+
style={style}
|
|
72
42
|
className={mx(
|
|
73
|
-
'group grid grid-cols-[100%] density-coarse',
|
|
74
|
-
stackItemSize === 'contain' && 'min-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
toolbar &&
|
|
80
|
-
'[&_.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',
|
|
81
49
|
classNames,
|
|
82
50
|
)}
|
|
83
|
-
style={style}
|
|
84
51
|
data-popover-collision-boundary={true}
|
|
85
52
|
ref={forwardedRef}
|
|
86
53
|
>
|
|
@@ -89,3 +56,5 @@ export const StackItemContent = forwardRef<HTMLDivElement, StackItemContentProps
|
|
|
89
56
|
);
|
|
90
57
|
},
|
|
91
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
|
};
|