@dxos/react-ui-stack 0.8.4-main.bc674ce → 0.8.4-main.c351d160a8

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 (48) hide show
  1. package/dist/lib/browser/index.mjs +92 -279
  2. package/dist/lib/browser/index.mjs.map +4 -4
  3. package/dist/lib/browser/meta.json +1 -1
  4. package/dist/lib/node-esm/index.mjs +92 -279
  5. package/dist/lib/node-esm/index.mjs.map +4 -4
  6. package/dist/lib/node-esm/meta.json +1 -1
  7. package/dist/types/src/components/Stack/Stack.d.ts +4 -4
  8. package/dist/types/src/components/Stack/Stack.d.ts.map +1 -1
  9. package/dist/types/src/components/StackItem/MenuSignifier.d.ts.map +1 -1
  10. package/dist/types/src/components/StackItem/StackItem.d.ts +2 -2
  11. package/dist/types/src/components/StackItem/StackItemContent.d.ts.map +1 -1
  12. package/dist/types/src/components/StackItem/StackItemDragHandle.d.ts.map +1 -1
  13. package/dist/types/src/components/StackItem/StackItemHeading.d.ts +1 -1
  14. package/dist/types/src/components/StackItem/StackItemHeading.d.ts.map +1 -1
  15. package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts +1 -1
  16. package/dist/types/src/components/StackItem/StackItemResizeHandle.d.ts.map +1 -1
  17. package/dist/types/src/components/StackItem/StackItemSigil.d.ts.map +1 -1
  18. package/dist/types/src/components/index.d.ts +0 -1
  19. package/dist/types/src/components/index.d.ts.map +1 -1
  20. package/dist/types/tsconfig.tsbuildinfo +1 -1
  21. package/package.json +25 -25
  22. package/src/components/Stack/Stack.stories.tsx +1 -1
  23. package/src/components/Stack/Stack.tsx +8 -8
  24. package/src/components/StackItem/MenuSignifier.tsx +2 -9
  25. package/src/components/StackItem/StackItem.stories.tsx +4 -4
  26. package/src/components/StackItem/StackItem.tsx +1 -1
  27. package/src/components/StackItem/StackItemContent.tsx +11 -9
  28. package/src/components/StackItem/StackItemDragHandle.tsx +4 -3
  29. package/src/components/StackItem/StackItemHeading.tsx +13 -12
  30. package/src/components/StackItem/StackItemResizeHandle.tsx +1 -1
  31. package/src/components/StackItem/StackItemSigil.tsx +6 -3
  32. package/src/components/index.ts +1 -1
  33. package/src/playwright/playwright.config.ts +1 -1
  34. package/dist/types/src/components/CardStack/CardStack.d.ts +0 -47
  35. package/dist/types/src/components/CardStack/CardStack.d.ts.map +0 -1
  36. package/dist/types/src/components/CardStack/CardStack.stories.d.ts +0 -15
  37. package/dist/types/src/components/CardStack/CardStack.stories.d.ts.map +0 -1
  38. package/dist/types/src/components/CardStack/CardStackDragPreview.d.ts +0 -9
  39. package/dist/types/src/components/CardStack/CardStackDragPreview.d.ts.map +0 -1
  40. package/dist/types/src/components/CardStack/index.d.ts +0 -3
  41. package/dist/types/src/components/CardStack/index.d.ts.map +0 -1
  42. package/dist/types/src/components/deprecated/LayoutControls.d.ts +0 -22
  43. package/dist/types/src/components/deprecated/LayoutControls.d.ts.map +0 -1
  44. package/src/components/CardStack/CardStack.stories.tsx +0 -173
  45. package/src/components/CardStack/CardStack.tsx +0 -196
  46. package/src/components/CardStack/CardStackDragPreview.tsx +0 -61
  47. package/src/components/CardStack/index.ts +0 -6
  48. package/src/components/deprecated/LayoutControls.tsx +0 -112
@@ -1,173 +0,0 @@
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 = {};
@@ -1,196 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import { Slot } from '@radix-ui/react-slot';
6
- import React, { type ComponentPropsWithoutRef, forwardRef } from 'react';
7
-
8
- import type { ThemedClassName } from '@dxos/react-ui';
9
- import { Card } from '@dxos/react-ui-mosaic';
10
- import { cardDefaultInlineSize, mx } from '@dxos/ui-theme';
11
-
12
- import { Stack, type StackProps, railGridHorizontalContainFitContent } from '../Stack';
13
-
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
- // TODO(burdon): Root should be headless.
26
- const CardStackRoot = forwardRef<HTMLDivElement, SharedCardStackProps>(
27
- ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
28
- const Root = asChild ? Slot : 'div';
29
- const rootProps = asChild
30
- ? { classNames: [cardStackRoot, classNames] }
31
- : { className: mx(cardStackRoot, classNames), role };
32
-
33
- return (
34
- <Root {...props} {...rootProps} ref={forwardedRef}>
35
- {children}
36
- </Root>
37
- );
38
- },
39
- );
40
-
41
- //
42
- // Content
43
- // TODO(burdon): Rename Viewport (should be the component that scrolls).
44
- //
45
-
46
- const cardStackContent = 'shrink min-bs-0 grid dx-focus-ring-group-x-indicator bg-baseSurface';
47
-
48
- type CardStackContentProps = SharedCardStackProps & {
49
- footer?: boolean;
50
- };
51
-
52
- const CardStackContent = forwardRef<HTMLDivElement, CardStackContentProps>(
53
- ({ children, classNames, asChild, role = 'none', footer, ...props }, forwardedRef) => {
54
- const Root = asChild ? Slot : 'div';
55
- const baseClassNames = footer ? [cardStackContent, railGridHorizontalContainFitContent] : [cardStackContent];
56
- const rootProps = asChild
57
- ? { classNames: [...baseClassNames, classNames] }
58
- : { className: mx(...baseClassNames, classNames), role };
59
-
60
- return (
61
- <Root {...props} {...rootProps} data-scroll-separator='false' ref={forwardedRef}>
62
- {children}
63
- </Root>
64
- );
65
- },
66
- );
67
-
68
- //
69
- // Stack
70
- // TODO(burdon): Rename Content.
71
- //
72
-
73
- type SharedCardStackProps = ThemedClassName<ComponentPropsWithoutRef<'div'>> & {
74
- asChild?: boolean;
75
- };
76
-
77
- const CardStackStack = forwardRef<
78
- HTMLDivElement,
79
- Omit<StackProps, 'orientation' | 'size' | 'rail' | 'separatorOnScroll'>
80
- >(({ children, classNames, itemsCount = 0, ...props }, forwardedRef) => {
81
- // NOTE: Should not have horizontal padding since separatorOnScroll should be full width.
82
- return (
83
- <Stack
84
- orientation='vertical'
85
- size='contain'
86
- rail={false}
87
- classNames={
88
- /* NOTE(thure): Do not let this element have zero intrinsic size, otherwise the drop indicator will not display. See #9035. */
89
- ['plb-2', classNames]
90
- }
91
- itemsCount={itemsCount}
92
- separatorOnScroll={9}
93
- data-density='fine'
94
- {...props}
95
- ref={forwardedRef}
96
- >
97
- {children}
98
- </Stack>
99
- );
100
- });
101
-
102
- //
103
- // Item
104
- //
105
-
106
- const cardStackItem = 'contain-layout pli-2 plb-1 first-of-type:pbs-0 last-of-type:pbe-0';
107
-
108
- const CardStackItem = forwardRef<HTMLDivElement, SharedCardStackProps>(
109
- ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
110
- const Root = asChild ? Slot : 'div';
111
- const rootProps = asChild
112
- ? { classNames: [cardStackItem, classNames] }
113
- : { className: mx(cardStackItem, classNames), role };
114
-
115
- return (
116
- <Root {...props} {...rootProps} ref={forwardedRef}>
117
- {children}
118
- </Root>
119
- );
120
- },
121
- );
122
-
123
- //
124
- // Heading
125
- //
126
-
127
- const cardStackHeading = 'mli-2 order-first bg-transparent rounded-bs-md flex items-center';
128
-
129
- const CardStackHeading = forwardRef<HTMLDivElement, SharedCardStackProps>(
130
- ({ children, classNames, asChild, role = 'heading', ...props }, forwardedRef) => {
131
- const Root = asChild ? Slot : 'div';
132
- const rootProps = asChild
133
- ? { classNames: [cardStackHeading, classNames] }
134
- : { className: mx(cardStackHeading, classNames), role };
135
-
136
- return (
137
- <Root {...props} {...rootProps} ref={forwardedRef}>
138
- {children}
139
- </Root>
140
- );
141
- },
142
- );
143
-
144
- //
145
- // Footer
146
- //
147
-
148
- const cardStackFooter =
149
- 'plb-2 mli-2 border-bs border-transparent [[data-scroll-separator-end="true"]_&]:border-subduedSeparator';
150
-
151
- const CardStackFooter = forwardRef<HTMLDivElement, SharedCardStackProps>(
152
- ({ children, classNames, asChild, role = 'none', ...props }, forwardedRef) => {
153
- const Root = asChild ? Slot : 'div';
154
- const rootProps = asChild
155
- ? { classNames: [cardStackFooter, classNames] }
156
- : { className: mx(cardStackFooter, classNames), role };
157
-
158
- return (
159
- <Root {...props} {...rootProps} ref={forwardedRef}>
160
- {children}
161
- </Root>
162
- );
163
- },
164
- );
165
-
166
- //
167
- // DragHandle
168
- //
169
-
170
- const CardStackDragHandle = Card.DragHandle;
171
-
172
- //
173
- // CardStack
174
- //
175
-
176
- /**
177
- * @deprecated Replace with Mosaic.Stack.
178
- */
179
- export const CardStack = {
180
- Root: CardStackRoot,
181
- Content: CardStackContent,
182
- Stack: CardStackStack,
183
- Heading: CardStackHeading,
184
- Footer: CardStackFooter,
185
- DragHandle: CardStackDragHandle,
186
- Item: CardStackItem,
187
- };
188
-
189
- export {
190
- cardStackRoot,
191
- cardStackFooter,
192
- cardStackHeading,
193
- cardStackContent,
194
- cardStackItem,
195
- cardStackDefaultInlineSizeRem,
196
- };
@@ -1,61 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- import React, { type PropsWithChildren } from 'react';
6
-
7
- import { IconButton, useTranslation } from '@dxos/react-ui';
8
- import { mx } from '@dxos/ui-theme';
9
-
10
- import { translationKey } from '../../translations';
11
- import { type StackProps } from '../Stack';
12
-
13
- const CardStackDragPreviewRoot = ({ children }: PropsWithChildren<{}>) => {
14
- return (
15
- <div className='p-2'>
16
- <div className='rounded-md max-bs-[calc(100dvh-1rem)] overflow-hidden bg-baseSurface border border-separator ring-focusLine ring-neutralFocusIndicator flex flex-col'>
17
- {children}
18
- </div>
19
- </div>
20
- );
21
- };
22
-
23
- const CardStackDragPreviewHeading = ({ children }: PropsWithChildren<{}>) => {
24
- const { t } = useTranslation(translationKey);
25
- return (
26
- <div className='flex items-center p-2'>
27
- <IconButton
28
- iconOnly
29
- icon='ph--dots-six-vertical--regular'
30
- variant='ghost'
31
- label={t('column drag handle label')}
32
- classNames='pli-2'
33
- />
34
- {children}
35
- </div>
36
- );
37
- };
38
-
39
- const CardStackDragPreviewContent = ({
40
- children,
41
- itemsCount = 0,
42
- }: PropsWithChildren<Pick<StackProps, 'itemsCount'>>) => {
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>
49
- );
50
- };
51
-
52
- const CardStackDragPreviewFooter = ({ children }: PropsWithChildren<{}>) => {
53
- return <div className='p-2 border-bs border-separator'>{children}</div>;
54
- };
55
-
56
- export const CardStackDragPreview = {
57
- Root: CardStackDragPreviewRoot,
58
- Heading: CardStackDragPreviewHeading,
59
- Content: CardStackDragPreviewContent,
60
- Footer: CardStackDragPreviewFooter,
61
- };
@@ -1,6 +0,0 @@
1
- //
2
- // Copyright 2025 DXOS.org
3
- //
4
-
5
- export * from './CardStack';
6
- export * from './CardStackDragPreview';
@@ -1,112 +0,0 @@
1
- //
2
- // Copyright 2024 DXOS.org
3
- //
4
-
5
- import React, { forwardRef } from 'react';
6
-
7
- import { ButtonGroup, type ButtonGroupProps, type ButtonProps, IconButton, useTranslation } from '@dxos/react-ui';
8
-
9
- import { translationKey } from '../../translations';
10
-
11
- export type LayoutControlEvent = 'solo' | 'close' | `${'pin' | 'increment'}-${'start' | 'end'}`;
12
- export type LayoutControlHandler = (event: LayoutControlEvent) => void;
13
-
14
- export type LayoutCapabilities = {
15
- incrementStart?: boolean;
16
- incrementEnd?: boolean;
17
- solo?: boolean;
18
- };
19
-
20
- export type LayoutControlsProps = Omit<ButtonGroupProps, 'onClick'> & {
21
- onClick?: LayoutControlHandler;
22
- variant?: 'hide-disabled' | 'default';
23
- close?: boolean | 'minify-start' | 'minify-end';
24
- capabilities: LayoutCapabilities;
25
- isSolo?: boolean;
26
- pin?: 'start' | 'end' | 'both';
27
- };
28
-
29
- const LayoutControl = ({ icon, label, ...props }: Omit<ButtonProps, 'children'> & { label: string; icon: string }) => {
30
- return <IconButton iconOnly icon={icon} label={label} tooltipSide='bottom' variant='ghost' {...props} />;
31
- };
32
-
33
- /**
34
- * @deprecated
35
- */
36
- export const LayoutControls = forwardRef<HTMLDivElement, LayoutControlsProps>(
37
- (
38
- { onClick, variant = 'default', capabilities: can, isSolo, pin, close = false, children, ...props },
39
- forwardedRef,
40
- ) => {
41
- const { t } = useTranslation(translationKey);
42
- const buttonClassNames = variant === 'hide-disabled' ? 'disabled:hidden !p-1' : '!p-1';
43
-
44
- return (
45
- <ButtonGroup {...props} ref={forwardedRef}>
46
- {pin && !isSolo && ['both', 'start'].includes(pin) && (
47
- <LayoutControl
48
- label={t('pin start label')}
49
- variant='ghost'
50
- classNames={buttonClassNames}
51
- onClick={() => onClick?.('pin-start')}
52
- icon='ph--caret-line-left--regular'
53
- />
54
- )}
55
-
56
- {can.solo && (
57
- <LayoutControl
58
- label={t('solo layout label')}
59
- classNames={buttonClassNames}
60
- onClick={() => onClick?.('solo')}
61
- icon={isSolo ? 'ph--arrows-in--regular' : 'ph--arrows-out--regular'}
62
- />
63
- )}
64
-
65
- {!isSolo && can.solo && (
66
- <>
67
- <LayoutControl
68
- label={t('increment start label')}
69
- disabled={!can.incrementStart}
70
- classNames={buttonClassNames}
71
- onClick={() => onClick?.('increment-start')}
72
- icon='ph--caret-left--regular'
73
- />
74
- <LayoutControl
75
- label={t('increment end label')}
76
- disabled={!can.incrementEnd}
77
- classNames={buttonClassNames}
78
- onClick={() => onClick?.('increment-end')}
79
- icon='ph--caret-right--regular'
80
- />
81
- </>
82
- )}
83
-
84
- {pin && !isSolo && ['both', 'end'].includes(pin) && (
85
- <LayoutControl
86
- label={t('pin end label')}
87
- classNames={buttonClassNames}
88
- onClick={() => onClick?.('pin-end')}
89
- icon='ph--caret-line-right--regular'
90
- />
91
- )}
92
-
93
- {close && !isSolo && (
94
- <LayoutControl
95
- label={t(`${typeof close === 'string' ? 'minify' : 'close'} label`)}
96
- classNames={buttonClassNames}
97
- onClick={() => onClick?.('close')}
98
- data-testid='layoutHeading.close'
99
- icon={
100
- close === 'minify-start'
101
- ? 'ph--caret-line-left--regular'
102
- : close === 'minify-end'
103
- ? 'ph--caret-line-right--regular'
104
- : 'ph--x--regular'
105
- }
106
- />
107
- )}
108
- {children}
109
- </ButtonGroup>
110
- );
111
- },
112
- );