@boyernick/standard-ui-react 0.1.1-canary.2 → 0.1.1-canary.22

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 (56) hide show
  1. package/package.json +5 -3
  2. package/src/accordion.tsx +1 -1
  3. package/src/alert-dialog.tsx +1 -1
  4. package/src/autocomplete.tsx +12 -11
  5. package/src/badge.tsx +73 -9
  6. package/src/brand.tsx +2 -2
  7. package/src/breadcrumb.tsx +38 -20
  8. package/src/button.tsx +2 -2
  9. package/src/calendar.tsx +22 -11
  10. package/src/card.tsx +57 -14
  11. package/src/carousel.tsx +163 -6
  12. package/src/checkbox.tsx +35 -13
  13. package/src/collapsible.tsx +4 -2
  14. package/src/combobox.tsx +13 -12
  15. package/src/command.tsx +38 -14
  16. package/src/context-menu.tsx +6 -3
  17. package/src/date-picker.tsx +174 -0
  18. package/src/dialog.tsx +33 -10
  19. package/src/drawer.tsx +1 -1
  20. package/src/empty.tsx +4 -4
  21. package/src/field.tsx +1 -1
  22. package/src/filter-group.tsx +139 -0
  23. package/src/icons.tsx +39 -0
  24. package/src/illustrations.tsx +219 -141
  25. package/src/image-modal.tsx +440 -49
  26. package/src/index.ts +188 -0
  27. package/src/input.tsx +1 -1
  28. package/src/kbd.tsx +49 -0
  29. package/src/lib/motion.ts +128 -18
  30. package/src/lib/popup.ts +45 -0
  31. package/src/menu.tsx +7 -4
  32. package/src/menubar.tsx +5 -0
  33. package/src/meter.tsx +1 -1
  34. package/src/minimap.tsx +267 -0
  35. package/src/navigation-menu.tsx +336 -67
  36. package/src/number-field.tsx +327 -61
  37. package/src/pagination.tsx +258 -42
  38. package/src/popover.tsx +3 -1
  39. package/src/preview-card.tsx +3 -1
  40. package/src/progress.tsx +6 -1
  41. package/src/questionnaire.tsx +279 -0
  42. package/src/scroll-area.tsx +1 -1
  43. package/src/select.tsx +8 -6
  44. package/src/sidebar.tsx +109 -28
  45. package/src/slider.tsx +64 -6
  46. package/src/sounds.tsx +6 -10
  47. package/src/spinner.tsx +105 -32
  48. package/src/switch.tsx +2 -2
  49. package/src/table.tsx +82 -15
  50. package/src/tabs.tsx +184 -38
  51. package/src/text-animate.tsx +71 -28
  52. package/src/textarea.tsx +1 -1
  53. package/src/timeline.tsx +321 -0
  54. package/src/toast.tsx +156 -23
  55. package/src/tooltip.tsx +43 -3
  56. package/src/video-player.tsx +296 -120
@@ -1,20 +1,156 @@
1
1
  "use client"
2
2
 
3
3
  import { NumberField as BaseNumberField } from "@base-ui/react/number-field"
4
- import type { ComponentProps } from "react"
4
+ import { cva, type VariantProps } from "class-variance-authority"
5
+ import { createContext, useContext, type ComponentProps } from "react"
5
6
  import { IconMinus, IconPlus } from "./icons"
6
7
  import { cn } from "./lib/cn"
7
8
  import { motion } from "./lib/motion"
8
9
 
9
- export type NumberFieldProps = ComponentProps<typeof BaseNumberField.Root>
10
- export type NumberFieldGroupProps = ComponentProps<typeof BaseNumberField.Group>
11
- export type NumberFieldInputProps = ComponentProps<typeof BaseNumberField.Input>
12
- export type NumberFieldIncrementProps = ComponentProps<
13
- typeof BaseNumberField.Increment
14
- >
15
- export type NumberFieldDecrementProps = ComponentProps<
16
- typeof BaseNumberField.Decrement
17
- >
10
+ export type NumberFieldSize = "sm" | "md" | "lg"
11
+ export type NumberFieldAlign = "start" | "center" | "end"
12
+ type NumberFieldControlLayout = "split" | "stacked"
13
+
14
+ const NumberFieldSizeContext = createContext<NumberFieldSize>("md")
15
+ const NumberFieldControlLayoutContext =
16
+ createContext<NumberFieldControlLayout>("split")
17
+
18
+ const numberFieldGroupVariants = cva(
19
+ "flex w-full items-stretch overflow-hidden border border-border-secondary bg-surface inset-shadow-outline-top outline-none transition-[background-color,border-color,box-shadow] focus-within:border-ring focus-within:ring-[3px] focus-within:ring-offset-1 focus-within:ring-offset-background-primary focus-within:ring-ring/20 aria-invalid:border-destructive aria-invalid:focus-within:border-destructive aria-invalid:focus-within:ring-destructive/20 has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:focus-within:border-destructive has-[[aria-invalid=true]]:focus-within:ring-destructive/20 data-disabled:opacity-50 data-readonly:bg-background-secondary has-[:disabled]:opacity-50",
20
+ {
21
+ variants: {
22
+ size: {
23
+ sm: "h-8 rounded-md",
24
+ md: "h-9 rounded-md",
25
+ lg: "h-10 rounded-lg",
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ size: "md",
30
+ },
31
+ },
32
+ )
33
+
34
+ const numberFieldInputVariants = cva(
35
+ "h-full min-w-0 flex-1 cursor-text bg-transparent tabular-nums text-fg-primary outline-none placeholder:text-fg-quaternary focus-visible:outline-none data-disabled:cursor-not-allowed data-readonly:cursor-default",
36
+ {
37
+ variants: {
38
+ size: {
39
+ sm: "px-2 text-xs",
40
+ md: "px-2.5 text-sm",
41
+ lg: "px-3 text-sm",
42
+ },
43
+ align: {
44
+ start: "text-left",
45
+ center: "text-center",
46
+ end: "text-right",
47
+ },
48
+ },
49
+ defaultVariants: {
50
+ size: "md",
51
+ align: "center",
52
+ },
53
+ },
54
+ )
55
+
56
+ const numberFieldControlVariants = cva(
57
+ cn(
58
+ "inline-flex shrink-0 cursor-pointer items-center justify-center text-fg-tertiary outline-none",
59
+ motion.colors,
60
+ "hover:bg-background-tertiary hover:text-fg-primary focus-visible:bg-background-tertiary focus-visible:text-fg-primary focus-visible:outline-none data-disabled:cursor-not-allowed data-disabled:opacity-50 data-readonly:cursor-default data-readonly:opacity-50",
61
+ ),
62
+ {
63
+ variants: {
64
+ size: {
65
+ sm: "",
66
+ md: "",
67
+ lg: "",
68
+ },
69
+ layout: {
70
+ split: "",
71
+ stacked: "h-1/2 w-full",
72
+ },
73
+ },
74
+ compoundVariants: [
75
+ { size: "sm", layout: "split", className: "size-8" },
76
+ { size: "md", layout: "split", className: "size-9" },
77
+ { size: "lg", layout: "split", className: "size-10" },
78
+ ],
79
+ defaultVariants: {
80
+ size: "md",
81
+ layout: "split",
82
+ },
83
+ },
84
+ )
85
+
86
+ const numberFieldStepperVariants = cva(
87
+ "flex h-full shrink-0 flex-col border-l border-border-primary [&>button+button]:border-t [&>button+button]:border-border-primary",
88
+ {
89
+ variants: {
90
+ size: {
91
+ sm: "w-7",
92
+ md: "w-8",
93
+ lg: "w-9",
94
+ },
95
+ },
96
+ defaultVariants: {
97
+ size: "md",
98
+ },
99
+ },
100
+ )
101
+
102
+ const numberFieldAffixVariants = cva(
103
+ "inline-flex h-full shrink-0 items-center text-fg-tertiary select-none",
104
+ {
105
+ variants: {
106
+ size: {
107
+ sm: "text-xs",
108
+ md: "text-sm",
109
+ lg: "text-sm",
110
+ },
111
+ side: {
112
+ prefix: "pl-2.5",
113
+ suffix: "pr-2.5",
114
+ },
115
+ },
116
+ defaultVariants: {
117
+ size: "md",
118
+ side: "prefix",
119
+ },
120
+ },
121
+ )
122
+
123
+ export type NumberFieldProps = Omit<
124
+ ComponentProps<typeof BaseNumberField.Root>,
125
+ "size"
126
+ > & {
127
+ size?: NumberFieldSize
128
+ }
129
+ export type NumberFieldGroupProps = Omit<
130
+ ComponentProps<typeof BaseNumberField.Group>,
131
+ "size"
132
+ > &
133
+ VariantProps<typeof numberFieldGroupVariants>
134
+ export type NumberFieldInputProps = Omit<
135
+ ComponentProps<typeof BaseNumberField.Input>,
136
+ "size"
137
+ > &
138
+ VariantProps<typeof numberFieldInputVariants>
139
+ export type NumberFieldIncrementProps = Omit<
140
+ ComponentProps<typeof BaseNumberField.Increment>,
141
+ "size"
142
+ > &
143
+ VariantProps<typeof numberFieldControlVariants>
144
+ export type NumberFieldDecrementProps = Omit<
145
+ ComponentProps<typeof BaseNumberField.Decrement>,
146
+ "size"
147
+ > &
148
+ VariantProps<typeof numberFieldControlVariants>
149
+ export type NumberFieldStepperProps = Omit<ComponentProps<"div">, "size"> &
150
+ VariantProps<typeof numberFieldStepperVariants>
151
+ export type NumberFieldPrefixProps = Omit<ComponentProps<"span">, "size"> &
152
+ Omit<VariantProps<typeof numberFieldAffixVariants>, "side">
153
+ export type NumberFieldSuffixProps = NumberFieldPrefixProps
18
154
  export type NumberFieldScrubAreaProps = ComponentProps<
19
155
  typeof BaseNumberField.ScrubArea
20
156
  >
@@ -22,78 +158,200 @@ export type NumberFieldScrubAreaCursorProps = ComponentProps<
22
158
  typeof BaseNumberField.ScrubAreaCursor
23
159
  >
24
160
 
25
- export const NumberField = ({ className, ...props }: NumberFieldProps) => (
26
- <BaseNumberField.Root
27
- className={cn("flex flex-col gap-1.5", className)}
28
- {...props}
29
- />
161
+ export const NumberField = ({
162
+ className,
163
+ size = "md",
164
+ ...props
165
+ }: NumberFieldProps) => (
166
+ <NumberFieldSizeContext.Provider value={size}>
167
+ <BaseNumberField.Root
168
+ className={cn("flex flex-col gap-1.5", className)}
169
+ {...props}
170
+ />
171
+ </NumberFieldSizeContext.Provider>
30
172
  )
31
173
 
32
174
  export const NumberFieldGroup = ({
33
175
  className,
176
+ size,
34
177
  ...props
35
- }: NumberFieldGroupProps) => (
36
- <BaseNumberField.Group
37
- className={cn(
38
- "flex h-9 w-full items-stretch overflow-hidden rounded-md border border-border-secondary bg-surface inset-shadow-outline-top outline-none transition-[color,box-shadow]",
39
- "focus-within:border-ring focus-within:ring-[3px] focus-within:ring-offset-1 focus-within:ring-offset-background-primary focus-within:ring-ring/20",
40
- "aria-invalid:border-destructive aria-invalid:focus-within:border-destructive aria-invalid:focus-within:ring-destructive/20",
41
- "has-[[aria-invalid=true]]:border-destructive has-[[aria-invalid=true]]:focus-within:border-destructive has-[[aria-invalid=true]]:focus-within:ring-destructive/20",
42
- "has-[:disabled]:opacity-50",
43
- className,
44
- )}
45
- {...props}
46
- />
47
- )
178
+ }: NumberFieldGroupProps) => {
179
+ const inheritedSize = useContext(NumberFieldSizeContext)
180
+
181
+ return (
182
+ <BaseNumberField.Group
183
+ className={cn(
184
+ numberFieldGroupVariants({ size: size ?? inheritedSize }),
185
+ className,
186
+ )}
187
+ {...props}
188
+ />
189
+ )
190
+ }
48
191
 
49
192
  export const NumberFieldInput = ({
50
193
  className,
194
+ size,
195
+ align,
51
196
  ...props
52
- }: NumberFieldInputProps) => (
53
- <BaseNumberField.Input
54
- className={cn(
55
- "h-full min-w-0 flex-1 cursor-text border-x border-border-primary bg-transparent px-2 text-center text-sm tabular-nums text-fg-primary outline-none focus-visible:outline-none",
56
- className,
57
- )}
58
- {...props}
59
- />
60
- )
197
+ }: NumberFieldInputProps) => {
198
+ const inheritedSize = useContext(NumberFieldSizeContext)
61
199
 
62
- const stepperClassName = cn(
63
- "inline-flex size-9 shrink-0 cursor-pointer items-center justify-center text-fg-tertiary outline-none",
64
- motion.colors,
65
- "hover:bg-background-tertiary hover:text-fg-primary focus-visible:bg-background-tertiary focus-visible:text-fg-primary focus-visible:outline-none data-disabled:cursor-not-allowed data-disabled:opacity-50",
66
- )
200
+ return (
201
+ <BaseNumberField.Input
202
+ className={cn(
203
+ numberFieldInputVariants({ size: size ?? inheritedSize, align }),
204
+ className,
205
+ )}
206
+ {...props}
207
+ />
208
+ )
209
+ }
210
+
211
+ const controlIconClassNames: Record<NumberFieldSize, string> = {
212
+ sm: "size-3",
213
+ md: "size-3.5",
214
+ lg: "size-4",
215
+ }
67
216
 
68
217
  export const NumberFieldDecrement = ({
69
218
  className,
70
219
  children,
220
+ size,
221
+ layout,
71
222
  "aria-label": ariaLabel = "Decrease",
72
223
  ...props
73
- }: NumberFieldDecrementProps) => (
74
- <BaseNumberField.Decrement
75
- aria-label={ariaLabel}
76
- className={cn(stepperClassName, className)}
77
- {...props}
78
- >
79
- {children ?? <IconMinus size={16} className="size-4" aria-hidden />}
80
- </BaseNumberField.Decrement>
81
- )
224
+ }: NumberFieldDecrementProps) => {
225
+ const inheritedSize = useContext(NumberFieldSizeContext)
226
+ const inheritedLayout = useContext(NumberFieldControlLayoutContext)
227
+ const resolvedSize = size ?? inheritedSize
228
+ const resolvedLayout = layout ?? inheritedLayout
229
+
230
+ return (
231
+ <BaseNumberField.Decrement
232
+ aria-label={ariaLabel}
233
+ className={cn(
234
+ numberFieldControlVariants({
235
+ size: resolvedSize,
236
+ layout: resolvedLayout,
237
+ }),
238
+ resolvedLayout === "split" && "border-r border-border-primary",
239
+ className,
240
+ )}
241
+ {...props}
242
+ >
243
+ {children ?? (
244
+ <IconMinus
245
+ size={16}
246
+ className={controlIconClassNames[resolvedSize]}
247
+ aria-hidden
248
+ />
249
+ )}
250
+ </BaseNumberField.Decrement>
251
+ )
252
+ }
82
253
 
83
254
  export const NumberFieldIncrement = ({
84
255
  className,
85
256
  children,
257
+ size,
258
+ layout,
86
259
  "aria-label": ariaLabel = "Increase",
87
260
  ...props
88
- }: NumberFieldIncrementProps) => (
89
- <BaseNumberField.Increment
90
- aria-label={ariaLabel}
91
- className={cn(stepperClassName, className)}
92
- {...props}
93
- >
94
- {children ?? <IconPlus size={16} className="size-4" aria-hidden />}
95
- </BaseNumberField.Increment>
96
- )
261
+ }: NumberFieldIncrementProps) => {
262
+ const inheritedSize = useContext(NumberFieldSizeContext)
263
+ const inheritedLayout = useContext(NumberFieldControlLayoutContext)
264
+ const resolvedSize = size ?? inheritedSize
265
+ const resolvedLayout = layout ?? inheritedLayout
266
+
267
+ return (
268
+ <BaseNumberField.Increment
269
+ aria-label={ariaLabel}
270
+ className={cn(
271
+ numberFieldControlVariants({
272
+ size: resolvedSize,
273
+ layout: resolvedLayout,
274
+ }),
275
+ resolvedLayout === "split" && "border-l border-border-primary",
276
+ className,
277
+ )}
278
+ {...props}
279
+ >
280
+ {children ?? (
281
+ <IconPlus
282
+ size={16}
283
+ className={controlIconClassNames[resolvedSize]}
284
+ aria-hidden
285
+ />
286
+ )}
287
+ </BaseNumberField.Increment>
288
+ )
289
+ }
290
+
291
+ export const NumberFieldStepper = ({
292
+ className,
293
+ size,
294
+ children,
295
+ ...props
296
+ }: NumberFieldStepperProps) => {
297
+ const inheritedSize = useContext(NumberFieldSizeContext)
298
+
299
+ return (
300
+ <NumberFieldControlLayoutContext.Provider value="stacked">
301
+ <div
302
+ className={cn(
303
+ numberFieldStepperVariants({ size: size ?? inheritedSize }),
304
+ className,
305
+ )}
306
+ {...props}
307
+ >
308
+ {children}
309
+ </div>
310
+ </NumberFieldControlLayoutContext.Provider>
311
+ )
312
+ }
313
+
314
+ export const NumberFieldPrefix = ({
315
+ className,
316
+ size,
317
+ ...props
318
+ }: NumberFieldPrefixProps) => {
319
+ const inheritedSize = useContext(NumberFieldSizeContext)
320
+
321
+ return (
322
+ <span
323
+ className={cn(
324
+ numberFieldAffixVariants({
325
+ size: size ?? inheritedSize,
326
+ side: "prefix",
327
+ }),
328
+ className,
329
+ )}
330
+ {...props}
331
+ />
332
+ )
333
+ }
334
+
335
+ export const NumberFieldSuffix = ({
336
+ className,
337
+ size,
338
+ ...props
339
+ }: NumberFieldSuffixProps) => {
340
+ const inheritedSize = useContext(NumberFieldSizeContext)
341
+
342
+ return (
343
+ <span
344
+ className={cn(
345
+ numberFieldAffixVariants({
346
+ size: size ?? inheritedSize,
347
+ side: "suffix",
348
+ }),
349
+ className,
350
+ )}
351
+ {...props}
352
+ />
353
+ )
354
+ }
97
355
 
98
356
  export const NumberFieldScrubArea = ({
99
357
  className,
@@ -101,7 +359,7 @@ export const NumberFieldScrubArea = ({
101
359
  }: NumberFieldScrubAreaProps) => (
102
360
  <BaseNumberField.ScrubArea
103
361
  className={cn(
104
- "inline-flex cursor-ew-resize items-center gap-1 text-sm text-fg-secondary select-none",
362
+ "inline-flex cursor-ew-resize items-center gap-1 text-sm text-fg-secondary select-none data-disabled:cursor-not-allowed data-disabled:opacity-50 data-readonly:cursor-default",
105
363
  className,
106
364
  )}
107
365
  {...props}
@@ -117,3 +375,11 @@ export const NumberFieldScrubAreaCursor = ({
117
375
  {...props}
118
376
  />
119
377
  )
378
+
379
+ export {
380
+ numberFieldAffixVariants,
381
+ numberFieldControlVariants,
382
+ numberFieldGroupVariants,
383
+ numberFieldInputVariants,
384
+ numberFieldStepperVariants,
385
+ }