@questpie/admin 0.0.1 → 1.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 (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-D7w7W1Hl.mjs +273 -0
  5. package/dist/bulk-upload-dialog-D7w7W1Hl.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-DbpZKSgH.d.mts +13585 -0
  10. package/dist/client-DbpZKSgH.d.mts.map +1 -0
  11. package/dist/client-njX1rZmi.mjs +22612 -0
  12. package/dist/client-njX1rZmi.mjs.map +1 -0
  13. package/dist/client.d.mts +3 -0
  14. package/dist/client.mjs +13 -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-mCY0pgZv.mjs +3 -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-CEwsdLwn.mjs +3 -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 +13 -0
  29. package/dist/login-page-BUnpCbCa.mjs +3 -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-CufHz3h3.mjs +3 -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-BNNzt_Z6.mjs +3 -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 -198
  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,42 +0,0 @@
1
- import "react";
2
- import { jsx } from "react/jsx-runtime";
3
- import { TextField } from "../../components/fields/text-field";
4
- import { EmailField } from "../../components/fields/email-field";
5
- import { PasswordField } from "../../components/fields/password-field";
6
- import { TextareaField } from "../../components/fields/textarea-field";
7
- import { NumberField } from "../../components/fields/number-field";
8
- import { CheckboxField } from "../../components/fields/checkbox-field";
9
- import { SwitchField } from "../../components/fields/switch-field";
10
- import { SelectField } from "../../components/fields/select-field";
11
- import { DateField } from "../../components/fields/date-field";
12
- import { DatetimeField } from "../../components/fields/datetime-field";
13
- import { CustomField } from "../../components/fields/custom-field";
14
-
15
- //#region src/views/collection/form-field.tsx
16
- /**
17
- * FormField - Generic form field with React Hook Form integration
18
- */
19
- function FormField({ type = "text", component, options, ...baseProps }) {
20
- if (component) return /* @__PURE__ */ jsx(CustomField, {
21
- ...baseProps,
22
- component
23
- });
24
- switch (type) {
25
- case "textarea": return /* @__PURE__ */ jsx(TextareaField, { ...baseProps });
26
- case "checkbox": return /* @__PURE__ */ jsx(CheckboxField, { ...baseProps });
27
- case "switch": return /* @__PURE__ */ jsx(SwitchField, { ...baseProps });
28
- case "select": return /* @__PURE__ */ jsx(SelectField, {
29
- ...baseProps,
30
- options
31
- });
32
- case "number": return /* @__PURE__ */ jsx(NumberField, { ...baseProps });
33
- case "date": return /* @__PURE__ */ jsx(DateField, { ...baseProps });
34
- case "datetime": return /* @__PURE__ */ jsx(DatetimeField, { ...baseProps });
35
- case "email": return /* @__PURE__ */ jsx(EmailField, { ...baseProps });
36
- case "password": return /* @__PURE__ */ jsx(PasswordField, { ...baseProps });
37
- default: return /* @__PURE__ */ jsx(TextField, { ...baseProps });
38
- }
39
- }
40
-
41
- //#endregion
42
- export { FormField };
@@ -1,6 +0,0 @@
1
- import { FormField } from "./form-field";
2
- import { CollectionList } from "./collection-list";
3
- import { CollectionForm } from "./collection-form";
4
- import { AutoFormFields } from "./auto-form-fields";
5
-
6
- export { AutoFormFields, CollectionForm, CollectionList, FormField };
@@ -1,4 +0,0 @@
1
- import { LocaleSwitcher } from "./locale-switcher";
2
- import { VersionHistory } from "./version-history";
3
-
4
- export { LocaleSwitcher, VersionHistory };
@@ -1,39 +0,0 @@
1
- import "react";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useAdminContext } from "../../hooks/admin-provider";
4
- import { Badge } from "../../components/ui/badge";
5
- import { Select, SelectContent, SelectItem, SelectTrigger } from "../../components/ui/select";
6
-
7
- //#region src/views/common/locale-switcher.tsx
8
- function LocaleSwitcher() {
9
- const { locale, setLocale, locales } = useAdminContext();
10
- const available = locales?.available ?? [];
11
- if (!setLocale || available.length <= 1) return null;
12
- const currentLocale = locale ?? locales?.default ?? available[0];
13
- return /* @__PURE__ */ jsxs("div", {
14
- className: "flex items-center gap-2",
15
- children: [/* @__PURE__ */ jsx(Badge, {
16
- variant: "outline",
17
- className: "uppercase text-[10px] tracking-wide",
18
- children: "Locale"
19
- }), /* @__PURE__ */ jsxs(Select, {
20
- value: currentLocale,
21
- onValueChange: (value) => {
22
- if (value) setLocale(value);
23
- },
24
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
25
- className: "h-8 w-[120px]",
26
- children: /* @__PURE__ */ jsx("span", {
27
- className: "truncate",
28
- children: currentLocale?.toUpperCase() ?? "Locale"
29
- })
30
- }), /* @__PURE__ */ jsx(SelectContent, { children: available.map((code) => /* @__PURE__ */ jsx(SelectItem, {
31
- value: code,
32
- children: code.toUpperCase()
33
- }, code)) })]
34
- })]
35
- });
36
- }
37
-
38
- //#endregion
39
- export { LocaleSwitcher };
@@ -1,272 +0,0 @@
1
- import * as React$1 from "react";
2
- import { useQuery } from "@tanstack/react-query";
3
- import { jsx, jsxs } from "react/jsx-runtime";
4
- import { useAdminContext } from "../../hooks/admin-provider";
5
- import { Badge } from "../../components/ui/badge";
6
- import { Button } from "../../components/ui/button";
7
- import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../../components/ui/card";
8
- import { Separator } from "../../components/ui/separator";
9
- import { Spinner } from "../../components/ui/spinner";
10
- import { ArrowCounterClockwise, CaretDown, CaretRight, Clock, ClockCounterClockwise, User } from "@phosphor-icons/react";
11
-
12
- //#region src/views/common/version-history.tsx
13
- /**
14
- * VersionHistory Component
15
- *
16
- * Displays version history and audit log for a collection item
17
- * - Shows all versions with timestamps
18
- * - Displays who made changes
19
- * - Allows comparing versions
20
- * - Shows diff between versions
21
- * - Ability to restore previous versions
22
- */
23
- function VersionHistory({ collection, itemId, allowRestore = false, onRestore, renderVersion, showFullDiff = false }) {
24
- const { client, locale } = useAdminContext();
25
- const localeKey = locale ?? "default";
26
- const [expandedVersions, setExpandedVersions] = React$1.useState(/* @__PURE__ */ new Set());
27
- const { data: versions, isLoading, error } = useQuery({
28
- queryKey: [
29
- "version-history",
30
- collection,
31
- itemId,
32
- localeKey
33
- ],
34
- queryFn: async () => {
35
- return [
36
- {
37
- id: "v3",
38
- versionNumber: 3,
39
- createdAt: (/* @__PURE__ */ new Date(Date.now() - 7200 * 1e3)).toISOString(),
40
- createdBy: {
41
- id: "user1",
42
- name: "John Doe",
43
- email: "john@example.com"
44
- },
45
- action: "updated",
46
- changes: [{
47
- field: "status",
48
- oldValue: "pending",
49
- newValue: "confirmed"
50
- }],
51
- data: {}
52
- },
53
- {
54
- id: "v2",
55
- versionNumber: 2,
56
- createdAt: (/* @__PURE__ */ new Date(Date.now() - 1440 * 60 * 1e3)).toISOString(),
57
- createdBy: {
58
- id: "user2",
59
- name: "Jane Smith",
60
- email: "jane@example.com"
61
- },
62
- action: "updated",
63
- changes: [{
64
- field: "scheduledAt",
65
- oldValue: "2025-01-15T10:00:00",
66
- newValue: "2025-01-20T14:00:00"
67
- }],
68
- data: {}
69
- },
70
- {
71
- id: "v1",
72
- versionNumber: 1,
73
- createdAt: (/* @__PURE__ */ new Date(Date.now() - 10080 * 60 * 1e3)).toISOString(),
74
- createdBy: {
75
- id: "user1",
76
- name: "John Doe",
77
- email: "john@example.com"
78
- },
79
- action: "created",
80
- changes: [],
81
- data: {}
82
- }
83
- ];
84
- }
85
- });
86
- const toggleVersion = (versionId) => {
87
- setExpandedVersions((prev) => {
88
- const next = new Set(prev);
89
- if (next.has(versionId)) next.delete(versionId);
90
- else next.add(versionId);
91
- return next;
92
- });
93
- };
94
- const handleRestore = (versionId) => {
95
- onRestore?.(versionId);
96
- };
97
- const formatDate = (dateString) => {
98
- const date = new Date(dateString);
99
- const diffMs = (/* @__PURE__ */ new Date()).getTime() - date.getTime();
100
- const diffMins = Math.floor(diffMs / 6e4);
101
- const diffHours = Math.floor(diffMs / 36e5);
102
- const diffDays = Math.floor(diffMs / 864e5);
103
- if (diffMins < 1) return "Just now";
104
- if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? "s" : ""} ago`;
105
- if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
106
- if (diffDays < 7) return `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
107
- return date.toLocaleDateString();
108
- };
109
- const getActionBadge = (action) => {
110
- const config = {
111
- created: {
112
- variant: "default",
113
- label: "Created"
114
- },
115
- updated: {
116
- variant: "secondary",
117
- label: "Updated"
118
- },
119
- deleted: {
120
- variant: "destructive",
121
- label: "Deleted"
122
- },
123
- restored: {
124
- variant: "outline",
125
- label: "Restored"
126
- }
127
- }[action];
128
- return /* @__PURE__ */ jsx(Badge, {
129
- variant: config.variant,
130
- children: config.label
131
- });
132
- };
133
- const formatValue = (value) => {
134
- if (value === null || value === void 0) return "—";
135
- if (typeof value === "boolean") return value ? "Yes" : "No";
136
- if (typeof value === "object") return JSON.stringify(value);
137
- return String(value);
138
- };
139
- if (isLoading) return /* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, {
140
- className: "flex items-center gap-2",
141
- children: [/* @__PURE__ */ jsx(ClockCounterClockwise, { className: "h-5 w-5" }), "Version History"]
142
- }) }), /* @__PURE__ */ jsx(CardContent, {
143
- className: "flex items-center justify-center p-8",
144
- children: /* @__PURE__ */ jsx(Spinner, { className: "h-6 w-6" })
145
- })] });
146
- if (error) return /* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, {
147
- className: "flex items-center gap-2",
148
- children: [/* @__PURE__ */ jsx(ClockCounterClockwise, { className: "h-5 w-5" }), "Version History"]
149
- }) }), /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs("p", {
150
- className: "text-sm text-destructive",
151
- children: [
152
- "Failed to load version history:",
153
- " ",
154
- error instanceof Error ? error.message : "Unknown error"
155
- ]
156
- }) })] });
157
- if (!versions || versions.length === 0) return /* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsxs(CardTitle, {
158
- className: "flex items-center gap-2",
159
- children: [/* @__PURE__ */ jsx(ClockCounterClockwise, { className: "h-5 w-5" }), "Version History"]
160
- }) }), /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("p", {
161
- className: "text-sm text-muted-foreground",
162
- children: "No version history available"
163
- }) })] });
164
- return /* @__PURE__ */ jsxs(Card, { children: [/* @__PURE__ */ jsxs(CardHeader, { children: [/* @__PURE__ */ jsxs(CardTitle, {
165
- className: "flex items-center gap-2",
166
- children: [/* @__PURE__ */ jsx(ClockCounterClockwise, { className: "h-5 w-5" }), "Version History"]
167
- }), /* @__PURE__ */ jsxs(CardDescription, { children: [
168
- versions.length,
169
- " version",
170
- versions.length !== 1 ? "s" : ""
171
- ] })] }), /* @__PURE__ */ jsx(CardContent, {
172
- className: "space-y-4",
173
- children: versions.map((version, index) => {
174
- const isExpanded = expandedVersions.has(version.id);
175
- const isLatest = index === 0;
176
- return /* @__PURE__ */ jsxs("div", { children: [index > 0 && /* @__PURE__ */ jsx(Separator, { className: "my-4" }), /* @__PURE__ */ jsx("div", {
177
- className: "space-y-2",
178
- children: /* @__PURE__ */ jsxs("div", {
179
- className: "flex items-start gap-3",
180
- children: [/* @__PURE__ */ jsx(Button, {
181
- variant: "ghost",
182
- size: "icon",
183
- className: "h-6 w-6 shrink-0",
184
- onClick: () => toggleVersion(version.id),
185
- children: isExpanded ? /* @__PURE__ */ jsx(CaretDown, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(CaretRight, { className: "h-4 w-4" })
186
- }), /* @__PURE__ */ jsxs("div", {
187
- className: "flex-1 space-y-1",
188
- children: [
189
- /* @__PURE__ */ jsxs("div", {
190
- className: "flex items-center gap-2",
191
- children: [
192
- /* @__PURE__ */ jsxs("span", {
193
- className: "text-sm font-medium",
194
- children: ["Version ", version.versionNumber]
195
- }),
196
- getActionBadge(version.action),
197
- isLatest && /* @__PURE__ */ jsx(Badge, {
198
- variant: "outline",
199
- children: "Current"
200
- })
201
- ]
202
- }),
203
- /* @__PURE__ */ jsxs("div", {
204
- className: "flex items-center gap-4 text-xs text-muted-foreground",
205
- children: [/* @__PURE__ */ jsxs("div", {
206
- className: "flex items-center gap-1",
207
- children: [/* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }), formatDate(version.createdAt)]
208
- }), version.createdBy && /* @__PURE__ */ jsxs("div", {
209
- className: "flex items-center gap-1",
210
- children: [/* @__PURE__ */ jsx(User, { className: "h-3 w-3" }), version.createdBy.name || version.createdBy.email]
211
- })]
212
- }),
213
- version.changes && version.changes.length > 0 && !isExpanded && /* @__PURE__ */ jsxs("p", {
214
- className: "text-xs text-muted-foreground",
215
- children: [
216
- version.changes.length,
217
- " field",
218
- version.changes.length !== 1 ? "s" : "",
219
- " changed"
220
- ]
221
- }),
222
- isExpanded && /* @__PURE__ */ jsxs("div", {
223
- className: "mt-3 space-y-2",
224
- children: [
225
- version.changes && version.changes.length > 0 ? /* @__PURE__ */ jsx("div", {
226
- className: "rounded-lg border bg-muted/50 p-3 space-y-2",
227
- children: version.changes.map((change, changeIndex) => /* @__PURE__ */ jsxs("div", {
228
- className: "text-xs",
229
- children: [/* @__PURE__ */ jsx("div", {
230
- className: "font-medium text-foreground mb-1",
231
- children: change.field
232
- }), /* @__PURE__ */ jsxs("div", {
233
- className: "grid grid-cols-2 gap-2",
234
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
235
- className: "text-muted-foreground",
236
- children: "Old value:"
237
- }), /* @__PURE__ */ jsx("div", {
238
- className: "font-mono rounded bg-background p-1 mt-1",
239
- children: formatValue(change.oldValue)
240
- })] }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
241
- className: "text-muted-foreground",
242
- children: "New value:"
243
- }), /* @__PURE__ */ jsx("div", {
244
- className: "font-mono rounded bg-background p-1 mt-1",
245
- children: formatValue(change.newValue)
246
- })] })]
247
- })]
248
- }, changeIndex))
249
- }) : /* @__PURE__ */ jsx("p", {
250
- className: "text-xs text-muted-foreground",
251
- children: "No changes recorded"
252
- }),
253
- renderVersion && renderVersion(version),
254
- allowRestore && !isLatest && /* @__PURE__ */ jsxs(Button, {
255
- variant: "outline",
256
- size: "sm",
257
- onClick: () => handleRestore(version.id),
258
- className: "mt-2",
259
- children: [/* @__PURE__ */ jsx(ArrowCounterClockwise, { className: "mr-2 h-3 w-3" }), "Restore this version"]
260
- })
261
- ]
262
- })
263
- ]
264
- })]
265
- })
266
- })] }, version.id);
267
- })
268
- })] });
269
- }
270
-
271
- //#endregion
272
- export { VersionHistory };
@@ -1,9 +0,0 @@
1
- export * from "./auth"
2
-
3
- export * from "./layout"
4
-
5
- export * from "./collection"
6
-
7
- export * from "./common"
8
-
9
- export { };
@@ -1,40 +0,0 @@
1
- import "react";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { cn } from "../../lib/utils";
4
- import { AdminSidebar } from "./admin-sidebar";
5
-
6
- //#region src/views/layout/admin-layout.tsx
7
- function AdminLayout({ config, activeRoute, LinkComponent, children, className, sidebarProps, renderHeader, renderFooter }) {
8
- const showHeader = config.app?.header?.show ?? false;
9
- const showFooter = config.app?.footer?.show ?? false;
10
- const HeaderComponent = config.app?.header?.component;
11
- const FooterComponent = config.app?.footer?.component;
12
- return /* @__PURE__ */ jsxs("div", {
13
- className: cn("flex h-screen flex-col", className),
14
- children: [
15
- showHeader && /* @__PURE__ */ jsx("header", {
16
- className: "border-b",
17
- children: renderHeader ? renderHeader() : HeaderComponent && /* @__PURE__ */ jsx(HeaderComponent, {})
18
- }),
19
- /* @__PURE__ */ jsxs("div", {
20
- className: "flex flex-1 overflow-hidden",
21
- children: [/* @__PURE__ */ jsx(AdminSidebar, {
22
- config,
23
- activeRoute,
24
- LinkComponent,
25
- ...sidebarProps
26
- }), /* @__PURE__ */ jsx("main", {
27
- className: "flex-1 overflow-auto",
28
- children
29
- })]
30
- }),
31
- showFooter && /* @__PURE__ */ jsx("footer", {
32
- className: "border-t",
33
- children: renderFooter ? renderFooter() : FooterComponent && /* @__PURE__ */ jsx(FooterComponent, {})
34
- })
35
- ]
36
- });
37
- }
38
-
39
- //#endregion
40
- export { AdminLayout };
@@ -1,95 +0,0 @@
1
- import "react";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { CollectionList } from "../collection/collection-list";
4
- import { CollectionForm } from "../collection/collection-form";
5
- import { AutoFormFields } from "../collection/auto-form-fields";
6
- import { LocaleSwitcher } from "../common/locale-switcher";
7
-
8
- //#region src/views/layout/admin-router.tsx
9
- /**
10
- * Default Dashboard
11
- */
12
- function DefaultDashboard() {
13
- return /* @__PURE__ */ jsxs("div", {
14
- className: "container py-8",
15
- children: [/* @__PURE__ */ jsx("h1", {
16
- className: "mb-8 text-3xl font-bold",
17
- children: "Dashboard"
18
- }), /* @__PURE__ */ jsx("div", {
19
- className: "grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4",
20
- children: /* @__PURE__ */ jsxs("div", {
21
- className: "rounded-lg border bg-card p-6",
22
- children: [/* @__PURE__ */ jsx("h3", {
23
- className: "font-semibold",
24
- children: "Collections"
25
- }), /* @__PURE__ */ jsx("p", {
26
- className: "mt-2 text-3xl font-bold",
27
- children: "--"
28
- })]
29
- })
30
- })]
31
- });
32
- }
33
- function AdminRouter({ config, segments, navigate, DashboardComponent, collectionComponents, renderFormFields, registry }) {
34
- if (segments.length === 0) return /* @__PURE__ */ jsx(DashboardComponent || DefaultDashboard, {});
35
- const [collection, idOrNew] = segments;
36
- const collectionConfig = config.collections?.[collection];
37
- const customComponents = collectionComponents?.[collection];
38
- if (!idOrNew) {
39
- if (customComponents?.List) return /* @__PURE__ */ jsx(customComponents.List, {});
40
- const columns = collectionConfig?.list?.defaultColumns?.map((field) => ({
41
- accessorKey: field,
42
- header: collectionConfig.fields?.[field]?.label || field
43
- })) || [{
44
- accessorKey: "id",
45
- header: "ID"
46
- }];
47
- const withRelations = collectionConfig?.list?.with;
48
- return /* @__PURE__ */ jsx("div", {
49
- className: "container py-8",
50
- children: /* @__PURE__ */ jsx(CollectionList, {
51
- collection,
52
- columns,
53
- baseFindOptions: withRelations ? { with: withRelations.reduce((acc, rel) => {
54
- acc[rel] = true;
55
- return acc;
56
- }, {}) } : void 0,
57
- realtime: true,
58
- headerActions: /* @__PURE__ */ jsxs("div", {
59
- className: "flex items-center gap-2",
60
- children: [/* @__PURE__ */ jsx(LocaleSwitcher, {}), /* @__PURE__ */ jsxs("button", {
61
- type: "button",
62
- onClick: () => navigate(`/admin/${collection}/new`),
63
- className: "rounded bg-primary px-4 py-2 text-primary-foreground",
64
- children: ["Create ", collectionConfig?.label || collection]
65
- })]
66
- }),
67
- onRowClick: (item) => {
68
- navigate(`/admin/${collection}/${item.id}`);
69
- }
70
- })
71
- });
72
- }
73
- const id = idOrNew === "new" ? void 0 : idOrNew;
74
- if (customComponents?.Form) return /* @__PURE__ */ jsx(customComponents.Form, {});
75
- return /* @__PURE__ */ jsx("div", {
76
- className: "container max-w-2xl py-8",
77
- children: /* @__PURE__ */ jsx(CollectionForm, {
78
- collection,
79
- id,
80
- title: id ? `Edit ${collectionConfig?.label || collection}` : `New ${collectionConfig?.label || collection}`,
81
- headerActions: /* @__PURE__ */ jsx(LocaleSwitcher, {}),
82
- onSuccess: () => navigate(`/admin/${collection}`),
83
- onCancel: () => navigate(`/admin/${collection}`),
84
- children: renderFormFields?.(collection) || /* @__PURE__ */ jsx(AutoFormFields, {
85
- collection,
86
- config: collectionConfig,
87
- registry,
88
- allCollectionsConfig: config.collections
89
- })
90
- })
91
- });
92
- }
93
-
94
- //#endregion
95
- export { AdminRouter };
@@ -1,63 +0,0 @@
1
- import * as React$1 from "react";
2
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
- import { cn } from "../../lib/utils";
4
-
5
- //#region src/views/layout/admin-sidebar.tsx
6
- /**
7
- * AdminSidebar Component
8
- *
9
- * Automatically generated sidebar from admin config
10
- * Fully customizable via config overrides
11
- */
12
- function AdminSidebar({ config, activeRoute, LinkComponent, className, brandClassName, navClassName, renderBrand, renderNavItem }) {
13
- const brand = config.app?.brand;
14
- const collections = config.collections || {};
15
- const groupedCollections = React$1.useMemo(() => {
16
- const groups = { "": {} };
17
- Object.entries(collections).forEach(([name, collectionConfig]) => {
18
- const group = collectionConfig.group || "";
19
- if (!groups[group]) groups[group] = {};
20
- groups[group][name] = collectionConfig;
21
- });
22
- return groups;
23
- }, [collections]);
24
- return /* @__PURE__ */ jsxs("aside", {
25
- className: cn("w-64 border-r bg-neutral-50 dark:bg-neutral-900", className),
26
- children: [/* @__PURE__ */ jsx("div", {
27
- className: cn("p-4", brandClassName),
28
- children: renderBrand ? renderBrand(config) : /* @__PURE__ */ jsxs(Fragment, { children: [brand?.logo && /* @__PURE__ */ jsx(brand.logo, {}), /* @__PURE__ */ jsx("h1", {
29
- className: "text-xl font-bold",
30
- children: brand?.name || "Admin"
31
- })] })
32
- }), /* @__PURE__ */ jsx("nav", {
33
- className: cn("space-y-1 p-2", navClassName),
34
- children: Object.entries(groupedCollections).map(([groupName, groupCollections]) => /* @__PURE__ */ jsxs("div", { children: [groupName && /* @__PURE__ */ jsx("div", {
35
- className: "px-3 py-2 text-xs font-semibold uppercase text-neutral-500",
36
- children: groupName
37
- }), Object.entries(groupCollections).map(([collectionName, collectionConfig]) => {
38
- const isActive = activeRoute === `/admin/${collectionName}`;
39
- if (renderNavItem) return /* @__PURE__ */ jsx(React$1.Fragment, { children: renderNavItem({
40
- collectionName,
41
- config: collectionConfig,
42
- isActive
43
- }) }, collectionName);
44
- return /* @__PURE__ */ jsxs(LinkComponent, {
45
- to: `/admin/${collectionName}`,
46
- className: "block rounded px-3 py-2 hover:bg-neutral-100 dark:hover:bg-neutral-800",
47
- activeProps: { className: "bg-neutral-100 dark:bg-neutral-800 font-medium" },
48
- children: [
49
- collectionConfig.icon && typeof collectionConfig.icon === "string" && /* @__PURE__ */ jsx("span", {
50
- className: "mr-2",
51
- children: collectionConfig.icon
52
- }),
53
- collectionConfig.icon && typeof collectionConfig.icon !== "string" && /* @__PURE__ */ jsx(collectionConfig.icon, {}),
54
- collectionConfig.label || collectionName
55
- ]
56
- }, collectionName);
57
- })] }, groupName))
58
- })]
59
- });
60
- }
61
-
62
- //#endregion
63
- export { AdminSidebar };
@@ -1,5 +0,0 @@
1
- import { AdminLayout } from "./admin-layout";
2
- import { AdminRouter } from "./admin-router";
3
- import { AdminSidebar } from "./admin-sidebar";
4
-
5
- export { AdminLayout, AdminRouter, AdminSidebar };
@@ -1,44 +0,0 @@
1
- /**
2
- * Vitest setup file for @questpie/admin
3
- */
4
-
5
- import * as matchers from "@testing-library/jest-dom/matchers";
6
- import { cleanup } from "@testing-library/react";
7
- import { afterEach, expect, vi } from "vitest";
8
-
9
- // Extend vitest's expect with jest-dom matchers
10
- expect.extend(matchers);
11
-
12
- // Cleanup after each test
13
- afterEach(() => {
14
- cleanup();
15
- });
16
-
17
- // Mock window.matchMedia for responsive components
18
- Object.defineProperty(window, "matchMedia", {
19
- writable: true,
20
- value: vi.fn().mockImplementation((query: string) => ({
21
- matches: false,
22
- media: query,
23
- onchange: null,
24
- addListener: vi.fn(),
25
- removeListener: vi.fn(),
26
- addEventListener: vi.fn(),
27
- removeEventListener: vi.fn(),
28
- dispatchEvent: vi.fn(),
29
- })),
30
- });
31
-
32
- // Mock ResizeObserver
33
- global.ResizeObserver = vi.fn().mockImplementation(() => ({
34
- observe: vi.fn(),
35
- unobserve: vi.fn(),
36
- disconnect: vi.fn(),
37
- }));
38
-
39
- // Mock IntersectionObserver
40
- global.IntersectionObserver = vi.fn().mockImplementation(() => ({
41
- observe: vi.fn(),
42
- unobserve: vi.fn(),
43
- disconnect: vi.fn(),
44
- }));
@@ -1,49 +0,0 @@
1
- /**
2
- * Test utilities for @questpie/admin components
3
- */
4
-
5
- import * as React from "react";
6
- import { render, type RenderOptions } from "@testing-library/react";
7
- import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
8
-
9
- /**
10
- * Create a fresh QueryClient for each test
11
- */
12
- function createTestQueryClient() {
13
- return new QueryClient({
14
- defaultOptions: {
15
- queries: {
16
- retry: false,
17
- gcTime: 0,
18
- },
19
- mutations: {
20
- retry: false,
21
- },
22
- },
23
- });
24
- }
25
-
26
- /**
27
- * Test wrapper with all required providers
28
- */
29
- function TestWrapper({ children }: { children: React.ReactNode }) {
30
- const [queryClient] = React.useState(() => createTestQueryClient());
31
-
32
- return (
33
- <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
34
- );
35
- }
36
-
37
- /**
38
- * Custom render function that wraps components with test providers
39
- */
40
- function customRender(
41
- ui: React.ReactElement,
42
- options?: Omit<RenderOptions, "wrapper">,
43
- ): ReturnType<typeof render> {
44
- return render(ui, { wrapper: TestWrapper, ...options });
45
- }
46
-
47
- // Re-export everything from testing-library
48
- export * from "@testing-library/react";
49
- export { customRender as render };