@questpie/admin 0.0.1 → 1.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 (250) hide show
  1. package/README.md +439 -424
  2. package/dist/auth-layout-M8K8_q5R.mjs +181 -0
  3. package/dist/auth-layout-M8K8_q5R.mjs.map +1 -0
  4. package/dist/bulk-upload-dialog-h7zXD78Y.mjs +274 -0
  5. package/dist/bulk-upload-dialog-h7zXD78Y.mjs.map +1 -0
  6. package/dist/{components/ui/card.mjs → card-BKHjBQfw.mjs} +8 -8
  7. package/dist/card-BKHjBQfw.mjs.map +1 -0
  8. package/dist/client/styles/index.css +434 -0
  9. package/dist/client-BCGpkAz6.mjs +22635 -0
  10. package/dist/client-BCGpkAz6.mjs.map +1 -0
  11. package/dist/client-CcWZbkBP.d.mts +13585 -0
  12. package/dist/client-CcWZbkBP.d.mts.map +1 -0
  13. package/dist/client.d.mts +3 -0
  14. package/dist/client.mjs +14 -0
  15. package/dist/content-locales-provider-BXvuIgfg.mjs +1650 -0
  16. package/dist/content-locales-provider-BXvuIgfg.mjs.map +1 -0
  17. package/dist/dashboard-page-B4PGEdc2.mjs +2500 -0
  18. package/dist/dashboard-page-B4PGEdc2.mjs.map +1 -0
  19. package/dist/dashboard-page-CVlyR40m.mjs +6 -0
  20. package/dist/dropzone-Do3awXKd.mjs +634 -0
  21. package/dist/dropzone-Do3awXKd.mjs.map +1 -0
  22. package/dist/{views/auth/forgot-password-form.mjs → forgot-password-page-Bcp-An4Y.mjs} +87 -14
  23. package/dist/forgot-password-page-Bcp-An4Y.mjs.map +1 -0
  24. package/dist/forgot-password-page-CIILVhfo.mjs +7 -0
  25. package/dist/index-B9Xwk4hi.d.mts +2753 -0
  26. package/dist/index-B9Xwk4hi.d.mts.map +1 -0
  27. package/dist/index.d.mts +3 -0
  28. package/dist/index.mjs +14 -0
  29. package/dist/login-page-8K7fo0qK.mjs +7 -0
  30. package/dist/login-page-CP4gA-dl.mjs +298 -0
  31. package/dist/login-page-CP4gA-dl.mjs.map +1 -0
  32. package/dist/preview-utils-BKQ9-TMa.mjs +65 -0
  33. package/dist/preview-utils-BKQ9-TMa.mjs.map +1 -0
  34. package/dist/{views/auth/reset-password-form.mjs → reset-password-page-BqfDmLxA.mjs} +111 -14
  35. package/dist/reset-password-page-BqfDmLxA.mjs.map +1 -0
  36. package/dist/reset-password-page-DLATv0xQ.mjs +7 -0
  37. package/dist/runtime-6VZM878K.mjs +69 -0
  38. package/dist/runtime-6VZM878K.mjs.map +1 -0
  39. package/dist/saved-views.types-BMsz5mCy.d.mts +42 -0
  40. package/dist/saved-views.types-BMsz5mCy.d.mts.map +1 -0
  41. package/dist/server.d.mts +250 -0
  42. package/dist/server.d.mts.map +1 -0
  43. package/dist/server.mjs +832 -0
  44. package/dist/server.mjs.map +1 -0
  45. package/dist/setup-page-CMZ5P_OE.mjs +6 -0
  46. package/dist/setup-page-YAP_fzqh.mjs +264 -0
  47. package/dist/setup-page-YAP_fzqh.mjs.map +1 -0
  48. package/dist/shared.d.mts +57 -0
  49. package/dist/shared.d.mts.map +1 -0
  50. package/dist/shared.mjs +3 -0
  51. package/dist/{hooks/use-auth.mjs → use-auth-BoLmWtmU.mjs} +42 -30
  52. package/dist/use-auth-BoLmWtmU.mjs.map +1 -0
  53. package/package.json +48 -197
  54. package/.turbo/turbo-build.log +0 -108
  55. package/CHANGELOG.md +0 -10
  56. package/STATUS.md +0 -917
  57. package/VALIDATION.md +0 -602
  58. package/components.json +0 -24
  59. package/dist/__tests__/setup.mjs +0 -38
  60. package/dist/__tests__/test-utils.mjs +0 -45
  61. package/dist/__tests__/vitest.d.mjs +0 -3
  62. package/dist/components/admin-app.mjs +0 -69
  63. package/dist/components/fields/array-field.mjs +0 -190
  64. package/dist/components/fields/checkbox-field.mjs +0 -34
  65. package/dist/components/fields/custom-field.mjs +0 -32
  66. package/dist/components/fields/date-field.mjs +0 -41
  67. package/dist/components/fields/datetime-field.mjs +0 -42
  68. package/dist/components/fields/email-field.mjs +0 -37
  69. package/dist/components/fields/embedded-collection.mjs +0 -253
  70. package/dist/components/fields/field-types.mjs +0 -1
  71. package/dist/components/fields/field-utils.mjs +0 -10
  72. package/dist/components/fields/field-wrapper.mjs +0 -34
  73. package/dist/components/fields/index.mjs +0 -23
  74. package/dist/components/fields/json-field.mjs +0 -243
  75. package/dist/components/fields/locale-badge.mjs +0 -16
  76. package/dist/components/fields/number-field.mjs +0 -39
  77. package/dist/components/fields/password-field.mjs +0 -37
  78. package/dist/components/fields/relation-field.mjs +0 -104
  79. package/dist/components/fields/relation-picker.mjs +0 -229
  80. package/dist/components/fields/relation-select.mjs +0 -188
  81. package/dist/components/fields/rich-text-editor/index.mjs +0 -897
  82. package/dist/components/fields/select-field.mjs +0 -41
  83. package/dist/components/fields/switch-field.mjs +0 -34
  84. package/dist/components/fields/text-field.mjs +0 -38
  85. package/dist/components/fields/textarea-field.mjs +0 -38
  86. package/dist/components/index.mjs +0 -59
  87. package/dist/components/primitives/checkbox-input.mjs +0 -127
  88. package/dist/components/primitives/date-input.mjs +0 -303
  89. package/dist/components/primitives/index.mjs +0 -12
  90. package/dist/components/primitives/number-input.mjs +0 -104
  91. package/dist/components/primitives/select-input.mjs +0 -177
  92. package/dist/components/primitives/tag-input.mjs +0 -135
  93. package/dist/components/primitives/text-input.mjs +0 -39
  94. package/dist/components/primitives/textarea-input.mjs +0 -37
  95. package/dist/components/primitives/toggle-input.mjs +0 -31
  96. package/dist/components/primitives/types.mjs +0 -12
  97. package/dist/components/ui/accordion.mjs +0 -55
  98. package/dist/components/ui/avatar.mjs +0 -54
  99. package/dist/components/ui/badge.mjs +0 -34
  100. package/dist/components/ui/button.mjs +0 -48
  101. package/dist/components/ui/checkbox.mjs +0 -21
  102. package/dist/components/ui/combobox.mjs +0 -163
  103. package/dist/components/ui/dialog.mjs +0 -95
  104. package/dist/components/ui/dropdown-menu.mjs +0 -138
  105. package/dist/components/ui/field.mjs +0 -113
  106. package/dist/components/ui/input-group.mjs +0 -82
  107. package/dist/components/ui/input.mjs +0 -17
  108. package/dist/components/ui/label.mjs +0 -15
  109. package/dist/components/ui/popover.mjs +0 -56
  110. package/dist/components/ui/scroll-area.mjs +0 -38
  111. package/dist/components/ui/select.mjs +0 -100
  112. package/dist/components/ui/separator.mjs +0 -16
  113. package/dist/components/ui/sheet.mjs +0 -90
  114. package/dist/components/ui/sidebar.mjs +0 -387
  115. package/dist/components/ui/skeleton.mjs +0 -14
  116. package/dist/components/ui/spinner.mjs +0 -16
  117. package/dist/components/ui/switch.mjs +0 -22
  118. package/dist/components/ui/table.mjs +0 -68
  119. package/dist/components/ui/tabs.mjs +0 -48
  120. package/dist/components/ui/textarea.mjs +0 -15
  121. package/dist/components/ui/tooltip.mjs +0 -44
  122. package/dist/config/component-registry.mjs +0 -38
  123. package/dist/config/index.mjs +0 -129
  124. package/dist/hooks/admin-provider.mjs +0 -70
  125. package/dist/hooks/index.mjs +0 -7
  126. package/dist/hooks/store.mjs +0 -178
  127. package/dist/hooks/use-collection-db.mjs +0 -146
  128. package/dist/hooks/use-collection.mjs +0 -112
  129. package/dist/hooks/use-global.mjs +0 -46
  130. package/dist/hooks/use-mobile.mjs +0 -20
  131. package/dist/lib/utils.mjs +0 -10
  132. package/dist/styles/index.css +0 -336
  133. package/dist/styles/index.mjs +0 -1
  134. package/dist/utils/index.mjs +0 -9
  135. package/dist/views/auth/auth-layout.mjs +0 -52
  136. package/dist/views/auth/index.mjs +0 -6
  137. package/dist/views/auth/login-form.mjs +0 -156
  138. package/dist/views/collection/auto-form-fields.mjs +0 -525
  139. package/dist/views/collection/collection-form.mjs +0 -91
  140. package/dist/views/collection/collection-list.mjs +0 -76
  141. package/dist/views/collection/form-field.mjs +0 -42
  142. package/dist/views/collection/index.mjs +0 -6
  143. package/dist/views/common/index.mjs +0 -4
  144. package/dist/views/common/locale-switcher.mjs +0 -39
  145. package/dist/views/common/version-history.mjs +0 -272
  146. package/dist/views/index.mjs +0 -9
  147. package/dist/views/layout/admin-layout.mjs +0 -40
  148. package/dist/views/layout/admin-router.mjs +0 -95
  149. package/dist/views/layout/admin-sidebar.mjs +0 -63
  150. package/dist/views/layout/index.mjs +0 -5
  151. package/src/__tests__/setup.ts +0 -44
  152. package/src/__tests__/test-utils.tsx +0 -49
  153. package/src/__tests__/vitest.d.ts +0 -9
  154. package/src/components/admin-app.tsx +0 -221
  155. package/src/components/fields/array-field.tsx +0 -237
  156. package/src/components/fields/checkbox-field.tsx +0 -47
  157. package/src/components/fields/custom-field.tsx +0 -50
  158. package/src/components/fields/date-field.tsx +0 -65
  159. package/src/components/fields/datetime-field.tsx +0 -67
  160. package/src/components/fields/email-field.tsx +0 -51
  161. package/src/components/fields/embedded-collection.tsx +0 -315
  162. package/src/components/fields/field-types.ts +0 -162
  163. package/src/components/fields/field-utils.ts +0 -6
  164. package/src/components/fields/field-wrapper.tsx +0 -52
  165. package/src/components/fields/index.ts +0 -66
  166. package/src/components/fields/json-field.tsx +0 -440
  167. package/src/components/fields/locale-badge.tsx +0 -15
  168. package/src/components/fields/number-field.tsx +0 -57
  169. package/src/components/fields/password-field.tsx +0 -51
  170. package/src/components/fields/relation-field.tsx +0 -243
  171. package/src/components/fields/relation-picker.tsx +0 -402
  172. package/src/components/fields/relation-select.tsx +0 -327
  173. package/src/components/fields/rich-text-editor/index.tsx +0 -1337
  174. package/src/components/fields/select-field.tsx +0 -61
  175. package/src/components/fields/switch-field.tsx +0 -47
  176. package/src/components/fields/text-field.tsx +0 -55
  177. package/src/components/fields/textarea-field.tsx +0 -55
  178. package/src/components/index.ts +0 -40
  179. package/src/components/primitives/checkbox-input.tsx +0 -193
  180. package/src/components/primitives/date-input.tsx +0 -401
  181. package/src/components/primitives/index.ts +0 -24
  182. package/src/components/primitives/number-input.tsx +0 -132
  183. package/src/components/primitives/select-input.tsx +0 -296
  184. package/src/components/primitives/tag-input.tsx +0 -200
  185. package/src/components/primitives/text-input.tsx +0 -49
  186. package/src/components/primitives/textarea-input.tsx +0 -46
  187. package/src/components/primitives/toggle-input.tsx +0 -36
  188. package/src/components/primitives/types.ts +0 -235
  189. package/src/components/ui/accordion.tsx +0 -72
  190. package/src/components/ui/avatar.tsx +0 -106
  191. package/src/components/ui/badge.tsx +0 -48
  192. package/src/components/ui/button.tsx +0 -53
  193. package/src/components/ui/card.tsx +0 -94
  194. package/src/components/ui/checkbox.tsx +0 -27
  195. package/src/components/ui/combobox.tsx +0 -290
  196. package/src/components/ui/dialog.tsx +0 -151
  197. package/src/components/ui/dropdown-menu.tsx +0 -254
  198. package/src/components/ui/field.tsx +0 -227
  199. package/src/components/ui/input-group.tsx +0 -149
  200. package/src/components/ui/input.tsx +0 -20
  201. package/src/components/ui/label.tsx +0 -18
  202. package/src/components/ui/popover.tsx +0 -88
  203. package/src/components/ui/scroll-area.tsx +0 -53
  204. package/src/components/ui/select.tsx +0 -192
  205. package/src/components/ui/separator.tsx +0 -23
  206. package/src/components/ui/sheet.tsx +0 -127
  207. package/src/components/ui/sidebar.tsx +0 -723
  208. package/src/components/ui/skeleton.tsx +0 -13
  209. package/src/components/ui/spinner.tsx +0 -10
  210. package/src/components/ui/switch.tsx +0 -32
  211. package/src/components/ui/table.tsx +0 -99
  212. package/src/components/ui/tabs.tsx +0 -82
  213. package/src/components/ui/textarea.tsx +0 -18
  214. package/src/components/ui/tooltip.tsx +0 -70
  215. package/src/config/component-registry.ts +0 -190
  216. package/src/config/index.ts +0 -1099
  217. package/src/hooks/README.md +0 -269
  218. package/src/hooks/admin-provider.tsx +0 -110
  219. package/src/hooks/index.ts +0 -41
  220. package/src/hooks/store.ts +0 -248
  221. package/src/hooks/use-auth.ts +0 -168
  222. package/src/hooks/use-collection-db.ts +0 -209
  223. package/src/hooks/use-collection.ts +0 -156
  224. package/src/hooks/use-global.ts +0 -69
  225. package/src/hooks/use-mobile.ts +0 -21
  226. package/src/lib/utils.ts +0 -6
  227. package/src/styles/index.css +0 -340
  228. package/src/utils/index.ts +0 -6
  229. package/src/views/auth/auth-layout.tsx +0 -77
  230. package/src/views/auth/forgot-password-form.tsx +0 -192
  231. package/src/views/auth/index.ts +0 -21
  232. package/src/views/auth/login-form.tsx +0 -229
  233. package/src/views/auth/reset-password-form.tsx +0 -232
  234. package/src/views/collection/auto-form-fields.tsx +0 -982
  235. package/src/views/collection/collection-form.tsx +0 -186
  236. package/src/views/collection/collection-list.tsx +0 -223
  237. package/src/views/collection/form-field.tsx +0 -52
  238. package/src/views/collection/index.ts +0 -15
  239. package/src/views/common/index.ts +0 -8
  240. package/src/views/common/locale-switcher.tsx +0 -45
  241. package/src/views/common/version-history.tsx +0 -406
  242. package/src/views/index.ts +0 -25
  243. package/src/views/layout/admin-layout.tsx +0 -117
  244. package/src/views/layout/admin-router.tsx +0 -206
  245. package/src/views/layout/admin-sidebar.tsx +0 -185
  246. package/src/views/layout/index.ts +0 -12
  247. package/tsconfig.json +0 -13
  248. package/tsconfig.tsbuildinfo +0 -1
  249. package/tsdown.config.ts +0 -13
  250. package/vitest.config.ts +0 -29
@@ -1,51 +0,0 @@
1
- import { Controller } from "react-hook-form";
2
- import { TextInput } from "../primitives/text-input";
3
- import { FieldWrapper } from "./field-wrapper";
4
- import { useResolvedControl } from "./field-utils";
5
- import type { BaseFieldProps } from "./field-types";
6
-
7
- export function EmailField({
8
- name,
9
- label,
10
- description,
11
- placeholder,
12
- required,
13
- disabled,
14
- localized,
15
- locale,
16
- control,
17
- className,
18
- }: BaseFieldProps) {
19
- const resolvedControl = useResolvedControl(control);
20
-
21
- return (
22
- <Controller
23
- name={name}
24
- control={resolvedControl}
25
- render={({ field, fieldState }) => (
26
- <FieldWrapper
27
- name={name}
28
- label={label}
29
- description={description}
30
- required={required}
31
- disabled={disabled}
32
- localized={localized}
33
- locale={locale}
34
- error={fieldState.error?.message}
35
- >
36
- <TextInput
37
- id={name}
38
- value={field.value ?? ""}
39
- onChange={field.onChange}
40
- type="email"
41
- placeholder={placeholder}
42
- disabled={disabled}
43
- autoComplete="email"
44
- aria-invalid={!!fieldState.error}
45
- className={className}
46
- />
47
- </FieldWrapper>
48
- )}
49
- />
50
- );
51
- }
@@ -1,315 +0,0 @@
1
- /**
2
- * EmbeddedCollectionField Component
3
- *
4
- * Manages embedded collections with inline, modal, or drawer editing.
5
- */
6
-
7
- import * as React from "react";
8
- import { useFieldArray, useFormContext, useWatch } from "react-hook-form";
9
- import { CaretDown, CaretUp, Pencil, Plus, Trash } from "@phosphor-icons/react";
10
- import { Button } from "../ui/button";
11
- import { LocaleBadge } from "./locale-badge";
12
- import {
13
- Dialog,
14
- DialogContent,
15
- DialogDescription,
16
- DialogHeader,
17
- DialogTitle,
18
- } from "../ui/dialog";
19
- import {
20
- Sheet,
21
- SheetContent,
22
- SheetDescription,
23
- SheetHeader,
24
- SheetTitle,
25
- } from "../ui/sheet";
26
- import type { EmbeddedCollectionProps } from "../../config/component-registry";
27
-
28
- type RowLabel = ((item: any) => string) | string;
29
-
30
- export interface EmbeddedCollectionFieldProps
31
- extends Omit<EmbeddedCollectionProps, "rowLabel"> {
32
- rowLabel?: RowLabel;
33
- renderFields?: (index: number) => React.ReactNode;
34
- minItems?: number;
35
- maxItems?: number;
36
- }
37
-
38
- export function EmbeddedCollectionField({
39
- name,
40
- value,
41
- collection,
42
- mode = "inline",
43
- orderable = false,
44
- rowLabel,
45
- label,
46
- description,
47
- required,
48
- disabled,
49
- readOnly,
50
- error,
51
- placeholder,
52
- localized,
53
- locale,
54
- renderFields,
55
- minItems,
56
- maxItems,
57
- }: EmbeddedCollectionFieldProps) {
58
- const form = useFormContext();
59
- const { control } = form;
60
- const { fields, append, remove, move } = useFieldArray({ control, name });
61
- const values = (useWatch({ control, name }) as any[] | undefined) ?? value;
62
-
63
- const [activeIndex, setActiveIndex] = React.useState<number | null>(null);
64
- const [isOpen, setIsOpen] = React.useState(false);
65
-
66
- const canAddMore = !maxItems || fields.length < maxItems;
67
- const canRemove = !readOnly && (!minItems || fields.length > minItems);
68
- const fallbackLabel = label || collection || "Item";
69
-
70
- const resolveRowLabel = React.useCallback(
71
- (item: any, index: number) => {
72
- if (typeof rowLabel === "function") {
73
- const labelValue = rowLabel(item);
74
- if (labelValue) return labelValue;
75
- }
76
- if (typeof rowLabel === "string") {
77
- const labelValue = item?.[rowLabel];
78
- if (labelValue) return String(labelValue);
79
- }
80
- if (item?.title) return String(item.title);
81
- if (item?.name) return String(item.name);
82
- return `${fallbackLabel} ${index + 1}`;
83
- },
84
- [fallbackLabel, rowLabel],
85
- );
86
-
87
- const handleAdd = () => {
88
- if (disabled || readOnly || !canAddMore) return;
89
- append({});
90
- if (mode !== "inline") {
91
- const nextIndex = fields.length;
92
- setActiveIndex(nextIndex);
93
- setIsOpen(true);
94
- }
95
- };
96
-
97
- const handleRemove = (index: number) => {
98
- if (!canRemove) return;
99
- remove(index);
100
- if (activeIndex === null) return;
101
- if (index === activeIndex) {
102
- setIsOpen(false);
103
- setActiveIndex(null);
104
- } else if (index < activeIndex) {
105
- setActiveIndex(activeIndex - 1);
106
- }
107
- };
108
-
109
- const handleMove = (from: number, to: number) => {
110
- if (to < 0 || to >= fields.length) return;
111
- move(from, to);
112
- if (activeIndex === null) return;
113
- if (activeIndex === from) {
114
- setActiveIndex(to);
115
- } else if (activeIndex === to) {
116
- setActiveIndex(from);
117
- }
118
- };
119
-
120
- const handleOpenChange = (open: boolean) => {
121
- setIsOpen(open);
122
- if (!open) {
123
- setActiveIndex(null);
124
- }
125
- };
126
-
127
- const renderItemFields = (index: number) => {
128
- if (!renderFields) {
129
- return (
130
- <div className="rounded-lg border border-dashed p-4 text-center">
131
- <p className="text-sm text-muted-foreground">
132
- Form fields not configured.
133
- </p>
134
- </div>
135
- );
136
- }
137
- return renderFields(index);
138
- };
139
-
140
- const emptyState = (
141
- <div className="rounded-lg border border-dashed p-4 text-center">
142
- <p className="text-sm text-muted-foreground">
143
- {placeholder || `No ${fallbackLabel} added yet`}
144
- </p>
145
- </div>
146
- );
147
-
148
- const editorContent =
149
- activeIndex !== null ? renderItemFields(activeIndex) : null;
150
- const editorTitle =
151
- activeIndex !== null
152
- ? resolveRowLabel(values?.[activeIndex], activeIndex)
153
- : fallbackLabel;
154
-
155
- const showEditor = mode === "modal" || mode === "drawer";
156
-
157
- return (
158
- <div className="space-y-2">
159
- {label && (
160
- <div className="flex items-center gap-2">
161
- <label htmlFor={name} className="text-sm font-medium">
162
- {label}
163
- {required && <span className="text-destructive">*</span>}
164
- {maxItems && (
165
- <span className="ml-2 text-xs text-muted-foreground">
166
- ({fields.length}/{maxItems})
167
- </span>
168
- )}
169
- </label>
170
- {localized && <LocaleBadge locale={locale || "i18n"} />}
171
- </div>
172
- )}
173
- {description && (
174
- <p className="text-sm text-muted-foreground">{description}</p>
175
- )}
176
-
177
- <div className="space-y-3">
178
- {fields.length === 0
179
- ? emptyState
180
- : fields.map((field, index) => {
181
- const itemValue = values?.[index];
182
- const itemLabel = resolveRowLabel(itemValue, index);
183
- const canMoveUp = orderable && index > 0;
184
- const canMoveDown = orderable && index < fields.length - 1;
185
-
186
- return (
187
- <div key={field.id} className="rounded-lg border bg-card">
188
- <div className="flex items-center justify-between border-b px-3 py-2">
189
- <div className="flex items-center gap-2">
190
- <span className="text-xs text-muted-foreground">
191
- #{index + 1}
192
- </span>
193
- <span className="text-sm font-medium">{itemLabel}</span>
194
- </div>
195
- <div className="flex items-center gap-1">
196
- {orderable && !readOnly && (
197
- <>
198
- <Button
199
- type="button"
200
- variant="ghost"
201
- size="icon"
202
- className="h-6 w-6"
203
- onClick={() => handleMove(index, index - 1)}
204
- disabled={!canMoveUp || disabled}
205
- title="Move up"
206
- >
207
- <CaretUp className="h-3 w-3" />
208
- </Button>
209
- <Button
210
- type="button"
211
- variant="ghost"
212
- size="icon"
213
- className="h-6 w-6"
214
- onClick={() => handleMove(index, index + 1)}
215
- disabled={!canMoveDown || disabled}
216
- title="Move down"
217
- >
218
- <CaretDown className="h-3 w-3" />
219
- </Button>
220
- </>
221
- )}
222
- {mode !== "inline" && (
223
- <Button
224
- type="button"
225
- variant="ghost"
226
- size="icon"
227
- className="h-6 w-6"
228
- onClick={() => {
229
- setActiveIndex(index);
230
- setIsOpen(true);
231
- }}
232
- disabled={disabled || !renderFields}
233
- title={readOnly ? "View" : "Edit"}
234
- >
235
- <Pencil className="h-3 w-3" />
236
- </Button>
237
- )}
238
- {!readOnly && canRemove && (
239
- <Button
240
- type="button"
241
- variant="ghost"
242
- size="icon"
243
- className="h-6 w-6"
244
- onClick={() => handleRemove(index)}
245
- disabled={disabled}
246
- title="Remove"
247
- >
248
- <Trash className="h-3 w-3" />
249
- </Button>
250
- )}
251
- </div>
252
- </div>
253
- {mode === "inline" && (
254
- <div className="space-y-3 p-3">
255
- {renderItemFields(index)}
256
- </div>
257
- )}
258
- </div>
259
- );
260
- })}
261
- </div>
262
-
263
- {!readOnly && canAddMore && (
264
- <Button
265
- type="button"
266
- variant="outline"
267
- onClick={handleAdd}
268
- disabled={disabled}
269
- >
270
- <Plus className="h-4 w-4" />
271
- Add {fallbackLabel}
272
- </Button>
273
- )}
274
-
275
- {error && <p className="text-sm text-destructive">{error}</p>}
276
-
277
- {showEditor && mode === "modal" && (
278
- <Dialog open={isOpen} onOpenChange={handleOpenChange}>
279
- <DialogContent className="sm:max-w-2xl">
280
- <DialogHeader>
281
- <DialogTitle>{editorTitle}</DialogTitle>
282
- {description && (
283
- <DialogDescription>{description}</DialogDescription>
284
- )}
285
- </DialogHeader>
286
- <div className="space-y-4">{editorContent}</div>
287
- </DialogContent>
288
- </Dialog>
289
- )}
290
-
291
- {showEditor && mode === "drawer" && (
292
- <Sheet open={isOpen} onOpenChange={handleOpenChange}>
293
- <SheetContent side="right" className="sm:max-w-lg">
294
- <SheetHeader>
295
- <SheetTitle>{editorTitle}</SheetTitle>
296
- {description && (
297
- <SheetDescription>{description}</SheetDescription>
298
- )}
299
- </SheetHeader>
300
- <div className="px-4 pb-4">{editorContent}</div>
301
- <div className="px-4 pb-4">
302
- <Button
303
- type="button"
304
- variant="outline"
305
- onClick={() => handleOpenChange(false)}
306
- >
307
- Close
308
- </Button>
309
- </div>
310
- </SheetContent>
311
- </Sheet>
312
- )}
313
- </div>
314
- );
315
- }
@@ -1,162 +0,0 @@
1
- import type * as React from "react";
2
- import type { Control } from "react-hook-form";
3
- import type {
4
- SelectOption as PrimitiveSelectOption,
5
- SelectOptionGroup,
6
- } from "../primitives/types";
7
-
8
- // Re-export SelectOption for backwards compatibility
9
- export type SelectOption<TValue = string> = PrimitiveSelectOption<TValue>;
10
- export type { SelectOptionGroup };
11
-
12
- /**
13
- * Base props shared by all field components.
14
- * These integrate with react-hook-form via Controller.
15
- */
16
- export type BaseFieldProps = {
17
- /** Field name (path in form values) */
18
- name: string;
19
- /** Field label */
20
- label?: string;
21
- /** Helper text shown below the field */
22
- description?: string;
23
- /** Placeholder text */
24
- placeholder?: string;
25
- /** Mark field as required (visual indicator) */
26
- required?: boolean;
27
- /** Disable the field */
28
- disabled?: boolean;
29
- /** Show locale badge for localized fields */
30
- localized?: boolean;
31
- /** Current locale code for localized fields */
32
- locale?: string;
33
- /** Form control from react-hook-form (optional if using FormProvider) */
34
- control?: Control<any>;
35
- /** Additional className for the field wrapper */
36
- className?: string;
37
- };
38
-
39
- /**
40
- * Field types supported by the FormField component
41
- */
42
- export type FormFieldType =
43
- | "text"
44
- | "email"
45
- | "password"
46
- | "url"
47
- | "tel"
48
- | "search"
49
- | "number"
50
- | "textarea"
51
- | "checkbox"
52
- | "switch"
53
- | "select"
54
- | "multiselect"
55
- | "date"
56
- | "datetime"
57
- | "daterange"
58
- | "tags";
59
-
60
- /**
61
- * Props for the generic FormField component
62
- */
63
- export type FormFieldProps = BaseFieldProps & {
64
- type?: FormFieldType;
65
- options?: SelectOption[];
66
- component?: React.ComponentType<any>;
67
- };
68
-
69
- /**
70
- * Props for text-based fields
71
- */
72
- export type TextFieldProps = BaseFieldProps & {
73
- type?: "text" | "email" | "password" | "url" | "tel" | "search";
74
- maxLength?: number;
75
- autoComplete?: string;
76
- };
77
-
78
- /**
79
- * Props for number field
80
- */
81
- export type NumberFieldProps = BaseFieldProps & {
82
- min?: number;
83
- max?: number;
84
- step?: number;
85
- showButtons?: boolean;
86
- };
87
-
88
- /**
89
- * Props for textarea field
90
- */
91
- export type TextareaFieldProps = BaseFieldProps & {
92
- rows?: number;
93
- maxLength?: number;
94
- autoResize?: boolean;
95
- };
96
-
97
- /**
98
- * Props for select field
99
- */
100
- export type SelectFieldProps<TValue = string> = BaseFieldProps & {
101
- options?: SelectOption<TValue>[];
102
- loadOptions?: (search: string) => Promise<SelectOption<TValue>[]>;
103
- multiple?: boolean;
104
- clearable?: boolean;
105
- maxSelections?: number;
106
- emptyMessage?: string;
107
- };
108
-
109
- /**
110
- * Props for date field
111
- */
112
- export type DateFieldProps = BaseFieldProps & {
113
- minDate?: Date;
114
- maxDate?: Date;
115
- format?: string;
116
- };
117
-
118
- /**
119
- * Props for datetime field
120
- */
121
- export type DateTimeFieldProps = DateFieldProps & {
122
- precision?: "minute" | "second";
123
- };
124
-
125
- /**
126
- * Props for date range field
127
- */
128
- export type DateRangeFieldProps = BaseFieldProps & {
129
- minDate?: Date;
130
- maxDate?: Date;
131
- };
132
-
133
- /**
134
- * Props for tags field
135
- */
136
- export type TagsFieldProps = BaseFieldProps & {
137
- suggestions?: string[];
138
- maxTags?: number;
139
- allowDuplicates?: boolean;
140
- pattern?: RegExp;
141
- };
142
-
143
- /**
144
- * Props for checkbox/switch fields
145
- */
146
- export type BooleanFieldProps = BaseFieldProps;
147
-
148
- /**
149
- * Props for checkbox group field
150
- */
151
- export type CheckboxGroupFieldProps<TValue = string> = BaseFieldProps & {
152
- options: SelectOption<TValue>[];
153
- orientation?: "horizontal" | "vertical";
154
- };
155
-
156
- /**
157
- * Props for radio group field
158
- */
159
- export type RadioGroupFieldProps<TValue = string> = BaseFieldProps & {
160
- options: SelectOption<TValue>[];
161
- orientation?: "horizontal" | "vertical";
162
- };
@@ -1,6 +0,0 @@
1
- import { useFormContext, type Control } from "react-hook-form";
2
-
3
- export function useResolvedControl(control?: Control<any>) {
4
- const form = useFormContext();
5
- return control ?? form.control;
6
- }
@@ -1,52 +0,0 @@
1
- import * as React from "react";
2
- import {
3
- Field,
4
- FieldContent,
5
- FieldDescription,
6
- FieldError,
7
- FieldLabel,
8
- } from "../ui/field";
9
- import { LocaleBadge } from "./locale-badge";
10
-
11
- type FieldWrapperProps = {
12
- name: string;
13
- label?: string;
14
- description?: string;
15
- required?: boolean;
16
- disabled?: boolean;
17
- error?: string;
18
- localized?: boolean;
19
- locale?: string;
20
- children: React.ReactNode;
21
- };
22
-
23
- export function FieldWrapper({
24
- name,
25
- label,
26
- description,
27
- required,
28
- disabled,
29
- error,
30
- localized,
31
- locale,
32
- children,
33
- }: FieldWrapperProps) {
34
- return (
35
- <Field data-disabled={disabled} data-invalid={!!error}>
36
- <div className="space-y-2">
37
- {label && (
38
- <FieldLabel htmlFor={name} className="flex items-center gap-2">
39
- <span className="flex items-center gap-1">
40
- {label}
41
- {required && <span className="text-destructive">*</span>}
42
- </span>
43
- {localized && <LocaleBadge locale={locale || "i18n"} />}
44
- </FieldLabel>
45
- )}
46
- <FieldContent>{children}</FieldContent>
47
- {description && <FieldDescription>{description}</FieldDescription>}
48
- {error && <FieldError errors={[{ message: error }]} />}
49
- </div>
50
- </Field>
51
- );
52
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * Field components for admin forms
3
- *
4
- * All field components are integrated with react-hook-form via Controller.
5
- * They use the primitive components from ../primitives for the actual UI.
6
- */
7
-
8
- // Complex field components
9
- export { RelationSelect } from "./relation-select";
10
- export type { RelationSelectProps } from "./relation-select";
11
-
12
- export { RelationPicker } from "./relation-picker";
13
- export type { RelationPickerProps } from "./relation-picker";
14
-
15
- export { RelationField } from "./relation-field";
16
- export type { RelationFieldProps } from "./relation-field";
17
-
18
- export { JsonField } from "./json-field";
19
- export type { JsonFieldProps, JsonFieldMode } from "./json-field";
20
-
21
- export { EmbeddedCollectionField } from "./embedded-collection";
22
- export type { EmbeddedCollectionFieldProps } from "./embedded-collection";
23
-
24
- export { ArrayField } from "./array-field";
25
- export type { ArrayFieldProps, ArrayFieldItemType } from "./array-field";
26
-
27
- export { RichTextEditor } from "./rich-text-editor";
28
- export type { RichTextEditorProps, RichTextFeatures } from "./rich-text-editor";
29
-
30
- // Basic field components (using primitives)
31
- export { TextField } from "./text-field";
32
- export { EmailField } from "./email-field";
33
- export { PasswordField } from "./password-field";
34
- export { TextareaField } from "./textarea-field";
35
- export { NumberField } from "./number-field";
36
- export { CheckboxField } from "./checkbox-field";
37
- export { SwitchField } from "./switch-field";
38
- export { SelectField } from "./select-field";
39
- export { DateField } from "./date-field";
40
- export { DatetimeField } from "./datetime-field";
41
- export { CustomField } from "./custom-field";
42
-
43
- // Utilities
44
- export { LocaleBadge } from "./locale-badge";
45
- export { FieldWrapper } from "./field-wrapper";
46
- export { useResolvedControl } from "./field-utils";
47
-
48
- // Types
49
- export type {
50
- BaseFieldProps,
51
- FormFieldProps,
52
- FormFieldType,
53
- SelectOption,
54
- SelectOptionGroup,
55
- TextFieldProps,
56
- NumberFieldProps,
57
- TextareaFieldProps,
58
- SelectFieldProps,
59
- DateFieldProps,
60
- DateTimeFieldProps,
61
- DateRangeFieldProps,
62
- TagsFieldProps,
63
- BooleanFieldProps,
64
- CheckboxGroupFieldProps,
65
- RadioGroupFieldProps,
66
- } from "./field-types";