@a-type/ui 0.3.2 → 0.3.3

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 (148) hide show
  1. package/package.json +3 -2
  2. package/src/components/actions/ActionBar.tsx +38 -0
  3. package/src/components/actions/ActionButton.tsx +59 -0
  4. package/src/components/actions/index.ts +2 -0
  5. package/src/components/actions.ts +1 -0
  6. package/src/components/avatar/Avatar.tsx +62 -0
  7. package/src/components/avatar/AvatarList.tsx +71 -0
  8. package/src/components/avatar/index.ts +2 -0
  9. package/src/components/avatar.ts +1 -0
  10. package/src/components/button/Button.stories.tsx +20 -0
  11. package/src/components/button/Button.tsx +66 -0
  12. package/src/components/button/ConfirmedButton.tsx +66 -0
  13. package/src/components/button/classes.tsx +56 -0
  14. package/src/components/button/index.ts +3 -0
  15. package/src/components/button.ts +1 -0
  16. package/src/components/camera/Camera.stories.tsx +40 -0
  17. package/src/components/camera/Camera.tsx +215 -0
  18. package/src/components/camera/index.ts +1 -0
  19. package/src/components/camera.ts +1 -0
  20. package/src/components/card/Card.stories.tsx +41 -0
  21. package/src/components/card/Card.tsx +68 -0
  22. package/src/components/card/index.ts +1 -0
  23. package/src/components/card.ts +1 -0
  24. package/src/components/checkbox/Checkbox.tsx +46 -0
  25. package/src/components/checkbox/index.ts +1 -0
  26. package/src/components/checkbox.ts +1 -0
  27. package/src/components/chip/Chip.tsx +29 -0
  28. package/src/components/chip/index.ts +1 -0
  29. package/src/components/chip.ts +1 -0
  30. package/src/components/collapsible/Collapsible.tsx +48 -0
  31. package/src/components/collapsible/index.ts +1 -0
  32. package/src/components/collapsible.ts +1 -0
  33. package/src/components/colorPicker/ColorPicker.tsx +82 -0
  34. package/src/components/colorPicker/index.ts +1 -0
  35. package/src/components/colorPicker.ts +1 -0
  36. package/src/components/contextMenu/contextMenu.tsx +43 -0
  37. package/src/components/contextMenu.ts +1 -0
  38. package/src/components/dialog/Dialog.stories.tsx +38 -0
  39. package/src/components/dialog/Dialog.tsx +267 -0
  40. package/src/components/dialog/index.ts +1 -0
  41. package/src/components/dialog.ts +1 -0
  42. package/src/components/divider/Divider.tsx +26 -0
  43. package/src/components/divider/index.ts +1 -0
  44. package/src/components/divider.ts +1 -0
  45. package/src/components/dropdownMenu/DropdownMenu.stories.tsx +47 -0
  46. package/src/components/dropdownMenu/DropdownMenu.tsx +89 -0
  47. package/src/components/dropdownMenu/index.ts +1 -0
  48. package/src/components/dropdownMenu.ts +1 -0
  49. package/src/components/errorBoundary/ErrorBoundary.tsx +23 -0
  50. package/src/components/errorBoundary/index.ts +1 -0
  51. package/src/components/errorBoundary.ts +1 -0
  52. package/src/components/forms/Form.tsx +9 -0
  53. package/src/components/forms/FormikForm.tsx +41 -0
  54. package/src/components/forms/SubmitButton.tsx +15 -0
  55. package/src/components/forms/TextField.tsx +112 -0
  56. package/src/components/forms/index.tsx +4 -0
  57. package/src/components/forms.ts +1 -0
  58. package/src/components/icon/Icon.tsx +28 -0
  59. package/src/components/icon/generated/IconSpritesheet.tsx +442 -0
  60. package/src/components/icon/generated/iconNames.ts +44 -0
  61. package/src/components/icon/index.ts +3 -0
  62. package/src/components/icon.ts +1 -0
  63. package/src/components/imageUploader/ImageUploader.stories.tsx +39 -0
  64. package/src/components/imageUploader/ImageUploader.tsx +203 -0
  65. package/src/components/imageUploader/UploadIcon.tsx +23 -0
  66. package/src/components/imageUploader/index.ts +1 -0
  67. package/src/components/imageUploader.ts +1 -0
  68. package/src/components/infiniteLoadTrigger/InfiniteLoadTrigger.tsx +38 -0
  69. package/src/components/infiniteLoadTrigger.ts +1 -0
  70. package/src/components/input/Input.stories.tsx +17 -0
  71. package/src/components/input/Input.tsx +32 -0
  72. package/src/components/input/index.ts +1 -0
  73. package/src/components/input.ts +1 -0
  74. package/src/components/layouts/PageContent.tsx +51 -0
  75. package/src/components/layouts/PageFixedArea.tsx +17 -0
  76. package/src/components/layouts/PageNav.tsx +23 -0
  77. package/src/components/layouts/PageNowPlaying.tsx +24 -0
  78. package/src/components/layouts/PageRoot.tsx +29 -0
  79. package/src/components/layouts/PageSection.tsx +23 -0
  80. package/src/components/layouts/index.tsx +6 -0
  81. package/src/components/layouts.ts +1 -0
  82. package/src/components/liveUpdateTextField/LiveUpdateTextField.tsx +132 -0
  83. package/src/components/liveUpdateTextField/index.ts +1 -0
  84. package/src/components/liveUpdateTextField.ts +1 -0
  85. package/src/components/navBar/NavBar.tsx +59 -0
  86. package/src/components/navBar/index.ts +1 -0
  87. package/src/components/navBar.ts +1 -0
  88. package/src/components/note/Note.tsx +21 -0
  89. package/src/components/note/index.ts +1 -0
  90. package/src/components/note.ts +1 -0
  91. package/src/components/numberStepper/NumberStepper.stories.tsx +21 -0
  92. package/src/components/numberStepper/NumberStepper.tsx +74 -0
  93. package/src/components/numberStepper/index.ts +1 -0
  94. package/src/components/numberStepper.ts +1 -0
  95. package/src/components/particles/ParticleContext.tsx +11 -0
  96. package/src/components/particles/ParticleLayer.stories.tsx +46 -0
  97. package/src/components/particles/ParticleLayer.tsx +28 -0
  98. package/src/components/particles/index.ts +7 -0
  99. package/src/components/particles/particlesState.ts +502 -0
  100. package/src/components/particles.ts +1 -0
  101. package/src/components/peek/Peek.tsx +74 -0
  102. package/src/components/peek/index.ts +1 -0
  103. package/src/components/peek.ts +1 -0
  104. package/src/components/popover/Popover.tsx +84 -0
  105. package/src/components/popover/index.ts +1 -0
  106. package/src/components/popover.ts +1 -0
  107. package/src/components/relativeTime/RelativeTime.tsx +43 -0
  108. package/src/components/relativeTime/index.ts +1 -0
  109. package/src/components/relativeTime.ts +1 -0
  110. package/src/components/richEditor/EditorContent.tsx +4 -0
  111. package/src/components/richEditor/RichEditor.tsx +38 -0
  112. package/src/components/richEditor/index.ts +1 -0
  113. package/src/components/richEditor.ts +1 -0
  114. package/src/components/select/Select.tsx +247 -0
  115. package/src/components/select/index.ts +1 -0
  116. package/src/components/select.ts +1 -0
  117. package/src/components/skeletons/skeletons.tsx +27 -0
  118. package/src/components/skeletons.ts +1 -0
  119. package/src/components/spinner/Spinner.tsx +59 -0
  120. package/src/components/spinner/index.ts +1 -0
  121. package/src/components/spinner.ts +1 -0
  122. package/src/components/switch/Switch.tsx +23 -0
  123. package/src/components/switch/index.ts +1 -0
  124. package/src/components/switch.ts +1 -0
  125. package/src/components/tabs/tabs.tsx +18 -0
  126. package/src/components/tabs.ts +1 -0
  127. package/src/components/textArea/TextArea.stories.tsx +21 -0
  128. package/src/components/textArea/TextArea.tsx +58 -0
  129. package/src/components/textArea/index.ts +1 -0
  130. package/src/components/textArea.ts +1 -0
  131. package/src/components/toggleGroup/toggleGroup.tsx +11 -0
  132. package/src/components/toggleGroup.ts +1 -0
  133. package/src/components/tooltip/Tooltip.tsx +56 -0
  134. package/src/components/tooltip/index.ts +1 -0
  135. package/src/components/tooltip.ts +1 -0
  136. package/src/components/typography/index.ts +1 -0
  137. package/src/components/typography/typography.tsx +18 -0
  138. package/src/components/typography.ts +1 -0
  139. package/src/hooks/index.ts +7 -0
  140. package/src/hooks/useMergedRef.ts +14 -0
  141. package/src/hooks/useOnUnmount.ts +20 -0
  142. package/src/hooks/useSize.ts +164 -0
  143. package/src/hooks/useStableCallback.ts +11 -0
  144. package/src/hooks/useToggle.tsx +9 -0
  145. package/src/hooks/useVisualViewportOffset.ts +35 -0
  146. package/src/hooks/withClassName.tsx +21 -0
  147. package/src/hooks.ts +1 -0
  148. package/src/uno.preset.ts +767 -0
@@ -0,0 +1,215 @@
1
+ import classNames from 'classnames';
2
+ import {
3
+ MouseEvent,
4
+ ReactNode,
5
+ createContext,
6
+ forwardRef,
7
+ useContext,
8
+ useEffect,
9
+ useRef,
10
+ useState,
11
+ } from 'react';
12
+ import { Button } from '../button.js';
13
+ import { Icon } from '../icon.js';
14
+ import { Select, SelectContent, SelectItem, SelectTrigger } from '../select.js';
15
+ import { Slot } from '@radix-ui/react-slot';
16
+ import { withClassName } from '../../hooks.js';
17
+
18
+ const CameraContext = createContext<{
19
+ triggerCapture: () => void;
20
+ selectedDeviceId: string | undefined;
21
+ selectDeviceId: (id: string) => void;
22
+ devices: MediaDeviceInfo[];
23
+ }>({
24
+ triggerCapture: () => {},
25
+ selectedDeviceId: 'default',
26
+ selectDeviceId: () => {},
27
+ devices: [],
28
+ });
29
+
30
+ export interface CameraRootProps {
31
+ className?: string;
32
+ onCapture?: (data: string) => void;
33
+ children?: ReactNode;
34
+ format?: 'image/png' | 'image/jpeg';
35
+ }
36
+
37
+ export const CameraRoot = forwardRef<HTMLDivElement, CameraRootProps>(
38
+ function Camera(
39
+ { className, onCapture, children, format = 'image/png', ...rest },
40
+ ref,
41
+ ) {
42
+ const videoRef = useRef<HTMLVideoElement>(null);
43
+
44
+ const triggerCapture = () => {
45
+ const video = videoRef.current;
46
+ if (video) {
47
+ const canvas = document.createElement('canvas');
48
+ canvas.width = video.videoWidth;
49
+ canvas.height = video.videoHeight;
50
+ canvas.getContext('2d')?.drawImage(video, 0, 0);
51
+ const data = canvas.toDataURL(format);
52
+ onCapture?.(data);
53
+ }
54
+ };
55
+
56
+ const [devices, setDevices] = useState<MediaDeviceInfo[]>([]);
57
+ useEffect(() => {
58
+ navigator.mediaDevices.enumerateDevices().then((devices): void => {
59
+ setDevices(devices.filter((device) => device.kind === 'videoinput'));
60
+ });
61
+ }, []);
62
+ const [selectedDeviceId, setSelectedDeviceId] = useState<
63
+ string | undefined
64
+ >();
65
+ const [stream, setStream] = useState<MediaStream | undefined>();
66
+ useEffect(() => {
67
+ navigator.mediaDevices
68
+ .getUserMedia({
69
+ video: {
70
+ deviceId: selectedDeviceId,
71
+ },
72
+ })
73
+ .then((s) => {
74
+ setStream(s);
75
+ });
76
+ }, [selectedDeviceId]);
77
+ useEffect(() => {
78
+ return () => {
79
+ stream?.getTracks().forEach((track) => track.stop());
80
+ };
81
+ }, [stream]);
82
+
83
+ useEffect(() => {
84
+ const video = videoRef.current;
85
+ if (video && stream) {
86
+ video.srcObject = stream;
87
+ return () => {
88
+ video.srcObject = null;
89
+ };
90
+ }
91
+ }, [stream]);
92
+
93
+ return (
94
+ <CameraContext.Provider
95
+ value={{
96
+ devices,
97
+ triggerCapture,
98
+ selectedDeviceId,
99
+ selectDeviceId: setSelectedDeviceId,
100
+ }}
101
+ >
102
+ <div
103
+ ref={ref}
104
+ className={classNames(
105
+ 'layer-components:([font-family:inherit] text-white bg-black rounded-lg overflow-hidden min-w-4 min-h-4 relative)',
106
+ className,
107
+ )}
108
+ {...rest}
109
+ >
110
+ <video
111
+ ref={videoRef}
112
+ className="w-full h-full object-cover"
113
+ autoPlay
114
+ muted
115
+ playsInline
116
+ ></video>
117
+ {children}
118
+ </div>
119
+ </CameraContext.Provider>
120
+ );
121
+ },
122
+ );
123
+
124
+ export interface CameraShutterButtonProps {
125
+ className?: string;
126
+ asChild?: boolean;
127
+ onClick?: (ev: MouseEvent<HTMLButtonElement>) => void;
128
+ }
129
+
130
+ export const CameraShutterButton = forwardRef<
131
+ HTMLButtonElement,
132
+ CameraShutterButtonProps
133
+ >(function CameraShutterButton({ asChild, onClick, ...rest }, ref) {
134
+ const Comp = asChild ? Slot : StyledShutterButton;
135
+ const { triggerCapture } = useContext(CameraContext);
136
+
137
+ return (
138
+ <Comp
139
+ ref={ref}
140
+ aria-label={asChild ? undefined : 'Capture photo'}
141
+ onClick={(ev) => {
142
+ triggerCapture();
143
+ onClick?.(ev);
144
+ }}
145
+ {...rest}
146
+ />
147
+ );
148
+ });
149
+
150
+ const StyledShutterButton = withClassName(
151
+ 'button',
152
+ 'absolute bottom-3 left-1/2 -translate-x-1/2 w-16 h-16 bg-white rounded-full cursor-pointer border-2 border-black border-solid ring-2 ring-white opacity-80',
153
+ 'hover:bg-gray-1 hover:opacity-100',
154
+ 'focus-visible:bg-gray-2',
155
+ 'focus:ring-primary focus:outline-none focus:opacity-100',
156
+ 'sm:w-8 sm:h-8',
157
+ );
158
+
159
+ export interface CameraDeviceSelectorProps {}
160
+
161
+ export const CameraDeviceSelector = (props: CameraDeviceSelectorProps) => {
162
+ const { devices, selectDeviceId, selectedDeviceId } =
163
+ useContext(CameraContext);
164
+ const swapCamera = () => {
165
+ if (selectedDeviceId) {
166
+ const index = devices.findIndex(
167
+ (device) => device.deviceId === selectedDeviceId,
168
+ );
169
+ if (index === -1) {
170
+ return;
171
+ }
172
+ selectDeviceId(devices[(index + 1) % devices.length].deviceId);
173
+ } else {
174
+ selectDeviceId(devices[0].deviceId);
175
+ }
176
+ };
177
+
178
+ if (!devices.length || devices.length === 1) return null;
179
+ if (devices.length === 2) {
180
+ return (
181
+ <Button
182
+ size="icon"
183
+ color="ghost"
184
+ className="absolute bottom-2 left-2 text-white"
185
+ onClick={swapCamera}
186
+ >
187
+ <Icon name="refresh" />
188
+ </Button>
189
+ );
190
+ }
191
+
192
+ return (
193
+ <Select
194
+ value={selectedDeviceId || 'default'}
195
+ onValueChange={selectDeviceId}
196
+ >
197
+ <SelectTrigger asChild>
198
+ <Button
199
+ size="icon"
200
+ color="ghost"
201
+ className="absolute bottom-2 left-2 text-white"
202
+ >
203
+ <Icon name="refresh" />
204
+ </Button>
205
+ </SelectTrigger>
206
+ <SelectContent>
207
+ {devices.map((device) => (
208
+ <SelectItem key={device.deviceId} value={device.deviceId}>
209
+ {device.label}
210
+ </SelectItem>
211
+ ))}
212
+ </SelectContent>
213
+ </Select>
214
+ );
215
+ };
@@ -0,0 +1 @@
1
+ export * from './Camera.js';
@@ -0,0 +1 @@
1
+ export * from './camera/index.js';
@@ -0,0 +1,41 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import {
3
+ CardActions,
4
+ CardFooter,
5
+ CardMain,
6
+ CardRoot,
7
+ CardTitle,
8
+ } from './Card.js';
9
+ import { Button } from '../button.js';
10
+ import { Icon } from '../icon.js';
11
+
12
+ const meta = {
13
+ title: 'Card',
14
+ component: CardRoot,
15
+ argTypes: {},
16
+ parameters: {
17
+ controls: { expanded: true },
18
+ },
19
+ } satisfies Meta<typeof CardRoot>;
20
+
21
+ export default meta;
22
+
23
+ type Story = StoryObj<typeof CardRoot>;
24
+
25
+ export const Default: Story = {
26
+ render: () => (
27
+ <CardRoot>
28
+ <CardMain>
29
+ <CardTitle>Card Title</CardTitle>
30
+ </CardMain>
31
+ <CardFooter>
32
+ <CardActions>
33
+ <Button size="small">Button</Button>
34
+ <Button size="icon" color="ghost">
35
+ <Icon name="placeholder" />
36
+ </Button>
37
+ </CardActions>
38
+ </CardFooter>
39
+ </CardRoot>
40
+ ),
41
+ };
@@ -0,0 +1,68 @@
1
+ import { MouseEvent, ReactNode, forwardRef } from 'react';
2
+ import { withClassName } from '../../hooks.js';
3
+ import { Slot } from '@radix-ui/react-slot';
4
+ import classNames from 'classnames';
5
+
6
+ export const CardRoot = withClassName(
7
+ 'div',
8
+ 'layer-components:(flex flex-col border-light rounded-lg text-lg overflow-hidden h-max-content relative bg-gray-1)',
9
+ );
10
+
11
+ export const CardMain = forwardRef<
12
+ any,
13
+ {
14
+ asChild?: boolean;
15
+ className?: string;
16
+ onClick?: (ev: MouseEvent) => void;
17
+ children?: ReactNode;
18
+ compact?: boolean;
19
+ }
20
+ >(function CardMain({ asChild, className, compact, ...rest }, ref) {
21
+ const Comp = asChild ? Slot : 'button';
22
+ return (
23
+ <Comp
24
+ ref={ref}
25
+ className={classNames(
26
+ 'layer-components:(flex flex-col gap-1 cursor-pointer transition p-4 pb-2 flex-1 relative z-1 bg-transparent border-none text-start)',
27
+ 'layer-components:hover:(bg-lightBlend color-black)',
28
+ 'layer-components:md:pt-4',
29
+ compact && 'layer-variants:(p-1 bg-white gap-0)',
30
+ className,
31
+ )}
32
+ data-compact={compact}
33
+ {...rest}
34
+ />
35
+ );
36
+ });
37
+
38
+ export const CardTitle = withClassName(
39
+ 'div',
40
+ 'layer-components:(flex flex-col gap-1 mt-auto bg-white p-2 rounded-lg w-auto mr-auto border border-solid border-grayDarkBlend text-md max-h-80px overflow-hidden text-ellipsis max-w-full)',
41
+ '[data-compact=true]>&:(bg-transparent border-none p-2 whitespace-nowrap text-ellipsis overflow-hidden)',
42
+ );
43
+
44
+ export const CardImage = withClassName(
45
+ 'div',
46
+ 'layer-components:(absolute z-0 right-0 top-0 bottom-0 w-full h-full)',
47
+ );
48
+
49
+ export const CardFooter = withClassName(
50
+ 'div',
51
+ 'layer-components:(flex flex-row p-2 bg-white relative z-1 border-0 border-t border-t-grayDarkBlend border-solid)',
52
+ );
53
+
54
+ export const CardActions = withClassName(
55
+ 'div',
56
+ 'layer-components:(ml-0 mr-auto flex flex-row gap-1 items-center)',
57
+ );
58
+
59
+ export const CardMenu = withClassName(
60
+ 'div',
61
+ 'layer-components:(mr-0 ml-auto flex flex-row gap-1 items-center)',
62
+ );
63
+
64
+ export const CardGrid = withClassName(
65
+ 'div',
66
+ 'layer-components:(grid grid-cols-[1fr] [grid-auto-rows:auto] gap-4 p-0 m-0)',
67
+ 'layer-components:md:(grid-cols-[repeat(2,1fr)] [grid-auto-rows:1fr] items-end)',
68
+ );
@@ -0,0 +1 @@
1
+ export * from './Card.js';
@@ -0,0 +1 @@
1
+ export * from './card/index.js';
@@ -0,0 +1,46 @@
1
+ 'use client';
2
+
3
+ import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
4
+ import { ComponentProps, forwardRef } from 'react';
5
+ import { CheckIcon } from '@radix-ui/react-icons';
6
+ import classNames from 'classnames';
7
+ import { withClassName } from '../../hooks/withClassName.js';
8
+
9
+ export const CheckboxRoot = withClassName(
10
+ CheckboxPrimitive.Root,
11
+ classNames(
12
+ 'layer-components:(w-28px h-28px flex-shrink-0 relative bg-white border-default transition rounded-full)',
13
+ 'layer-components:focus-visible:(outline-off shadow-focus)',
14
+ 'layer-components:[&[data-state=checked]]:(bg-primary-light border-primary-dark)',
15
+ 'layer-components:[&:hover:not(:disabled)]:shadow-[0_0_0_1px_var(--color-black)]',
16
+ ),
17
+ );
18
+
19
+ export function CheckboxIndicator({
20
+ children,
21
+ className,
22
+ ...props
23
+ }: CheckboxPrimitive.CheckboxIndicatorProps) {
24
+ return (
25
+ <CheckboxPrimitive.Indicator
26
+ className={classNames(
27
+ 'absolute center translate-[-50%] color-black',
28
+ className,
29
+ )}
30
+ {...props}
31
+ >
32
+ {children ?? <CheckIcon width={18} height={18} />}
33
+ </CheckboxPrimitive.Indicator>
34
+ );
35
+ }
36
+
37
+ export const Checkbox = forwardRef<
38
+ HTMLButtonElement,
39
+ ComponentProps<typeof CheckboxRoot>
40
+ >(function Checkbox(props, ref) {
41
+ return (
42
+ <CheckboxRoot ref={ref} {...props}>
43
+ <CheckboxIndicator />
44
+ </CheckboxRoot>
45
+ );
46
+ });
@@ -0,0 +1 @@
1
+ export * from './Checkbox.js';
@@ -0,0 +1 @@
1
+ export * from './checkbox/index.js';
@@ -0,0 +1,29 @@
1
+ import { Slot } from '@radix-ui/react-slot';
2
+ import classNames from 'classnames';
3
+ import { HTMLAttributes, forwardRef } from 'react';
4
+
5
+ export interface ChipProps extends HTMLAttributes<HTMLElement> {
6
+ color?: 'neutral' | 'primary' | 'accent';
7
+ asChild?: boolean;
8
+ }
9
+
10
+ export const Chip = forwardRef<any, ChipProps>(function Chip(
11
+ { className, color = 'neutral', asChild, ...rest },
12
+ ref,
13
+ ) {
14
+ const Component = asChild ? Slot : 'div';
15
+ return (
16
+ <Component
17
+ ref={ref}
18
+ className={classNames(
19
+ 'inline-flex flex-row gap-1 items-center whitespace-nowrap border-light border-solid border-1 rounded-full px-2 py-1',
20
+ {
21
+ 'bg-primary-wash': color === 'primary',
22
+ 'bg-accent-wash': color === 'accent',
23
+ },
24
+ className,
25
+ )}
26
+ {...rest}
27
+ />
28
+ );
29
+ });
@@ -0,0 +1 @@
1
+ export * from './Chip.js';
@@ -0,0 +1 @@
1
+ export * from './chip/index.js';
@@ -0,0 +1,48 @@
1
+ 'use client';
2
+
3
+ import { forwardRef } from 'react';
4
+ import { withClassName } from '../../hooks/withClassName.js';
5
+ import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
6
+
7
+ export const CollapsibleRoot = CollapsiblePrimitive.Root;
8
+ const CollapsibleContentBase = withClassName(
9
+ CollapsiblePrimitive.Content,
10
+ 'overflow-hidden animate-forwards',
11
+ 'layer-components:[&[data-state=open]]:(animate-radix-collapsible-open-vertical animate-duration-300 animate-ease-springy) layer-components:[&[data-state=closed]]:(animate-radix-collapsible-close-vertical animate-duration-300 animate-ease-springy)',
12
+ 'layer-variants:[&[data-horizontal][data-state=open]]:(animate-radix-collapsible-open-horizontal animate-duration-300 animate-ease-springy) layer-variants:[&[data-horizontal][data-state=closed]]:(animate-radix-collapsible-close-horizontal animate-duration-300 animate-ease-springy)',
13
+ 'layer-variants:[&[data-both][data-state=open]]:(animate-radix-collapsible-open-both animate-duration-300 animate-ease-springy) layer-variants:[&[data-both][data-state=closed]]:(animate-radix-collapsible-close-both animate-duration-300 animate-ease-springy)',
14
+ );
15
+ // specifically removing className... it's causing problems?
16
+ export const CollapsibleContent = forwardRef<
17
+ HTMLDivElement,
18
+ CollapsiblePrimitive.CollapsibleContentProps & {
19
+ horizontal?: boolean;
20
+ both?: boolean;
21
+ }
22
+ >(function CollapsibleContent({ horizontal, both, ...props }, ref) {
23
+ return (
24
+ <CollapsibleContentBase
25
+ data-horizontal={horizontal}
26
+ data-both={both}
27
+ {...props}
28
+ ref={ref}
29
+ />
30
+ );
31
+ });
32
+ export const CollapsibleTrigger = CollapsiblePrimitive.Trigger;
33
+
34
+ export const CollapsibleSimple = ({
35
+ horizontal,
36
+ both,
37
+ children,
38
+ ...props
39
+ }: CollapsiblePrimitive.CollapsibleProps & {
40
+ horizontal?: boolean;
41
+ both?: boolean;
42
+ }) => (
43
+ <CollapsibleRoot {...props}>
44
+ <CollapsibleContent horizontal={horizontal} both={both}>
45
+ {children}
46
+ </CollapsibleContent>
47
+ </CollapsibleRoot>
48
+ );
@@ -0,0 +1 @@
1
+ export * from './Collapsible.js';
@@ -0,0 +1 @@
1
+ export * from './collapsible/index.js';
@@ -0,0 +1,82 @@
1
+ 'use client';
2
+
3
+ import {
4
+ Select,
5
+ SelectContent,
6
+ SelectItem,
7
+ SelectTrigger,
8
+ SelectValue,
9
+ } from '../select/Select.js';
10
+ import classNames from 'classnames';
11
+ import { ReactNode } from 'react';
12
+ import { withClassName } from '../../hooks/withClassName.js';
13
+
14
+ export type ThemeName = 'lemon' | 'tomato' | 'leek' | 'blueberry' | 'eggplant';
15
+
16
+ export interface ColorPickerProps {
17
+ value: ThemeName | null;
18
+ onChange: (value: ThemeName) => void;
19
+ }
20
+
21
+ export function ColorPicker({ value, onChange }: ColorPickerProps) {
22
+ const resolvedValue = [
23
+ 'lemon',
24
+ 'tomato',
25
+ 'leek',
26
+ 'blueberry',
27
+ 'eggplant',
28
+ ].includes(value || '')
29
+ ? (value as ThemeName)
30
+ : 'lemon';
31
+
32
+ return (
33
+ <Select value={resolvedValue} onValueChange={onChange}>
34
+ <SelectTrigger>
35
+ <SelectValue />
36
+ </SelectTrigger>
37
+ <SelectContent className="z-[calc(var(--z-dialog)+1)]">
38
+ <SelectItem value="lemon">
39
+ <ColorSwatch value="lemon" />
40
+ <ItemLabel>Lemon</ItemLabel>
41
+ </SelectItem>
42
+ <SelectItem value="tomato">
43
+ <ColorSwatch value="tomato" />
44
+ <ItemLabel>Tomato</ItemLabel>
45
+ </SelectItem>
46
+ <SelectItem value="leek">
47
+ <ColorSwatch value="leek" />
48
+ <ItemLabel>Leek</ItemLabel>
49
+ </SelectItem>
50
+ <SelectItem value="blueberry">
51
+ <ColorSwatch value="blueberry" />
52
+ <ItemLabel>Blueberry</ItemLabel>
53
+ </SelectItem>
54
+ <SelectItem value="eggplant">
55
+ <ColorSwatch value="eggplant" />
56
+ <ItemLabel>Eggplant</ItemLabel>
57
+ </SelectItem>
58
+ </SelectContent>
59
+ </Select>
60
+ );
61
+ }
62
+
63
+ const ItemLabel = withClassName('span', 'display-none');
64
+
65
+ export function ColorSwatch({
66
+ value,
67
+ children,
68
+ }: {
69
+ value: ThemeName;
70
+ children?: ReactNode;
71
+ }) {
72
+ return (
73
+ <div
74
+ className={classNames(
75
+ 'bg-primary w-16px h-16px rounded-sm',
76
+ `theme-${value ?? 'lemon'}`,
77
+ )}
78
+ >
79
+ {children}
80
+ </div>
81
+ );
82
+ }
@@ -0,0 +1 @@
1
+ export * from './ColorPicker.js';
@@ -0,0 +1 @@
1
+ export * from './colorPicker/index.js';
@@ -0,0 +1,43 @@
1
+ import * as ContextMenu from '@radix-ui/react-context-menu';
2
+ import { ComponentPropsWithoutRef, forwardRef } from 'react';
3
+ import { withClassName } from '../../hooks/withClassName.js';
4
+ import classNames from 'classnames';
5
+
6
+ export const ContextMenuRoot = ContextMenu.Root;
7
+
8
+ export const ContextMenuContent = forwardRef<
9
+ HTMLDivElement,
10
+ ComponentPropsWithoutRef<typeof ContextMenu.Content>
11
+ >(function Content({ className, onClick, ...props }, ref) {
12
+ return (
13
+ <ContextMenu.Portal>
14
+ <ContextMenu.Content
15
+ className={classNames(
16
+ 'layer-components:(min-w-120px bg-white rounded-md border-default overflow-hidden p-2 shadow-md z-menu)',
17
+ 'layer-components:transform-origin-[var(--radix-context-menu-transform-origin)]',
18
+ 'layer-components:[&[data-state=open]]:animate-popover-in',
19
+ 'layer-components:[&[data-state=closed]]:animate-popover-out',
20
+ 'layer-components:(max-h-[var(--radix-context-menu-content-available-height)] overflow-y-auto)',
21
+ 'important:motion-reduce:animate-none',
22
+ className,
23
+ )}
24
+ onClick={(ev) => {
25
+ ev.stopPropagation();
26
+ onClick?.(ev);
27
+ }}
28
+ ref={ref}
29
+ {...props}
30
+ />
31
+ </ContextMenu.Portal>
32
+ );
33
+ });
34
+
35
+ export const ContextMenuArrow = withClassName(ContextMenu.Arrow, 'fill-white');
36
+
37
+ export const ContextMenuItem = withClassName(
38
+ ContextMenu.Item,
39
+ 'flex items-center py-1 px-2 relative pl-25px select-none outline-none cursor-pointer',
40
+ 'hover:bg-gray2 [&[data-highlighted=true]]:bg-gray2 [&[data-disabled=true]]:(opacity-50 cursor-default) disabled:(opacity-50 cursor-default)',
41
+ );
42
+
43
+ export const ContextMenuTrigger = withClassName(ContextMenu.Trigger, '');
@@ -0,0 +1 @@
1
+ export * from './contextMenu/contextMenu.js';
@@ -0,0 +1,38 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import {
3
+ Dialog,
4
+ DialogContent,
5
+ DialogTrigger,
6
+ DialogActions,
7
+ DialogClose,
8
+ DialogTitle,
9
+ } from './Dialog.js';
10
+
11
+ const meta = {
12
+ title: 'Dialog',
13
+ component: Dialog,
14
+ argTypes: {},
15
+ parameters: {
16
+ controls: { expanded: true },
17
+ },
18
+ } satisfies Meta<typeof Dialog>;
19
+
20
+ export default meta;
21
+
22
+ type Story = StoryObj<typeof Dialog>;
23
+
24
+ export const Default: Story = {
25
+ args: {
26
+ children: (
27
+ <>
28
+ <DialogTrigger>Open</DialogTrigger>
29
+ <DialogContent>
30
+ <DialogTitle>Hello world</DialogTitle>
31
+ <DialogActions>
32
+ <DialogClose>Close</DialogClose>
33
+ </DialogActions>
34
+ </DialogContent>
35
+ </>
36
+ ),
37
+ },
38
+ };