@a-type/ui 6.1.16 → 6.1.18
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/components/button/ConfirmedButton.js +2 -2
- package/dist/components/button/ConfirmedButton.js.map +1 -1
- package/dist/components/datePicker/DatePicker.d.ts +1 -1
- package/dist/components/datePicker/DatePicker.stories.d.ts +1 -1
- package/dist/components/datePicker/DateRangePicker.d.ts +1 -1
- package/dist/components/datePicker/DateRangePicker.js +15 -1
- package/dist/components/datePicker/DateRangePicker.js.map +1 -1
- package/dist/components/dialog/Dialog.d.ts +20 -34
- package/dist/components/dialog/Dialog.js +47 -208
- package/dist/components/dialog/Dialog.js.map +1 -1
- package/dist/components/dialog/Dialog.module.css +10 -82
- package/dist/components/dialog/Dialog.stories.js +8 -7
- package/dist/components/dialog/Dialog.stories.js.map +1 -1
- package/dist/components/drawer/Drawer.d.ts +25 -0
- package/dist/components/drawer/Drawer.js +102 -0
- package/dist/components/drawer/Drawer.js.map +1 -0
- package/dist/components/drawer/Drawer.module.css +182 -0
- package/dist/components/drawer/Drawer.stories.d.ts +7 -0
- package/dist/components/drawer/Drawer.stories.js +27 -0
- package/dist/components/drawer/Drawer.stories.js.map +1 -0
- package/dist/components/drawer/index.d.ts +1 -0
- package/dist/components/drawer/index.js +2 -0
- package/dist/components/drawer/index.js.map +1 -0
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/components/index.js.map +1 -1
- package/dist/hooks/withContextVariant.d.ts +8 -0
- package/dist/hooks/withContextVariant.js +21 -0
- package/dist/hooks/withContextVariant.js.map +1 -0
- package/package.json +2 -2
- package/src/components/button/ConfirmedButton.tsx +9 -16
- package/src/components/datePicker/DateRangePicker.tsx +18 -1
- package/src/components/dialog/Dialog.module.css +10 -82
- package/src/components/dialog/Dialog.stories.tsx +45 -51
- package/src/components/dialog/Dialog.tsx +98 -332
- package/src/components/drawer/Drawer.module.css +181 -0
- package/src/components/drawer/Drawer.stories.tsx +68 -0
- package/src/components/drawer/Drawer.tsx +204 -0
- package/src/components/drawer/index.ts +1 -0
- package/src/components/index.ts +1 -0
- package/src/hooks/withContextVariant.tsx +24 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
+
import { Button } from '../button/index.js';
|
|
3
|
+
import { H1, P } from '../typography/index.js';
|
|
4
|
+
import { Drawer } from './Drawer.js';
|
|
5
|
+
|
|
6
|
+
const meta: any = {
|
|
7
|
+
title: 'Components/Drawer',
|
|
8
|
+
component: Drawer,
|
|
9
|
+
argTypes: {},
|
|
10
|
+
parameters: {
|
|
11
|
+
controls: { expanded: true },
|
|
12
|
+
},
|
|
13
|
+
} satisfies Meta<typeof Drawer>;
|
|
14
|
+
|
|
15
|
+
export default meta;
|
|
16
|
+
|
|
17
|
+
type Story = StoryObj<typeof Drawer>;
|
|
18
|
+
|
|
19
|
+
function DummyContent() {
|
|
20
|
+
return (
|
|
21
|
+
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
|
22
|
+
<H1>Some content</H1>
|
|
23
|
+
<P>
|
|
24
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam at
|
|
25
|
+
porttitor sem. Aliquam erat volutpat. Donec fermentum tortor eget ligula
|
|
26
|
+
accumsan, sit amet ullamcorper nunc ultricies. Nulla facilisi.
|
|
27
|
+
</P>
|
|
28
|
+
<Button disabled color="primary">
|
|
29
|
+
Click me
|
|
30
|
+
</Button>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
children: (
|
|
38
|
+
<>
|
|
39
|
+
<Drawer.Trigger render={<Button />}>Open</Drawer.Trigger>
|
|
40
|
+
<Drawer.Content>
|
|
41
|
+
<Drawer.Title>Hello world</Drawer.Title>
|
|
42
|
+
<DummyContent />
|
|
43
|
+
<Drawer.Actions>
|
|
44
|
+
<Drawer.Close />
|
|
45
|
+
<Button emphasis="primary">Accept</Button>
|
|
46
|
+
</Drawer.Actions>
|
|
47
|
+
</Drawer.Content>
|
|
48
|
+
</>
|
|
49
|
+
),
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export const NoDefaultClose: Story = {
|
|
54
|
+
args: {
|
|
55
|
+
children: (
|
|
56
|
+
<>
|
|
57
|
+
<Drawer.Trigger render={<Button />}>Open</Drawer.Trigger>
|
|
58
|
+
<Drawer.Content disableDefaultClose>
|
|
59
|
+
<Drawer.Title>No default close</Drawer.Title>
|
|
60
|
+
<DummyContent />
|
|
61
|
+
<Drawer.Actions>
|
|
62
|
+
<Drawer.Close />
|
|
63
|
+
</Drawer.Actions>
|
|
64
|
+
</Drawer.Content>
|
|
65
|
+
</>
|
|
66
|
+
),
|
|
67
|
+
},
|
|
68
|
+
};
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Drawer as BaseDrawer,
|
|
3
|
+
DrawerCloseProps,
|
|
4
|
+
DrawerPopupProps,
|
|
5
|
+
DrawerRootProps,
|
|
6
|
+
DrawerTriggerProps,
|
|
7
|
+
} from '@base-ui/react/drawer';
|
|
8
|
+
import clsx from 'clsx';
|
|
9
|
+
import { ComponentPropsWithoutRef, Ref, useCallback, useRef } from 'react';
|
|
10
|
+
import useMergedRef from '../../hooks/useMergedRef.js';
|
|
11
|
+
import { withClassName } from '../../hooks/withClassName.js';
|
|
12
|
+
import { Box } from '../box/Box.js';
|
|
13
|
+
import { Button } from '../button/index.js';
|
|
14
|
+
import { Icon } from '../icon/Icon.js';
|
|
15
|
+
import { useParticles } from '../particles/ParticleContext.js';
|
|
16
|
+
import { ScrollArea } from '../scrollArea/ScrollArea.js';
|
|
17
|
+
import cls from './Drawer.module.css';
|
|
18
|
+
|
|
19
|
+
const DrawerOverlay = withClassName(BaseDrawer.Backdrop, cls.overlay);
|
|
20
|
+
|
|
21
|
+
const StyledPopup = withClassName(BaseDrawer.Popup, cls.popup);
|
|
22
|
+
|
|
23
|
+
export interface DrawerContentProps extends DrawerPopupProps {
|
|
24
|
+
disableDefaultClose?: boolean;
|
|
25
|
+
ref?: Ref<HTMLDivElement>;
|
|
26
|
+
innerClassName?: string;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const DrawerContent = function DrawerContent({
|
|
30
|
+
ref,
|
|
31
|
+
children,
|
|
32
|
+
className,
|
|
33
|
+
disableDefaultClose,
|
|
34
|
+
innerClassName,
|
|
35
|
+
...props
|
|
36
|
+
}: DrawerContentProps) {
|
|
37
|
+
const particles = useParticles();
|
|
38
|
+
const wasOpenRef = useRef(false);
|
|
39
|
+
|
|
40
|
+
const openRef = useCallback(
|
|
41
|
+
(element: HTMLDivElement | null) => {
|
|
42
|
+
if (!wasOpenRef.current && element?.hasAttribute('data-open')) {
|
|
43
|
+
wasOpenRef.current = true;
|
|
44
|
+
|
|
45
|
+
setTimeout(() => {
|
|
46
|
+
particles?.addParticles(
|
|
47
|
+
particles.elementExplosion({
|
|
48
|
+
count: 20,
|
|
49
|
+
margin: 40,
|
|
50
|
+
borders: ['top'],
|
|
51
|
+
color: [
|
|
52
|
+
{
|
|
53
|
+
space: 'rgb',
|
|
54
|
+
values: [0, 0, 0],
|
|
55
|
+
opacity: 0.02,
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
space: 'rgb',
|
|
59
|
+
values: [0, 0, 0],
|
|
60
|
+
opacity: 0,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
element,
|
|
64
|
+
startRadius: 15,
|
|
65
|
+
endRadius: 0,
|
|
66
|
+
lifespan: 1000,
|
|
67
|
+
force: 0.5,
|
|
68
|
+
drag: 0.01,
|
|
69
|
+
forceFuzz: 0.5,
|
|
70
|
+
angleFuzz: 0.1,
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
73
|
+
}, 180);
|
|
74
|
+
} else if (!element?.hasAttribute('data-open')) {
|
|
75
|
+
wasOpenRef.current = false;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
[particles],
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const finalRef = useMergedRef(ref, openRef);
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<BaseDrawer.Portal>
|
|
85
|
+
<DrawerOverlay />
|
|
86
|
+
<BaseDrawer.Viewport className={cls.viewport}>
|
|
87
|
+
<StyledPopup ref={finalRef} {...props} className={className}>
|
|
88
|
+
{!disableDefaultClose && <DrawerDefaultClose />}
|
|
89
|
+
<DrawerSwipeHandle />
|
|
90
|
+
<ScrollArea direction="vertical" className={cls.contentScrollArea}>
|
|
91
|
+
<ScrollArea.Content
|
|
92
|
+
className={clsx(cls.contentScrollAreaContent, innerClassName)}
|
|
93
|
+
style={{ minWidth: undefined }}
|
|
94
|
+
>
|
|
95
|
+
{children}
|
|
96
|
+
</ScrollArea.Content>
|
|
97
|
+
</ScrollArea>
|
|
98
|
+
</StyledPopup>
|
|
99
|
+
</BaseDrawer.Viewport>
|
|
100
|
+
</BaseDrawer.Portal>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
function DrawerSwipeHandle({
|
|
105
|
+
ref,
|
|
106
|
+
className,
|
|
107
|
+
...props
|
|
108
|
+
}: ComponentPropsWithoutRef<'div'> & {
|
|
109
|
+
ref?: React.Ref<HTMLDivElement>;
|
|
110
|
+
}) {
|
|
111
|
+
return (
|
|
112
|
+
<div ref={ref} {...props} className={clsx(cls.swipeHandle, className)}>
|
|
113
|
+
<div className={cls.swipeHandleBar} />
|
|
114
|
+
</div>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function DrawerDefaultClose({
|
|
119
|
+
ref,
|
|
120
|
+
className,
|
|
121
|
+
...props
|
|
122
|
+
}: DrawerCloseProps & {
|
|
123
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
124
|
+
}) {
|
|
125
|
+
return (
|
|
126
|
+
<DrawerClose
|
|
127
|
+
className={clsx(cls.close, className)}
|
|
128
|
+
aria-label="Close drawer"
|
|
129
|
+
ref={ref}
|
|
130
|
+
{...props}
|
|
131
|
+
render={<Button emphasis="ghost" size="small" />}
|
|
132
|
+
>
|
|
133
|
+
<Icon name="x" />
|
|
134
|
+
</DrawerClose>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const DrawerTitle = withClassName(BaseDrawer.Title, cls.title);
|
|
139
|
+
const DrawerDescription = withClassName(
|
|
140
|
+
BaseDrawer.Description,
|
|
141
|
+
cls.description,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
// TODO: support swipeDirection
|
|
145
|
+
export interface DrawerProps
|
|
146
|
+
extends Omit<DrawerRootProps, 'children' | 'swipeDirection'> {
|
|
147
|
+
children: React.ReactNode;
|
|
148
|
+
}
|
|
149
|
+
const defaultSnapPoints = [0.75, 1];
|
|
150
|
+
const DrawerRoot = ({
|
|
151
|
+
children,
|
|
152
|
+
defaultSnapPoint = 0.5,
|
|
153
|
+
snapPoints = defaultSnapPoints,
|
|
154
|
+
...props
|
|
155
|
+
}: DrawerProps) => {
|
|
156
|
+
return (
|
|
157
|
+
<BaseDrawer.Root
|
|
158
|
+
swipeDirection="down"
|
|
159
|
+
defaultSnapPoint={defaultSnapPoint}
|
|
160
|
+
snapPoints={snapPoints}
|
|
161
|
+
{...props}
|
|
162
|
+
>
|
|
163
|
+
<BaseDrawer.VirtualKeyboardProvider>
|
|
164
|
+
{children}
|
|
165
|
+
</BaseDrawer.VirtualKeyboardProvider>
|
|
166
|
+
</BaseDrawer.Root>
|
|
167
|
+
);
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const DrawerTrigger = ({ render, ...props }: DrawerTriggerProps) => (
|
|
171
|
+
<BaseDrawer.Trigger render={render || <Button />} {...props} />
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
function DrawerClose({
|
|
175
|
+
children,
|
|
176
|
+
render,
|
|
177
|
+
...props
|
|
178
|
+
}: DrawerCloseProps & {
|
|
179
|
+
ref?: React.Ref<HTMLButtonElement>;
|
|
180
|
+
}) {
|
|
181
|
+
return (
|
|
182
|
+
<BaseDrawer.Close
|
|
183
|
+
render={render ?? <Button emphasis="default" />}
|
|
184
|
+
{...props}
|
|
185
|
+
>
|
|
186
|
+
{children ?? 'Close'}
|
|
187
|
+
</BaseDrawer.Close>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const DrawerActions = withClassName(Box, cls.actions);
|
|
192
|
+
|
|
193
|
+
export const Drawer = Object.assign(DrawerRoot, {
|
|
194
|
+
Trigger: DrawerTrigger,
|
|
195
|
+
Content: DrawerContent,
|
|
196
|
+
Title: DrawerTitle,
|
|
197
|
+
Description: DrawerDescription,
|
|
198
|
+
Close: DrawerClose,
|
|
199
|
+
Actions: DrawerActions,
|
|
200
|
+
Unstyled: BaseDrawer as DrawerParts,
|
|
201
|
+
createHandle: BaseDrawer.createHandle,
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
export type DrawerParts = typeof BaseDrawer;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Drawer.js';
|
package/src/components/index.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from './combobox/Combobox.js';
|
|
|
14
14
|
export * from './contextMenu/contextMenu.js';
|
|
15
15
|
export * from './datePicker/index.js';
|
|
16
16
|
export * from './dialog/index.js';
|
|
17
|
+
export * from './drawer/index.js';
|
|
17
18
|
export * from './divider/index.js';
|
|
18
19
|
export * from './dropdownMenu/index.js';
|
|
19
20
|
export * from './editableText/EditableText.js';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createContext, useContext } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Creates a context and HOC which swaps between two components
|
|
5
|
+
* based on a contextual value
|
|
6
|
+
*/
|
|
7
|
+
export function createWithContextVariant() {
|
|
8
|
+
const Context = createContext(false);
|
|
9
|
+
function withContextVariant<P extends object>(
|
|
10
|
+
TrueComponent: React.ComponentType<P>,
|
|
11
|
+
FalseComponent: React.ComponentType<P>,
|
|
12
|
+
) {
|
|
13
|
+
return function WithContextVariant(props: P) {
|
|
14
|
+
const contextValue = useContext(Context);
|
|
15
|
+
const Component = contextValue ? TrueComponent : FalseComponent;
|
|
16
|
+
return <Component {...props} />;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
Context,
|
|
22
|
+
withContextVariant,
|
|
23
|
+
};
|
|
24
|
+
}
|