@dxos/react-ui-stack 0.6.13-main.ed424a1 → 0.6.13
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 +8 -9
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/browser/testing/index.mjs.map +3 -3
- package/dist/lib/node/index.cjs +6 -7
- package/dist/lib/node/index.cjs.map +3 -3
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs.map +2 -2
- package/dist/types/src/components/CaretDownUp.d.ts.map +1 -1
- package/dist/types/src/components/Deck.stories.d.ts.map +1 -1
- package/dist/types/src/components/Section.d.ts +3 -2
- package/dist/types/src/components/Section.d.ts.map +1 -1
- package/dist/types/src/playwright/playwright.config.d.ts +2 -2
- package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
- package/dist/types/src/testing/TableContent.d.ts.map +1 -1
- package/dist/types/src/testing/generator.d.ts +2 -2
- package/dist/types/src/testing/generator.d.ts.map +1 -1
- package/package.json +21 -28
- package/src/components/CaretDownUp.tsx +0 -1
- package/src/components/Deck.stories.tsx +26 -16
- package/src/components/Section.tsx +18 -9
- package/src/playwright/playwright.config.ts +2 -13
- package/src/playwright/smoke.spec.ts +19 -11
- package/src/testing/TableContent.tsx +0 -1
- package/src/testing/generator.ts +4 -4
- package/dist/lib/node-esm/index.mjs +0 -378
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/testing/index.mjs +0 -161
- package/dist/lib/node-esm/testing/index.mjs.map +0 -7
- package/dist/types/src/next/Stack.d.ts +0 -9
- package/dist/types/src/next/Stack.d.ts.map +0 -1
- package/dist/types/src/next/Stack.stories.d.ts +0 -8
- package/dist/types/src/next/Stack.stories.d.ts.map +0 -1
- package/dist/types/src/next/StackItem.d.ts +0 -14
- package/dist/types/src/next/StackItem.d.ts.map +0 -1
- package/dist/types/src/next/index.d.ts +0 -2
- package/dist/types/src/next/index.d.ts.map +0 -1
- package/src/next/Stack.stories.tsx +0 -146
- package/src/next/Stack.tsx +0 -30
- package/src/next/StackItem.tsx +0 -78
- package/src/next/index.ts +0 -5
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/testing/generator.ts", "../../../../src/testing/stack-manager.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { create, type ReactiveObject, S } from '@dxos/echo-schema';\nimport { faker } from '@dxos/random';\n\n// TODO(burdon): Reconcile with @dxos/plugin-debug, @dxos/react-ui/testing.\n\n// TODO(burdon): Bug when adding stale objects to space (e.g., static objects already added in previous story invocation).\n\n// TODO(burdon): Util.\nexport const range = <T>(fn: (i: number) => T | undefined, length: number): T[] =>\n Array.from({ length })\n .map((_, i) => fn(i))\n .filter(Boolean) as T[];\n\n// TODO(burdon): Commit to using ECHO to generate all test data? Or convert from raw data?\nexport type TestItem = { id: string; type: string } & Record<string, any>;\n\ntype ObjectDataGenerator = {\n createSchema?: () => S.Schema<any>;\n createData: () => any;\n};\n\ntype ObjectFactory<T extends ReactiveObject<any>> = {\n schema?: S.Schema<any>; // TODO(burdon): Support both typed and expando schema.\n createObject: () => T;\n};\n\ntype ObjectFactoryMap = { [type: string]: ObjectFactory<any> };\n\nconst createFactory = ({ createSchema, createData }: ObjectDataGenerator) => {\n const schema = createSchema?.();\n return {\n schema,\n createObject: () => (schema ? create(schema, createData()) : create(createData())),\n };\n};\n\n// TODO(burdon): Handle restricted values.\nexport const Status = ['pending', 'active', 'done'];\nexport const Priority = [1, 2, 3, 4, 5];\n\nexport const defaultGenerators: { [type: string]: ObjectDataGenerator } = {\n document: {\n createData: () => ({\n title: faker.lorem.sentence(3),\n body: faker.lorem.sentences({ min: 1, max: faker.number.int({ min: 1, max: 3 }) }),\n }),\n },\n\n image: {\n createData: () => ({\n title: faker.lorem.sentence(3),\n image: faker.helpers.arrayElement(data.images),\n body: faker.datatype.boolean() ? faker.lorem.sentences() : undefined,\n }),\n },\n\n project: {\n createSchema: () =>\n S.Struct({\n title: S.String,\n repo: S.String,\n status: S.String,\n priority: S.Number,\n }),\n createData: () => ({\n title: faker.commerce.productName(),\n repo: faker.datatype.boolean({ probability: 0.3 }) ? faker.internet.url() : undefined,\n status: faker.helpers.arrayElement(Status),\n priority: faker.helpers.arrayElement(Priority),\n }),\n },\n};\n\n/**\n * Typed object generator.\n * @deprecated\n */\n// TODO(wittjosiah): Remove.\nexport class TestObjectGenerator {\n public readonly factories: ObjectFactoryMap;\n\n constructor({ types, factories }: { types?: string[]; factories?: ObjectFactoryMap } = {}) {\n this.factories =\n factories ??\n (types ?? Object.keys(defaultGenerators)).reduce<ObjectFactoryMap>((acc, type) => {\n acc[type] = createFactory(defaultGenerators[type]);\n return acc;\n }, {});\n }\n\n get schema(): S.Schema<any>[] {\n return Object.values(this.factories).map((f) => f.schema!);\n }\n\n createObject({ types }: { types?: string[] } = {}) {\n const type = faker.helpers.arrayElement(types ?? Object.keys(this.factories));\n const factory = this.factories[type];\n return factory?.createObject();\n }\n\n createObjects({ types, length }: { types?: string[]; length: number }) {\n return range(() => this.createObject({ types }), length);\n }\n}\n\n// https://unsplash.com\n// TODO(burdon): Use https://picsum.photos?\nconst data = {\n images: [\n '/images/image-1.png',\n '/images/image-2.png',\n '/images/image-3.png',\n '/images/image-4.png',\n '/images/image-5.png',\n '/images/image-6.png',\n ],\n};\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport type { Locator, Page } from '@playwright/test';\n\nexport class StackManager {\n private readonly _page: Page;\n\n constructor(readonly locator: Locator) {\n this._page = locator.page();\n }\n\n empty() {\n return this.locator.getByTestId('stack.empty');\n }\n\n sections() {\n return this.locator.locator('li');\n }\n\n order() {\n return this.locator.locator('li').evaluateAll((els) => els.map((el) => el.getAttribute('id')));\n }\n\n section(index: number) {\n return new SectionManager(this.locator.locator('li').nth(index));\n }\n}\n\nexport class SectionManager {\n private readonly _page: Page;\n\n constructor(readonly locator: Locator) {\n this._page = locator.page();\n }\n\n async id() {\n return this.locator.getAttribute('id');\n }\n\n async remove() {\n await this.locator.getByTestId('section.drag-handle-menu-trigger').click();\n await this._page.getByTestId('section.remove').click();\n }\n\n async navigateTo() {\n await this.locator.getByTestId('section.drag-handle-menu-trigger').click();\n await this._page.getByTestId('section.navigate-to').click();\n }\n\n async dragTo(target: Locator, offset: { x: number; y: number } = { x: 0, y: 0 }) {\n const active = this.locator.getByTestId('section.drag-handle-menu-trigger');\n const box = await target.boundingBox();\n if (box) {\n await active.hover();\n await this._page.mouse.down();\n // Timeouts are for input discretization in WebKit\n await this._page.waitForTimeout(100);\n await this._page.pause();\n await this._page.mouse.move(offset.x + box.x + box.width / 2, offset.y + box.y + box.height / 2, { steps: 4 });\n await this._page.pause();\n await this._page.waitForTimeout(100);\n await this._page.mouse.up();\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["create", "S", "faker", "range", "fn", "length", "Array", "from", "map", "_", "i", "filter", "Boolean", "createFactory", "createSchema", "createData", "schema", "createObject", "create", "Status", "Priority", "defaultGenerators", "document", "title", "faker", "lorem", "sentence", "body", "sentences", "min", "max", "number", "int", "image", "helpers", "arrayElement", "data", "images", "datatype", "boolean", "undefined", "project", "S", "Struct", "String", "repo", "status", "priority", "Number", "commerce", "productName", "probability", "internet", "url", "TestObjectGenerator", "constructor", "types", "factories", "Object", "keys", "reduce", "acc", "type", "values", "f", "factory", "createObjects", "StackManager", "constructor", "locator", "_page", "page", "empty", "getByTestId", "sections", "order", "evaluateAll", "els", "map", "el", "getAttribute", "section", "index", "SectionManager", "nth", "id", "remove", "click", "navigateTo", "dragTo", "target", "offset", "x", "y", "active", "box", "boundingBox", "hover", "mouse", "down", "waitForTimeout", "pause", "move", "width", "height", "steps", "up"]
|
|
7
|
-
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import React, { type ComponentPropsWithoutRef } from 'react';
|
|
2
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
3
|
-
type Orientation = 'horizontal' | 'vertical';
|
|
4
|
-
export type StackProps = Omit<ThemedClassName<ComponentPropsWithoutRef<'div'>>, 'aria-orientation'> & {
|
|
5
|
-
orientation?: Orientation;
|
|
6
|
-
};
|
|
7
|
-
export declare const Stack: ({ children, classNames, style, orientation, ...props }: StackProps) => React.JSX.Element;
|
|
8
|
-
export {};
|
|
9
|
-
//# sourceMappingURL=Stack.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Stack.d.ts","sourceRoot":"","sources":["../../../../src/next/Stack.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,EAAsB,KAAK,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAEjF,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,KAAK,WAAW,GAAG,YAAY,GAAG,UAAU,CAAC;AAE7C,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,GAAG;IACpG,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B,CAAC;AAEF,eAAO,MAAM,KAAK,2DAA4D,UAAU,sBAcvF,CAAC"}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type Meta, type StoryObj } from '@storybook/react';
|
|
2
|
-
import React from 'react';
|
|
3
|
-
declare const StorybookStack: () => React.JSX.Element;
|
|
4
|
-
declare const meta: Meta<typeof StorybookStack>;
|
|
5
|
-
export default meta;
|
|
6
|
-
type Story = StoryObj<typeof StorybookStack>;
|
|
7
|
-
export declare const Default: Story;
|
|
8
|
-
//# sourceMappingURL=Stack.stories.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Stack.stories.d.ts","sourceRoot":"","sources":["../../../../src/next/Stack.stories.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,KAAK,IAAI,EAAE,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5D,OAAO,KAAgC,MAAM,OAAO,CAAC;AA4BrD,QAAA,MAAM,cAAc,yBAgGnB,CAAC;AAEF,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,cAAc,CAKrC,CAAC;AAEF,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,cAAc,CAAC,CAAC;AAE7C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { type Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
2
|
-
import React, { type ComponentPropsWithoutRef } from 'react';
|
|
3
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
4
|
-
import { type StackProps } from './Stack';
|
|
5
|
-
export type StackItemProps = Omit<ThemedClassName<ComponentPropsWithoutRef<'div'>>, 'aria-orientation'> & {
|
|
6
|
-
item: {
|
|
7
|
-
id: string;
|
|
8
|
-
type: 'column' | 'card';
|
|
9
|
-
};
|
|
10
|
-
orientation?: StackProps['orientation'];
|
|
11
|
-
onReorder: (sourceId: string, targetId: string, closestEdge: Edge | null) => void;
|
|
12
|
-
};
|
|
13
|
-
export declare const StackItem: ({ item, children, classNames, orientation, onReorder, ...props }: StackItemProps) => React.JSX.Element;
|
|
14
|
-
//# sourceMappingURL=StackItem.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"StackItem.d.ts","sourceRoot":"","sources":["../../../../src/next/StackItem.tsx"],"names":[],"mappings":"AAMA,OAAO,EAEL,KAAK,IAAI,EAEV,MAAM,uDAAuD,CAAC;AAE/D,OAAO,KAAK,EAAE,EAAoB,KAAK,wBAAwB,EAAE,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAGtD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,eAAe,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,GAAG;IACxG,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAAA;KAAE,CAAC;IAC9C,WAAW,CAAC,EAAE,UAAU,CAAC,aAAa,CAAC,CAAC;IACxC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;CACnF,CAAC;AAEF,eAAO,MAAM,SAAS,qEAAsE,cAAc,sBAoDzG,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/next/index.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC"}
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import { type Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
6
|
-
import { type Meta, type StoryObj } from '@storybook/react';
|
|
7
|
-
import React, { useState, useCallback } from 'react';
|
|
8
|
-
|
|
9
|
-
import { withTheme } from '@dxos/storybook-utils';
|
|
10
|
-
|
|
11
|
-
import { Stack } from './Stack';
|
|
12
|
-
import { StackItem } from './StackItem';
|
|
13
|
-
|
|
14
|
-
type CardItem = {
|
|
15
|
-
id: string;
|
|
16
|
-
type: 'card';
|
|
17
|
-
content: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
type ColumnItem = {
|
|
21
|
-
id: string;
|
|
22
|
-
type: 'column';
|
|
23
|
-
title: string;
|
|
24
|
-
cards: CardItem[];
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const KanbanBlock = ({ item }: { item: CardItem }) => {
|
|
28
|
-
return (
|
|
29
|
-
<div className='is-64 bs-24 bg-input rounded-lg border border-separator shadow-sm grid place-content-center'>
|
|
30
|
-
<span className='text-sm font-medium'>{item.content}</span>
|
|
31
|
-
</div>
|
|
32
|
-
);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const StorybookStack = () => {
|
|
36
|
-
const [columns, setColumns] = useState<ColumnItem[]>([
|
|
37
|
-
{
|
|
38
|
-
id: 'col-0',
|
|
39
|
-
type: 'column',
|
|
40
|
-
title: 'To Do',
|
|
41
|
-
cards: [
|
|
42
|
-
{ id: 'banana', type: 'card', content: 'Banana' },
|
|
43
|
-
{ id: 'pickle', type: 'card', content: 'Pickle' },
|
|
44
|
-
{ id: 'wombat', type: 'card', content: 'Wombat' },
|
|
45
|
-
{ id: 'kazoo', type: 'card', content: 'Kazoo' },
|
|
46
|
-
],
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
id: 'col-1',
|
|
50
|
-
type: 'column',
|
|
51
|
-
title: 'In Progress',
|
|
52
|
-
cards: [
|
|
53
|
-
{ id: 'noodle', type: 'card', content: 'Noodle' },
|
|
54
|
-
{ id: 'squish', type: 'card', content: 'Squish' },
|
|
55
|
-
{ id: 'wobble', type: 'card', content: 'Wobble' },
|
|
56
|
-
{ id: 'floof', type: 'card', content: 'Floof' },
|
|
57
|
-
],
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
id: 'col-2',
|
|
61
|
-
type: 'column',
|
|
62
|
-
title: 'Done',
|
|
63
|
-
cards: [
|
|
64
|
-
{ id: 'snorkel', type: 'card', content: 'Snorkel' },
|
|
65
|
-
{ id: 'bloop', type: 'card', content: 'Bloop' },
|
|
66
|
-
{ id: 'wiggle', type: 'card', content: 'Wiggle' },
|
|
67
|
-
{ id: 'zoop', type: 'card', content: 'Zoop' },
|
|
68
|
-
],
|
|
69
|
-
},
|
|
70
|
-
]);
|
|
71
|
-
|
|
72
|
-
const reorderItem = useCallback((sourceId: string, targetId: string, closestEdge: Edge | null) => {
|
|
73
|
-
setColumns((prevColumns) => {
|
|
74
|
-
const newColumns = [...prevColumns];
|
|
75
|
-
const sourceColumn = newColumns.find(
|
|
76
|
-
(col) => col.id === sourceId || col.cards.some((card) => card.id === sourceId),
|
|
77
|
-
);
|
|
78
|
-
const targetColumn = newColumns.find(
|
|
79
|
-
(col) => col.id === targetId || col.cards.some((card) => card.id === targetId),
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
if (sourceColumn && targetColumn) {
|
|
83
|
-
if (sourceId.startsWith('col-') && targetId.startsWith('col-')) {
|
|
84
|
-
// Reordering columns
|
|
85
|
-
const sourceIndex = newColumns.findIndex((col) => col.id === sourceId);
|
|
86
|
-
const targetIndex = newColumns.findIndex((col) => col.id === targetId);
|
|
87
|
-
const [movedColumn] = newColumns.splice(sourceIndex, 1);
|
|
88
|
-
const insertIndex = closestEdge === 'right' ? targetIndex + 1 : targetIndex;
|
|
89
|
-
newColumns.splice(insertIndex, 0, movedColumn);
|
|
90
|
-
} else {
|
|
91
|
-
// Reordering cards within a column
|
|
92
|
-
const sourceCardIndex = sourceColumn.cards.findIndex((card) => card.id === sourceId);
|
|
93
|
-
const targetCardIndex = targetColumn.cards.findIndex((card) => card.id === targetId);
|
|
94
|
-
const [movedCard] = sourceColumn.cards.splice(sourceCardIndex, 1);
|
|
95
|
-
|
|
96
|
-
let insertIndex;
|
|
97
|
-
if (sourceColumn === targetColumn && sourceCardIndex < targetCardIndex) {
|
|
98
|
-
insertIndex = closestEdge === 'bottom' ? targetCardIndex : targetCardIndex - 1;
|
|
99
|
-
} else {
|
|
100
|
-
insertIndex = closestEdge === 'bottom' ? targetCardIndex + 1 : targetCardIndex;
|
|
101
|
-
}
|
|
102
|
-
targetColumn.cards.splice(insertIndex, 0, movedCard);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return newColumns;
|
|
107
|
-
});
|
|
108
|
-
}, []);
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<Stack orientation={'horizontal'} classNames='gap-1'>
|
|
112
|
-
{columns.map((column) => (
|
|
113
|
-
<StackItem
|
|
114
|
-
key={column.id}
|
|
115
|
-
item={column}
|
|
116
|
-
orientation={'horizontal'}
|
|
117
|
-
classNames='p-4 bg-deck rounded-md'
|
|
118
|
-
onReorder={reorderItem}
|
|
119
|
-
>
|
|
120
|
-
<Stack orientation={'vertical'} classNames='gap-1'>
|
|
121
|
-
{column.cards.map((card) => (
|
|
122
|
-
<StackItem key={card.id} item={card} orientation={'vertical'} onReorder={reorderItem}>
|
|
123
|
-
<KanbanBlock item={card} />
|
|
124
|
-
</StackItem>
|
|
125
|
-
))}
|
|
126
|
-
</Stack>
|
|
127
|
-
</StackItem>
|
|
128
|
-
))}
|
|
129
|
-
</Stack>
|
|
130
|
-
);
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
const meta: Meta<typeof StorybookStack> = {
|
|
134
|
-
title: 'react-ui-stack-next/Stack',
|
|
135
|
-
component: StorybookStack,
|
|
136
|
-
decorators: [withTheme],
|
|
137
|
-
argTypes: { orientation: { control: 'radio', options: ['horizontal', 'vertical'] } },
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
export default meta;
|
|
141
|
-
|
|
142
|
-
type Story = StoryObj<typeof StorybookStack>;
|
|
143
|
-
|
|
144
|
-
export const Default: Story = {
|
|
145
|
-
args: { orientation: 'horizontal' },
|
|
146
|
-
};
|
package/src/next/Stack.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
import React, { type CSSProperties, type ComponentPropsWithoutRef } from 'react';
|
|
6
|
-
|
|
7
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
8
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
9
|
-
|
|
10
|
-
type Orientation = 'horizontal' | 'vertical';
|
|
11
|
-
|
|
12
|
-
export type StackProps = Omit<ThemedClassName<ComponentPropsWithoutRef<'div'>>, 'aria-orientation'> & {
|
|
13
|
-
orientation?: Orientation;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export const Stack = ({ children, classNames, style, orientation, ...props }: StackProps) => {
|
|
17
|
-
const childrenCount = React.Children.count(children);
|
|
18
|
-
|
|
19
|
-
const styles: CSSProperties = {
|
|
20
|
-
[orientation === 'horizontal' ? 'gridTemplateColumns' : 'gridTemplateRows']:
|
|
21
|
-
`repeat(${childrenCount}, min-content)`,
|
|
22
|
-
...style,
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<div className={mx('grid relative', classNames)} aria-orientation={orientation} style={styles} {...props}>
|
|
27
|
-
{children}
|
|
28
|
-
</div>
|
|
29
|
-
);
|
|
30
|
-
};
|
package/src/next/StackItem.tsx
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
// Copyright 2024 DXOS.org
|
|
3
|
-
//
|
|
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 {
|
|
8
|
-
attachClosestEdge,
|
|
9
|
-
type Edge,
|
|
10
|
-
extractClosestEdge,
|
|
11
|
-
} from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
|
|
12
|
-
import { DropIndicator } from '@atlaskit/pragmatic-drag-and-drop-react-drop-indicator/box';
|
|
13
|
-
import React, { useRef, useState, type ComponentPropsWithoutRef } from 'react';
|
|
14
|
-
|
|
15
|
-
import { type ThemedClassName } from '@dxos/react-ui';
|
|
16
|
-
import { mx } from '@dxos/react-ui-theme';
|
|
17
|
-
|
|
18
|
-
import { type StackProps } from './Stack';
|
|
19
|
-
|
|
20
|
-
export type StackItemProps = Omit<ThemedClassName<ComponentPropsWithoutRef<'div'>>, 'aria-orientation'> & {
|
|
21
|
-
item: { id: string; type: 'column' | 'card' };
|
|
22
|
-
orientation?: StackProps['orientation'];
|
|
23
|
-
onReorder: (sourceId: string, targetId: string, closestEdge: Edge | null) => void;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const StackItem = ({ item, children, classNames, orientation, onReorder, ...props }: StackItemProps) => {
|
|
27
|
-
const ref = useRef<HTMLDivElement>(null);
|
|
28
|
-
const [closestEdge, setEdge] = useState<Edge | null>(null);
|
|
29
|
-
|
|
30
|
-
React.useEffect(() => {
|
|
31
|
-
if (!ref.current) {
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const element = ref.current;
|
|
36
|
-
|
|
37
|
-
return combine(
|
|
38
|
-
draggable({ element, getInitialData: () => ({ id: item.id, type: item.type }) }),
|
|
39
|
-
dropTargetForElements({
|
|
40
|
-
element,
|
|
41
|
-
getData: ({ input, element }) => {
|
|
42
|
-
return attachClosestEdge(
|
|
43
|
-
{ id: item.id, type: item.type },
|
|
44
|
-
{ input, element, allowedEdges: orientation === 'vertical' ? ['top', 'bottom'] : ['left', 'right'] },
|
|
45
|
-
);
|
|
46
|
-
},
|
|
47
|
-
onDragEnter: ({ self, source }) => {
|
|
48
|
-
if (source.data.type === self.data.type) {
|
|
49
|
-
setEdge(extractClosestEdge(self.data));
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
onDrag: ({ self, source }) => {
|
|
53
|
-
if (source.data.type === self.data.type) {
|
|
54
|
-
setEdge(extractClosestEdge(self.data));
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
onDragLeave: () => setEdge(null),
|
|
58
|
-
onDrop: ({ self, source }) => {
|
|
59
|
-
setEdge(null);
|
|
60
|
-
if (source.data.type === self.data.type) {
|
|
61
|
-
onReorder(source.data.id as string, self.data.id as string, extractClosestEdge(self.data));
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
}),
|
|
65
|
-
);
|
|
66
|
-
}, [orientation, item, onReorder]);
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<div
|
|
70
|
-
ref={ref}
|
|
71
|
-
className={mx('relative', orientation === 'horizontal' ? 'grid-cols-subgrid' : 'grid-rows-subgrid', classNames)}
|
|
72
|
-
{...props}
|
|
73
|
-
>
|
|
74
|
-
{children}
|
|
75
|
-
{closestEdge && <DropIndicator edge={closestEdge} />}
|
|
76
|
-
</div>
|
|
77
|
-
);
|
|
78
|
-
};
|