@blips/ui 1.0.1 → 2.0.0

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 (59) hide show
  1. package/dist/index.cjs +3612 -2515
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.cts +329 -484
  4. package/dist/index.d.ts +329 -484
  5. package/dist/index.js +3602 -2513
  6. package/dist/index.js.map +1 -1
  7. package/package.json +14 -12
  8. package/src/components/accordion.tsx +56 -46
  9. package/src/components/alert-dialog.tsx +166 -109
  10. package/src/components/alert.tsx +45 -38
  11. package/src/components/aspect-ratio.tsx +7 -1
  12. package/src/components/avatar.tsx +104 -45
  13. package/src/components/badge.tsx +25 -13
  14. package/src/components/breadcrumb.tsx +76 -82
  15. package/src/components/button-group.tsx +2 -2
  16. package/src/components/button.tsx +36 -28
  17. package/src/components/calendar.tsx +35 -28
  18. package/src/components/card.tsx +83 -70
  19. package/src/components/carousel.tsx +118 -137
  20. package/src/components/chart.tsx +197 -208
  21. package/src/components/checkbox.tsx +25 -21
  22. package/src/components/collapsible.tsx +25 -3
  23. package/src/components/command.tsx +138 -105
  24. package/src/components/context-menu.tsx +215 -161
  25. package/src/components/dialog.tsx +127 -91
  26. package/src/components/drawer.tsx +102 -83
  27. package/src/components/dropdown-menu.tsx +227 -170
  28. package/src/components/form.tsx +41 -52
  29. package/src/components/hover-card.tsx +36 -19
  30. package/src/components/input-group.tsx +4 -4
  31. package/src/components/input-otp.tsx +51 -43
  32. package/src/components/input.tsx +16 -17
  33. package/src/components/kbd.tsx +1 -1
  34. package/src/components/label.tsx +16 -18
  35. package/src/components/menubar.tsx +214 -192
  36. package/src/components/navigation-menu.tsx +140 -98
  37. package/src/components/pagination.tsx +97 -87
  38. package/src/components/popover.tsx +83 -23
  39. package/src/components/progress.tsx +23 -20
  40. package/src/components/radio-group.tsx +23 -20
  41. package/src/components/resizable.tsx +39 -31
  42. package/src/components/scroll-area.tsx +51 -39
  43. package/src/components/select.tsx +161 -131
  44. package/src/components/separator.tsx +13 -14
  45. package/src/components/sheet.tsx +112 -109
  46. package/src/components/sidebar.tsx +422 -470
  47. package/src/components/skeleton.tsx +4 -6
  48. package/src/components/slider.tsx +57 -20
  49. package/src/components/sonner.tsx +19 -24
  50. package/src/components/spinner.tsx +3 -3
  51. package/src/components/switch.tsx +28 -20
  52. package/src/components/table.tsx +94 -95
  53. package/src/components/tabs.tsx +88 -50
  54. package/src/components/textarea.tsx +5 -9
  55. package/src/components/toggle-group.tsx +52 -30
  56. package/src/components/toggle.tsx +24 -20
  57. package/src/components/tooltip.tsx +46 -19
  58. package/src/globals.css +213 -96
  59. package/src/index.ts +27 -6
@@ -1,34 +1,37 @@
1
1
  "use client"
2
2
 
3
3
  import * as React from "react"
4
- import type * as LabelPrimitive from "@radix-ui/react-label"
4
+ import * as LabelPrimitive from "@radix-ui/react-label"
5
5
  import { Slot } from "@radix-ui/react-slot"
6
6
  import {
7
7
  Controller,
8
8
  FormProvider,
9
9
  useFormContext,
10
+ useFormState,
10
11
  type ControllerProps,
11
12
  type FieldPath,
12
13
  type FieldValues,
13
14
  } from "react-hook-form"
14
15
 
15
- import { cn } from "@/lib/utils"
16
- import { Label } from "@/components/label"
16
+ import { cn } from "../lib/utils"
17
+ import { Label } from "./label"
17
18
 
18
19
  const Form = FormProvider
19
20
 
20
21
  type FormFieldContextValue<
21
22
  TFieldValues extends FieldValues = FieldValues,
22
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
23
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
23
24
  > = {
24
25
  name: TName
25
26
  }
26
27
 
27
- const FormFieldContext = React.createContext<FormFieldContextValue | null>(null)
28
+ const FormFieldContext = React.createContext<FormFieldContextValue>(
29
+ {} as FormFieldContextValue
30
+ )
28
31
 
29
32
  const FormField = <
30
33
  TFieldValues extends FieldValues = FieldValues,
31
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
34
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
32
35
  >({
33
36
  ...props
34
37
  }: ControllerProps<TFieldValues, TName>) => {
@@ -42,18 +45,14 @@ const FormField = <
42
45
  const useFormField = () => {
43
46
  const fieldContext = React.useContext(FormFieldContext)
44
47
  const itemContext = React.useContext(FormItemContext)
45
- const { getFieldState, formState } = useFormContext()
48
+ const { getFieldState } = useFormContext()
49
+ const formState = useFormState({ name: fieldContext.name })
50
+ const fieldState = getFieldState(fieldContext.name, formState)
46
51
 
47
52
  if (!fieldContext) {
48
53
  throw new Error("useFormField should be used within <FormField>")
49
54
  }
50
55
 
51
- if (!itemContext) {
52
- throw new Error("useFormField should be used within <FormItem>")
53
- }
54
-
55
- const fieldState = getFieldState(fieldContext.name, formState)
56
-
57
56
  const { id } = itemContext
58
57
 
59
58
  return {
@@ -70,48 +69,47 @@ type FormItemContextValue = {
70
69
  id: string
71
70
  }
72
71
 
73
- const FormItemContext = React.createContext<FormItemContextValue | null>(null)
72
+ const FormItemContext = React.createContext<FormItemContextValue>(
73
+ {} as FormItemContextValue
74
+ )
74
75
 
75
- const FormItem = React.forwardRef<
76
- HTMLDivElement,
77
- React.HTMLAttributes<HTMLDivElement>
78
- >(({ className, ...props }, ref) => {
76
+ function FormItem({ className, ...props }: React.ComponentProps<"div">) {
79
77
  const id = React.useId()
80
78
 
81
79
  return (
82
80
  <FormItemContext.Provider value={{ id }}>
83
- <div ref={ref} className={cn("space-y-2", className)} {...props} />
81
+ <div
82
+ data-slot="form-item"
83
+ className={cn("grid gap-2", className)}
84
+ {...props}
85
+ />
84
86
  </FormItemContext.Provider>
85
87
  )
86
- })
87
- FormItem.displayName = "FormItem"
88
+ }
88
89
 
89
- const FormLabel = React.forwardRef<
90
- React.ElementRef<typeof LabelPrimitive.Root>,
91
- React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
92
- >(({ className, ...props }, ref) => {
90
+ function FormLabel({
91
+ className,
92
+ ...props
93
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
93
94
  const { error, formItemId } = useFormField()
94
95
 
95
96
  return (
96
97
  <Label
97
- ref={ref}
98
- className={cn(error && "text-destructive", className)}
98
+ data-slot="form-label"
99
+ data-error={!!error}
100
+ className={cn("data-[error=true]:text-destructive", className)}
99
101
  htmlFor={formItemId}
100
102
  {...props}
101
103
  />
102
104
  )
103
- })
104
- FormLabel.displayName = "FormLabel"
105
+ }
105
106
 
106
- const FormControl = React.forwardRef<
107
- React.ElementRef<typeof Slot>,
108
- React.ComponentPropsWithoutRef<typeof Slot>
109
- >(({ ...props }, ref) => {
107
+ function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
110
108
  const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
111
109
 
112
110
  return (
113
111
  <Slot
114
- ref={ref}
112
+ data-slot="form-control"
115
113
  id={formItemId}
116
114
  aria-describedby={
117
115
  !error
@@ -122,32 +120,24 @@ const FormControl = React.forwardRef<
122
120
  {...props}
123
121
  />
124
122
  )
125
- })
126
- FormControl.displayName = "FormControl"
123
+ }
127
124
 
128
- const FormDescription = React.forwardRef<
129
- HTMLParagraphElement,
130
- React.HTMLAttributes<HTMLParagraphElement>
131
- >(({ className, ...props }, ref) => {
125
+ function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
132
126
  const { formDescriptionId } = useFormField()
133
127
 
134
128
  return (
135
129
  <p
136
- ref={ref}
130
+ data-slot="form-description"
137
131
  id={formDescriptionId}
138
132
  className={cn("text-sm text-muted-foreground", className)}
139
133
  {...props}
140
134
  />
141
135
  )
142
- })
143
- FormDescription.displayName = "FormDescription"
136
+ }
144
137
 
145
- const FormMessage = React.forwardRef<
146
- HTMLParagraphElement,
147
- React.HTMLAttributes<HTMLParagraphElement>
148
- >(({ className, children, ...props }, ref) => {
138
+ function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
149
139
  const { error, formMessageId } = useFormField()
150
- const body = error ? String(error?.message ?? "") : children
140
+ const body = error ? String(error?.message ?? "") : props.children
151
141
 
152
142
  if (!body) {
153
143
  return null
@@ -155,16 +145,15 @@ const FormMessage = React.forwardRef<
155
145
 
156
146
  return (
157
147
  <p
158
- ref={ref}
148
+ data-slot="form-message"
159
149
  id={formMessageId}
160
- className={cn("text-sm font-medium text-destructive", className)}
150
+ className={cn("text-sm text-destructive", className)}
161
151
  {...props}
162
152
  >
163
153
  {body}
164
154
  </p>
165
155
  )
166
- })
167
- FormMessage.displayName = "FormMessage"
156
+ }
168
157
 
169
158
  export {
170
159
  useFormField,
@@ -1,27 +1,44 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
3
5
 
4
- import { cn } from "@/lib/utils"
6
+ import { cn } from "../lib/utils"
5
7
 
6
- const HoverCard = HoverCardPrimitive.Root
8
+ function HoverCard({
9
+ ...props
10
+ }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
11
+ return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />
12
+ }
7
13
 
8
- const HoverCardTrigger = HoverCardPrimitive.Trigger
14
+ function HoverCardTrigger({
15
+ ...props
16
+ }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
17
+ return (
18
+ <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />
19
+ )
20
+ }
9
21
 
10
- const HoverCardContent = React.forwardRef<
11
- React.ElementRef<typeof HoverCardPrimitive.Content>,
12
- React.ComponentPropsWithoutRef<typeof HoverCardPrimitive.Content>
13
- >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
14
- <HoverCardPrimitive.Content
15
- ref={ref}
16
- align={align}
17
- sideOffset={sideOffset}
18
- className={cn(
19
- "z-50 w-64 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-hover-card-content-transform-origin]",
20
- className
21
- )}
22
- {...props}
23
- />
24
- ))
25
- HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
22
+ function HoverCardContent({
23
+ className,
24
+ align = "center",
25
+ sideOffset = 4,
26
+ ...props
27
+ }: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
28
+ return (
29
+ <HoverCardPrimitive.Portal data-slot="hover-card-portal">
30
+ <HoverCardPrimitive.Content
31
+ data-slot="hover-card-content"
32
+ align={align}
33
+ sideOffset={sideOffset}
34
+ className={cn(
35
+ "z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
36
+ className
37
+ )}
38
+ {...props}
39
+ />
40
+ </HoverCardPrimitive.Portal>
41
+ )
42
+ }
26
43
 
27
44
  export { HoverCard, HoverCardTrigger, HoverCardContent }
@@ -1,10 +1,10 @@
1
1
  import type * as React from "react"
2
2
  import { cva, type VariantProps } from "class-variance-authority"
3
3
 
4
- import { cn } from "@/lib/utils"
5
- import { Button } from "@/components/button"
6
- import { Input } from "@/components/input"
7
- import { Textarea } from "@/components/textarea"
4
+ import { cn } from "../lib/utils"
5
+ import { Button } from "./button"
6
+ import { Input } from "./input"
7
+ import { Textarea } from "./textarea"
8
8
 
9
9
  function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
10
10
  return (
@@ -1,46 +1,57 @@
1
+ "use client"
2
+
1
3
  import * as React from "react"
2
4
  import { OTPInput, OTPInputContext } from "input-otp"
3
- import { Dot } from "lucide-react"
5
+ import { Minus } from "@phosphor-icons/react"
4
6
 
5
- import { cn } from "@/lib/utils"
7
+ import { cn } from "../lib/utils"
6
8
 
7
- const InputOTP = React.forwardRef<
8
- React.ElementRef<typeof OTPInput>,
9
- React.ComponentPropsWithoutRef<typeof OTPInput>
10
- >(({ className, containerClassName, ...props }, ref) => (
11
- <OTPInput
12
- ref={ref}
13
- containerClassName={cn(
14
- "flex items-center gap-2 has-[:disabled]:opacity-50",
15
- containerClassName
16
- )}
17
- className={cn("disabled:cursor-not-allowed", className)}
18
- {...props}
19
- />
20
- ))
21
- InputOTP.displayName = "InputOTP"
9
+ function InputOTP({
10
+ className,
11
+ containerClassName,
12
+ ...props
13
+ }: React.ComponentProps<typeof OTPInput> & {
14
+ containerClassName?: string
15
+ }) {
16
+ return (
17
+ <OTPInput
18
+ data-slot="input-otp"
19
+ containerClassName={cn(
20
+ "flex items-center gap-2 has-disabled:opacity-50",
21
+ containerClassName
22
+ )}
23
+ className={cn("disabled:cursor-not-allowed", className)}
24
+ {...props}
25
+ />
26
+ )
27
+ }
22
28
 
23
- const InputOTPGroup = React.forwardRef<
24
- React.ElementRef<"div">,
25
- React.ComponentPropsWithoutRef<"div">
26
- >(({ className, ...props }, ref) => (
27
- <div ref={ref} className={cn("flex items-center", className)} {...props} />
28
- ))
29
- InputOTPGroup.displayName = "InputOTPGroup"
29
+ function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
30
+ return (
31
+ <div
32
+ data-slot="input-otp-group"
33
+ className={cn("flex items-center", className)}
34
+ {...props}
35
+ />
36
+ )
37
+ }
30
38
 
31
- const InputOTPSlot = React.forwardRef<
32
- React.ElementRef<"div">,
33
- React.ComponentPropsWithoutRef<"div"> & { index: number }
34
- >(({ index, className, ...props }, ref) => {
39
+ function InputOTPSlot({
40
+ index,
41
+ className,
42
+ ...props
43
+ }: React.ComponentProps<"div"> & {
44
+ index: number
45
+ }) {
35
46
  const inputOTPContext = React.useContext(OTPInputContext)
36
- const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index]
47
+ const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {}
37
48
 
38
49
  return (
39
50
  <div
40
- ref={ref}
51
+ data-slot="input-otp-slot"
52
+ data-active={isActive}
41
53
  className={cn(
42
- "relative flex h-10 w-10 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md",
43
- isActive && "z-10 ring-2 ring-ring ring-offset-background",
54
+ "relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-[3px] data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40",
44
55
  className
45
56
  )}
46
57
  {...props}
@@ -53,17 +64,14 @@ const InputOTPSlot = React.forwardRef<
53
64
  )}
54
65
  </div>
55
66
  )
56
- })
57
- InputOTPSlot.displayName = "InputOTPSlot"
67
+ }
58
68
 
59
- const InputOTPSeparator = React.forwardRef<
60
- React.ElementRef<"div">,
61
- React.ComponentPropsWithoutRef<"div">
62
- >(({ ...props }, ref) => (
63
- <div ref={ref} role="separator" {...props}>
64
- <Dot />
65
- </div>
66
- ))
67
- InputOTPSeparator.displayName = "InputOTPSeparator"
69
+ function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
70
+ return (
71
+ <div data-slot="input-otp-separator" role="separator" {...props}>
72
+ <Minus />
73
+ </div>
74
+ )
75
+ }
68
76
 
69
77
  export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator }
@@ -1,22 +1,21 @@
1
1
  import * as React from "react"
2
2
 
3
- import { cn } from "@/lib/utils"
3
+ import { cn } from "../lib/utils"
4
4
 
5
- const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>(
6
- ({ className, type, ...props }, ref) => {
7
- return (
8
- <input
9
- type={type}
10
- className={cn(
11
- "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-base ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
12
- className
13
- )}
14
- ref={ref}
15
- {...props}
16
- />
17
- )
18
- }
19
- )
20
- Input.displayName = "Input"
5
+ function Input({ className, type, ...props }: React.ComponentProps<"input">) {
6
+ return (
7
+ <input
8
+ type={type}
9
+ data-slot="input"
10
+ className={cn(
11
+ "h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30",
12
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
13
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
14
+ className
15
+ )}
16
+ {...props}
17
+ />
18
+ )
19
+ }
21
20
 
22
21
  export { Input }
@@ -1,4 +1,4 @@
1
- import { cn } from "@/lib/utils"
1
+ import { cn } from "../lib/utils"
2
2
 
3
3
  function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
4
4
  return (
@@ -2,25 +2,23 @@
2
2
 
3
3
  import * as React from "react"
4
4
  import * as LabelPrimitive from "@radix-ui/react-label"
5
- import { cva, type VariantProps } from "class-variance-authority"
6
5
 
7
- import { cn } from "@/lib/utils"
6
+ import { cn } from "../lib/utils"
8
7
 
9
- const labelVariants = cva(
10
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11
- )
12
-
13
- const Label = React.forwardRef<
14
- React.ElementRef<typeof LabelPrimitive.Root>,
15
- React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
16
- VariantProps<typeof labelVariants>
17
- >(({ className, ...props }, ref) => (
18
- <LabelPrimitive.Root
19
- ref={ref}
20
- className={cn(labelVariants(), className)}
21
- {...props}
22
- />
23
- ))
24
- Label.displayName = LabelPrimitive.Root.displayName
8
+ function Label({
9
+ className,
10
+ ...props
11
+ }: React.ComponentProps<typeof LabelPrimitive.Root>) {
12
+ return (
13
+ <LabelPrimitive.Root
14
+ data-slot="label"
15
+ className={cn(
16
+ "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
17
+ className
18
+ )}
19
+ {...props}
20
+ />
21
+ )
22
+ }
25
23
 
26
24
  export { Label }