@dxos/react-ui-list 0.8.4-main.d05673bc65 → 0.8.4-main.e00bdcdb52
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 +42 -48
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +42 -48
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Accordion/Accordion.d.ts +1 -1
- package/dist/types/src/components/Accordion/Accordion.d.ts.map +1 -1
- package/dist/types/src/components/Accordion/Accordion.stories.d.ts.map +1 -1
- package/dist/types/src/components/Accordion/AccordionItem.d.ts.map +1 -1
- package/dist/types/src/components/Accordion/AccordionRoot.d.ts +1 -1
- package/dist/types/src/components/Accordion/AccordionRoot.d.ts.map +1 -1
- package/dist/types/src/components/List/List.d.ts +5 -3
- package/dist/types/src/components/List/List.d.ts.map +1 -1
- package/dist/types/src/components/List/List.stories.d.ts +2 -2
- package/dist/types/src/components/List/List.stories.d.ts.map +1 -1
- package/dist/types/src/components/List/ListItem.d.ts +7 -7
- package/dist/types/src/components/List/ListItem.d.ts.map +1 -1
- package/dist/types/src/components/List/ListRoot.d.ts.map +1 -1
- package/dist/types/src/components/List/testing.d.ts.map +1 -1
- package/dist/types/src/components/Tree/Tree.d.ts.map +1 -1
- package/dist/types/src/components/Tree/Tree.stories.d.ts.map +1 -1
- package/dist/types/src/components/Tree/TreeItem.d.ts.map +1 -1
- package/dist/types/src/components/Tree/TreeItemHeading.d.ts.map +1 -1
- package/dist/types/src/components/Tree/helpers.d.ts.map +1 -1
- package/dist/types/src/components/Tree/testing.d.ts.map +1 -1
- package/dist/types/src/util/path.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -20
- package/src/components/Accordion/Accordion.stories.tsx +3 -3
- package/src/components/Accordion/AccordionItem.tsx +0 -1
- package/src/components/List/List.stories.tsx +3 -3
- package/src/components/List/List.tsx +2 -7
- package/src/components/List/ListItem.tsx +32 -30
- package/src/components/List/ListRoot.tsx +1 -1
- package/src/components/List/testing.ts +4 -4
- package/src/components/Tree/Tree.stories.tsx +4 -5
- package/src/components/Tree/TreeItem.tsx +12 -4
- package/src/components/Tree/TreeItemHeading.tsx +1 -4
- package/src/components/Tree/TreeItemToggle.tsx +3 -3
- package/src/components/Tree/testing.ts +5 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-list",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.e00bdcdb52",
|
|
4
4
|
"description": "A list component.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -20,9 +20,6 @@
|
|
|
20
20
|
}
|
|
21
21
|
},
|
|
22
22
|
"types": "dist/types/src/index.d.ts",
|
|
23
|
-
"typesVersions": {
|
|
24
|
-
"*": {}
|
|
25
|
-
},
|
|
26
23
|
"files": [
|
|
27
24
|
"dist",
|
|
28
25
|
"src"
|
|
@@ -34,32 +31,32 @@
|
|
|
34
31
|
"@radix-ui/react-accordion": "1.2.3",
|
|
35
32
|
"@radix-ui/react-context": "1.1.1",
|
|
36
33
|
"@radix-ui/react-slot": "1.1.2",
|
|
37
|
-
"@dxos/debug": "0.8.4-main.
|
|
38
|
-
"@dxos/echo": "0.8.4-main.
|
|
39
|
-
"@dxos/
|
|
40
|
-
"@dxos/
|
|
41
|
-
"@dxos/ui
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/
|
|
44
|
-
"@dxos/
|
|
45
|
-
"@dxos/ui-types": "0.8.4-main.
|
|
34
|
+
"@dxos/debug": "0.8.4-main.e00bdcdb52",
|
|
35
|
+
"@dxos/echo": "0.8.4-main.e00bdcdb52",
|
|
36
|
+
"@dxos/log": "0.8.4-main.e00bdcdb52",
|
|
37
|
+
"@dxos/invariant": "0.8.4-main.e00bdcdb52",
|
|
38
|
+
"@dxos/react-ui": "0.8.4-main.e00bdcdb52",
|
|
39
|
+
"@dxos/react-ui-text-tooltip": "0.8.4-main.e00bdcdb52",
|
|
40
|
+
"@dxos/util": "0.8.4-main.e00bdcdb52",
|
|
41
|
+
"@dxos/ui-theme": "0.8.4-main.e00bdcdb52",
|
|
42
|
+
"@dxos/ui-types": "0.8.4-main.e00bdcdb52"
|
|
46
43
|
},
|
|
47
44
|
"devDependencies": {
|
|
48
45
|
"@types/react": "~19.2.7",
|
|
49
46
|
"@types/react-dom": "~19.2.3",
|
|
50
|
-
"effect": "3.
|
|
47
|
+
"effect": "3.20.0",
|
|
51
48
|
"react": "~19.2.3",
|
|
52
49
|
"react-dom": "~19.2.3",
|
|
53
|
-
"vite": "^
|
|
54
|
-
"@dxos/random": "0.8.4-main.
|
|
55
|
-
"@dxos/storybook-utils": "0.8.4-main.
|
|
50
|
+
"vite": "^8.0.10",
|
|
51
|
+
"@dxos/random": "0.8.4-main.e00bdcdb52",
|
|
52
|
+
"@dxos/storybook-utils": "0.8.4-main.e00bdcdb52"
|
|
56
53
|
},
|
|
57
54
|
"peerDependencies": {
|
|
58
|
-
"effect": "3.
|
|
55
|
+
"effect": "3.20.0",
|
|
59
56
|
"react": "~19.2.3",
|
|
60
57
|
"react-dom": "~19.2.3",
|
|
61
|
-
"@dxos/
|
|
62
|
-
"@dxos/ui
|
|
58
|
+
"@dxos/ui-theme": "0.8.4-main.e00bdcdb52",
|
|
59
|
+
"@dxos/react-ui": "0.8.4-main.e00bdcdb52"
|
|
63
60
|
},
|
|
64
61
|
"publishConfig": {
|
|
65
62
|
"access": "public"
|
|
@@ -5,19 +5,19 @@
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
6
|
import React from 'react';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { random } from '@dxos/random';
|
|
9
9
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
10
10
|
|
|
11
11
|
import { Accordion } from './Accordion';
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
random.seed(1);
|
|
14
14
|
|
|
15
15
|
type TestItem = { id: string; name: string; text: string };
|
|
16
16
|
|
|
17
17
|
const items: TestItem[] = Array.from({ length: 10 }, (_, i) => ({
|
|
18
18
|
id: i.toString(),
|
|
19
19
|
name: `Item ${i}`,
|
|
20
|
-
text:
|
|
20
|
+
text: random.lorem.paragraphs(3),
|
|
21
21
|
}));
|
|
22
22
|
|
|
23
23
|
const DefaultStory = () => {
|
|
@@ -10,7 +10,6 @@ import { Icon, type ThemedClassName } from '@dxos/react-ui';
|
|
|
10
10
|
import { mx } from '@dxos/ui-theme';
|
|
11
11
|
|
|
12
12
|
import { type ListItemRecord } from '../List';
|
|
13
|
-
|
|
14
13
|
import { useAccordionContext } from './AccordionRoot';
|
|
15
14
|
|
|
16
15
|
const ACCORDION_ITEM_NAME = 'AccordionItem';
|
|
@@ -9,7 +9,7 @@ import React, { useContext, useMemo } from 'react';
|
|
|
9
9
|
|
|
10
10
|
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
11
|
import { withRegistry } from '@dxos/storybook-utils';
|
|
12
|
-
import {
|
|
12
|
+
import { mx } from '@dxos/ui-theme';
|
|
13
13
|
import { arrayMove } from '@dxos/util';
|
|
14
14
|
|
|
15
15
|
import { List, type ListRootProps } from './List';
|
|
@@ -51,7 +51,7 @@ const DefaultStory = (props: Omit<ListRootProps<TestItemType>, 'items'>) => {
|
|
|
51
51
|
<div className='flex items-center text-sm'>Items</div>
|
|
52
52
|
</div>
|
|
53
53
|
|
|
54
|
-
<div role='list' className='
|
|
54
|
+
<div role='list' className='h-full w-full overflow-auto'>
|
|
55
55
|
{items?.map((item) => (
|
|
56
56
|
<List.Item<TestItemType> key={item.id} item={item} classNames={mx(grid)}>
|
|
57
57
|
<List.ItemDragHandle />
|
|
@@ -89,7 +89,7 @@ const SimpleStory = (props: Omit<ListRootProps<TestItemType>, 'items'>) => {
|
|
|
89
89
|
return (
|
|
90
90
|
<List.Root<TestItemType> dragPreview items={items} {...props}>
|
|
91
91
|
{({ items }) => (
|
|
92
|
-
<div role='list' className='
|
|
92
|
+
<div role='list' className='h-full w-full overflow-auto'>
|
|
93
93
|
{items?.map((item) => (
|
|
94
94
|
<List.Item<TestItemType> key={item.id} item={item} classNames={mx(grid)}>
|
|
95
95
|
<List.ItemDragHandle />
|
|
@@ -15,17 +15,12 @@ import {
|
|
|
15
15
|
} from './ListItem';
|
|
16
16
|
import { ListRoot, type ListRootProps } from './ListRoot';
|
|
17
17
|
|
|
18
|
-
// TODO(burdon): Multi-select model.
|
|
19
|
-
// TODO(burdon): Key nav.
|
|
20
|
-
// TODO(burdon): Animation.
|
|
21
|
-
// TODO(burdon): Constrain axis.
|
|
22
|
-
// TODO(burdon): Tree view.
|
|
23
|
-
// TODO(burdon): Fix autoscroll while dragging.
|
|
24
|
-
|
|
25
18
|
/**
|
|
26
19
|
* Draggable list.
|
|
27
20
|
* Ref: https://github.com/atlassian/pragmatic-drag-and-drop
|
|
28
21
|
* Ref: https://github.com/alexreardon/pdnd-react-tailwind/blob/main/src/task.tsx
|
|
22
|
+
*
|
|
23
|
+
* @deprecated Use react-ui-mosaic.
|
|
29
24
|
*/
|
|
30
25
|
export const List = {
|
|
31
26
|
Root: ListRoot,
|
|
@@ -2,22 +2,22 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
6
|
-
import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
7
|
-
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
8
5
|
import {
|
|
9
6
|
type Edge,
|
|
10
7
|
attachClosestEdge,
|
|
11
8
|
extractClosestEdge,
|
|
12
9
|
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
10
|
+
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
11
|
+
import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
12
|
+
import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
|
|
13
13
|
import { createContext } from '@radix-ui/react-context';
|
|
14
14
|
import { Slot } from '@radix-ui/react-slot';
|
|
15
15
|
import React, {
|
|
16
16
|
type ComponentProps,
|
|
17
17
|
type HTMLAttributes,
|
|
18
|
-
type MutableRefObject,
|
|
19
18
|
type PropsWithChildren,
|
|
20
19
|
type ReactNode,
|
|
20
|
+
RefObject,
|
|
21
21
|
useEffect,
|
|
22
22
|
useRef,
|
|
23
23
|
useState,
|
|
@@ -47,22 +47,22 @@ export type ItemDragState =
|
|
|
47
47
|
container: HTMLElement;
|
|
48
48
|
}
|
|
49
49
|
| {
|
|
50
|
-
type: '
|
|
50
|
+
type: 'is-dragging';
|
|
51
51
|
}
|
|
52
52
|
| {
|
|
53
|
-
type: '
|
|
53
|
+
type: 'is-dragging-over';
|
|
54
54
|
closestEdge: Edge | null;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
export const idle: ItemDragState = { type: 'idle' };
|
|
58
58
|
|
|
59
59
|
const stateStyles: { [Key in ItemDragState['type']]?: HTMLAttributes<HTMLDivElement>['className'] } = {
|
|
60
|
-
'
|
|
60
|
+
'is-dragging': 'opacity-50',
|
|
61
61
|
};
|
|
62
62
|
|
|
63
63
|
type ListItemContext<T extends ListItemRecord> = {
|
|
64
64
|
item: T;
|
|
65
|
-
dragHandleRef:
|
|
65
|
+
dragHandleRef: RefObject<HTMLButtonElement | null>;
|
|
66
66
|
};
|
|
67
67
|
|
|
68
68
|
/**
|
|
@@ -100,12 +100,12 @@ export const ListItem = <T extends ListItemRecord>({
|
|
|
100
100
|
}: ListItemProps<T>) => {
|
|
101
101
|
const Comp = asChild ? Slot : 'div';
|
|
102
102
|
const { isItem, readonly, dragPreview, setState: setRootState } = useListContext(LIST_ITEM_NAME);
|
|
103
|
-
const
|
|
104
|
-
const dragHandleRef = useRef<
|
|
103
|
+
const rootRef = useRef<HTMLDivElement | null>(null);
|
|
104
|
+
const dragHandleRef = useRef<HTMLButtonElement | null>(null);
|
|
105
105
|
const [state, setState] = useState<ItemDragState>(idle);
|
|
106
106
|
|
|
107
107
|
useEffect(() => {
|
|
108
|
-
const element =
|
|
108
|
+
const element = rootRef.current;
|
|
109
109
|
invariant(element);
|
|
110
110
|
return combine(
|
|
111
111
|
//
|
|
@@ -135,8 +135,8 @@ export const ListItem = <T extends ListItemRecord>({
|
|
|
135
135
|
}
|
|
136
136
|
: undefined,
|
|
137
137
|
onDragStart: () => {
|
|
138
|
-
setState({ type: '
|
|
139
|
-
setRootState({ type: '
|
|
138
|
+
setState({ type: 'is-dragging' });
|
|
139
|
+
setRootState({ type: 'is-dragging', item });
|
|
140
140
|
},
|
|
141
141
|
onDrop: () => {
|
|
142
142
|
setState(idle);
|
|
@@ -158,7 +158,7 @@ export const ListItem = <T extends ListItemRecord>({
|
|
|
158
158
|
getIsSticky: () => true,
|
|
159
159
|
onDragEnter: ({ self }) => {
|
|
160
160
|
const closestEdge = extractClosestEdge(self.data);
|
|
161
|
-
setState({ type: '
|
|
161
|
+
setState({ type: 'is-dragging-over', closestEdge });
|
|
162
162
|
},
|
|
163
163
|
onDragLeave: () => {
|
|
164
164
|
setState(idle);
|
|
@@ -166,10 +166,10 @@ export const ListItem = <T extends ListItemRecord>({
|
|
|
166
166
|
onDrag: ({ self }) => {
|
|
167
167
|
const closestEdge = extractClosestEdge(self.data);
|
|
168
168
|
setState((current) => {
|
|
169
|
-
if (current.type === '
|
|
169
|
+
if (current.type === 'is-dragging-over' && current.closestEdge === closestEdge) {
|
|
170
170
|
return current;
|
|
171
171
|
}
|
|
172
|
-
return { type: '
|
|
172
|
+
return { type: 'is-dragging-over', closestEdge };
|
|
173
173
|
});
|
|
174
174
|
},
|
|
175
175
|
onDrop: () => {
|
|
@@ -182,15 +182,15 @@ export const ListItem = <T extends ListItemRecord>({
|
|
|
182
182
|
return (
|
|
183
183
|
<ListItemProvider item={item} dragHandleRef={dragHandleRef}>
|
|
184
184
|
<Comp
|
|
185
|
-
|
|
185
|
+
{...props}
|
|
186
186
|
role='listitem'
|
|
187
187
|
aria-selected={selected}
|
|
188
|
-
className={mx('relative dx-selected', classNames, stateStyles[state.type])}
|
|
189
|
-
{
|
|
188
|
+
className={mx('relative p-1 dx-selected dx-hover', classNames, stateStyles[state.type])}
|
|
189
|
+
ref={rootRef}
|
|
190
190
|
>
|
|
191
191
|
{children}
|
|
192
192
|
</Comp>
|
|
193
|
-
{state.type === '
|
|
193
|
+
{state.type === 'is-dragging-over' && state.closestEdge && (
|
|
194
194
|
<NaturalListItem.DropIndicator edge={state.closestEdge} />
|
|
195
195
|
)}
|
|
196
196
|
</ListItemProvider>
|
|
@@ -237,12 +237,12 @@ export const ListItemDeleteButton = ({
|
|
|
237
237
|
const { t } = useTranslation(osTranslations);
|
|
238
238
|
return (
|
|
239
239
|
<IconButton
|
|
240
|
-
iconOnly
|
|
241
|
-
variant='ghost'
|
|
242
240
|
{...props}
|
|
243
|
-
|
|
241
|
+
variant='ghost'
|
|
244
242
|
disabled={isDisabled}
|
|
245
|
-
|
|
243
|
+
icon={icon}
|
|
244
|
+
iconOnly
|
|
245
|
+
label={label ?? t('delete.label')}
|
|
246
246
|
classNames={[classNames, autoHide && disabled && 'hidden']}
|
|
247
247
|
/>
|
|
248
248
|
);
|
|
@@ -253,12 +253,12 @@ export const ListItemDragHandle = ({ disabled }: Pick<IconButtonProps, 'disabled
|
|
|
253
253
|
const { t } = useTranslation(osTranslations);
|
|
254
254
|
return (
|
|
255
255
|
<IconButton
|
|
256
|
-
iconOnly
|
|
257
256
|
variant='ghost'
|
|
258
|
-
label={t('drag handle label')}
|
|
259
|
-
ref={dragHandleRef as any}
|
|
260
|
-
icon='ph--dots-six-vertical--regular'
|
|
261
257
|
disabled={disabled}
|
|
258
|
+
icon='ph--dots-six-vertical--regular'
|
|
259
|
+
iconOnly
|
|
260
|
+
label={t('drag-handle.label')}
|
|
261
|
+
ref={dragHandleRef}
|
|
262
262
|
/>
|
|
263
263
|
);
|
|
264
264
|
};
|
|
@@ -273,7 +273,9 @@ export const ListItemDragPreview = <T extends ListItemRecord>({
|
|
|
273
273
|
};
|
|
274
274
|
|
|
275
275
|
export const ListItemWrapper = ({ classNames, children }: ThemedClassName<PropsWithChildren>) => (
|
|
276
|
-
<div className={mx('flex w-full gap-2', classNames)}>
|
|
276
|
+
<div role='none' className={mx('flex w-full gap-2', classNames)}>
|
|
277
|
+
{children}
|
|
278
|
+
</div>
|
|
277
279
|
);
|
|
278
280
|
|
|
279
281
|
export const ListItemTitle = ({
|
|
@@ -281,7 +283,7 @@ export const ListItemTitle = ({
|
|
|
281
283
|
children,
|
|
282
284
|
...props
|
|
283
285
|
}: ThemedClassName<PropsWithChildren<ComponentProps<'div'>>>) => (
|
|
284
|
-
<div className={mx('flex grow items-center truncate', classNames)} {...props}>
|
|
286
|
+
<div role='none' className={mx('flex grow items-center truncate', classNames)} {...props}>
|
|
285
287
|
{children}
|
|
286
288
|
</div>
|
|
287
289
|
);
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
5
|
import { extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
7
6
|
import { getReorderDestinationIndex } from '@atlaskit/pragmatic-drag-and-drop-hitbox/util/get-reorder-destination-index';
|
|
7
|
+
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
8
8
|
import { createContext } from '@radix-ui/react-context';
|
|
9
9
|
import React, { type ReactNode, useCallback, useEffect, useState } from 'react';
|
|
10
10
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
7
|
import { Obj } from '@dxos/echo';
|
|
8
|
-
import {
|
|
8
|
+
import { random } from '@dxos/random';
|
|
9
9
|
|
|
10
10
|
export const TestItemSchema = Schema.Struct({
|
|
11
11
|
id: Obj.ID,
|
|
@@ -21,10 +21,10 @@ export const TestList = Schema.Struct({
|
|
|
21
21
|
export type TestList = Schema.Schema.Type<typeof TestList>;
|
|
22
22
|
|
|
23
23
|
export const createList = (n = 10): TestList => ({
|
|
24
|
-
items:
|
|
24
|
+
items: random.helpers.multiple(
|
|
25
25
|
() => ({
|
|
26
|
-
id:
|
|
27
|
-
name:
|
|
26
|
+
id: random.string.uuid(),
|
|
27
|
+
name: random.commerce.productName(),
|
|
28
28
|
}),
|
|
29
29
|
{ count: n },
|
|
30
30
|
),
|
|
@@ -2,25 +2,24 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
6
5
|
import { type Instruction, extractInstruction } from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
|
|
6
|
+
import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
7
7
|
import { Atom, RegistryContext } from '@effect-atom/atom-react';
|
|
8
8
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
9
9
|
import React, { useCallback, useContext, useEffect, useMemo, useRef } from 'react';
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { random } from '@dxos/random';
|
|
12
12
|
import { Icon } from '@dxos/react-ui';
|
|
13
13
|
import { withTheme } from '@dxos/react-ui/testing';
|
|
14
14
|
import { withRegistry } from '@dxos/storybook-utils';
|
|
15
15
|
|
|
16
16
|
import { Path } from '../../util';
|
|
17
|
-
|
|
18
17
|
import { type TestItem, createTree, updateState } from './testing';
|
|
19
18
|
import { Tree } from './Tree';
|
|
20
19
|
import { type TreeModel } from './TreeContext';
|
|
21
20
|
import { type TreeData } from './TreeItem';
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
random.seed(1234);
|
|
24
23
|
|
|
25
24
|
const tree = createTree() as TestItem;
|
|
26
25
|
|
|
@@ -180,7 +179,7 @@ const DefaultStory = ({ draggable }: { draggable?: boolean }) => {
|
|
|
180
179
|
draggable={draggable}
|
|
181
180
|
renderColumns={() => (
|
|
182
181
|
<div className='flex items-center'>
|
|
183
|
-
<Icon icon='ph--placeholder--regular'
|
|
182
|
+
<Icon icon='ph--placeholder--regular' />
|
|
184
183
|
</div>
|
|
185
184
|
)}
|
|
186
185
|
onOpenChange={handleOpenChange}
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
6
|
-
import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
7
5
|
import {
|
|
8
6
|
type Instruction,
|
|
9
7
|
type ItemMode,
|
|
10
8
|
attachInstruction,
|
|
11
9
|
extractInstruction,
|
|
12
10
|
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/tree-item';
|
|
11
|
+
import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
|
|
12
|
+
import { draggable, dropTargetForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
|
|
13
13
|
import { useAtomValue } from '@effect-atom/atom-react';
|
|
14
14
|
import * as Schema from 'effect/Schema';
|
|
15
15
|
import React, {
|
|
@@ -25,7 +25,7 @@ import React, {
|
|
|
25
25
|
} from 'react';
|
|
26
26
|
|
|
27
27
|
import { invariant } from '@dxos/invariant';
|
|
28
|
-
import { TreeItem as NaturalTreeItem, Treegrid } from '@dxos/react-ui';
|
|
28
|
+
import { TreeItem as NaturalTreeItem, Treegrid, TREEGRID_PARENT_OF_SEPARATOR } from '@dxos/react-ui';
|
|
29
29
|
import {
|
|
30
30
|
ghostFocusWithin,
|
|
31
31
|
ghostHover,
|
|
@@ -129,6 +129,7 @@ const RawTreeItem = <T extends { id: string } = any>({
|
|
|
129
129
|
const mode: ItemMode = last ? 'last-in-group' : open ? 'expanded' : 'standard';
|
|
130
130
|
const canSelectItem = canSelect?.({ item, path }) ?? true;
|
|
131
131
|
const data = { id, path, item } satisfies TreeData;
|
|
132
|
+
const shouldSeedNativeDragData = typeof document !== 'undefined' && document.body.hasAttribute('data-platform');
|
|
132
133
|
|
|
133
134
|
const cancelExpand = useCallback(() => {
|
|
134
135
|
if (cancelExpandRef.current) {
|
|
@@ -139,6 +140,7 @@ const RawTreeItem = <T extends { id: string } = any>({
|
|
|
139
140
|
|
|
140
141
|
const isItemDraggable = draggableProp && itemDraggable !== false;
|
|
141
142
|
const isItemDroppable = itemDroppable !== false;
|
|
143
|
+
const nativeDragText = id;
|
|
142
144
|
|
|
143
145
|
useEffect(() => {
|
|
144
146
|
if (!draggableProp) {
|
|
@@ -151,6 +153,12 @@ const RawTreeItem = <T extends { id: string } = any>({
|
|
|
151
153
|
draggable({
|
|
152
154
|
element: buttonRef.current!,
|
|
153
155
|
getInitialData: () => data,
|
|
156
|
+
getInitialDataForExternal: () => {
|
|
157
|
+
if (!shouldSeedNativeDragData) {
|
|
158
|
+
return {};
|
|
159
|
+
}
|
|
160
|
+
return { 'text/plain': nativeDragText };
|
|
161
|
+
},
|
|
154
162
|
onDragStart: () => {
|
|
155
163
|
setState('dragging');
|
|
156
164
|
if (open) {
|
|
@@ -297,7 +305,7 @@ const RawTreeItem = <T extends { id: string } = any>({
|
|
|
297
305
|
key={id}
|
|
298
306
|
id={id}
|
|
299
307
|
aria-labelledby={`${id}__label`}
|
|
300
|
-
parentOf={parentOf?.join(
|
|
308
|
+
parentOf={parentOf?.join(TREEGRID_PARENT_OF_SEPARATOR)}
|
|
301
309
|
data-object-id={id}
|
|
302
310
|
data-testid={testId}
|
|
303
311
|
// NOTE(thure): This is intentionally an empty string to for descendents to select by in the CSS
|
|
@@ -56,7 +56,6 @@ export const TreeItemHeading = memo(
|
|
|
56
56
|
<Button
|
|
57
57
|
data-testid='treeItem.heading'
|
|
58
58
|
variant='ghost'
|
|
59
|
-
density='fine'
|
|
60
59
|
classNames={[
|
|
61
60
|
'grow gap-2 ps-0.5 hover:bg-transparent dark:hover:bg-transparent',
|
|
62
61
|
'disabled:cursor-default disabled:opacity-100',
|
|
@@ -67,9 +66,7 @@ export const TreeItemHeading = memo(
|
|
|
67
66
|
onKeyDown={handleButtonKeydown}
|
|
68
67
|
{...(current && { 'aria-current': 'location' })}
|
|
69
68
|
>
|
|
70
|
-
{icon &&
|
|
71
|
-
<Icon icon={icon ?? 'ph--placeholder--regular'} size={5} classNames={['my-1', styles?.surfaceText]} />
|
|
72
|
-
)}
|
|
69
|
+
{icon && <Icon icon={icon ?? 'ph--placeholder--regular'} classNames={['my-1', styles?.surfaceText]} />}
|
|
73
70
|
<span className='flex-1 w-0 truncate text-start font-normal' data-tooltip>
|
|
74
71
|
{toLocalizedString(label, t)}
|
|
75
72
|
</span>
|
|
@@ -14,7 +14,7 @@ export type TreeItemToggleProps = Omit<IconButtonProps, 'icon' | 'size' | 'label
|
|
|
14
14
|
|
|
15
15
|
export const TreeItemToggle = memo(
|
|
16
16
|
forwardRef<HTMLButtonElement, TreeItemToggleProps>(
|
|
17
|
-
({ open, isBranch, hidden,
|
|
17
|
+
({ classNames, open, isBranch, hidden, ...props }, forwardedRef) => {
|
|
18
18
|
return (
|
|
19
19
|
<IconButton
|
|
20
20
|
ref={forwardedRef}
|
|
@@ -24,8 +24,8 @@ export const TreeItemToggle = memo(
|
|
|
24
24
|
density='fine'
|
|
25
25
|
classNames={[
|
|
26
26
|
'h-full w-6 px-0',
|
|
27
|
-
'[&_svg]:transition-
|
|
28
|
-
open
|
|
27
|
+
'[&_svg]:transition-transform [&_svg]:duration-200',
|
|
28
|
+
open ? '[&_svg]:rotate-90' : '[&_svg]:rotate-0',
|
|
29
29
|
hidden ? 'hidden' : !isBranch && 'invisible',
|
|
30
30
|
classNames,
|
|
31
31
|
]}
|
|
@@ -7,7 +7,7 @@ import * as Schema from 'effect/Schema';
|
|
|
7
7
|
|
|
8
8
|
import { Obj } from '@dxos/echo';
|
|
9
9
|
import { log } from '@dxos/log';
|
|
10
|
-
import {
|
|
10
|
+
import { random } from '@dxos/random';
|
|
11
11
|
|
|
12
12
|
import { type TreeData } from './TreeItem';
|
|
13
13
|
|
|
@@ -26,18 +26,18 @@ export const TestItemSchema = Schema.Struct({
|
|
|
26
26
|
});
|
|
27
27
|
|
|
28
28
|
export const createTree = (n = 4, d = 4): TestItem => ({
|
|
29
|
-
id:
|
|
30
|
-
name:
|
|
29
|
+
id: random.string.uuid(),
|
|
30
|
+
name: random.commerce.productName(),
|
|
31
31
|
icon:
|
|
32
32
|
d === 3
|
|
33
33
|
? undefined
|
|
34
|
-
:
|
|
34
|
+
: random.helpers.arrayElement([
|
|
35
35
|
'ph--planet--regular',
|
|
36
36
|
'ph--sailboat--regular',
|
|
37
37
|
'ph--house--regular',
|
|
38
38
|
'ph--gear--regular',
|
|
39
39
|
]),
|
|
40
|
-
items: d > 0 ?
|
|
40
|
+
items: d > 0 ? random.helpers.multiple(() => createTree(n, d - 1), { count: n }) : [],
|
|
41
41
|
});
|
|
42
42
|
|
|
43
43
|
const removeItem = (tree: TestItem, source: TreeData) => {
|