@questpie/admin 0.0.1

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 (203) hide show
  1. package/.turbo/turbo-build.log +108 -0
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +556 -0
  4. package/STATUS.md +917 -0
  5. package/VALIDATION.md +602 -0
  6. package/components.json +24 -0
  7. package/dist/__tests__/setup.mjs +38 -0
  8. package/dist/__tests__/test-utils.mjs +45 -0
  9. package/dist/__tests__/vitest.d.mjs +3 -0
  10. package/dist/components/admin-app.mjs +69 -0
  11. package/dist/components/fields/array-field.mjs +190 -0
  12. package/dist/components/fields/checkbox-field.mjs +34 -0
  13. package/dist/components/fields/custom-field.mjs +32 -0
  14. package/dist/components/fields/date-field.mjs +41 -0
  15. package/dist/components/fields/datetime-field.mjs +42 -0
  16. package/dist/components/fields/email-field.mjs +37 -0
  17. package/dist/components/fields/embedded-collection.mjs +253 -0
  18. package/dist/components/fields/field-types.mjs +1 -0
  19. package/dist/components/fields/field-utils.mjs +10 -0
  20. package/dist/components/fields/field-wrapper.mjs +34 -0
  21. package/dist/components/fields/index.mjs +23 -0
  22. package/dist/components/fields/json-field.mjs +243 -0
  23. package/dist/components/fields/locale-badge.mjs +16 -0
  24. package/dist/components/fields/number-field.mjs +39 -0
  25. package/dist/components/fields/password-field.mjs +37 -0
  26. package/dist/components/fields/relation-field.mjs +104 -0
  27. package/dist/components/fields/relation-picker.mjs +229 -0
  28. package/dist/components/fields/relation-select.mjs +188 -0
  29. package/dist/components/fields/rich-text-editor/index.mjs +897 -0
  30. package/dist/components/fields/select-field.mjs +41 -0
  31. package/dist/components/fields/switch-field.mjs +34 -0
  32. package/dist/components/fields/text-field.mjs +38 -0
  33. package/dist/components/fields/textarea-field.mjs +38 -0
  34. package/dist/components/index.mjs +59 -0
  35. package/dist/components/primitives/checkbox-input.mjs +127 -0
  36. package/dist/components/primitives/date-input.mjs +303 -0
  37. package/dist/components/primitives/index.mjs +12 -0
  38. package/dist/components/primitives/number-input.mjs +104 -0
  39. package/dist/components/primitives/select-input.mjs +177 -0
  40. package/dist/components/primitives/tag-input.mjs +135 -0
  41. package/dist/components/primitives/text-input.mjs +39 -0
  42. package/dist/components/primitives/textarea-input.mjs +37 -0
  43. package/dist/components/primitives/toggle-input.mjs +31 -0
  44. package/dist/components/primitives/types.mjs +12 -0
  45. package/dist/components/ui/accordion.mjs +55 -0
  46. package/dist/components/ui/avatar.mjs +54 -0
  47. package/dist/components/ui/badge.mjs +34 -0
  48. package/dist/components/ui/button.mjs +48 -0
  49. package/dist/components/ui/card.mjs +58 -0
  50. package/dist/components/ui/checkbox.mjs +21 -0
  51. package/dist/components/ui/combobox.mjs +163 -0
  52. package/dist/components/ui/dialog.mjs +95 -0
  53. package/dist/components/ui/dropdown-menu.mjs +138 -0
  54. package/dist/components/ui/field.mjs +113 -0
  55. package/dist/components/ui/input-group.mjs +82 -0
  56. package/dist/components/ui/input.mjs +17 -0
  57. package/dist/components/ui/label.mjs +15 -0
  58. package/dist/components/ui/popover.mjs +56 -0
  59. package/dist/components/ui/scroll-area.mjs +38 -0
  60. package/dist/components/ui/select.mjs +100 -0
  61. package/dist/components/ui/separator.mjs +16 -0
  62. package/dist/components/ui/sheet.mjs +90 -0
  63. package/dist/components/ui/sidebar.mjs +387 -0
  64. package/dist/components/ui/skeleton.mjs +14 -0
  65. package/dist/components/ui/spinner.mjs +16 -0
  66. package/dist/components/ui/switch.mjs +22 -0
  67. package/dist/components/ui/table.mjs +68 -0
  68. package/dist/components/ui/tabs.mjs +48 -0
  69. package/dist/components/ui/textarea.mjs +15 -0
  70. package/dist/components/ui/tooltip.mjs +44 -0
  71. package/dist/config/component-registry.mjs +38 -0
  72. package/dist/config/index.mjs +129 -0
  73. package/dist/hooks/admin-provider.mjs +70 -0
  74. package/dist/hooks/index.mjs +7 -0
  75. package/dist/hooks/store.mjs +178 -0
  76. package/dist/hooks/use-auth.mjs +76 -0
  77. package/dist/hooks/use-collection-db.mjs +146 -0
  78. package/dist/hooks/use-collection.mjs +112 -0
  79. package/dist/hooks/use-global.mjs +46 -0
  80. package/dist/hooks/use-mobile.mjs +20 -0
  81. package/dist/lib/utils.mjs +10 -0
  82. package/dist/styles/index.css +336 -0
  83. package/dist/styles/index.mjs +1 -0
  84. package/dist/utils/index.mjs +9 -0
  85. package/dist/views/auth/auth-layout.mjs +52 -0
  86. package/dist/views/auth/forgot-password-form.mjs +148 -0
  87. package/dist/views/auth/index.mjs +6 -0
  88. package/dist/views/auth/login-form.mjs +156 -0
  89. package/dist/views/auth/reset-password-form.mjs +184 -0
  90. package/dist/views/collection/auto-form-fields.mjs +525 -0
  91. package/dist/views/collection/collection-form.mjs +91 -0
  92. package/dist/views/collection/collection-list.mjs +76 -0
  93. package/dist/views/collection/form-field.mjs +42 -0
  94. package/dist/views/collection/index.mjs +6 -0
  95. package/dist/views/common/index.mjs +4 -0
  96. package/dist/views/common/locale-switcher.mjs +39 -0
  97. package/dist/views/common/version-history.mjs +272 -0
  98. package/dist/views/index.mjs +9 -0
  99. package/dist/views/layout/admin-layout.mjs +40 -0
  100. package/dist/views/layout/admin-router.mjs +95 -0
  101. package/dist/views/layout/admin-sidebar.mjs +63 -0
  102. package/dist/views/layout/index.mjs +5 -0
  103. package/package.json +276 -0
  104. package/src/__tests__/setup.ts +44 -0
  105. package/src/__tests__/test-utils.tsx +49 -0
  106. package/src/__tests__/vitest.d.ts +9 -0
  107. package/src/components/admin-app.tsx +221 -0
  108. package/src/components/fields/array-field.tsx +237 -0
  109. package/src/components/fields/checkbox-field.tsx +47 -0
  110. package/src/components/fields/custom-field.tsx +50 -0
  111. package/src/components/fields/date-field.tsx +65 -0
  112. package/src/components/fields/datetime-field.tsx +67 -0
  113. package/src/components/fields/email-field.tsx +51 -0
  114. package/src/components/fields/embedded-collection.tsx +315 -0
  115. package/src/components/fields/field-types.ts +162 -0
  116. package/src/components/fields/field-utils.ts +6 -0
  117. package/src/components/fields/field-wrapper.tsx +52 -0
  118. package/src/components/fields/index.ts +66 -0
  119. package/src/components/fields/json-field.tsx +440 -0
  120. package/src/components/fields/locale-badge.tsx +15 -0
  121. package/src/components/fields/number-field.tsx +57 -0
  122. package/src/components/fields/password-field.tsx +51 -0
  123. package/src/components/fields/relation-field.tsx +243 -0
  124. package/src/components/fields/relation-picker.tsx +402 -0
  125. package/src/components/fields/relation-select.tsx +327 -0
  126. package/src/components/fields/rich-text-editor/index.tsx +1337 -0
  127. package/src/components/fields/select-field.tsx +61 -0
  128. package/src/components/fields/switch-field.tsx +47 -0
  129. package/src/components/fields/text-field.tsx +55 -0
  130. package/src/components/fields/textarea-field.tsx +55 -0
  131. package/src/components/index.ts +40 -0
  132. package/src/components/primitives/checkbox-input.tsx +193 -0
  133. package/src/components/primitives/date-input.tsx +401 -0
  134. package/src/components/primitives/index.ts +24 -0
  135. package/src/components/primitives/number-input.tsx +132 -0
  136. package/src/components/primitives/select-input.tsx +296 -0
  137. package/src/components/primitives/tag-input.tsx +200 -0
  138. package/src/components/primitives/text-input.tsx +49 -0
  139. package/src/components/primitives/textarea-input.tsx +46 -0
  140. package/src/components/primitives/toggle-input.tsx +36 -0
  141. package/src/components/primitives/types.ts +235 -0
  142. package/src/components/ui/accordion.tsx +72 -0
  143. package/src/components/ui/avatar.tsx +106 -0
  144. package/src/components/ui/badge.tsx +48 -0
  145. package/src/components/ui/button.tsx +53 -0
  146. package/src/components/ui/card.tsx +94 -0
  147. package/src/components/ui/checkbox.tsx +27 -0
  148. package/src/components/ui/combobox.tsx +290 -0
  149. package/src/components/ui/dialog.tsx +151 -0
  150. package/src/components/ui/dropdown-menu.tsx +254 -0
  151. package/src/components/ui/field.tsx +227 -0
  152. package/src/components/ui/input-group.tsx +149 -0
  153. package/src/components/ui/input.tsx +20 -0
  154. package/src/components/ui/label.tsx +18 -0
  155. package/src/components/ui/popover.tsx +88 -0
  156. package/src/components/ui/scroll-area.tsx +53 -0
  157. package/src/components/ui/select.tsx +192 -0
  158. package/src/components/ui/separator.tsx +23 -0
  159. package/src/components/ui/sheet.tsx +127 -0
  160. package/src/components/ui/sidebar.tsx +723 -0
  161. package/src/components/ui/skeleton.tsx +13 -0
  162. package/src/components/ui/spinner.tsx +10 -0
  163. package/src/components/ui/switch.tsx +32 -0
  164. package/src/components/ui/table.tsx +99 -0
  165. package/src/components/ui/tabs.tsx +82 -0
  166. package/src/components/ui/textarea.tsx +18 -0
  167. package/src/components/ui/tooltip.tsx +70 -0
  168. package/src/config/component-registry.ts +190 -0
  169. package/src/config/index.ts +1099 -0
  170. package/src/hooks/README.md +269 -0
  171. package/src/hooks/admin-provider.tsx +110 -0
  172. package/src/hooks/index.ts +41 -0
  173. package/src/hooks/store.ts +248 -0
  174. package/src/hooks/use-auth.ts +168 -0
  175. package/src/hooks/use-collection-db.ts +209 -0
  176. package/src/hooks/use-collection.ts +156 -0
  177. package/src/hooks/use-global.ts +69 -0
  178. package/src/hooks/use-mobile.ts +21 -0
  179. package/src/lib/utils.ts +6 -0
  180. package/src/styles/index.css +340 -0
  181. package/src/utils/index.ts +6 -0
  182. package/src/views/auth/auth-layout.tsx +77 -0
  183. package/src/views/auth/forgot-password-form.tsx +192 -0
  184. package/src/views/auth/index.ts +21 -0
  185. package/src/views/auth/login-form.tsx +229 -0
  186. package/src/views/auth/reset-password-form.tsx +232 -0
  187. package/src/views/collection/auto-form-fields.tsx +982 -0
  188. package/src/views/collection/collection-form.tsx +186 -0
  189. package/src/views/collection/collection-list.tsx +223 -0
  190. package/src/views/collection/form-field.tsx +52 -0
  191. package/src/views/collection/index.ts +15 -0
  192. package/src/views/common/index.ts +8 -0
  193. package/src/views/common/locale-switcher.tsx +45 -0
  194. package/src/views/common/version-history.tsx +406 -0
  195. package/src/views/index.ts +25 -0
  196. package/src/views/layout/admin-layout.tsx +117 -0
  197. package/src/views/layout/admin-router.tsx +206 -0
  198. package/src/views/layout/admin-sidebar.tsx +185 -0
  199. package/src/views/layout/index.ts +12 -0
  200. package/tsconfig.json +13 -0
  201. package/tsconfig.tsbuildinfo +1 -0
  202. package/tsdown.config.ts +13 -0
  203. package/vitest.config.ts +29 -0
@@ -0,0 +1,290 @@
1
+ import * as React from "react"
2
+ import { Combobox as ComboboxPrimitive } from "@base-ui/react"
3
+
4
+ import { cn } from "../../lib/utils"
5
+ import { Button } from "./button"
6
+ import {
7
+ InputGroup,
8
+ InputGroupAddon,
9
+ InputGroupButton,
10
+ InputGroupInput,
11
+ } from "./input-group"
12
+ import { CaretDownIcon, XIcon, CheckIcon } from "@phosphor-icons/react"
13
+
14
+ const Combobox = ComboboxPrimitive.Root
15
+
16
+ function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {
17
+ return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />
18
+ }
19
+
20
+ function ComboboxTrigger({
21
+ className,
22
+ children,
23
+ ...props
24
+ }: ComboboxPrimitive.Trigger.Props) {
25
+ return (
26
+ <ComboboxPrimitive.Trigger
27
+ data-slot="combobox-trigger"
28
+ className={cn("[&_svg:not([class*='size-'])]:size-3.5", className)}
29
+ {...props}
30
+ >
31
+ {children}
32
+ <CaretDownIcon className="text-muted-foreground size-3.5 pointer-events-none" />
33
+ </ComboboxPrimitive.Trigger>
34
+ )
35
+ }
36
+
37
+ function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {
38
+ return (
39
+ <ComboboxPrimitive.Clear
40
+ data-slot="combobox-clear"
41
+ render={<InputGroupButton variant="ghost" size="icon-xs" />}
42
+ className={cn(className)}
43
+ {...props}
44
+ >
45
+ <XIcon className="pointer-events-none" />
46
+ </ComboboxPrimitive.Clear>
47
+ )
48
+ }
49
+
50
+ function ComboboxInput({
51
+ className,
52
+ children,
53
+ disabled = false,
54
+ showTrigger = true,
55
+ showClear = false,
56
+ ...props
57
+ }: ComboboxPrimitive.Input.Props & {
58
+ showTrigger?: boolean
59
+ showClear?: boolean
60
+ }) {
61
+ return (
62
+ <InputGroup className={cn("w-auto", className)}>
63
+ <ComboboxPrimitive.Input
64
+ render={<InputGroupInput disabled={disabled} />}
65
+ {...props}
66
+ />
67
+ <InputGroupAddon align="inline-end">
68
+ {showTrigger && (
69
+ <InputGroupButton
70
+ size="icon-xs"
71
+ variant="ghost"
72
+ render={<ComboboxTrigger />}
73
+ data-slot="input-group-button"
74
+ className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent"
75
+ disabled={disabled}
76
+ />
77
+ )}
78
+ {showClear && <ComboboxClear disabled={disabled} />}
79
+ </InputGroupAddon>
80
+ {children}
81
+ </InputGroup>
82
+ )
83
+ }
84
+
85
+ function ComboboxContent({
86
+ className,
87
+ side = "bottom",
88
+ sideOffset = 6,
89
+ align = "start",
90
+ alignOffset = 0,
91
+ anchor,
92
+ ...props
93
+ }: ComboboxPrimitive.Popup.Props &
94
+ Pick<
95
+ ComboboxPrimitive.Positioner.Props,
96
+ "side" | "align" | "sideOffset" | "alignOffset" | "anchor"
97
+ >) {
98
+ return (
99
+ <ComboboxPrimitive.Portal>
100
+ <ComboboxPrimitive.Positioner
101
+ side={side}
102
+ sideOffset={sideOffset}
103
+ align={align}
104
+ alignOffset={alignOffset}
105
+ anchor={anchor}
106
+ className="isolate z-50"
107
+ >
108
+ <ComboboxPrimitive.Popup
109
+ data-slot="combobox-content"
110
+ data-chips={!!anchor}
111
+ className={cn("bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 *:data-[slot=input-group]:bg-input/20 dark:bg-popover max-h-72 min-w-32 overflow-hidden rounded-lg shadow-md ring-1 duration-100 *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-7 *:data-[slot=input-group]:border-none *:data-[slot=input-group]:shadow-none group/combobox-content relative max-h-(--available-height) w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) data-[chips=true]:min-w-(--anchor-width)", className )}
112
+ {...props}
113
+ />
114
+ </ComboboxPrimitive.Positioner>
115
+ </ComboboxPrimitive.Portal>
116
+ )
117
+ }
118
+
119
+ function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {
120
+ return (
121
+ <ComboboxPrimitive.List
122
+ data-slot="combobox-list"
123
+ className={cn(
124
+ "no-scrollbar max-h-[min(calc(--spacing(72)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto p-1 data-empty:p-0 overflow-y-auto overscroll-contain",
125
+ className
126
+ )}
127
+ {...props}
128
+ />
129
+ )
130
+ }
131
+
132
+ function ComboboxItem({
133
+ className,
134
+ children,
135
+ ...props
136
+ }: ComboboxPrimitive.Item.Props) {
137
+ return (
138
+ <ComboboxPrimitive.Item
139
+ data-slot="combobox-item"
140
+ className={cn(
141
+ "data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 relative flex w-full cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
142
+ className
143
+ )}
144
+ {...props}
145
+ >
146
+ {children}
147
+ <ComboboxPrimitive.ItemIndicator
148
+ render={<span className="pointer-events-none absolute right-2 flex items-center justify-center" />}
149
+ >
150
+ <CheckIcon className="pointer-events-none" />
151
+ </ComboboxPrimitive.ItemIndicator>
152
+ </ComboboxPrimitive.Item>
153
+ )
154
+ }
155
+
156
+ function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {
157
+ return (
158
+ <ComboboxPrimitive.Group
159
+ data-slot="combobox-group"
160
+ className={cn(className)}
161
+ {...props}
162
+ />
163
+ )
164
+ }
165
+
166
+ function ComboboxLabel({
167
+ className,
168
+ ...props
169
+ }: ComboboxPrimitive.GroupLabel.Props) {
170
+ return (
171
+ <ComboboxPrimitive.GroupLabel
172
+ data-slot="combobox-label"
173
+ className={cn("text-muted-foreground px-2 py-1.5 text-xs", className)}
174
+ {...props}
175
+ />
176
+ )
177
+ }
178
+
179
+ function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) {
180
+ return (
181
+ <ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} />
182
+ )
183
+ }
184
+
185
+ function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {
186
+ return (
187
+ <ComboboxPrimitive.Empty
188
+ data-slot="combobox-empty"
189
+ className={cn("text-muted-foreground hidden w-full justify-center py-2 text-center text-xs/relaxed group-data-empty/combobox-content:flex", className)}
190
+ {...props}
191
+ />
192
+ )
193
+ }
194
+
195
+ function ComboboxSeparator({
196
+ className,
197
+ ...props
198
+ }: ComboboxPrimitive.Separator.Props) {
199
+ return (
200
+ <ComboboxPrimitive.Separator
201
+ data-slot="combobox-separator"
202
+ className={cn("bg-border/50 -mx-1 my-1 h-px", className)}
203
+ {...props}
204
+ />
205
+ )
206
+ }
207
+
208
+ function ComboboxChips({
209
+ className,
210
+ ...props
211
+ }: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> &
212
+ ComboboxPrimitive.Chips.Props) {
213
+ return (
214
+ <ComboboxPrimitive.Chips
215
+ data-slot="combobox-chips"
216
+ className={cn("bg-input/20 dark:bg-input/30 border-input focus-within:border-ring focus-within:ring-ring/30 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 flex min-h-7 flex-wrap items-center gap-1 rounded-md border bg-clip-padding px-2 py-0.5 text-xs/relaxed transition-colors focus-within:ring-[2px] has-aria-invalid:ring-[2px] has-data-[slot=combobox-chip]:px-1", className)}
217
+ {...props}
218
+ />
219
+ )
220
+ }
221
+
222
+ function ComboboxChip({
223
+ className,
224
+ children,
225
+ showRemove = true,
226
+ ...props
227
+ }: ComboboxPrimitive.Chip.Props & {
228
+ showRemove?: boolean
229
+ }) {
230
+ return (
231
+ <ComboboxPrimitive.Chip
232
+ data-slot="combobox-chip"
233
+ className={cn(
234
+ "bg-muted-foreground/10 text-foreground flex h-[calc(--spacing(4.75))] w-fit items-center justify-center gap-1 rounded-[calc(var(--radius-sm)-2px)] px-1.5 text-xs/relaxed font-medium whitespace-nowrap has-data-[slot=combobox-chip-remove]:pr-0 has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50",
235
+ className
236
+ )}
237
+ {...props}
238
+ >
239
+ {children}
240
+ {showRemove && (
241
+ <ComboboxPrimitive.ChipRemove
242
+ render={<Button variant="ghost" size="icon-xs" />}
243
+ className="-ml-1 opacity-50 hover:opacity-100"
244
+ data-slot="combobox-chip-remove"
245
+ >
246
+ <XIcon className="pointer-events-none" />
247
+ </ComboboxPrimitive.ChipRemove>
248
+ )}
249
+ </ComboboxPrimitive.Chip>
250
+ )
251
+ }
252
+
253
+ function ComboboxChipsInput({
254
+ className,
255
+ ...props
256
+ }: ComboboxPrimitive.Input.Props) {
257
+ return (
258
+ <ComboboxPrimitive.Input
259
+ data-slot="combobox-chip-input"
260
+ className={cn(
261
+ "min-w-16 flex-1 outline-none",
262
+ className
263
+ )}
264
+ {...props}
265
+ />
266
+ )
267
+ }
268
+
269
+ function useComboboxAnchor() {
270
+ return React.useRef<HTMLDivElement | null>(null)
271
+ }
272
+
273
+ export {
274
+ Combobox,
275
+ ComboboxInput,
276
+ ComboboxContent,
277
+ ComboboxList,
278
+ ComboboxItem,
279
+ ComboboxGroup,
280
+ ComboboxLabel,
281
+ ComboboxCollection,
282
+ ComboboxEmpty,
283
+ ComboboxSeparator,
284
+ ComboboxChips,
285
+ ComboboxChip,
286
+ ComboboxChipsInput,
287
+ ComboboxTrigger,
288
+ ComboboxValue,
289
+ useComboboxAnchor,
290
+ }
@@ -0,0 +1,151 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Dialog as DialogPrimitive } from "@base-ui/react/dialog"
5
+
6
+ import { cn } from "../../lib/utils"
7
+ import { Button } from "./button"
8
+ import { XIcon } from "@phosphor-icons/react"
9
+
10
+ function Dialog({ ...props }: DialogPrimitive.Root.Props) {
11
+ return <DialogPrimitive.Root data-slot="dialog" {...props} />
12
+ }
13
+
14
+ function DialogTrigger({ ...props }: DialogPrimitive.Trigger.Props) {
15
+ return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />
16
+ }
17
+
18
+ function DialogPortal({ ...props }: DialogPrimitive.Portal.Props) {
19
+ return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />
20
+ }
21
+
22
+ function DialogClose({ ...props }: DialogPrimitive.Close.Props) {
23
+ return <DialogPrimitive.Close data-slot="dialog-close" {...props} />
24
+ }
25
+
26
+ function DialogOverlay({
27
+ className,
28
+ ...props
29
+ }: DialogPrimitive.Backdrop.Props) {
30
+ return (
31
+ <DialogPrimitive.Backdrop
32
+ data-slot="dialog-overlay"
33
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 bg-black/80 duration-100 supports-backdrop-filter:backdrop-blur-xs fixed inset-0 isolate z-50", className)}
34
+ {...props}
35
+ />
36
+ )
37
+ }
38
+
39
+ function DialogContent({
40
+ className,
41
+ children,
42
+ showCloseButton = true,
43
+ ...props
44
+ }: DialogPrimitive.Popup.Props & {
45
+ showCloseButton?: boolean
46
+ }) {
47
+ return (
48
+ <DialogPortal>
49
+ <DialogOverlay />
50
+ <DialogPrimitive.Popup
51
+ data-slot="dialog-content"
52
+ className={cn(
53
+ "bg-background data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 ring-foreground/10 grid max-w-[calc(100%-2rem)] gap-4 rounded-xl p-4 text-xs/relaxed ring-1 duration-100 sm:max-w-sm fixed top-1/2 left-1/2 z-50 w-full -translate-x-1/2 -translate-y-1/2 outline-none",
54
+ className
55
+ )}
56
+ {...props}
57
+ >
58
+ {children}
59
+ {showCloseButton && (
60
+ <DialogPrimitive.Close
61
+ data-slot="dialog-close"
62
+ render={
63
+ <Button
64
+ variant="ghost"
65
+ className="absolute top-2 right-2"
66
+ size="icon-sm"
67
+ />
68
+ }
69
+ >
70
+ <XIcon
71
+ />
72
+ <span className="sr-only">Close</span>
73
+ </DialogPrimitive.Close>
74
+ )}
75
+ </DialogPrimitive.Popup>
76
+ </DialogPortal>
77
+ )
78
+ }
79
+
80
+ function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
81
+ return (
82
+ <div
83
+ data-slot="dialog-header"
84
+ className={cn("gap-1 flex flex-col", className)}
85
+ {...props}
86
+ />
87
+ )
88
+ }
89
+
90
+ function DialogFooter({
91
+ className,
92
+ showCloseButton = false,
93
+ children,
94
+ ...props
95
+ }: React.ComponentProps<"div"> & {
96
+ showCloseButton?: boolean
97
+ }) {
98
+ return (
99
+ <div
100
+ data-slot="dialog-footer"
101
+ className={cn(
102
+ "gap-2 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
103
+ className
104
+ )}
105
+ {...props}
106
+ >
107
+ {children}
108
+ {showCloseButton && (
109
+ <DialogPrimitive.Close render={<Button variant="outline" />}>
110
+ Close
111
+ </DialogPrimitive.Close>
112
+ )}
113
+ </div>
114
+ )
115
+ }
116
+
117
+ function DialogTitle({ className, ...props }: DialogPrimitive.Title.Props) {
118
+ return (
119
+ <DialogPrimitive.Title
120
+ data-slot="dialog-title"
121
+ className={cn("text-sm font-medium", className)}
122
+ {...props}
123
+ />
124
+ )
125
+ }
126
+
127
+ function DialogDescription({
128
+ className,
129
+ ...props
130
+ }: DialogPrimitive.Description.Props) {
131
+ return (
132
+ <DialogPrimitive.Description
133
+ data-slot="dialog-description"
134
+ className={cn("text-muted-foreground *:[a]:hover:text-foreground text-xs/relaxed *:[a]:underline *:[a]:underline-offset-3", className)}
135
+ {...props}
136
+ />
137
+ )
138
+ }
139
+
140
+ export {
141
+ Dialog,
142
+ DialogClose,
143
+ DialogContent,
144
+ DialogDescription,
145
+ DialogFooter,
146
+ DialogHeader,
147
+ DialogOverlay,
148
+ DialogPortal,
149
+ DialogTitle,
150
+ DialogTrigger,
151
+ }
@@ -0,0 +1,254 @@
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import { Menu as MenuPrimitive } from "@base-ui/react/menu"
5
+
6
+ import { cn } from "../../lib/utils"
7
+ import { CaretRightIcon, CheckIcon } from "@phosphor-icons/react"
8
+
9
+ function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
10
+ return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />
11
+ }
12
+
13
+ function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
14
+ return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
15
+ }
16
+
17
+ function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
18
+ return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />
19
+ }
20
+
21
+ function DropdownMenuContent({
22
+ align = "start",
23
+ alignOffset = 0,
24
+ side = "bottom",
25
+ sideOffset = 4,
26
+ className,
27
+ ...props
28
+ }: MenuPrimitive.Popup.Props &
29
+ Pick<
30
+ MenuPrimitive.Positioner.Props,
31
+ "align" | "alignOffset" | "side" | "sideOffset"
32
+ >) {
33
+ return (
34
+ <MenuPrimitive.Portal>
35
+ <MenuPrimitive.Positioner
36
+ className="isolate z-50 outline-none"
37
+ align={align}
38
+ alignOffset={alignOffset}
39
+ side={side}
40
+ sideOffset={sideOffset}
41
+ >
42
+ <MenuPrimitive.Popup
43
+ data-slot="dropdown-menu-content"
44
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 z-50 max-h-(--available-height) w-(--anchor-width) origin-(--transform-origin) overflow-x-hidden overflow-y-auto outline-none data-closed:overflow-hidden", className )}
45
+ {...props}
46
+ />
47
+ </MenuPrimitive.Positioner>
48
+ </MenuPrimitive.Portal>
49
+ )
50
+ }
51
+
52
+ function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
53
+ return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
54
+ }
55
+
56
+ function DropdownMenuLabel({
57
+ className,
58
+ inset,
59
+ ...props
60
+ }: MenuPrimitive.GroupLabel.Props & {
61
+ inset?: boolean
62
+ }) {
63
+ return (
64
+ <MenuPrimitive.GroupLabel
65
+ data-slot="dropdown-menu-label"
66
+ data-inset={inset}
67
+ className={cn("text-muted-foreground px-2 py-1.5 text-xs data-[inset]:pl-8", className)}
68
+ {...props}
69
+ />
70
+ )
71
+ }
72
+
73
+ function DropdownMenuItem({
74
+ className,
75
+ inset,
76
+ variant = "default",
77
+ ...props
78
+ }: MenuPrimitive.Item.Props & {
79
+ inset?: boolean
80
+ variant?: "default" | "destructive"
81
+ }) {
82
+ return (
83
+ <MenuPrimitive.Item
84
+ data-slot="dropdown-menu-item"
85
+ data-inset={inset}
86
+ data-variant={variant}
87
+ className={cn(
88
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:text-destructive not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs/relaxed [&_svg:not([class*='size-'])]:size-3.5 group/dropdown-menu-item relative flex cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
89
+ className
90
+ )}
91
+ {...props}
92
+ />
93
+ )
94
+ }
95
+
96
+ function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
97
+ return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />
98
+ }
99
+
100
+ function DropdownMenuSubTrigger({
101
+ className,
102
+ inset,
103
+ children,
104
+ ...props
105
+ }: MenuPrimitive.SubmenuTrigger.Props & {
106
+ inset?: boolean
107
+ }) {
108
+ return (
109
+ <MenuPrimitive.SubmenuTrigger
110
+ data-slot="dropdown-menu-sub-trigger"
111
+ data-inset={inset}
112
+ className={cn(
113
+ "focus:bg-accent focus:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground min-h-7 gap-2 rounded-md px-2 py-1 text-xs [&_svg:not([class*='size-'])]:size-3.5 flex cursor-default items-center outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0",
114
+ className
115
+ )}
116
+ {...props}
117
+ >
118
+ {children}
119
+ <CaretRightIcon className="ml-auto" />
120
+ </MenuPrimitive.SubmenuTrigger>
121
+ )
122
+ }
123
+
124
+ function DropdownMenuSubContent({
125
+ align = "start",
126
+ alignOffset = -3,
127
+ side = "right",
128
+ sideOffset = 0,
129
+ className,
130
+ ...props
131
+ }: React.ComponentProps<typeof DropdownMenuContent>) {
132
+ return (
133
+ <DropdownMenuContent
134
+ data-slot="dropdown-menu-sub-content"
135
+ className={cn("data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground min-w-32 rounded-lg p-1 shadow-md ring-1 duration-100 w-auto", className)}
136
+ align={align}
137
+ alignOffset={alignOffset}
138
+ side={side}
139
+ sideOffset={sideOffset}
140
+ {...props}
141
+ />
142
+ )
143
+ }
144
+
145
+ function DropdownMenuCheckboxItem({
146
+ className,
147
+ children,
148
+ checked,
149
+ ...props
150
+ }: MenuPrimitive.CheckboxItem.Props) {
151
+ return (
152
+ <MenuPrimitive.CheckboxItem
153
+ data-slot="dropdown-menu-checkbox-item"
154
+ className={cn(
155
+ "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
156
+ className
157
+ )}
158
+ checked={checked}
159
+ {...props}
160
+ >
161
+ <span
162
+ className="pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none"
163
+ data-slot="dropdown-menu-checkbox-item-indicator"
164
+ >
165
+ <MenuPrimitive.CheckboxItemIndicator>
166
+ <CheckIcon
167
+ />
168
+ </MenuPrimitive.CheckboxItemIndicator>
169
+ </span>
170
+ {children}
171
+ </MenuPrimitive.CheckboxItem>
172
+ )
173
+ }
174
+
175
+ function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
176
+ return (
177
+ <MenuPrimitive.RadioGroup
178
+ data-slot="dropdown-menu-radio-group"
179
+ {...props}
180
+ />
181
+ )
182
+ }
183
+
184
+ function DropdownMenuRadioItem({
185
+ className,
186
+ children,
187
+ ...props
188
+ }: MenuPrimitive.RadioItem.Props) {
189
+ return (
190
+ <MenuPrimitive.RadioItem
191
+ data-slot="dropdown-menu-radio-item"
192
+ className={cn(
193
+ "focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground min-h-7 gap-2 rounded-md py-1.5 pr-8 pl-2 text-xs [&_svg:not([class*='size-'])]:size-3.5 relative flex cursor-default items-center outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
194
+ className
195
+ )}
196
+ {...props}
197
+ >
198
+ <span
199
+ className="pointer-events-none absolute right-2 flex items-center justify-center pointer-events-none"
200
+ data-slot="dropdown-menu-radio-item-indicator"
201
+ >
202
+ <MenuPrimitive.RadioItemIndicator>
203
+ <CheckIcon
204
+ />
205
+ </MenuPrimitive.RadioItemIndicator>
206
+ </span>
207
+ {children}
208
+ </MenuPrimitive.RadioItem>
209
+ )
210
+ }
211
+
212
+ function DropdownMenuSeparator({
213
+ className,
214
+ ...props
215
+ }: MenuPrimitive.Separator.Props) {
216
+ return (
217
+ <MenuPrimitive.Separator
218
+ data-slot="dropdown-menu-separator"
219
+ className={cn("bg-border/50 -mx-1 my-1 h-px", className)}
220
+ {...props}
221
+ />
222
+ )
223
+ }
224
+
225
+ function DropdownMenuShortcut({
226
+ className,
227
+ ...props
228
+ }: React.ComponentProps<"span">) {
229
+ return (
230
+ <span
231
+ data-slot="dropdown-menu-shortcut"
232
+ className={cn("text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground ml-auto text-[0.625rem] tracking-widest", className)}
233
+ {...props}
234
+ />
235
+ )
236
+ }
237
+
238
+ export {
239
+ DropdownMenu,
240
+ DropdownMenuPortal,
241
+ DropdownMenuTrigger,
242
+ DropdownMenuContent,
243
+ DropdownMenuGroup,
244
+ DropdownMenuLabel,
245
+ DropdownMenuItem,
246
+ DropdownMenuCheckboxItem,
247
+ DropdownMenuRadioGroup,
248
+ DropdownMenuRadioItem,
249
+ DropdownMenuSeparator,
250
+ DropdownMenuShortcut,
251
+ DropdownMenuSub,
252
+ DropdownMenuSubTrigger,
253
+ DropdownMenuSubContent,
254
+ }