@dxos/react-ui-stack 0.8.3 → 0.8.4-main.1068cf700f

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/lib/browser/index.mjs +767 -1016
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/browser/{testing → playwright}/index.mjs +5 -1
  5. package/dist/lib/browser/{testing → playwright}/index.mjs.map +3 -3
  6. package/dist/lib/node-esm/index.mjs +767 -1016
  7. package/dist/lib/node-esm/index.mjs.map +4 -4
  8. package/dist/lib/node-esm/meta.json +1 -1
  9. package/dist/lib/node-esm/{testing → playwright}/index.mjs +5 -1
  10. package/dist/lib/node-esm/{testing → playwright}/index.mjs.map +3 -3
  11. package/dist/types/src/{exemplars → components}/CardStack/CardStack.d.ts +24 -11
  12. package/dist/types/src/components/CardStack/CardStack.d.ts.map +1 -0
  13. package/dist/types/src/components/CardStack/CardStack.stories.d.ts +15 -0
  14. package/dist/types/src/components/CardStack/CardStack.stories.d.ts.map +1 -0
  15. package/dist/types/src/{exemplars → components}/CardStack/CardStackDragPreview.d.ts +4 -1
  16. package/dist/types/src/components/CardStack/CardStackDragPreview.d.ts.map +1 -0
  17. package/dist/types/src/components/CardStack/index.d.ts.map +1 -0
  18. package/dist/types/src/components/Stack/Stack.d.ts +15 -7
  19. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
  20. package/dist/types/src/components/Stack/Stack.stories.d.ts +12 -3
  21. package/dist/types/src/components/Stack/Stack.stories.d.ts.map +1 -1
  22. package/dist/types/src/components/StackContext.d.ts +2 -1
  23. package/dist/types/src/components/StackContext.d.ts.map +1 -1
  24. package/dist/types/src/components/StackItem/StackItem.d.ts +9 -12
  25. package/dist/types/src/components/StackItem/StackItem.d.ts.map +1 -1
  26. package/dist/types/src/components/StackItem/StackItem.stories.d.ts +13 -5
  27. package/dist/types/src/components/StackItem/StackItem.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/StackItem/StackItemContent.d.ts +4 -37
  29. package/dist/types/src/components/StackItem/StackItemContent.d.ts.map +1 -1
  30. package/dist/types/src/components/StackItem/StackItemHeading.d.ts +1 -1
  31. package/dist/types/src/components/StackItem/StackItemHeading.d.ts.map +1 -1
  32. package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts.map +1 -1
  33. package/dist/types/src/components/StackItem/StackItemSigil.d.ts +2 -2
  34. package/dist/types/src/components/StackItem/StackItemSigil.d.ts.map +1 -1
  35. package/dist/types/src/components/deprecated/LayoutControls.d.ts +3 -0
  36. package/dist/types/src/components/deprecated/LayoutControls.d.ts.map +1 -1
  37. package/dist/types/src/components/index.d.ts +2 -1
  38. package/dist/types/src/components/index.d.ts.map +1 -1
  39. package/dist/types/src/components/{defs.d.ts → types.d.ts} +1 -1
  40. package/dist/types/src/components/types.d.ts.map +1 -0
  41. package/dist/types/src/hooks/useStackDropForElements.d.ts +9 -7
  42. package/dist/types/src/hooks/useStackDropForElements.d.ts.map +1 -1
  43. package/dist/types/src/index.d.ts +1 -2
  44. package/dist/types/src/index.d.ts.map +1 -1
  45. package/dist/types/src/playwright/index.d.ts.map +1 -0
  46. package/dist/types/src/playwright/playwright.config.d.ts +3 -0
  47. package/dist/types/src/playwright/playwright.config.d.ts.map +1 -0
  48. package/dist/types/src/playwright/stack-manager.d.ts.map +1 -0
  49. package/dist/types/src/translations.d.ts +13 -14
  50. package/dist/types/src/translations.d.ts.map +1 -1
  51. package/dist/types/tsconfig.tsbuildinfo +1 -1
  52. package/package.json +48 -41
  53. package/src/components/CardStack/CardStack.stories.tsx +173 -0
  54. package/src/{exemplars → components}/CardStack/CardStack.tsx +115 -39
  55. package/src/{exemplars → components}/CardStack/CardStackDragPreview.tsx +12 -9
  56. package/src/components/Stack/Stack.stories.tsx +9 -10
  57. package/src/components/Stack/Stack.tsx +225 -26
  58. package/src/components/StackContext.tsx +2 -1
  59. package/src/components/StackItem/StackItem.stories.tsx +21 -17
  60. package/src/components/StackItem/StackItem.tsx +49 -29
  61. package/src/components/StackItem/StackItemContent.tsx +23 -42
  62. package/src/components/StackItem/StackItemHeading.tsx +5 -9
  63. package/src/components/StackItem/StackItemResizeHandle.tsx +2 -1
  64. package/src/components/StackItem/StackItemSigil.tsx +5 -4
  65. package/src/components/deprecated/LayoutControls.tsx +3 -0
  66. package/src/components/index.ts +2 -1
  67. package/src/hooks/useStackDropForElements.ts +59 -42
  68. package/src/index.ts +1 -5
  69. package/src/{testing → playwright}/index.ts +1 -1
  70. package/src/playwright/playwright.config.ts +17 -0
  71. package/src/playwright/smoke.spec.ts +7 -5
  72. package/src/translations.ts +5 -3
  73. package/dist/lib/node/index.cjs +0 -1220
  74. package/dist/lib/node/index.cjs.map +0 -7
  75. package/dist/lib/node/meta.json +0 -1
  76. package/dist/lib/node/testing/index.cjs +0 -81
  77. package/dist/lib/node/testing/index.cjs.map +0 -7
  78. package/dist/types/src/components/defs.d.ts.map +0 -1
  79. package/dist/types/src/exemplars/Card/Card.d.ts +0 -62
  80. package/dist/types/src/exemplars/Card/Card.d.ts.map +0 -1
  81. package/dist/types/src/exemplars/Card/Card.stories-todo.d.ts +0 -1
  82. package/dist/types/src/exemplars/Card/Card.stories-todo.d.ts.map +0 -1
  83. package/dist/types/src/exemplars/Card/CardDragPreview.d.ts +0 -6
  84. package/dist/types/src/exemplars/Card/CardDragPreview.d.ts.map +0 -1
  85. package/dist/types/src/exemplars/Card/fragments.d.ts +0 -13
  86. package/dist/types/src/exemplars/Card/fragments.d.ts.map +0 -1
  87. package/dist/types/src/exemplars/Card/index.d.ts +0 -4
  88. package/dist/types/src/exemplars/Card/index.d.ts.map +0 -1
  89. package/dist/types/src/exemplars/CardStack/CardStack.d.ts.map +0 -1
  90. package/dist/types/src/exemplars/CardStack/CardStack.stories-todo.d.ts +0 -1
  91. package/dist/types/src/exemplars/CardStack/CardStack.stories-todo.d.ts.map +0 -1
  92. package/dist/types/src/exemplars/CardStack/CardStackDragPreview.d.ts.map +0 -1
  93. package/dist/types/src/exemplars/CardStack/index.d.ts.map +0 -1
  94. package/dist/types/src/exemplars/index.d.ts +0 -3
  95. package/dist/types/src/exemplars/index.d.ts.map +0 -1
  96. package/dist/types/src/testing/index.d.ts.map +0 -1
  97. package/dist/types/src/testing/stack-manager.d.ts.map +0 -1
  98. package/src/exemplars/Card/Card.stories-todo.tsx +0 -135
  99. package/src/exemplars/Card/Card.tsx +0 -182
  100. package/src/exemplars/Card/CardDragPreview.tsx +0 -22
  101. package/src/exemplars/Card/fragments.ts +0 -25
  102. package/src/exemplars/Card/index.ts +0 -7
  103. package/src/exemplars/CardStack/CardStack.stories-todo.tsx +0 -80
  104. package/src/exemplars/index.ts +0 -6
  105. package/src/playwright/playwright.config.cts +0 -18
  106. /package/dist/types/src/{exemplars → components}/CardStack/index.d.ts +0 -0
  107. /package/dist/types/src/{testing → playwright}/index.d.ts +0 -0
  108. /package/dist/types/src/{testing → playwright}/stack-manager.d.ts +0 -0
  109. /package/src/{exemplars → components}/CardStack/index.ts +0 -0
  110. /package/src/components/{defs.ts → types.ts} +0 -0
  111. /package/src/{testing → playwright}/stack-manager.ts +0 -0
package/package.json CHANGED
@@ -1,12 +1,16 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-stack",
3
- "version": "0.8.3",
3
+ "version": "0.8.4-main.1068cf700f",
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": true,
13
+ "sideEffects": false,
10
14
  "type": "module",
11
15
  "exports": {
12
16
  ".": {
@@ -14,18 +18,18 @@
14
18
  "browser": "./dist/lib/browser/index.mjs",
15
19
  "node": "./dist/lib/node-esm/index.mjs"
16
20
  },
17
- "./testing": {
18
- "types": "./dist/types/src/testing/index.d.ts",
19
- "browser": "./dist/lib/browser/testing/index.mjs",
20
- "node": {
21
- "require": "./dist/lib/node/testing/index.cjs",
22
- "default": "./dist/lib/node-esm/testing/index.mjs"
23
- }
21
+ "./playwright": {
22
+ "types": "./dist/types/src/playwright/index.d.ts",
23
+ "browser": "./dist/lib/browser/playwright/index.mjs",
24
+ "node": "./dist/lib/node-esm/playwright/index.mjs"
24
25
  }
25
26
  },
26
27
  "types": "dist/types/src/index.d.ts",
27
28
  "typesVersions": {
28
29
  "*": {
30
+ "playwright": [
31
+ "dist/types/src/playwright/index.d.ts"
32
+ ],
29
33
  "testing": [
30
34
  "dist/types/src/testing/index.d.ts"
31
35
  ]
@@ -36,11 +40,11 @@
36
40
  "src"
37
41
  ],
38
42
  "dependencies": {
39
- "@atlaskit/pragmatic-drag-and-drop": "^1.4.0",
40
- "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^2.1.0",
41
- "@atlaskit/pragmatic-drag-and-drop-hitbox": "^1.0.3",
42
- "@fluentui/react-tabster": "^9.24.2",
43
- "@preact-signals/safe-react": "^0.9.0",
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",
44
48
  "@radix-ui/primitive": "1.1.1",
45
49
  "@radix-ui/react-compose-refs": "1.1.1",
46
50
  "@radix-ui/react-context": "1.1.1",
@@ -49,37 +53,40 @@
49
53
  "@radix-ui/react-slot": "1.1.2",
50
54
  "@radix-ui/react-use-controllable-state": "1.1.0",
51
55
  "react-resize-detector": "^11.0.1",
52
- "@dxos/echo-schema": "0.8.3",
53
- "@dxos/keyboard": "0.8.3",
54
- "@dxos/react-ui-attention": "0.8.3",
55
- "@dxos/live-object": "0.8.3",
56
- "@dxos/react-ui-dnd": "0.8.3",
57
- "@dxos/util": "0.8.3"
56
+ "@dxos/echo": "0.8.4-main.1068cf700f",
57
+ "@dxos/keyboard": "0.8.4-main.1068cf700f",
58
+ "@dxos/react-ui-dnd": "0.8.4-main.1068cf700f",
59
+ "@dxos/react-ui-mosaic": "0.8.4-main.1068cf700f",
60
+ "@dxos/util": "0.8.4-main.1068cf700f",
61
+ "@dxos/react-ui-attention": "0.8.4-main.1068cf700f"
58
62
  },
59
63
  "devDependencies": {
60
- "@phosphor-icons/react": "^2.1.5",
61
- "@types/react": "~18.2.0",
62
- "@types/react-dom": "~18.2.0",
63
- "react": "~18.2.0",
64
- "react-dom": "~18.2.0",
65
- "vite": "5.4.7",
66
- "@dxos/app-graph": "0.8.3",
67
- "@dxos/client": "0.8.3",
68
- "@dxos/echo-schema": "0.8.3",
69
- "@dxos/react-ui": "0.8.3",
70
- "@dxos/random": "0.8.3",
71
- "@dxos/react-ui-theme": "0.8.3",
72
- "@dxos/test-utils": "0.8.3",
73
- "@dxos/storybook-utils": "0.8.3"
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.9",
69
+ "@dxos/app-framework": "0.8.4-main.1068cf700f",
70
+ "@dxos/app-graph": "0.8.4-main.1068cf700f",
71
+ "@dxos/client": "0.8.4-main.1068cf700f",
72
+ "@dxos/random": "0.8.4-main.1068cf700f",
73
+ "@dxos/echo-db": "0.8.4-main.1068cf700f",
74
+ "@dxos/echo": "0.8.4-main.1068cf700f",
75
+ "@dxos/react-client": "0.8.4-main.1068cf700f",
76
+ "@dxos/react-ui": "0.8.4-main.1068cf700f",
77
+ "@dxos/schema": "0.8.4-main.1068cf700f",
78
+ "@dxos/storybook-utils": "0.8.4-main.1068cf700f",
79
+ "@dxos/test-utils": "0.8.4-main.1068cf700f",
80
+ "@dxos/types": "0.8.4-main.1068cf700f",
81
+ "@dxos/ui-theme": "0.8.4-main.1068cf700f"
74
82
  },
75
83
  "peerDependencies": {
76
- "@phosphor-icons/react": "^2.1.5",
77
- "react": "~18.2.0",
78
- "react-dom": "~18.2.0",
79
- "@dxos/client": "0.8.3",
80
- "@dxos/random": "0.8.3",
81
- "@dxos/react-ui-theme": "0.8.3",
82
- "@dxos/react-ui": "0.8.3"
84
+ "react": "~19.2.3",
85
+ "react-dom": "~19.2.3",
86
+ "@dxos/client": "0.8.4-main.1068cf700f",
87
+ "@dxos/random": "0.8.4-main.1068cf700f",
88
+ "@dxos/react-ui": "0.8.4-main.1068cf700f",
89
+ "@dxos/ui-theme": "0.8.4-main.1068cf700f"
83
90
  },
84
91
  "publishConfig": {
85
92
  "access": "public"
@@ -0,0 +1,173 @@
1
+ //
2
+ // Copyright 2025 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-vite';
7
+ import React, { useCallback, useState } from 'react';
8
+
9
+ import { faker } from '@dxos/random';
10
+ import { IconButton } from '@dxos/react-ui';
11
+ import { withTheme } from '@dxos/react-ui/testing';
12
+ import { Card, CardDragPreview } from '@dxos/react-ui-mosaic';
13
+
14
+ import { StackItem } from '../StackItem';
15
+
16
+ import { CardStack } from './CardStack';
17
+
18
+ faker.seed(0);
19
+
20
+ type CardItem = {
21
+ id: string;
22
+ title: string;
23
+ description: string;
24
+ image: string;
25
+ };
26
+
27
+ type StackItemData = {
28
+ id: string;
29
+ type?: 'column' | 'card';
30
+ };
31
+
32
+ const CardStackStory = () => {
33
+ const [column, setColumn] = useState<CardItem[]>(
34
+ faker.helpers.multiple(
35
+ () => ({
36
+ id: faker.string.uuid(),
37
+ title: faker.commerce.productName(),
38
+ description: faker.lorem.paragraph(),
39
+ image: faker.image.url(),
40
+ }),
41
+ { count: 12 },
42
+ ),
43
+ );
44
+
45
+ const handleRearrange = useCallback((source: StackItemData, target: StackItemData, closestEdge: Edge | null) => {
46
+ setColumn((prevColumn) => {
47
+ const newColumns = [...prevColumn];
48
+ // Reordering cards within a column
49
+ const sourceCardIndex = prevColumn.findIndex((card) => card.id === source.id);
50
+ const targetCardIndex = prevColumn.findIndex((card) => card.id === target.id);
51
+
52
+ if (typeof sourceCardIndex === 'number' && typeof targetCardIndex === 'number') {
53
+ const [movedCard] = newColumns.splice(sourceCardIndex, 1);
54
+
55
+ let insertIndex;
56
+ if (sourceCardIndex < targetCardIndex) {
57
+ insertIndex = closestEdge === 'bottom' ? targetCardIndex : targetCardIndex - 1;
58
+ } else {
59
+ insertIndex = closestEdge === 'bottom' ? targetCardIndex + 1 : targetCardIndex;
60
+ }
61
+ newColumns.splice(insertIndex, 0, movedCard);
62
+ }
63
+ return newColumns;
64
+ });
65
+ }, []);
66
+
67
+ const handleAddCard = useCallback(() => {
68
+ setColumn((prevColumn) => {
69
+ const newColumn = [...prevColumn];
70
+ const newCard = {
71
+ id: faker.string.uuid(),
72
+ title: faker.commerce.productName(),
73
+ description: faker.lorem.paragraph(),
74
+ image: faker.image.url(),
75
+ } satisfies CardItem;
76
+ newColumn.push(newCard);
77
+ console.log('[add card]', prevColumn.length, newColumn.length);
78
+ return newColumn;
79
+ });
80
+ }, []);
81
+
82
+ const handleRemoveCard = useCallback((cardId: string) => {
83
+ setColumn((prevColumn) => {
84
+ const newColumn = [...prevColumn];
85
+
86
+ const cardIndex = prevColumn.findIndex((card) => card.id === cardId);
87
+ if (cardIndex !== -1) {
88
+ newColumn.splice(cardIndex, 1);
89
+ }
90
+
91
+ return newColumn;
92
+ });
93
+ }, []);
94
+
95
+ return (
96
+ <CardStack.Root classNames='is-96'>
97
+ <CardStack.Content footer>
98
+ <CardStack.Stack id='story column' onRearrange={handleRearrange} itemsCount={column.length}>
99
+ {column.map((card, cardIndex, cardsArray) => {
100
+ const cardItem = { id: card.id, type: 'card' as const };
101
+ const prevCardId = cardIndex > 0 ? cardsArray[cardIndex - 1].id : undefined;
102
+ const nextCardId = cardIndex < cardsArray.length - 1 ? cardsArray[cardIndex + 1].id : undefined;
103
+
104
+ return (
105
+ <CardStack.Item asChild key={card.id}>
106
+ <StackItem.Root
107
+ item={cardItem}
108
+ focusIndicatorVariant='group'
109
+ prevSiblingId={prevCardId}
110
+ nextSiblingId={nextCardId}
111
+ >
112
+ <Card.Root>
113
+ <Card.Toolbar>
114
+ <StackItem.DragHandle asChild>
115
+ <Card.DragHandle />
116
+ </StackItem.DragHandle>
117
+ <Card.ToolbarSeparator variant='gap' />
118
+ <Card.ToolbarIconButton
119
+ iconOnly
120
+ variant='ghost'
121
+ icon='ph--x--regular'
122
+ label='Remove card'
123
+ onClick={() => handleRemoveCard(card.id)}
124
+ />
125
+ </Card.Toolbar>
126
+ <Card.Poster alt={card.title} image={card.image} />
127
+ <Card.Heading>{card.title}</Card.Heading>
128
+ <Card.Text variant='description'>{card.description}</Card.Text>
129
+ </Card.Root>
130
+ <StackItem.DragPreview>
131
+ {() => (
132
+ <CardDragPreview.Root>
133
+ <CardDragPreview.Content>
134
+ <Card.Toolbar>
135
+ <Card.DragHandle />
136
+ </Card.Toolbar>
137
+ <Card.Poster alt={card.title} image={card.image} />
138
+ <Card.Heading>{card.title}</Card.Heading>
139
+ <Card.Text variant='description'>{card.description}</Card.Text>
140
+ </CardDragPreview.Content>
141
+ </CardDragPreview.Root>
142
+ )}
143
+ </StackItem.DragPreview>
144
+ </StackItem.Root>
145
+ </CardStack.Item>
146
+ );
147
+ })}
148
+ </CardStack.Stack>
149
+
150
+ <CardStack.Footer>
151
+ <IconButton icon='ph--plus--regular' label='Add card' onClick={handleAddCard} classNames='is-full' />
152
+ </CardStack.Footer>
153
+
154
+ <CardStack.Heading>{faker.company.name()}</CardStack.Heading>
155
+ </CardStack.Content>
156
+ </CardStack.Root>
157
+ );
158
+ };
159
+
160
+ const meta = {
161
+ title: 'ui/react-ui-stack/CardStack',
162
+ component: CardStackStory,
163
+ decorators: [withTheme()],
164
+ parameters: {
165
+ layout: 'fullscreen',
166
+ },
167
+ } satisfies Meta<typeof CardStackStory>;
168
+
169
+ export default meta;
170
+
171
+ type Story = StoryObj<typeof CardStackStory>;
172
+
173
+ export const Default: Story = {};
@@ -6,17 +6,78 @@ import { Slot } from '@radix-ui/react-slot';
6
6
  import React, { type ComponentPropsWithoutRef, forwardRef } from 'react';
7
7
 
8
8
  import type { ThemedClassName } from '@dxos/react-ui';
9
- import { mx } from '@dxos/react-ui-theme';
9
+ import { Card } from '@dxos/react-ui-mosaic';
10
+ import { cardDefaultInlineSize, mx } from '@dxos/ui-theme';
10
11
 
11
- import { railGridHorizontalContainFitContent, Stack, type StackProps } from '../../components';
12
- import { Card } from '../Card';
12
+ import { Stack, type StackProps, railGridHorizontalContainFitContent } from '../Stack';
13
13
 
14
- type SharedCardStackProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & { asChild?: boolean };
14
+ /**
15
+ * This is `cardDefaultInlineSize` plus 2 times the sum of the inner and outer spacing applied by CardStack on the inline axis.
16
+ */
17
+ const cardStackDefaultInlineSizeRem = cardDefaultInlineSize + 2.125;
18
+
19
+ //
20
+ // Root
21
+ //
22
+
23
+ const cardStackRoot = 'flex flex-col';
24
+
25
+ const CardStackRoot = forwardRef<HTMLDivElement, SharedCardStackProps>(
26
+ ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
27
+ const Root = asChild ? Slot : 'div';
28
+ const rootProps = asChild
29
+ ? { classNames: [cardStackRoot, classNames] }
30
+ : { className: mx(cardStackRoot, classNames), role };
31
+
32
+ return (
33
+ <Root {...props} {...rootProps} ref={forwardedRef}>
34
+ {children}
35
+ </Root>
36
+ );
37
+ },
38
+ );
39
+
40
+ //
41
+ // Content
42
+ // TODO(burdon): Rename Viewport (should be the component that scrolls).
43
+ //
44
+
45
+ const cardStackContent = 'shrink min-bs-0 grid dx-focus-ring-group-x-indicator bg-baseSurface';
46
+
47
+ type CardStackContentProps = SharedCardStackProps & {
48
+ footer?: boolean;
49
+ };
50
+
51
+ const CardStackContent = forwardRef<HTMLDivElement, CardStackContentProps>(
52
+ ({ children, classNames, asChild, role = 'none', footer, ...props }, forwardedRef) => {
53
+ const Root = asChild ? Slot : 'div';
54
+ const baseClassNames = footer ? [cardStackContent, railGridHorizontalContainFitContent] : [cardStackContent];
55
+ const rootProps = asChild
56
+ ? { classNames: [...baseClassNames, classNames] }
57
+ : { className: mx(...baseClassNames, classNames), role };
58
+
59
+ return (
60
+ <Root {...props} {...rootProps} data-scroll-separator='false' ref={forwardedRef}>
61
+ {children}
62
+ </Root>
63
+ );
64
+ },
65
+ );
66
+
67
+ //
68
+ // Stack
69
+ // TODO(burdon): Rename Content.
70
+ //
71
+
72
+ type SharedCardStackProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & {
73
+ asChild?: boolean;
74
+ };
15
75
 
16
76
  const CardStackStack = forwardRef<
17
77
  HTMLDivElement,
18
78
  Omit<StackProps, 'orientation' | 'size' | 'rail' | 'separatorOnScroll'>
19
79
  >(({ children, classNames, itemsCount = 0, ...props }, forwardedRef) => {
80
+ // NOTE: Should not have horizontal padding since separatorOnScroll should be full width.
20
81
  return (
21
82
  <Stack
22
83
  orientation='vertical'
@@ -24,7 +85,7 @@ const CardStackStack = forwardRef<
24
85
  rail={false}
25
86
  classNames={
26
87
  /* NOTE(thure): Do not let this element have zero intrinsic size, otherwise the drop indicator will not display. See #9035. */
27
- ['plb-1', itemsCount > 0 && 'plb-2', classNames]
88
+ ['plb-2', classNames]
28
89
  }
29
90
  itemsCount={itemsCount}
30
91
  separatorOnScroll={9}
@@ -37,7 +98,30 @@ const CardStackStack = forwardRef<
37
98
  );
38
99
  });
39
100
 
40
- const CardStackDragHandle = Card.DragHandle;
101
+ //
102
+ // Item
103
+ //
104
+
105
+ const cardStackItem = 'contain-layout pli-2 plb-1 first-of-type:pbs-0 last-of-type:pbe-0';
106
+
107
+ const CardStackItem = forwardRef<HTMLDivElement, SharedCardStackProps>(
108
+ ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
109
+ const Root = asChild ? Slot : 'div';
110
+ const rootProps = asChild
111
+ ? { classNames: [cardStackItem, classNames] }
112
+ : { className: mx(cardStackItem, classNames), role };
113
+
114
+ return (
115
+ <Root {...props} {...rootProps} ref={forwardedRef}>
116
+ {children}
117
+ </Root>
118
+ );
119
+ },
120
+ );
121
+
122
+ //
123
+ // Heading
124
+ //
41
125
 
42
126
  const cardStackHeading = 'mli-2 order-first bg-transparent rounded-bs-md flex items-center';
43
127
 
@@ -47,6 +131,7 @@ const CardStackHeading = forwardRef<HTMLDivElement, SharedCardStackProps>(
47
131
  const rootProps = asChild
48
132
  ? { classNames: [cardStackHeading, classNames] }
49
133
  : { className: mx(cardStackHeading, classNames), role };
134
+
50
135
  return (
51
136
  <Root {...props} {...rootProps} ref={forwardedRef}>
52
137
  {children}
@@ -55,6 +140,10 @@ const CardStackHeading = forwardRef<HTMLDivElement, SharedCardStackProps>(
55
140
  },
56
141
  );
57
142
 
143
+ //
144
+ // Footer
145
+ //
146
+
58
147
  const cardStackFooter =
59
148
  'plb-2 mli-2 border-bs border-transparent [[data-scroll-separator-end="true"]_&]:border-subduedSeparator';
60
149
 
@@ -64,6 +153,7 @@ const CardStackFooter = forwardRef<HTMLDivElement, SharedCardStackProps>(
64
153
  const rootProps = asChild
65
154
  ? { classNames: [cardStackFooter, classNames] }
66
155
  : { className: mx(cardStackFooter, classNames), role };
156
+
67
157
  return (
68
158
  <Root {...props} {...rootProps} ref={forwardedRef}>
69
159
  {children}
@@ -72,41 +162,19 @@ const CardStackFooter = forwardRef<HTMLDivElement, SharedCardStackProps>(
72
162
  },
73
163
  );
74
164
 
75
- const cardStackContent = [
76
- 'shrink min-bs-0 bg-baseSurface border border-separator rounded-md grid dx-focus-ring-group-x-indicator kanban-drop',
77
- railGridHorizontalContainFitContent,
78
- ];
79
-
80
- const CardStackContent = forwardRef<HTMLDivElement, SharedCardStackProps>(
81
- ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
82
- const Root = asChild ? Slot : 'div';
83
- const rootProps = asChild
84
- ? { classNames: [...cardStackContent, classNames] }
85
- : { className: mx(...cardStackContent, classNames), role };
86
- return (
87
- <Root {...props} {...rootProps} data-scroll-separator='false' ref={forwardedRef}>
88
- {children}
89
- </Root>
90
- );
91
- },
92
- );
165
+ //
166
+ // DragHandle
167
+ //
93
168
 
94
- const cardStackRoot = 'flex flex-col pli-2 plb-2';
169
+ const CardStackDragHandle = Card.DragHandle;
95
170
 
96
- const CardStackRoot = forwardRef<HTMLDivElement, SharedCardStackProps>(
97
- ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
98
- const Root = asChild ? Slot : 'div';
99
- const rootProps = asChild
100
- ? { classNames: [cardStackRoot, classNames] }
101
- : { className: mx(cardStackRoot, classNames), role };
102
- return (
103
- <Root {...props} {...rootProps} ref={forwardedRef}>
104
- {children}
105
- </Root>
106
- );
107
- },
108
- );
171
+ //
172
+ // CardStack
173
+ //
109
174
 
175
+ /**
176
+ * @deprecated Replace with Mosaic.Stack.
177
+ */
110
178
  export const CardStack = {
111
179
  Root: CardStackRoot,
112
180
  Content: CardStackContent,
@@ -114,6 +182,14 @@ export const CardStack = {
114
182
  Heading: CardStackHeading,
115
183
  Footer: CardStackFooter,
116
184
  DragHandle: CardStackDragHandle,
185
+ Item: CardStackItem,
117
186
  };
118
187
 
119
- export { cardStackRoot, cardStackFooter, cardStackHeading, cardStackContent };
188
+ export {
189
+ cardStackRoot,
190
+ cardStackFooter,
191
+ cardStackHeading,
192
+ cardStackContent,
193
+ cardStackItem,
194
+ cardStackDefaultInlineSizeRem,
195
+ };
@@ -4,11 +4,11 @@
4
4
 
5
5
  import React, { type PropsWithChildren } from 'react';
6
6
 
7
- import { IconButton, useTranslation } from '@dxos/react-ui';
8
- import { mx } from '@dxos/react-ui-theme';
7
+ import { IconButton, ScrollArea, useTranslation } from '@dxos/react-ui';
8
+ import { mx } from '@dxos/ui-theme';
9
9
 
10
- import { type StackProps } from '../../components';
11
10
  import { translationKey } from '../../translations';
11
+ import { type StackProps } from '../Stack';
12
12
 
13
13
  const CardStackDragPreviewRoot = ({ children }: PropsWithChildren<{}>) => {
14
14
  return (
@@ -41,18 +41,21 @@ const CardStackDragPreviewContent = ({
41
41
  itemsCount = 0,
42
42
  }: PropsWithChildren<Pick<StackProps, 'itemsCount'>>) => {
43
43
  return (
44
- <div
45
- className={mx('overflow-y-auto flex-1 pli-2 flex flex-col gap-2', 'plb-1', itemsCount > 0 ? 'plb-2' : 'plb-1')}
46
- >
47
- {children}
48
- </div>
44
+ <ScrollArea.Root orientation='vertical'>
45
+ <ScrollArea.Viewport classNames={mx('pli-2 plb-1 gap-2', itemsCount > 0 ? 'plb-2' : 'plb-1')}>
46
+ {children}
47
+ </ScrollArea.Viewport>
48
+ </ScrollArea.Root>
49
49
  );
50
50
  };
51
51
 
52
52
  const CardStackDragPreviewFooter = ({ children }: PropsWithChildren<{}>) => {
53
- return <div className='p-2 border-t border-separator'>{children}</div>;
53
+ return <div className='p-2 border-bs border-separator'>{children}</div>;
54
54
  };
55
55
 
56
+ /**
57
+ * @deprecated
58
+ */
56
59
  export const CardStackDragPreview = {
57
60
  Root: CardStackDragPreviewRoot,
58
61
  Heading: CardStackDragPreviewHeading,
@@ -2,18 +2,17 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
5
  import { type Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
8
- import { type Meta, type StoryObj } from '@storybook/react';
9
- import React, { useState, useCallback } from 'react';
6
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
7
+ import React, { useCallback, useState } from 'react';
10
8
 
11
9
  import { faker } from '@dxos/random';
12
- import { withTheme } from '@dxos/storybook-utils';
10
+ import { withTheme } from '@dxos/react-ui/testing';
13
11
 
14
- import { Stack } from './Stack';
15
12
  import { StackItem } from '../StackItem';
16
- import { type StackItemData } from '../defs';
13
+ import { type StackItemData } from '../types';
14
+
15
+ import { Stack } from './Stack';
17
16
 
18
17
  type StoryStackItem = {
19
18
  id: string;
@@ -129,12 +128,12 @@ const DefaultStory = () => {
129
128
  );
130
129
  };
131
130
 
132
- const meta: Meta<typeof DefaultStory> = {
131
+ const meta = {
133
132
  title: 'ui/react-ui-stack/Stack',
134
133
  component: DefaultStory,
135
- decorators: [withTheme],
136
134
  argTypes: { orientation: { control: 'radio', options: ['horizontal', 'vertical'] } },
137
- };
135
+ decorators: [withTheme()],
136
+ } satisfies Meta<typeof DefaultStory>;
138
137
 
139
138
  export default meta;
140
139