@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.
Files changed (41) hide show
  1. package/dist/components/button/ConfirmedButton.js +2 -2
  2. package/dist/components/button/ConfirmedButton.js.map +1 -1
  3. package/dist/components/datePicker/DatePicker.d.ts +1 -1
  4. package/dist/components/datePicker/DatePicker.stories.d.ts +1 -1
  5. package/dist/components/datePicker/DateRangePicker.d.ts +1 -1
  6. package/dist/components/datePicker/DateRangePicker.js +15 -1
  7. package/dist/components/datePicker/DateRangePicker.js.map +1 -1
  8. package/dist/components/dialog/Dialog.d.ts +20 -34
  9. package/dist/components/dialog/Dialog.js +47 -208
  10. package/dist/components/dialog/Dialog.js.map +1 -1
  11. package/dist/components/dialog/Dialog.module.css +10 -82
  12. package/dist/components/dialog/Dialog.stories.js +8 -7
  13. package/dist/components/dialog/Dialog.stories.js.map +1 -1
  14. package/dist/components/drawer/Drawer.d.ts +25 -0
  15. package/dist/components/drawer/Drawer.js +102 -0
  16. package/dist/components/drawer/Drawer.js.map +1 -0
  17. package/dist/components/drawer/Drawer.module.css +182 -0
  18. package/dist/components/drawer/Drawer.stories.d.ts +7 -0
  19. package/dist/components/drawer/Drawer.stories.js +27 -0
  20. package/dist/components/drawer/Drawer.stories.js.map +1 -0
  21. package/dist/components/drawer/index.d.ts +1 -0
  22. package/dist/components/drawer/index.js +2 -0
  23. package/dist/components/drawer/index.js.map +1 -0
  24. package/dist/components/index.d.ts +1 -0
  25. package/dist/components/index.js +1 -0
  26. package/dist/components/index.js.map +1 -1
  27. package/dist/hooks/withContextVariant.d.ts +8 -0
  28. package/dist/hooks/withContextVariant.js +21 -0
  29. package/dist/hooks/withContextVariant.js.map +1 -0
  30. package/package.json +2 -2
  31. package/src/components/button/ConfirmedButton.tsx +9 -16
  32. package/src/components/datePicker/DateRangePicker.tsx +18 -1
  33. package/src/components/dialog/Dialog.module.css +10 -82
  34. package/src/components/dialog/Dialog.stories.tsx +45 -51
  35. package/src/components/dialog/Dialog.tsx +98 -332
  36. package/src/components/drawer/Drawer.module.css +181 -0
  37. package/src/components/drawer/Drawer.stories.tsx +68 -0
  38. package/src/components/drawer/Drawer.tsx +204 -0
  39. package/src/components/drawer/index.ts +1 -0
  40. package/src/components/index.ts +1 -0
  41. 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';
@@ -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
+ }