@questpie/admin 3.0.3 → 3.0.4

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 (249) hide show
  1. package/README.md +34 -5
  2. package/dist/client/blocks/block-renderer.d.mts +2 -2
  3. package/dist/client/blocks/block-renderer.mjs +4 -1
  4. package/dist/client/builder/types/action-types.d.mts +31 -3
  5. package/dist/client/builder/types/collection-types.d.mts +140 -0
  6. package/dist/client/builder/types/ui-config.d.mts +16 -2
  7. package/dist/client/builder/types/views.d.mts +57 -0
  8. package/dist/client/builder/types/widget-types.d.mts +5 -0
  9. package/dist/client/components/actions/action-button.mjs +137 -199
  10. package/dist/client/components/actions/action-dialog.mjs +198 -156
  11. package/dist/client/components/actions/confirmation-dialog.mjs +2 -2
  12. package/dist/client/components/actions/header-actions.mjs +52 -53
  13. package/dist/client/components/admin-link.d.mts +2 -2
  14. package/dist/client/components/auth/auth-loading.mjs +41 -18
  15. package/dist/client/components/blocks/block-fields-renderer.mjs +64 -28
  16. package/dist/client/components/blocks/block-insert-button.mjs +4 -4
  17. package/dist/client/components/blocks/block-item.mjs +2 -2
  18. package/dist/client/components/blocks/block-library-sidebar.mjs +2 -2
  19. package/dist/client/components/component-renderer.mjs +1 -1
  20. package/dist/client/components/fields/array-field.mjs +14 -14
  21. package/dist/client/components/fields/asset-preview-field.mjs +1 -1
  22. package/dist/client/components/fields/blocks-field/blocks-field.mjs +84 -104
  23. package/dist/client/components/fields/json-field.mjs +2 -2
  24. package/dist/client/components/fields/object-array-field.mjs +22 -22
  25. package/dist/client/components/fields/object-field.mjs +5 -5
  26. package/dist/client/components/fields/relation/displays/cards-display.mjs +16 -9
  27. package/dist/client/components/fields/relation/displays/chips-display.mjs +15 -12
  28. package/dist/client/components/fields/relation/displays/grid-display.mjs +15 -11
  29. package/dist/client/components/fields/relation/displays/list-display.mjs +33 -20
  30. package/dist/client/components/fields/relation/displays/table-display.mjs +62 -93
  31. package/dist/client/components/fields/relation/relation-items-display.mjs +1 -1
  32. package/dist/client/components/fields/relation-picker.mjs +7 -6
  33. package/dist/client/components/fields/relation-select.mjs +71 -47
  34. package/dist/client/components/fields/rich-text-editor/bubble-menu.mjs +392 -82
  35. package/dist/client/components/fields/rich-text-editor/extensions.mjs +54 -23
  36. package/dist/client/components/fields/rich-text-editor/image-popover.mjs +24 -50
  37. package/dist/client/components/fields/rich-text-editor/image-upload.mjs +66 -0
  38. package/dist/client/components/fields/rich-text-editor/index.d.mts +38 -0
  39. package/dist/client/components/fields/rich-text-editor/index.mjs +637 -376
  40. package/dist/client/components/fields/rich-text-editor/link-utils.mjs +26 -0
  41. package/dist/client/components/fields/rich-text-editor/presets.d.mts +10 -0
  42. package/dist/client/components/fields/rich-text-editor/slash-commands.mjs +27 -6
  43. package/dist/client/components/fields/rich-text-editor/toolbar.mjs +464 -346
  44. package/dist/client/components/fields/rich-text-editor/types.d.mts +77 -0
  45. package/dist/client/components/fields/upload-field.mjs +45 -49
  46. package/dist/client/components/filter-builder/columns-tab.mjs +69 -62
  47. package/dist/client/components/filter-builder/filter-builder-sheet.mjs +473 -308
  48. package/dist/client/components/filter-builder/filters-tab.mjs +109 -82
  49. package/dist/client/components/filter-builder/saved-views-tab.mjs +300 -198
  50. package/dist/client/components/history-sidebar.mjs +850 -340
  51. package/dist/client/components/layout/field-layout-renderer.mjs +6 -5
  52. package/dist/client/components/locale-switcher.mjs +8 -8
  53. package/dist/client/components/media/media-grid.mjs +12 -9
  54. package/dist/client/components/media/media-picker-dialog.mjs +242 -230
  55. package/dist/client/components/preview/live-preview-mode.mjs +1 -1
  56. package/dist/client/components/primitives/asset-preview.mjs +37 -22
  57. package/dist/client/components/primitives/date-input.mjs +212 -249
  58. package/dist/client/components/primitives/dropzone.mjs +192 -159
  59. package/dist/client/components/primitives/field-select-control.mjs +93 -0
  60. package/dist/client/components/primitives/select-multi.mjs +251 -230
  61. package/dist/client/components/primitives/select-single.mjs +345 -290
  62. package/dist/client/components/primitives/time-input.mjs +2 -2
  63. package/dist/client/components/sheets/resource-sheet.mjs +2 -0
  64. package/dist/client/components/ui/accordion.mjs +4 -4
  65. package/dist/client/components/ui/alert.mjs +3 -3
  66. package/dist/client/components/ui/badge.mjs +4 -4
  67. package/dist/client/components/ui/button.mjs +47 -37
  68. package/dist/client/components/ui/card.mjs +2 -2
  69. package/dist/client/components/ui/checkbox.mjs +1 -1
  70. package/dist/client/components/ui/command.mjs +5 -5
  71. package/dist/client/components/ui/dialog.mjs +3 -3
  72. package/dist/client/components/ui/drawer.mjs +1 -1
  73. package/dist/client/components/ui/dropdown-menu.mjs +157 -15
  74. package/dist/client/components/ui/empty-state.mjs +88 -59
  75. package/dist/client/components/ui/field.mjs +2 -2
  76. package/dist/client/components/ui/input-group.mjs +3 -3
  77. package/dist/client/components/ui/input.mjs +1 -1
  78. package/dist/client/components/ui/kbd.mjs +1 -1
  79. package/dist/client/components/ui/label.mjs +1 -1
  80. package/dist/client/components/ui/popover.mjs +19 -11
  81. package/dist/client/components/ui/scroll-fade.mjs +170 -0
  82. package/dist/client/components/ui/search-input.mjs +1 -1
  83. package/dist/client/components/ui/select.mjs +129 -27
  84. package/dist/client/components/ui/sheet.mjs +54 -34
  85. package/dist/client/components/ui/sidebar.mjs +15 -14
  86. package/dist/client/components/ui/skeleton.mjs +28 -12
  87. package/dist/client/components/ui/switch.mjs +2 -2
  88. package/dist/client/components/ui/table.mjs +82 -74
  89. package/dist/client/components/ui/tabs.mjs +26 -31
  90. package/dist/client/components/ui/textarea.mjs +1 -1
  91. package/dist/client/components/ui/tooltip.mjs +1 -1
  92. package/dist/client/components/widgets/chart-widget.mjs +134 -96
  93. package/dist/client/components/widgets/progress-widget.mjs +59 -34
  94. package/dist/client/components/widgets/quick-actions-widget.mjs +184 -113
  95. package/dist/client/components/widgets/recent-items-widget.mjs +144 -102
  96. package/dist/client/components/widgets/stats-widget.mjs +91 -72
  97. package/dist/client/components/widgets/table-widget.mjs +159 -246
  98. package/dist/client/components/widgets/timeline-widget.mjs +66 -43
  99. package/dist/client/components/widgets/value-widget.mjs +261 -152
  100. package/dist/client/components/widgets/widget-empty-state.mjs +88 -0
  101. package/dist/client/components/widgets/widget-skeletons.mjs +53 -20
  102. package/dist/client/contexts/focus-context.d.mts +2 -2
  103. package/dist/client/hooks/use-action.mjs +63 -55
  104. package/dist/client/hooks/use-audit-history.mjs +1 -65
  105. package/dist/client/hooks/use-collection-validation.mjs +36 -23
  106. package/dist/client/hooks/use-collection.mjs +96 -1
  107. package/dist/client/hooks/use-saved-views.mjs +70 -49
  108. package/dist/client/hooks/use-server-actions.mjs +59 -40
  109. package/dist/client/hooks/use-server-validation.mjs +156 -41
  110. package/dist/client/hooks/use-server-widget-data.mjs +1 -1
  111. package/dist/client/hooks/use-setup-status.d.mts +3 -3
  112. package/dist/client/hooks/use-setup-status.mjs +2 -2
  113. package/dist/client/hooks/use-transition-stage.mjs +2 -10
  114. package/dist/client/hooks/use-validation-error-map.mjs +31 -13
  115. package/dist/client/hooks/use-view-state.mjs +238 -174
  116. package/dist/client/i18n/date-locale.mjs +33 -0
  117. package/dist/client/i18n/hooks.mjs +17 -1
  118. package/dist/client/lib/utils.mjs +3 -2
  119. package/dist/client/preview/block-scope-context.d.mts +2 -2
  120. package/dist/client/preview/preview-banner.d.mts +2 -2
  121. package/dist/client/preview/preview-field.d.mts +4 -4
  122. package/dist/client/preview/preview-field.mjs +2 -2
  123. package/dist/client/runtime/provider.mjs +8 -1
  124. package/dist/client/runtime/translations-provider.mjs +1 -1
  125. package/dist/client/scope/picker.d.mts +2 -2
  126. package/dist/client/scope/provider.d.mts +2 -2
  127. package/dist/client/styles/base.css +1022 -0
  128. package/dist/client/styles/index.css +3 -589
  129. package/dist/client/utils/auto-expand-fields.mjs +4 -2
  130. package/dist/client/utils/keyboard-shortcuts.mjs +26 -0
  131. package/dist/client/utils/use-lazy-component.mjs +80 -0
  132. package/dist/client/views/auth/auth-layout.d.mts +18 -11
  133. package/dist/client/views/auth/auth-layout.mjs +291 -80
  134. package/dist/client/views/auth/forgot-password-form.d.mts +2 -2
  135. package/dist/client/views/auth/forgot-password-form.mjs +2 -2
  136. package/dist/client/views/auth/login-form.d.mts +2 -2
  137. package/dist/client/views/auth/login-form.mjs +1 -1
  138. package/dist/client/views/auth/reset-password-form.d.mts +2 -2
  139. package/dist/client/views/auth/reset-password-form.mjs +2 -2
  140. package/dist/client/views/auth/setup-form.d.mts +2 -2
  141. package/dist/client/views/collection/auto-form-fields.mjs +11 -9
  142. package/dist/client/views/collection/bulk-action-toolbar.mjs +173 -138
  143. package/dist/client/views/collection/cells/complex-cells.mjs +22 -22
  144. package/dist/client/views/collection/cells/primitive-cells.mjs +1 -1
  145. package/dist/client/views/collection/cells/relation-cells.mjs +147 -129
  146. package/dist/client/views/collection/cells/shared/asset-thumbnail.mjs +224 -278
  147. package/dist/client/views/collection/cells/shared/relation-chip.mjs +64 -36
  148. package/dist/client/views/collection/cells/upload-cells.mjs +199 -9
  149. package/dist/client/views/collection/columns/build-columns.mjs +29 -9
  150. package/dist/client/views/collection/columns/column-defaults.mjs +2 -2
  151. package/dist/client/views/collection/field-renderer.mjs +50 -89
  152. package/dist/client/views/collection/form-view.mjs +237 -227
  153. package/dist/client/views/collection/table-view.mjs +1162 -229
  154. package/dist/client/views/collection/view-skeletons.mjs +222 -79
  155. package/dist/client/views/common/global-search.mjs +29 -18
  156. package/dist/client/views/dashboard/dashboard-grid.mjs +678 -501
  157. package/dist/client/views/dashboard/dashboard-widget.mjs +6 -3
  158. package/dist/client/views/dashboard/widget-card.mjs +23 -14
  159. package/dist/client/views/globals/global-form-view.mjs +634 -589
  160. package/dist/client/views/layout/admin-layout-provider.mjs +67 -70
  161. package/dist/client/views/layout/admin-layout.d.mts +3 -6
  162. package/dist/client/views/layout/admin-layout.mjs +149 -172
  163. package/dist/client/views/layout/admin-router.mjs +747 -544
  164. package/dist/client/views/layout/admin-sidebar.d.mts +38 -1
  165. package/dist/client/views/layout/admin-sidebar.mjs +751 -591
  166. package/dist/client/views/layout/admin-theme.d.mts +10 -0
  167. package/dist/client/views/layout/admin-theme.mjs +84 -0
  168. package/dist/client/views/layout/admin-view-layout.mjs +161 -0
  169. package/dist/client/views/pages/accept-invite-page.d.mts +2 -2
  170. package/dist/client/views/pages/accept-invite-page.mjs +49 -26
  171. package/dist/client/views/pages/dashboard-page.d.mts +2 -2
  172. package/dist/client/views/pages/forgot-password-page.d.mts +2 -2
  173. package/dist/client/views/pages/forgot-password-page.mjs +2 -19
  174. package/dist/client/views/pages/invite-page.d.mts +2 -2
  175. package/dist/client/views/pages/invite-page.mjs +2 -19
  176. package/dist/client/views/pages/login-page.d.mts +1 -1
  177. package/dist/client/views/pages/login-page.mjs +4 -21
  178. package/dist/client/views/pages/reset-password-page.d.mts +2 -2
  179. package/dist/client/views/pages/reset-password-page.mjs +3 -20
  180. package/dist/client/views/pages/setup-page.d.mts +2 -2
  181. package/dist/client/views/pages/setup-page.mjs +3 -20
  182. package/dist/client.d.mts +6 -2
  183. package/dist/client.mjs +2 -1
  184. package/dist/components/rich-text/rich-text-renderer.d.mts +2 -2
  185. package/dist/index.d.mts +6 -2
  186. package/dist/index.mjs +2 -1
  187. package/dist/server/augmentation/dashboard.d.mts +67 -3
  188. package/dist/server/augmentation/form-layout.d.mts +21 -0
  189. package/dist/server/augmentation/index.d.mts +1 -1
  190. package/dist/server/codegen/admin-client-template.mjs +4 -0
  191. package/dist/server/fields/blocks.d.mts +1 -1
  192. package/dist/server/fields/blocks.mjs +12 -0
  193. package/dist/server/fields/rich-text.d.mts +1 -1
  194. package/dist/server/fields/rich-text.mjs +8 -0
  195. package/dist/server/i18n/index.mjs +17 -1
  196. package/dist/server/i18n/messages/cs.mjs +23 -0
  197. package/dist/server/i18n/messages/de.mjs +23 -0
  198. package/dist/server/i18n/messages/en.mjs +64 -1
  199. package/dist/server/i18n/messages/es.mjs +23 -0
  200. package/dist/server/i18n/messages/fr.mjs +23 -0
  201. package/dist/server/i18n/messages/pl.mjs +23 -0
  202. package/dist/server/i18n/messages/pt.mjs +23 -0
  203. package/dist/server/i18n/messages/sk.mjs +83 -1
  204. package/dist/server/modules/admin/block/introspection.mjs +4 -1
  205. package/dist/server/modules/admin/block/prefetch.mjs +12 -2
  206. package/dist/server/modules/admin/collections/account.d.mts +50 -50
  207. package/dist/server/modules/admin/collections/admin-locks.d.mts +54 -54
  208. package/dist/server/modules/admin/collections/admin-preferences.d.mts +39 -39
  209. package/dist/server/modules/admin/collections/admin-saved-views.d.mts +47 -47
  210. package/dist/server/modules/admin/collections/apikey.d.mts +68 -68
  211. package/dist/server/modules/admin/collections/assets.d.mts +20 -20
  212. package/dist/server/modules/admin/collections/assets.mjs +0 -1
  213. package/dist/server/modules/admin/collections/session.d.mts +42 -42
  214. package/dist/server/modules/admin/collections/user.d.mts +12 -0
  215. package/dist/server/modules/admin/collections/user.mjs +40 -9
  216. package/dist/server/modules/admin/collections/verification.d.mts +2 -2
  217. package/dist/server/modules/admin/dto/admin-config.dto.mjs +2 -0
  218. package/dist/server/modules/admin/factories.mjs +7 -18
  219. package/dist/server/modules/admin/index.d.mts +1 -1
  220. package/dist/server/modules/admin/routes/admin-config.d.mts +2 -2
  221. package/dist/server/modules/admin/routes/admin-config.mjs +34 -16
  222. package/dist/server/modules/admin/routes/execute-action.d.mts +9 -9
  223. package/dist/server/modules/admin/routes/execute-action.mjs +33 -0
  224. package/dist/server/modules/admin/routes/locales.d.mts +2 -2
  225. package/dist/server/modules/admin/routes/preview.d.mts +11 -11
  226. package/dist/server/modules/admin/routes/reactive.d.mts +9 -9
  227. package/dist/server/modules/admin/routes/setup.d.mts +10 -10
  228. package/dist/server/modules/admin/routes/setup.mjs +7 -7
  229. package/dist/server/modules/admin/routes/translations.d.mts +4 -4
  230. package/dist/server/modules/admin/routes/translations.mjs +5 -1
  231. package/dist/server/modules/admin/routes/widget-data.d.mts +5 -5
  232. package/dist/server/modules/admin-preferences/collections/admin-preferences.mjs +1 -1
  233. package/dist/server/modules/admin-preferences/collections/saved-views.d.mts +27 -27
  234. package/dist/server/modules/audit/.generated/module.d.mts +1 -1
  235. package/dist/server/modules/audit/.generated/module.mjs +1 -1
  236. package/dist/server/modules/audit/collections/audit-log.d.mts +2 -2
  237. package/dist/server/modules/audit/collections/audit-log.mjs +1 -1
  238. package/dist/server/modules/audit/config/app.mjs +99 -42
  239. package/dist/server/modules/audit/jobs/audit-cleanup.mjs +1 -1
  240. package/dist/server/plugin.mjs +4 -2
  241. package/dist/server/proxy-factories.d.mts +4 -3
  242. package/dist/server/proxy-factories.mjs +34 -8
  243. package/dist/shared/types/saved-views.types.d.mts +2 -0
  244. package/package.json +6 -4
  245. package/dist/client/components/fields/rich-text-editor/link-popover.mjs +0 -85
  246. package/dist/client/components/ui/spinner.mjs +0 -52
  247. package/dist/client/components/ui/toolbar.mjs +0 -136
  248. package/dist/client/contexts/breadcrumb-context.mjs +0 -60
  249. package/dist/client/views/layout/admin-topbar.mjs +0 -236
@@ -1,5 +1,6 @@
1
1
  import { useResolveText } from "../../../../i18n/hooks.mjs";
2
2
  import { cn } from "../../../../lib/utils.mjs";
3
+ import { Badge } from "../../../../components/ui/badge.mjs";
3
4
  import { getRelationItemAvatarUrl, getRelationItemId, getRelationItemLabelWithField } from "./cell-helpers.mjs";
4
5
  import { c } from "react/compiler-runtime";
5
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -10,7 +11,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
10
11
  * Shows label and navigates to related item on click (or opens sheet if onClick provided)
11
12
  */
12
13
  function RelationChip(t0) {
13
- const $ = c(31);
14
+ const $ = c(37);
14
15
  const { item, targetCollection, onClick, className, showAvatar: t1, avatarField, labelField } = t0;
15
16
  const showAvatar = t1 === void 0 ? false : t1;
16
17
  const resolveText = useResolveText();
@@ -44,7 +45,7 @@ function RelationChip(t0) {
44
45
  t5 = showAvatar && avatarUrl ? /* @__PURE__ */ jsx("img", {
45
46
  src: avatarUrl,
46
47
  alt: label,
47
- className: "border-border size-4 rounded-full border object-cover"
48
+ className: "image-outline size-4 rounded-full object-cover"
48
49
  }) : null;
49
50
  $[9] = avatarUrl;
50
51
  $[10] = label;
@@ -70,48 +71,75 @@ function RelationChip(t0) {
70
71
  if (canInteract) {
71
72
  const href = `/admin/collections/${targetCollection}/${id}`;
72
73
  let t7$1;
73
- if ($[17] !== className) {
74
- t7$1 = cn("qa-relation-chip inline-flex items-center gap-1 px-2 py-0.5 text-xs", "bg-primary/10 text-primary hover:bg-primary/20", "cursor-pointer transition-colors", "border-primary/20 hover:border-primary/40 border", className);
75
- $[17] = className;
76
- $[18] = t7$1;
77
- } else t7$1 = $[18];
78
- const chipClassName = t7$1;
79
- let t8$1;
80
- if ($[19] !== avatar || $[20] !== chipClassName || $[21] !== handleClick || $[22] !== href || $[23] !== label) {
81
- t8$1 = /* @__PURE__ */ jsxs("a", {
74
+ if ($[17] !== handleClick || $[18] !== href) {
75
+ t7$1 = /* @__PURE__ */ jsx("a", {
82
76
  href,
83
77
  onClick: handleClick,
84
- onPointerDown: _temp,
85
- className: chipClassName,
86
- children: [avatar, label]
78
+ onPointerDown: _temp
79
+ });
80
+ $[17] = handleClick;
81
+ $[18] = href;
82
+ $[19] = t7$1;
83
+ } else t7$1 = $[19];
84
+ let t8$1;
85
+ if ($[20] !== className) {
86
+ t8$1 = cn("qa-relation-chip cursor-pointer", "max-w-40", className);
87
+ $[20] = className;
88
+ $[21] = t8$1;
89
+ } else t8$1 = $[21];
90
+ let t9$1;
91
+ if ($[22] !== label) {
92
+ t9$1 = /* @__PURE__ */ jsx("span", {
93
+ className: "truncate",
94
+ children: label
87
95
  });
88
- $[19] = avatar;
89
- $[20] = chipClassName;
90
- $[21] = handleClick;
91
- $[22] = href;
92
- $[23] = label;
93
- $[24] = t8$1;
94
- } else t8$1 = $[24];
95
- return t8$1;
96
+ $[22] = label;
97
+ $[23] = t9$1;
98
+ } else t9$1 = $[23];
99
+ let t10;
100
+ if ($[24] !== avatar || $[25] !== t7$1 || $[26] !== t8$1 || $[27] !== t9$1) {
101
+ t10 = /* @__PURE__ */ jsxs(Badge, {
102
+ variant: "secondary",
103
+ render: t7$1,
104
+ className: t8$1,
105
+ children: [avatar, t9$1]
106
+ });
107
+ $[24] = avatar;
108
+ $[25] = t7$1;
109
+ $[26] = t8$1;
110
+ $[27] = t9$1;
111
+ $[28] = t10;
112
+ } else t10 = $[28];
113
+ return t10;
96
114
  }
97
115
  let t7;
98
- if ($[25] !== className) {
99
- t7 = cn("qa-relation-chip inline-flex items-center gap-1 px-2 py-0.5 text-xs", "bg-muted text-muted-foreground", "border-border border", className);
100
- $[25] = className;
101
- $[26] = t7;
102
- } else t7 = $[26];
116
+ if ($[29] !== className) {
117
+ t7 = cn("qa-relation-chip cursor-default", className);
118
+ $[29] = className;
119
+ $[30] = t7;
120
+ } else t7 = $[30];
103
121
  let t8;
104
- if ($[27] !== avatar || $[28] !== label || $[29] !== t7) {
105
- t8 = /* @__PURE__ */ jsxs("span", {
122
+ if ($[31] !== label) {
123
+ t8 = /* @__PURE__ */ jsx("span", {
124
+ className: "truncate",
125
+ children: label
126
+ });
127
+ $[31] = label;
128
+ $[32] = t8;
129
+ } else t8 = $[32];
130
+ let t9;
131
+ if ($[33] !== avatar || $[34] !== t7 || $[35] !== t8) {
132
+ t9 = /* @__PURE__ */ jsxs(Badge, {
133
+ variant: "secondary",
106
134
  className: t7,
107
- children: [avatar, label]
135
+ children: [avatar, t8]
108
136
  });
109
- $[27] = avatar;
110
- $[28] = label;
111
- $[29] = t7;
112
- $[30] = t8;
113
- } else t8 = $[30];
114
- return t8;
137
+ $[33] = avatar;
138
+ $[34] = t7;
139
+ $[35] = t8;
140
+ $[36] = t9;
141
+ } else t9 = $[36];
142
+ return t9;
115
143
  }
116
144
  function _temp(e_0) {
117
145
  return e_0.stopPropagation();
@@ -1,4 +1,7 @@
1
+ import { useTranslation } from "../../../i18n/hooks.mjs";
2
+ import { Badge } from "../../../components/ui/badge.mjs";
1
3
  import { AssetThumbnail } from "./shared/asset-thumbnail.mjs";
4
+ import { useCollectionItem } from "../../../hooks/use-collection.mjs";
2
5
  import { c } from "react/compiler-runtime";
3
6
  import "react";
4
7
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -9,19 +12,206 @@ import { jsx, jsxs } from "react/jsx-runtime";
9
12
  * Uses AssetThumbnail with size="sm"
10
13
  */
11
14
  function UploadCell(t0) {
12
- const $ = c(2);
13
- const { value } = t0;
15
+ const $ = c(6);
16
+ const { value, fieldDef } = t0;
17
+ if (Array.isArray(value)) {
18
+ let t1$1;
19
+ if ($[0] !== fieldDef || $[1] !== value) {
20
+ t1$1 = /* @__PURE__ */ jsx(UploadManyCell, {
21
+ value,
22
+ fieldDef
23
+ });
24
+ $[0] = fieldDef;
25
+ $[1] = value;
26
+ $[2] = t1$1;
27
+ } else t1$1 = $[2];
28
+ return t1$1;
29
+ }
14
30
  let t1;
15
- if ($[0] !== value) {
16
- t1 = /* @__PURE__ */ jsx(AssetThumbnail, {
17
- asset: value,
18
- size: "sm",
19
- showFilename: true
31
+ if ($[3] !== fieldDef || $[4] !== value) {
32
+ t1 = /* @__PURE__ */ jsx(UploadSingleCell, {
33
+ value,
34
+ fieldDef
20
35
  });
21
- $[0] = value;
36
+ $[3] = fieldDef;
37
+ $[4] = value;
38
+ $[5] = t1;
39
+ } else t1 = $[5];
40
+ return t1;
41
+ }
42
+ function getUploadCollection(fieldDef) {
43
+ const options = fieldDef?.["~options"] ?? {};
44
+ const target = options.to ?? options.targetCollection;
45
+ if (typeof target === "string" && target.length > 0) return target;
46
+ return "assets";
47
+ }
48
+ function getAssetId(value) {
49
+ if (typeof value === "string" && value.length > 0) return value;
50
+ if (typeof value === "object" && value !== null) {
51
+ const id = value.id;
52
+ return typeof id === "string" && id.length > 0 ? id : void 0;
53
+ }
54
+ }
55
+ function hasAssetDisplayData(value) {
56
+ if (typeof value !== "object" || value === null) return false;
57
+ const asset = value;
58
+ return !!(asset.url || asset.filename || asset.mimeType);
59
+ }
60
+ function UploadSingleCell(t0) {
61
+ const $ = c(11);
62
+ const { value, fieldDef } = t0;
63
+ let t1;
64
+ if ($[0] !== fieldDef) {
65
+ t1 = getUploadCollection(fieldDef);
66
+ $[0] = fieldDef;
22
67
  $[1] = t1;
23
68
  } else t1 = $[1];
24
- return t1;
69
+ const collection = t1;
70
+ let t2;
71
+ if ($[2] !== value) {
72
+ t2 = getAssetId(value);
73
+ $[2] = value;
74
+ $[3] = t2;
75
+ } else t2 = $[3];
76
+ const assetId = t2;
77
+ let t3;
78
+ if ($[4] !== assetId || $[5] !== value) {
79
+ t3 = !!assetId && !hasAssetDisplayData(value);
80
+ $[4] = assetId;
81
+ $[5] = value;
82
+ $[6] = t3;
83
+ } else t3 = $[6];
84
+ const shouldFetch = t3;
85
+ let t4;
86
+ if ($[7] !== shouldFetch) {
87
+ t4 = {
88
+ enabled: shouldFetch,
89
+ staleTime: 3e4
90
+ };
91
+ $[7] = shouldFetch;
92
+ $[8] = t4;
93
+ } else t4 = $[8];
94
+ const { data: fetchedAsset } = useCollectionItem(collection, assetId || "", void 0, t4);
95
+ const t5 = fetchedAsset || value;
96
+ let t6;
97
+ if ($[9] !== t5) {
98
+ t6 = /* @__PURE__ */ jsx(AssetThumbnail, {
99
+ asset: t5,
100
+ size: "sm",
101
+ showFilename: true
102
+ });
103
+ $[9] = t5;
104
+ $[10] = t6;
105
+ } else t6 = $[10];
106
+ return t6;
107
+ }
108
+ /**
109
+ * Upload many cell - displays multiple assets count or thumbnails
110
+ */
111
+ function UploadManyCell(t0) {
112
+ const $ = c(15);
113
+ const { value } = t0;
114
+ const { t } = useTranslation();
115
+ if (value === null || value === void 0) {
116
+ let t1$1;
117
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
118
+ t1$1 = /* @__PURE__ */ jsx("span", {
119
+ className: "text-muted-foreground",
120
+ children: "-"
121
+ });
122
+ $[0] = t1$1;
123
+ } else t1$1 = $[0];
124
+ return t1$1;
125
+ }
126
+ if (!Array.isArray(value)) {
127
+ let t1$1;
128
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
129
+ t1$1 = /* @__PURE__ */ jsx("span", {
130
+ className: "text-muted-foreground",
131
+ children: "-"
132
+ });
133
+ $[1] = t1$1;
134
+ } else t1$1 = $[1];
135
+ return t1$1;
136
+ }
137
+ if (value.length === 0) {
138
+ let t1$1;
139
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
140
+ t1$1 = /* @__PURE__ */ jsx("span", {
141
+ className: "text-muted-foreground",
142
+ children: "-"
143
+ });
144
+ $[2] = t1$1;
145
+ } else t1$1 = $[2];
146
+ return t1$1;
147
+ }
148
+ let t1;
149
+ if ($[3] !== value) {
150
+ t1 = Symbol.for("react.early_return_sentinel");
151
+ bb0: {
152
+ const imageAssets = value.filter(_temp).slice(0, 3);
153
+ if (imageAssets.length > 0) {
154
+ const remaining = value.length - imageAssets.length;
155
+ const t2$1 = /* @__PURE__ */ jsx("div", {
156
+ className: "flex -space-x-2",
157
+ children: imageAssets.map(_temp2)
158
+ });
159
+ let t3$1;
160
+ if ($[5] !== remaining) {
161
+ t3$1 = remaining > 0 && /* @__PURE__ */ jsxs("span", {
162
+ className: "text-muted-foreground ml-1 text-xs tabular-nums",
163
+ children: ["+", remaining]
164
+ });
165
+ $[5] = remaining;
166
+ $[6] = t3$1;
167
+ } else t3$1 = $[6];
168
+ let t4;
169
+ if ($[7] !== t2$1 || $[8] !== t3$1) {
170
+ t4 = /* @__PURE__ */ jsxs("div", {
171
+ className: "flex items-center gap-1",
172
+ children: [t2$1, t3$1]
173
+ });
174
+ $[7] = t2$1;
175
+ $[8] = t3$1;
176
+ $[9] = t4;
177
+ } else t4 = $[9];
178
+ t1 = t4;
179
+ break bb0;
180
+ }
181
+ }
182
+ $[3] = value;
183
+ $[4] = t1;
184
+ } else t1 = $[4];
185
+ if (t1 !== Symbol.for("react.early_return_sentinel")) return t1;
186
+ let t2;
187
+ if ($[10] !== t || $[11] !== value.length) {
188
+ t2 = t("cell.file", { count: value.length });
189
+ $[10] = t;
190
+ $[11] = value.length;
191
+ $[12] = t2;
192
+ } else t2 = $[12];
193
+ let t3;
194
+ if ($[13] !== t2) {
195
+ t3 = /* @__PURE__ */ jsx(Badge, {
196
+ variant: "secondary",
197
+ children: t2
198
+ });
199
+ $[13] = t2;
200
+ $[14] = t3;
201
+ } else t3 = $[14];
202
+ return t3;
203
+ }
204
+ function _temp2(asset, index) {
205
+ return /* @__PURE__ */ jsx("img", {
206
+ src: asset.url,
207
+ alt: asset.filename || "Asset",
208
+ className: "image-outline bg-background size-6 rounded object-cover"
209
+ }, asset.id || index);
210
+ }
211
+ function _temp(item) {
212
+ if (typeof item !== "object" || item === null) return false;
213
+ const mimeType = item.mimeType;
214
+ return typeof mimeType === "string" && mimeType.startsWith("image/");
25
215
  }
26
216
 
27
217
  //#endregion
@@ -76,8 +76,27 @@ const FIELD_TYPES_NEEDING_FIELD_DEF = new Set([
76
76
  "object",
77
77
  "array",
78
78
  "relation",
79
- "reverseRelation"
79
+ "reverseRelation",
80
+ "upload",
81
+ "uploadMany"
80
82
  ]);
83
+ function getDefaultColumnSize(fieldType) {
84
+ switch (fieldType) {
85
+ case "number":
86
+ case "boolean": return 120;
87
+ case "date":
88
+ case "datetime":
89
+ case "time": return 180;
90
+ case "select": return 160;
91
+ case "relation":
92
+ case "reverseRelation": return 220;
93
+ case "upload":
94
+ case "uploadMany": return 160;
95
+ case "textarea":
96
+ case "richText": return 360;
97
+ default: return 240;
98
+ }
99
+ }
81
100
  /**
82
101
  * Build column definitions from collection config
83
102
  *
@@ -106,16 +125,16 @@ function buildColumns(options) {
106
125
  const { config, fallbackColumns = ["id"], buildAllColumns = false, meta } = options;
107
126
  const fields = config?.fields ?? {};
108
127
  const listConfig = config?.list;
109
- const isLocalizedField = (field, definition) => {
110
- const fieldOptions = definition?.["~options"] ?? {};
111
- return fieldOptions.localized !== void 0 ? !!fieldOptions.localized : meta?.localizedFields?.includes(field) ?? false;
112
- };
113
128
  const titleFieldName = meta?.title?.fieldName;
114
129
  const titleType = meta?.title?.type;
115
130
  const titleColumn = titleType === "field" && titleFieldName ? titleFieldName : "_title";
116
131
  let columnConfigs;
117
132
  if (buildAllColumns) {
118
133
  const allFields = Object.keys(fields);
134
+ if (meta?.timestamps) {
135
+ if (!allFields.includes("createdAt")) allFields.push("createdAt");
136
+ if (!allFields.includes("updatedAt")) allFields.push("updatedAt");
137
+ }
119
138
  columnConfigs = [titleColumn, ...titleColumn === "_title" ? allFields : allFields.filter((f) => f !== titleColumn)];
120
139
  } else if (listConfig?.columns && listConfig.columns.length > 0) columnConfigs = listConfig.columns;
121
140
  else if (Object.keys(fields).length > 0) columnConfigs = computeDefaultColumns(fields, { meta });
@@ -125,7 +144,6 @@ function buildColumns(options) {
125
144
  const fieldName = normalized.field;
126
145
  const fieldDef = fields[fieldName];
127
146
  if (fieldName === "_title") {
128
- titleFieldName && isLocalizedField(titleFieldName, fields[titleFieldName]);
129
147
  let titleLabel = "Title";
130
148
  let titleFallback = "Title";
131
149
  if (titleType === "virtual" && titleFieldName && fields[titleFieldName]) {
@@ -144,18 +162,19 @@ function buildColumns(options) {
144
162
  cell: ({ row }) => {
145
163
  return /* @__PURE__ */ jsx(TextCell, { value: row.getValue("_title") });
146
164
  },
165
+ size: 360,
166
+ minSize: 220,
147
167
  enableSorting: false
148
168
  };
149
169
  }
150
- const fieldType = fieldDef?.name ?? "text";
170
+ const fieldType = fieldDef?.name ?? (meta?.timestamps ? "datetime" : "text");
151
171
  const fieldOptions = fieldDef?.["~options"] ?? {};
152
- isLocalizedField(fieldName, fieldDef);
153
172
  let CellComponent;
154
173
  if (normalized.cell) CellComponent = normalized.cell;
155
174
  else if (fieldDef?.cell) CellComponent = fieldDef.cell;
156
175
  else CellComponent = DefaultCell;
157
176
  const needsFieldDef = FIELD_TYPES_NEEDING_FIELD_DEF.has(fieldType);
158
- const accessorKey = fieldType === "relation" && fieldOptions.relationName ? fieldOptions.relationName : fieldName;
177
+ const accessorKey = (fieldType === "relation" || fieldType === "upload" || fieldType === "uploadMany") && fieldOptions.relationName ? fieldOptions.relationName : fieldName;
159
178
  const headerLabel = normalized.header ?? fieldOptions.label;
160
179
  const headerFallback = formatHeader(fieldName);
161
180
  const computeFn = fieldOptions.compute;
@@ -163,6 +182,7 @@ function buildColumns(options) {
163
182
  const columnDef = {
164
183
  id: fieldName,
165
184
  accessorKey: isComputed ? void 0 : accessorKey,
185
+ size: getDefaultColumnSize(fieldType),
166
186
  header: () => /* @__PURE__ */ jsx(ColumnHeader, {
167
187
  label: headerLabel,
168
188
  fallback: headerFallback
@@ -40,13 +40,13 @@ function computeDefaultColumns(fields, options) {
40
40
  if (!fields || Object.keys(fields).length === 0) return defaultCols;
41
41
  const contentFields = [];
42
42
  const systemFields = [];
43
- for (const [key, fieldDef] of Object.entries(fields)) {
43
+ for (const key of Object.keys(fields)) {
44
44
  if (useTitleField && key === titleFieldName) continue;
45
45
  if (SYSTEM_FIELDS.has(key)) systemFields.push(key);
46
46
  else contentFields.push(key);
47
47
  }
48
48
  defaultCols.push(...contentFields);
49
- if ((options?.meta?.timestamps ?? !!fields.createdAt) && fields.createdAt && !defaultCols.includes("createdAt")) defaultCols.push("createdAt");
49
+ if ((options?.meta?.timestamps ?? !!fields.createdAt) && !defaultCols.includes("createdAt")) defaultCols.push("createdAt");
50
50
  return defaultCols;
51
51
  }
52
52
  /**
@@ -1,28 +1,54 @@
1
1
  import { useResolveText } from "../../i18n/hooks.mjs";
2
2
  import { useScopedLocale } from "../../runtime/locale-scope.mjs";
3
3
  import { useAdminConfig } from "../../hooks/use-admin-config.mjs";
4
+ import { useLazyComponent } from "../../utils/use-lazy-component.mjs";
5
+ import { Skeleton } from "../../components/ui/skeleton.mjs";
4
6
  import { scopeDependencies, trackDependencies } from "../../utils/dependency-tracker.mjs";
5
7
  import { buildComponentProps, getFieldContext, getFieldOptions, getFullFieldName } from "./field-context.mjs";
6
- import { Spinner } from "../../components/ui/spinner.mjs";
7
8
  import { useFieldHooks } from "../../hooks/use-field-hooks.mjs";
8
9
  import { c } from "react/compiler-runtime";
9
- import * as React from "react";
10
- import { Fragment, jsx } from "react/jsx-runtime";
10
+ import "react";
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
11
12
  import { useFormContext, useWatch } from "react-hook-form";
12
13
 
13
14
  //#region src/client/views/collection/field-renderer.tsx
14
- /**
15
- * FieldRenderer Component
16
- *
17
- * Renders a single form field using FieldDefinition.
18
- * Shared between AutoFormFields and BlockEditor.
19
- */
20
15
  function renderConfigError(message) {
21
16
  return /* @__PURE__ */ jsx("div", {
22
17
  className: "border-destructive/40 bg-destructive/5 text-destructive rounded border p-3 text-sm",
23
18
  children: message
24
19
  });
25
20
  }
21
+ function FieldComponentSkeleton(t0) {
22
+ const $ = c(3);
23
+ const { type } = t0;
24
+ const largeFieldTypes = new Set([
25
+ "blocks",
26
+ "json",
27
+ "object",
28
+ "richText"
29
+ ]);
30
+ const tallFieldTypes = new Set(["textarea", "upload"]);
31
+ const controlClassName = largeFieldTypes.has(type ?? "") ? "h-40 w-full" : tallFieldTypes.has(type ?? "") ? "h-28 w-full" : "h-10 w-full";
32
+ let t1;
33
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
34
+ t1 = /* @__PURE__ */ jsx(Skeleton, {
35
+ variant: "text",
36
+ className: "h-4 w-24"
37
+ });
38
+ $[0] = t1;
39
+ } else t1 = $[0];
40
+ let t2;
41
+ if ($[1] !== controlClassName) {
42
+ t2 = /* @__PURE__ */ jsxs("div", {
43
+ className: "space-y-2",
44
+ "aria-busy": "true",
45
+ children: [t1, /* @__PURE__ */ jsx(Skeleton, { className: controlClassName })]
46
+ });
47
+ $[1] = controlClassName;
48
+ $[2] = t2;
49
+ } else t2 = $[2];
50
+ return t2;
51
+ }
26
52
  function stripFieldUiOptions(options) {
27
53
  const rest = { ...options };
28
54
  delete rest.label;
@@ -60,61 +86,6 @@ function computeDynamicDependencyPaths({ fieldOptions, form, fieldPrefix }) {
60
86
  return scopeDependencies(collectFieldOptionDependencies(fieldOptions, (fieldPrefix ? form.getValues(fieldPrefix) : form.getValues()) ?? {}), fieldPrefix);
61
87
  }
62
88
  /**
63
- * Resolve a MaybeLazyComponent to a concrete React component.
64
- * Handles direct components, React.lazy, and `() => import(...)` loaders.
65
- */
66
- function useLazyComponent(loader) {
67
- const [state, setState] = React.useState(() => {
68
- if (!loader) return {
69
- Component: null,
70
- loading: false
71
- };
72
- if (!(typeof loader === "function" && !loader.prototype?.render && !loader.prototype?.isReactComponent && loader.length === 0 && !loader.$$typeof)) return {
73
- Component: loader,
74
- loading: false
75
- };
76
- return {
77
- Component: null,
78
- loading: true
79
- };
80
- });
81
- React.useEffect(() => {
82
- if (!loader) {
83
- setState({
84
- Component: null,
85
- loading: false
86
- });
87
- return;
88
- }
89
- if (!(typeof loader === "function" && !loader.prototype?.render && !loader.prototype?.isReactComponent && loader.length === 0 && !loader.$$typeof)) {
90
- setState({
91
- Component: loader,
92
- loading: false
93
- });
94
- return;
95
- }
96
- let mounted = true;
97
- (async () => {
98
- try {
99
- const result = await loader();
100
- if (mounted) setState({
101
- Component: result.default || result,
102
- loading: false
103
- });
104
- } catch {
105
- if (mounted) setState({
106
- Component: null,
107
- loading: false
108
- });
109
- }
110
- })();
111
- return () => {
112
- mounted = false;
113
- };
114
- }, [loader]);
115
- return state;
116
- }
117
- /**
118
89
  * Render field using FieldDefinition.field.component
119
90
  *
120
91
  * This is the primary rendering method. Field components receive:
@@ -172,7 +143,7 @@ function renderEmbeddedField({ context, registry, allCollectionsConfig, componen
172
143
  * 3. Error message if no component registered
173
144
  */
174
145
  function FieldRenderer(t0) {
175
- const $ = c(32);
146
+ const $ = c(31);
176
147
  const { fieldName, fieldDef, collection, mode: t1, registry, fieldPrefix, allCollectionsConfig, renderEmbeddedFields, className, entityMeta: entityMetaProp } = t0;
177
148
  const mode = t1 === void 0 ? "collection" : t1;
178
149
  const form = useFormContext();
@@ -313,17 +284,7 @@ function FieldRenderer(t0) {
313
284
  componentProps,
314
285
  renderEmbeddedFields
315
286
  });
316
- if (!content && componentLoading) {
317
- let t10$1;
318
- if ($[24] === Symbol.for("react.memo_cache_sentinel")) {
319
- t10$1 = /* @__PURE__ */ jsx("div", {
320
- className: "flex items-center justify-center p-4",
321
- children: /* @__PURE__ */ jsx(Spinner, { className: "size-5" })
322
- });
323
- $[24] = t10$1;
324
- } else t10$1 = $[24];
325
- content = t10$1;
326
- }
287
+ if (!content && componentLoading) content = /* @__PURE__ */ jsx(FieldComponentSkeleton, { type: context.type });
327
288
  if (!content && resolvedComponent) content = renderDefinitionComponent({
328
289
  context: {
329
290
  ...context,
@@ -335,32 +296,32 @@ function FieldRenderer(t0) {
335
296
  if (!content) {
336
297
  const t10$1 = `No component registered for field type "${context.type}" (field: "${context.fieldName}").`;
337
298
  let t11;
338
- if ($[25] !== t10$1) {
299
+ if ($[24] !== t10$1) {
339
300
  t11 = renderConfigError(t10$1);
340
- $[25] = t10$1;
341
- $[26] = t11;
342
- } else t11 = $[26];
301
+ $[24] = t10$1;
302
+ $[25] = t11;
303
+ } else t11 = $[25];
343
304
  content = t11;
344
305
  }
345
306
  if (className) {
346
307
  let t10$1;
347
- if ($[27] !== className || $[28] !== content) {
308
+ if ($[26] !== className || $[27] !== content) {
348
309
  t10$1 = /* @__PURE__ */ jsx("div", {
349
310
  className,
350
311
  children: content
351
312
  });
352
- $[27] = className;
353
- $[28] = content;
354
- $[29] = t10$1;
355
- } else t10$1 = $[29];
313
+ $[26] = className;
314
+ $[27] = content;
315
+ $[28] = t10$1;
316
+ } else t10$1 = $[28];
356
317
  return t10$1;
357
318
  }
358
319
  let t10;
359
- if ($[30] !== content) {
320
+ if ($[29] !== content) {
360
321
  t10 = /* @__PURE__ */ jsx(Fragment, { children: content });
361
- $[30] = content;
362
- $[31] = t10;
363
- } else t10 = $[31];
322
+ $[29] = content;
323
+ $[30] = t10;
324
+ } else t10 = $[30];
364
325
  return t10;
365
326
  }
366
327