@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,186 +0,0 @@
1
- import React from "react";
2
- import { useForm, FormProvider } from "react-hook-form";
3
- import type { Questpie } from "questpie";
4
- import type { QuestpieClient } from "questpie/client";
5
- import {
6
- useCollection,
7
- useCollectionItemById,
8
- } from "../../hooks/use-collection-db";
9
- import { Button } from "../../components/ui/button";
10
- import {
11
- Card,
12
- CardContent,
13
- CardFooter,
14
- CardHeader,
15
- CardTitle,
16
- } from "../../components/ui/card";
17
-
18
- /**
19
- * Collection item type helper
20
- */
21
- type CollectionItem<
22
- T extends Questpie<any>,
23
- K extends keyof QuestpieClient<T>["collections"],
24
- > = Awaited<ReturnType<QuestpieClient<T>["collections"][K]["find"]>> extends {
25
- docs: Array<infer TItem>;
26
- }
27
- ? TItem
28
- : never;
29
-
30
- /**
31
- * CollectionForm props
32
- */
33
- export type CollectionFormProps<
34
- T extends Questpie<any>,
35
- K extends keyof QuestpieClient<T>["collections"],
36
- > = {
37
- /**
38
- * Collection name
39
- */
40
- collection: K;
41
-
42
- /**
43
- * Item ID (for edit mode)
44
- */
45
- id?: string;
46
-
47
- /**
48
- * Default values (for create mode)
49
- */
50
- defaultValues?: Partial<CollectionItem<T, K>>;
51
-
52
- /**
53
- * Custom field renderer
54
- */
55
- children: React.ReactNode;
56
-
57
- /**
58
- * On submit success callback
59
- */
60
- onSuccess?: (item: CollectionItem<T, K>) => void;
61
-
62
- /**
63
- * On cancel callback
64
- */
65
- onCancel?: () => void;
66
-
67
- /**
68
- * Form title
69
- */
70
- title?: string;
71
-
72
- /**
73
- * Header actions (e.g. locale switcher)
74
- */
75
- headerActions?: React.ReactNode;
76
-
77
- /**
78
- * Submit button text
79
- */
80
- submitText?: string;
81
-
82
- /**
83
- * Cancel button text
84
- */
85
- cancelText?: string;
86
- };
87
-
88
- /**
89
- * CollectionForm - Form wrapper for CMS collections
90
- * Uses React Hook Form + TanStack DB Collection for optimistic updates
91
- *
92
- * @example
93
- * ```tsx
94
- * import { CollectionForm } from '@questpie/admin/views'
95
- * import type { cms } from './server/cms'
96
- *
97
- * function PostForm({ id }: { id?: string }) {
98
- * return (
99
- * <CollectionForm<typeof cms, 'posts'>
100
- * collection="posts"
101
- * id={id}
102
- * title={id ? 'Edit Post' : 'Create Post'}
103
- * onSuccess={() => router.push('/posts')}
104
- * >
105
- * <FormField name="title" label="Title" />
106
- * <FormField name="content" label="Content" type="textarea" />
107
- * </CollectionForm>
108
- * )
109
- * }
110
- * ```
111
- */
112
- export function CollectionForm<
113
- T extends Questpie<any>,
114
- K extends keyof QuestpieClient<T>["collections"],
115
- >({
116
- collection,
117
- id,
118
- defaultValues,
119
- children,
120
- onSuccess,
121
- onCancel,
122
- title,
123
- headerActions,
124
- submitText = "Save",
125
- cancelText = "Cancel",
126
- }: CollectionFormProps<T, K>): React.ReactElement {
127
- const collectionData = useCollection<T, K>(collection);
128
- // Get item from collection - useCollectionItemById returns undefined if not found
129
- const item = id
130
- ? collectionData.toArray.find((i) => collectionData.config.getKey(i) === id)
131
- : undefined;
132
-
133
- const form = useForm({
134
- defaultValues: (item ?? defaultValues ?? {}) as any,
135
- });
136
-
137
- React.useEffect(() => {
138
- form.reset((item ?? defaultValues ?? {}) as any);
139
- }, [form, item, defaultValues]);
140
-
141
- const onSubmit = async (data: any) => {
142
- try {
143
- let result: any;
144
-
145
- if (id) {
146
- // Update existing item
147
- await collectionData.update(id, data);
148
- result = { ...item, ...data };
149
- } else {
150
- // Create new item
151
- result = await collectionData.insert(data);
152
- }
153
-
154
- onSuccess?.(result);
155
- } catch (error) {
156
- console.error("Form submission error:", error);
157
- // TODO: Show error toast
158
- }
159
- };
160
-
161
- return (
162
- <FormProvider {...form}>
163
- <form onSubmit={form.handleSubmit(onSubmit)}>
164
- <Card>
165
- {(title || headerActions) && (
166
- <CardHeader className="flex flex-wrap items-center justify-between gap-3">
167
- {title && <CardTitle>{title}</CardTitle>}
168
- {headerActions && <div>{headerActions}</div>}
169
- </CardHeader>
170
- )}
171
- <CardContent className="space-y-4">{children}</CardContent>
172
- <CardFooter className="flex justify-end gap-2">
173
- {onCancel && (
174
- <Button type="button" variant="outline" onClick={onCancel}>
175
- {cancelText}
176
- </Button>
177
- )}
178
- <Button type="submit" disabled={form.formState.isSubmitting}>
179
- {form.formState.isSubmitting ? "Saving..." : submitText}
180
- </Button>
181
- </CardFooter>
182
- </Card>
183
- </form>
184
- </FormProvider>
185
- );
186
- }
@@ -1,223 +0,0 @@
1
- import React from "react";
2
- import {
3
- type ColumnDef,
4
- flexRender,
5
- getCoreRowModel,
6
- useReactTable,
7
- getSortedRowModel,
8
- type SortingState,
9
- } from "@tanstack/react-table";
10
- import type { Questpie } from "questpie";
11
- import type { QuestpieClient } from "questpie/client";
12
- import { useCollection } from "../../hooks/use-collection-db";
13
- import {
14
- Table,
15
- TableBody,
16
- TableCell,
17
- TableHead,
18
- TableHeader,
19
- TableRow,
20
- } from "../../components/ui/table";
21
- import { Button } from "../../components/ui/button";
22
-
23
- /**
24
- * Collection item type helper
25
- */
26
- type CollectionItem<
27
- T extends Questpie<any>,
28
- K extends keyof QuestpieClient<T>["collections"],
29
- > = Awaited<ReturnType<QuestpieClient<T>["collections"][K]["find"]>> extends {
30
- docs: Array<infer TItem>;
31
- }
32
- ? TItem
33
- : never;
34
-
35
- /**
36
- * CollectionList props
37
- */
38
- export type CollectionListProps<
39
- T extends Questpie<any>,
40
- K extends keyof QuestpieClient<T>["collections"],
41
- > = {
42
- /**
43
- * Collection name
44
- */
45
- collection: K;
46
-
47
- /**
48
- * Column definitions
49
- */
50
- columns: ColumnDef<CollectionItem<T, K>>[];
51
-
52
- /**
53
- * Base query options (filters, sorting, relations)
54
- */
55
- baseFindOptions?: Parameters<QuestpieClient<T>["collections"][K]["find"]>[0];
56
-
57
- /**
58
- * Enable realtime sync
59
- */
60
- realtime?: boolean;
61
-
62
- /**
63
- * Custom row actions
64
- */
65
- rowActions?: (item: CollectionItem<T, K>) => React.ReactNode;
66
-
67
- /**
68
- * Custom header actions
69
- */
70
- headerActions?: React.ReactNode;
71
-
72
- /**
73
- * Custom empty state
74
- */
75
- emptyState?: React.ReactNode;
76
-
77
- /**
78
- * On row click handler
79
- */
80
- onRowClick?: (item: CollectionItem<T, K>) => void;
81
- };
82
-
83
- /**
84
- * CollectionList - Table view for CMS collections
85
- * Uses TanStack DB Collection for offline-first, realtime data
86
- *
87
- * @example
88
- * ```tsx
89
- * import { CollectionList } from '@questpie/admin/views'
90
- * import type { cms } from './server/cms'
91
- *
92
- * function PostsList() {
93
- * return (
94
- * <CollectionList<typeof cms, 'posts'>
95
- * collection="posts"
96
- * columns={[
97
- * { accessorKey: 'title', header: 'Title' },
98
- * { accessorKey: 'createdAt', header: 'Created' },
99
- * ]}
100
- * realtime={true}
101
- * onRowClick={(post) => router.push(`/posts/${post.id}`)}
102
- * />
103
- * )
104
- * }
105
- * ```
106
- */
107
- export function CollectionList<
108
- T extends Questpie<any>,
109
- K extends keyof QuestpieClient<T>["collections"],
110
- >({
111
- collection,
112
- columns,
113
- baseFindOptions,
114
- realtime = false,
115
- rowActions,
116
- headerActions,
117
- emptyState,
118
- onRowClick,
119
- }: CollectionListProps<T, K>): React.ReactElement {
120
- const collectionData = useCollection<T, K>(collection, {
121
- baseFindOptions,
122
- realtime,
123
- });
124
-
125
- const [sorting, setSorting] = React.useState<SortingState>([]);
126
-
127
- const items = collectionData.toArray;
128
-
129
- const table = useReactTable({
130
- data: items as any[],
131
- columns: columns as ColumnDef<any>[],
132
- getCoreRowModel: getCoreRowModel(),
133
- getSortedRowModel: getSortedRowModel(),
134
- onSortingChange: setSorting,
135
- state: {
136
- sorting,
137
- },
138
- });
139
-
140
- return (
141
- <div className="space-y-4">
142
- {/* Header */}
143
- {headerActions && (
144
- <div className="flex items-center justify-between">
145
- <div className="text-sm text-muted-foreground">
146
- {items.length} items
147
- </div>
148
- <div>{headerActions}</div>
149
- </div>
150
- )}
151
-
152
- {/* Table */}
153
- <div className="rounded-md border">
154
- <Table>
155
- <TableHeader>
156
- {table.getHeaderGroups().map((headerGroup) => (
157
- <TableRow key={headerGroup.id}>
158
- {headerGroup.headers.map((header) => (
159
- <TableHead key={header.id}>
160
- {header.isPlaceholder ? null : (
161
- <div
162
- className={
163
- header.column.getCanSort()
164
- ? "cursor-pointer select-none flex items-center gap-2"
165
- : ""
166
- }
167
- onClick={header.column.getToggleSortingHandler()}
168
- >
169
- {flexRender(
170
- header.column.columnDef.header,
171
- header.getContext(),
172
- )}
173
- {header.column.getIsSorted() && (
174
- <span>
175
- {header.column.getIsSorted() === "asc" ? "↑" : "↓"}
176
- </span>
177
- )}
178
- </div>
179
- )}
180
- </TableHead>
181
- ))}
182
- {rowActions && <TableHead>Actions</TableHead>}
183
- </TableRow>
184
- ))}
185
- </TableHeader>
186
- <TableBody>
187
- {table.getRowModel().rows?.length ? (
188
- table.getRowModel().rows.map((row) => (
189
- <TableRow
190
- key={row.id}
191
- data-state={row.getIsSelected() && "selected"}
192
- onClick={() => onRowClick?.(row.original)}
193
- className={onRowClick ? "cursor-pointer" : ""}
194
- >
195
- {row.getVisibleCells().map((cell) => (
196
- <TableCell key={cell.id}>
197
- {flexRender(
198
- cell.column.columnDef.cell,
199
- cell.getContext(),
200
- )}
201
- </TableCell>
202
- ))}
203
- {rowActions && (
204
- <TableCell>{rowActions(row.original)}</TableCell>
205
- )}
206
- </TableRow>
207
- ))
208
- ) : (
209
- <TableRow>
210
- <TableCell
211
- colSpan={columns.length + (rowActions ? 1 : 0)}
212
- className="h-24 text-center"
213
- >
214
- {emptyState || "No results."}
215
- </TableCell>
216
- </TableRow>
217
- )}
218
- </TableBody>
219
- </Table>
220
- </div>
221
- </div>
222
- );
223
- }
@@ -1,52 +0,0 @@
1
- import * as React from "react";
2
- import type { FormFieldProps } from "../../components/fields/field-types";
3
- import { CheckboxField } from "../../components/fields/checkbox-field";
4
- import { CustomField } from "../../components/fields/custom-field";
5
- import { DateField } from "../../components/fields/date-field";
6
- import { DatetimeField } from "../../components/fields/datetime-field";
7
- import { EmailField } from "../../components/fields/email-field";
8
- import { NumberField } from "../../components/fields/number-field";
9
- import { PasswordField } from "../../components/fields/password-field";
10
- import { SelectField } from "../../components/fields/select-field";
11
- import { SwitchField } from "../../components/fields/switch-field";
12
- import { TextareaField } from "../../components/fields/textarea-field";
13
- import { TextField } from "../../components/fields/text-field";
14
-
15
- export type { FormFieldProps } from "../../components/fields/field-types";
16
-
17
- /**
18
- * FormField - Generic form field with React Hook Form integration
19
- */
20
- export function FormField({
21
- type = "text",
22
- component,
23
- options,
24
- ...baseProps
25
- }: FormFieldProps): React.ReactElement {
26
- if (component) {
27
- return <CustomField {...baseProps} component={component} />;
28
- }
29
-
30
- switch (type) {
31
- case "textarea":
32
- return <TextareaField {...baseProps} />;
33
- case "checkbox":
34
- return <CheckboxField {...baseProps} />;
35
- case "switch":
36
- return <SwitchField {...baseProps} />;
37
- case "select":
38
- return <SelectField {...baseProps} options={options} />;
39
- case "number":
40
- return <NumberField {...baseProps} />;
41
- case "date":
42
- return <DateField {...baseProps} />;
43
- case "datetime":
44
- return <DatetimeField {...baseProps} />;
45
- case "email":
46
- return <EmailField {...baseProps} />;
47
- case "password":
48
- return <PasswordField {...baseProps} />;
49
- default:
50
- return <TextField {...baseProps} />;
51
- }
52
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * Collection views - CRUD for CMS collections
3
- */
4
-
5
- export { CollectionList } from "./collection-list";
6
- export type { CollectionListProps } from "./collection-list";
7
-
8
- export { CollectionForm } from "./collection-form";
9
- export type { CollectionFormProps } from "./collection-form";
10
-
11
- export { FormField } from "./form-field";
12
- export type { FormFieldProps } from "./form-field";
13
-
14
- export { AutoFormFields } from "./auto-form-fields";
15
- export type { AutoFormFieldsProps } from "./auto-form-fields";
@@ -1,8 +0,0 @@
1
- /**
2
- * Common views - shared utility views
3
- */
4
-
5
- export { LocaleSwitcher } from "./locale-switcher";
6
-
7
- export { VersionHistory } from "./version-history";
8
- export type { VersionHistoryProps } from "./version-history";
@@ -1,45 +0,0 @@
1
- import * as React from "react";
2
- import { useAdminContext } from "../../hooks/admin-provider";
3
- import {
4
- Select,
5
- SelectContent,
6
- SelectItem,
7
- SelectTrigger,
8
- } from "../../components/ui/select";
9
- import { Badge } from "../../components/ui/badge";
10
-
11
- export function LocaleSwitcher() {
12
- const { locale, setLocale, locales } = useAdminContext<any>();
13
- const available = locales?.available ?? [];
14
-
15
- if (!setLocale || available.length <= 1) return null;
16
-
17
- const currentLocale = locale ?? locales?.default ?? available[0];
18
-
19
- return (
20
- <div className="flex items-center gap-2">
21
- <Badge variant="outline" className="uppercase text-[10px] tracking-wide">
22
- Locale
23
- </Badge>
24
- <Select
25
- value={currentLocale}
26
- onValueChange={(value) => {
27
- if (value) setLocale(value);
28
- }}
29
- >
30
- <SelectTrigger className="h-8 w-[120px]">
31
- <span className="truncate">
32
- {currentLocale?.toUpperCase() ?? "Locale"}
33
- </span>
34
- </SelectTrigger>
35
- <SelectContent>
36
- {available.map((code: string) => (
37
- <SelectItem key={code} value={code}>
38
- {code.toUpperCase()}
39
- </SelectItem>
40
- ))}
41
- </SelectContent>
42
- </Select>
43
- </div>
44
- );
45
- }