@michaelthielemann/kestrel 4.1.2 → 5.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 (340) hide show
  1. package/README.md +26 -201
  2. package/dist/boot.d.ts +45 -0
  3. package/dist/boot.js +274 -0
  4. package/dist/cast.d.ts +3 -0
  5. package/dist/cast.js +6 -0
  6. package/dist/catalogue.d.ts +11 -0
  7. package/dist/catalogue.js +1 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +55 -0
  10. package/dist/context.d.ts +62 -0
  11. package/dist/context.js +61 -0
  12. package/dist/dataflow.d.ts +3 -0
  13. package/dist/dataflow.js +65 -0
  14. package/dist/defineConfig.d.ts +157 -0
  15. package/dist/defineConfig.js +41 -0
  16. package/dist/defineContract.d.ts +12 -0
  17. package/dist/defineContract.js +16 -0
  18. package/dist/defineModule.d.ts +75 -0
  19. package/dist/defineModule.js +9 -0
  20. package/dist/definePipeline.d.ts +7 -0
  21. package/dist/definePipeline.js +11 -0
  22. package/dist/errors.d.ts +26 -0
  23. package/dist/errors.js +48 -0
  24. package/dist/index.d.ts +19 -0
  25. package/dist/index.js +14 -0
  26. package/dist/load.d.ts +7 -0
  27. package/dist/load.js +79 -0
  28. package/dist/logger.d.ts +18 -0
  29. package/dist/logger.js +36 -0
  30. package/dist/registry.d.ts +14 -0
  31. package/dist/registry.js +87 -0
  32. package/dist/result.d.ts +19 -0
  33. package/dist/result.js +19 -0
  34. package/dist/runner.d.ts +29 -0
  35. package/dist/runner.js +133 -0
  36. package/dist/schema.d.ts +7 -0
  37. package/dist/schema.js +142 -0
  38. package/dist/sort.d.ts +2 -0
  39. package/dist/sort.js +50 -0
  40. package/dist/testing/runPipeline.d.ts +9 -0
  41. package/dist/testing/runPipeline.js +22 -0
  42. package/dist/triggers/cron.d.ts +10 -0
  43. package/dist/triggers/cron.js +44 -0
  44. package/dist/triggers/cronMatch.d.ts +10 -0
  45. package/dist/triggers/cronMatch.js +68 -0
  46. package/dist/triggers/http.d.ts +58 -0
  47. package/dist/triggers/http.js +292 -0
  48. package/package.json +25 -151
  49. package/NOTICE +0 -12
  50. package/kestrel.config.ts +0 -28
  51. package/layers/access/nuxt.config.ts +0 -5
  52. package/layers/access/server/middleware/00.ip-allowlist.ts +0 -52
  53. package/layers/access/server/middleware/access-guard.ts +0 -32
  54. package/layers/access/server/types.d.ts +0 -7
  55. package/layers/admin/app/components/AdminAccount.vue +0 -212
  56. package/layers/admin/app/components/AdminNav.vue +0 -44
  57. package/layers/admin/app/components/BlockFields.vue +0 -67
  58. package/layers/admin/app/components/BlockPreview.vue +0 -413
  59. package/layers/admin/app/components/BlockTree.vue +0 -433
  60. package/layers/admin/app/components/BlocksBody.vue +0 -163
  61. package/layers/admin/app/components/CollectionDeleteDialog.vue +0 -38
  62. package/layers/admin/app/components/CollectionEditor.vue +0 -324
  63. package/layers/admin/app/components/CollectionList.vue +0 -429
  64. package/layers/admin/app/components/CollectionListBulkBar.vue +0 -62
  65. package/layers/admin/app/components/CollectionListColumnsPanel.vue +0 -37
  66. package/layers/admin/app/components/CollectionListFilterPanel.vue +0 -145
  67. package/layers/admin/app/components/CollectionListPager.vue +0 -70
  68. package/layers/admin/app/components/CollectionListTable.vue +0 -347
  69. package/layers/admin/app/components/EditorStatus.vue +0 -211
  70. package/layers/admin/app/components/EditorUnsupported.vue +0 -28
  71. package/layers/admin/app/components/FieldsBody.vue +0 -23
  72. package/layers/admin/app/components/LocaleBar.vue +0 -107
  73. package/layers/admin/app/components/PageFields.vue +0 -129
  74. package/layers/admin/app/components/PageFieldsPane.vue +0 -39
  75. package/layers/admin/app/components/SeoFields.vue +0 -210
  76. package/layers/admin/app/components/SingletonEditor.vue +0 -93
  77. package/layers/admin/app/composables/useAuth.ts +0 -68
  78. package/layers/admin/app/composables/useBlockTree.ts +0 -95
  79. package/layers/admin/app/composables/useBlocks.ts +0 -7
  80. package/layers/admin/app/composables/useCachedResource.ts +0 -35
  81. package/layers/admin/app/composables/useCollectionOps.ts +0 -102
  82. package/layers/admin/app/composables/useCollections.ts +0 -6
  83. package/layers/admin/app/composables/useContentLocales.ts +0 -23
  84. package/layers/admin/app/composables/useEditForm.ts +0 -402
  85. package/layers/admin/app/composables/useLinkResolver.ts +0 -40
  86. package/layers/admin/app/composables/useListBatchActions.ts +0 -78
  87. package/layers/admin/app/composables/useListColumns.ts +0 -53
  88. package/layers/admin/app/composables/useListFilterDraft.ts +0 -129
  89. package/layers/admin/app/composables/useListRows.ts +0 -75
  90. package/layers/admin/app/composables/useListSelection.ts +0 -28
  91. package/layers/admin/app/composables/useListUrlState.ts +0 -53
  92. package/layers/admin/app/composables/usePendingPublishPoll.ts +0 -15
  93. package/layers/admin/app/composables/usePreviewViewport.ts +0 -30
  94. package/layers/admin/app/composables/usePublishStatus.ts +0 -107
  95. package/layers/admin/app/composables/useRailCollapsed.ts +0 -14
  96. package/layers/admin/app/composables/useTheme.ts +0 -36
  97. package/layers/admin/app/composables/useToolbarPanel.ts +0 -38
  98. package/layers/admin/app/composables/useUnsavedGuard.ts +0 -22
  99. package/layers/admin/app/layouts/admin.vue +0 -266
  100. package/layers/admin/app/middleware/admin-auth.ts +0 -4
  101. package/layers/admin/app/pages/admin/[collection]/[id].vue +0 -203
  102. package/layers/admin/app/pages/admin/[collection]/index.vue +0 -62
  103. package/layers/admin/app/pages/admin/index.vue +0 -118
  104. package/layers/admin/app/pages/admin/login.vue +0 -68
  105. package/layers/admin/app/pages/admin/media.vue +0 -28
  106. package/layers/admin/app/pages/admin/references.vue +0 -146
  107. package/layers/admin/app/plugins/admin-style-guard.client.ts +0 -76
  108. package/layers/admin/app/plugins/reauth.client.ts +0 -20
  109. package/layers/admin/app/utils/admin-style-guard.ts +0 -20
  110. package/layers/admin/app/utils/block-tree.ts +0 -214
  111. package/layers/admin/app/utils/collection-ops.ts +0 -69
  112. package/layers/admin/app/utils/dead-refs.ts +0 -30
  113. package/layers/admin/app/utils/edit-form.ts +0 -267
  114. package/layers/admin/app/utils/editor-expose.ts +0 -36
  115. package/layers/admin/app/utils/editor-form-context.ts +0 -82
  116. package/layers/admin/app/utils/editor-registry.ts +0 -20
  117. package/layers/admin/app/utils/field-keys.ts +0 -11
  118. package/layers/admin/app/utils/list-cell.ts +0 -46
  119. package/layers/admin/app/utils/list-columns.ts +0 -142
  120. package/layers/admin/app/utils/list-query.ts +0 -96
  121. package/layers/admin/app/utils/nav-active.ts +0 -9
  122. package/layers/admin/app/utils/populate-blocks.ts +0 -288
  123. package/layers/admin/app/utils/preview-channel.ts +0 -62
  124. package/layers/admin/app/utils/preview-viewport.ts +0 -80
  125. package/layers/admin/app/utils/reauth.ts +0 -67
  126. package/layers/admin/app/utils/record-title.ts +0 -15
  127. package/layers/admin/app/utils/register-builtin-editors.ts +0 -9
  128. package/layers/admin/app/utils/safe-redirect.ts +0 -12
  129. package/layers/admin/nuxt.config.ts +0 -20
  130. package/layers/auth/nuxt.config.ts +0 -1
  131. package/layers/auth/server/plugins/01.register-auth-pipelines.ts +0 -7
  132. package/layers/collections/nuxt.config.ts +0 -1
  133. package/layers/collections/server/plugins/01.register.ts +0 -29
  134. package/layers/collections/server/plugins/02.register-relation-populate.ts +0 -18
  135. package/layers/core/app/composables/layouts.ts +0 -5
  136. package/layers/core/app/utils/field-factories.ts +0 -129
  137. package/layers/core/app/utils/layouts.ts +0 -38
  138. package/layers/core/modules/auto-discovery/extract-block.ts +0 -179
  139. package/layers/core/modules/auto-discovery/index.ts +0 -112
  140. package/layers/core/modules/auto-discovery/package-registry.ts +0 -19
  141. package/layers/core/modules/auto-discovery/scan.ts +0 -170
  142. package/layers/core/modules/auto-discovery/virtual.d.ts +0 -20
  143. package/layers/core/modules/component-namespace/index.ts +0 -44
  144. package/layers/core/modules/component-namespace/shared.ts +0 -24
  145. package/layers/core/modules/kestrel/app-shell.ts +0 -55
  146. package/layers/core/modules/kestrel/auto-imports.ts +0 -44
  147. package/layers/core/modules/kestrel/index.ts +0 -144
  148. package/layers/core/modules/plugin-order/index.ts +0 -69
  149. package/layers/core/modules/plugin-order/plugin-order.ts +0 -273
  150. package/layers/core/nuxt.config.ts +0 -10
  151. package/layers/core/server/api/[...path].ts +0 -98
  152. package/layers/core/server/plugins/00.config.ts +0 -12
  153. package/layers/core/server/plugins/00.migrate.ts +0 -12
  154. package/layers/core/server/plugins/01.register-introspection-pipeline.ts +0 -5
  155. package/layers/core/server/plugins/01.register-openapi-pipeline.ts +0 -5
  156. package/layers/core/server/plugins/01.register-tooling-pipelines.ts +0 -5
  157. package/layers/core/server/plugins/02.schema-sync.ts +0 -58
  158. package/layers/core/server/plugins/04.outbox-worker.ts +0 -31
  159. package/layers/core/server/plugins/05.reindex-refs.ts +0 -5
  160. package/layers/core/server/routes/__kestrel/dashboard.get.ts +0 -29
  161. package/layers/core/server/tasks/db/migrate-module.ts +0 -83
  162. package/layers/core/server/tasks/db/migrate-revisions.ts +0 -20
  163. package/layers/core/server/tasks/db/migrate.ts +0 -50
  164. package/layers/core/server/utils/server-config.ts +0 -81
  165. package/layers/fields/nuxt.config.ts +0 -1
  166. package/layers/fields/server/plugins/01.register-blocks-pipeline.ts +0 -7
  167. package/layers/fields/server/plugins/01.register-field-populate.ts +0 -11
  168. package/layers/media/app/components/KestrelImg.vue +0 -94
  169. package/layers/media/app/components/MediaConflictDialog.vue +0 -35
  170. package/layers/media/app/components/MediaDeleteDialog.vue +0 -52
  171. package/layers/media/app/components/MediaGrid.vue +0 -113
  172. package/layers/media/app/components/MediaImage.vue +0 -70
  173. package/layers/media/app/components/MediaLibrary.vue +0 -456
  174. package/layers/media/app/components/MediaNewFolderDialog.vue +0 -32
  175. package/layers/media/app/components/MediaPathBar.vue +0 -163
  176. package/layers/media/app/components/MediaPicker.vue +0 -19
  177. package/layers/media/app/components/MediaRenameDialog.vue +0 -32
  178. package/layers/media/app/components/MediaTable.vue +0 -75
  179. package/layers/media/app/components/MediaThumb.vue +0 -25
  180. package/layers/media/app/components/MediaToolbar.vue +0 -90
  181. package/layers/media/app/components/MediaUploadDialog.vue +0 -87
  182. package/layers/media/app/components/MediaViewer.vue +0 -137
  183. package/layers/media/app/components/field/Media.vue +0 -263
  184. package/layers/media/app/composables/useBlurUp.ts +0 -55
  185. package/layers/media/app/composables/useMediaClipboard.ts +0 -14
  186. package/layers/media/app/composables/useMediaContextMenu.ts +0 -56
  187. package/layers/media/app/composables/useMediaDnd.ts +0 -56
  188. package/layers/media/app/composables/useMediaLibrary.ts +0 -152
  189. package/layers/media/app/composables/useMediaOps.ts +0 -50
  190. package/layers/media/app/composables/useMediaRelocate.ts +0 -39
  191. package/layers/media/app/composables/useMediaResolver.ts +0 -50
  192. package/layers/media/app/composables/useMediaUpload.ts +0 -93
  193. package/layers/media/app/composables/useMediaVariant.ts +0 -34
  194. package/layers/media/app/plugins/field-media.client.ts +0 -6
  195. package/layers/media/app/utils/ai-disclosure.ts +0 -19
  196. package/layers/media/app/utils/dnd.ts +0 -69
  197. package/layers/media/app/utils/library.ts +0 -81
  198. package/layers/media/app/utils/ops.ts +0 -60
  199. package/layers/media/app/utils/picture-model.ts +0 -125
  200. package/layers/media/app/utils/thumbhash.ts +0 -19
  201. package/layers/media/app/utils/variant-name.ts +0 -20
  202. package/layers/media/nuxt.config.ts +0 -7
  203. package/layers/media/server/middleware/ondemand-variants.ts +0 -38
  204. package/layers/media/server/plugins/01.register-media-pipelines.ts +0 -7
  205. package/layers/media/server/plugins/02.register-media.ts +0 -22
  206. package/layers/media/server/plugins/04.variant-capture.ts +0 -27
  207. package/layers/media/server/plugins/05.media-cleanup.ts +0 -5
  208. package/layers/media/server/tasks/media/backfill.ts +0 -17
  209. package/layers/public/app/app.vue +0 -5
  210. package/layers/public/app/components/BlockRenderer.vue +0 -56
  211. package/layers/public/app/components/KestrelLink.vue +0 -26
  212. package/layers/public/app/components/KestrelPreviewBridge.vue +0 -133
  213. package/layers/public/app/composables/public-page.ts +0 -24
  214. package/layers/public/app/error.vue +0 -12
  215. package/layers/public/app/layouts/default.vue +0 -5
  216. package/layers/public/app/pages/[...slug].vue +0 -239
  217. package/layers/public/app/pages/__kestrel/preview.vue +0 -46
  218. package/layers/public/app/utils/block-edit-context.ts +0 -16
  219. package/layers/public/app/utils/json-ld.ts +0 -139
  220. package/layers/public/app/utils/link-href.ts +0 -46
  221. package/layers/public/app/utils/page-head.ts +0 -84
  222. package/layers/public/app/utils/page-layout.ts +0 -18
  223. package/layers/public/app/utils/preview-protocol.ts +0 -117
  224. package/layers/public/app/utils/public-route.ts +0 -46
  225. package/layers/public/app/utils/site-head.ts +0 -43
  226. package/layers/public/modules/deploy-output/index.ts +0 -80
  227. package/layers/public/modules/prerender-routes/discover.ts +0 -37
  228. package/layers/public/modules/prerender-routes/index.ts +0 -88
  229. package/layers/public/modules/prerender-routes/routes.ts +0 -16
  230. package/layers/public/modules/prune-media/index.ts +0 -48
  231. package/layers/public/modules/prune-media/prune-media.ts +0 -81
  232. package/layers/public/nuxt.config.ts +0 -14
  233. package/layers/public/server/delivery-live/serve.ts +0 -111
  234. package/layers/public/server/middleware/delivery-live-catchall.ts +0 -7
  235. package/layers/public/server/pipelines/index.ts +0 -23
  236. package/layers/public/server/plugins/00.ensure-snapshot-triggers.ts +0 -14
  237. package/layers/public/server/plugins/01.register-public-pipelines.ts +0 -7
  238. package/layers/public/server/plugins/02.register-links.ts +0 -16
  239. package/layers/public/server/plugins/03.redirects.ts +0 -55
  240. package/layers/public/server/plugins/05.plan-publish.ts +0 -5
  241. package/layers/public/server/plugins/zz.publish.ts +0 -127
  242. package/layers/public/server/routes/llms-full.txt.get.ts +0 -99
  243. package/layers/public/server/routes/llms.txt.get.ts +0 -66
  244. package/layers/public/server/routes/redirects.json.get.ts +0 -58
  245. package/layers/public/server/routes/robots.txt.get.ts +0 -11
  246. package/layers/public/server/routes/sitemap.xml.get.ts +0 -79
  247. package/layers/public/server/tasks/publish/run.ts +0 -32
  248. package/layers/public/server/utils/publish/render-live.ts +0 -26
  249. package/layers/ui/app/assets/scss/_base.scss +0 -16
  250. package/layers/ui/app/assets/scss/_datepicker.scss +0 -82
  251. package/layers/ui/app/assets/scss/_mixins.scss +0 -50
  252. package/layers/ui/app/assets/scss/_reset.scss +0 -65
  253. package/layers/ui/app/assets/scss/_tokens.scss +0 -183
  254. package/layers/ui/app/assets/scss/main.scss +0 -4
  255. package/layers/ui/app/components/field/Boolean.vue +0 -30
  256. package/layers/ui/app/components/field/Choice.vue +0 -73
  257. package/layers/ui/app/components/field/Datetime.vue +0 -98
  258. package/layers/ui/app/components/field/DeadRefNote.vue +0 -28
  259. package/layers/ui/app/components/field/Json.vue +0 -62
  260. package/layers/ui/app/components/field/Layout.vue +0 -138
  261. package/layers/ui/app/components/field/Link.vue +0 -112
  262. package/layers/ui/app/components/field/LinkInternalPicker.vue +0 -95
  263. package/layers/ui/app/components/field/Number.vue +0 -30
  264. package/layers/ui/app/components/field/Relation.vue +0 -49
  265. package/layers/ui/app/components/field/Renderer.vue +0 -30
  266. package/layers/ui/app/components/field/Repeater.vue +0 -460
  267. package/layers/ui/app/components/field/Richtext.vue +0 -26
  268. package/layers/ui/app/components/field/Slug.vue +0 -65
  269. package/layers/ui/app/components/field/Text.vue +0 -35
  270. package/layers/ui/app/components/field/Unsupported.vue +0 -34
  271. package/layers/ui/app/components/ui/Alert.vue +0 -50
  272. package/layers/ui/app/components/ui/Brand.vue +0 -22
  273. package/layers/ui/app/components/ui/Button.vue +0 -116
  274. package/layers/ui/app/components/ui/ButtonGroup.vue +0 -96
  275. package/layers/ui/app/components/ui/Checkbox.vue +0 -53
  276. package/layers/ui/app/components/ui/CheckboxGroup.vue +0 -51
  277. package/layers/ui/app/components/ui/Combobox.vue +0 -345
  278. package/layers/ui/app/components/ui/DatePicker.vue +0 -92
  279. package/layers/ui/app/components/ui/DateRangePicker.vue +0 -100
  280. package/layers/ui/app/components/ui/Dialog.vue +0 -107
  281. package/layers/ui/app/components/ui/EmptyState.vue +0 -46
  282. package/layers/ui/app/components/ui/Field.vue +0 -58
  283. package/layers/ui/app/components/ui/Fieldset.vue +0 -65
  284. package/layers/ui/app/components/ui/Icon.vue +0 -44
  285. package/layers/ui/app/components/ui/Menu.vue +0 -54
  286. package/layers/ui/app/components/ui/NumberInput.vue +0 -175
  287. package/layers/ui/app/components/ui/Richtext.vue +0 -141
  288. package/layers/ui/app/components/ui/RichtextToolbar.vue +0 -251
  289. package/layers/ui/app/components/ui/Select.vue +0 -52
  290. package/layers/ui/app/components/ui/TextInput.vue +0 -111
  291. package/layers/ui/app/components/ui/Textarea.vue +0 -39
  292. package/layers/ui/app/components/ui/TimeInput.vue +0 -18
  293. package/layers/ui/app/components/ui/Toasts.vue +0 -103
  294. package/layers/ui/app/components/ui/Tooltip.vue +0 -45
  295. package/layers/ui/app/composables/useAdminLang.ts +0 -8
  296. package/layers/ui/app/composables/useDragReorder.ts +0 -41
  297. package/layers/ui/app/composables/useEchoGuard.ts +0 -28
  298. package/layers/ui/app/composables/useLinkField.ts +0 -70
  299. package/layers/ui/app/composables/useRecordOptions.ts +0 -84
  300. package/layers/ui/app/composables/useRepeater.ts +0 -99
  301. package/layers/ui/app/composables/useT.ts +0 -32
  302. package/layers/ui/app/composables/useToast.ts +0 -46
  303. package/layers/ui/app/i18n/de.ts +0 -432
  304. package/layers/ui/app/i18n/en.ts +0 -434
  305. package/layers/ui/app/utils/boolean-field.ts +0 -10
  306. package/layers/ui/app/utils/field-component.ts +0 -22
  307. package/layers/ui/app/utils/field-empty.ts +0 -21
  308. package/layers/ui/app/utils/field-registry.ts +0 -36
  309. package/layers/ui/app/utils/humanize.ts +0 -14
  310. package/layers/ui/app/utils/icons.ts +0 -143
  311. package/layers/ui/app/utils/iso-date.ts +0 -18
  312. package/layers/ui/app/utils/localized.ts +0 -13
  313. package/layers/ui/app/utils/record-context.ts +0 -15
  314. package/layers/ui/app/utils/reorder.ts +0 -8
  315. package/layers/ui/app/utils/richtext-preserve-class.ts +0 -31
  316. package/layers/ui/app/utils/useFieldA11y.ts +0 -40
  317. package/layers/ui/nuxt.config.ts +0 -9
  318. package/nuxt.config.ts +0 -108
  319. package/scripts/consumer-template-ci.mjs +0 -160
  320. package/scripts/copy-create-payload.mjs +0 -49
  321. package/scripts/coverage-all.mjs +0 -163
  322. package/scripts/dashboard.mjs +0 -89
  323. package/scripts/hash-password.mjs +0 -29
  324. package/scripts/kestrel.mjs +0 -240
  325. package/scripts/lib/cli.mjs +0 -129
  326. package/scripts/lib/coverage-model.mjs +0 -51
  327. package/scripts/lib/password.mjs +0 -19
  328. package/scripts/lib/scaffold.mjs +0 -205
  329. package/scripts/port-graph.mjs +0 -350
  330. package/scripts/typecheck.mjs +0 -62
  331. package/templates/starter/README.md +0 -65
  332. package/templates/starter/_env.example +0 -17
  333. package/templates/starter/_gitignore +0 -26
  334. package/templates/starter/_package.json +0 -22
  335. package/templates/starter/app/app.vue +0 -7
  336. package/templates/starter/app/blocks/Prose.vue +0 -13
  337. package/templates/starter/app/layouts/default.vue +0 -6
  338. package/templates/starter/nuxt.config.ts +0 -23
  339. package/templates/starter/pnpm-workspace.yaml +0 -8
  340. package/templates/starter/tsconfig.json +0 -3
@@ -1,434 +0,0 @@
1
- import type { Catalog } from '../composables/useT'
2
-
3
- // Admin-UI chrome strings (source language + fallback). Keys are dot-namespaced by area. Strings may
4
- // carry `{name}` placeholders interpolated by `useT().t`. Content (collection data) is NOT translated
5
- // here — only the dashboard chrome. Keep `en` the complete set; other catalogs may be partial.
6
- export const en: Catalog = {
7
- 'common.new': 'New {label}',
8
- 'common.save': 'Save',
9
- 'common.publish': 'Publish',
10
- 'common.cancel': 'Cancel',
11
- 'common.create': 'Create',
12
- 'common.delete': 'Delete',
13
- 'common.close': 'Close',
14
- 'common.retry': 'Retry',
15
-
16
- 'nav.dashboard': 'Dashboard',
17
- 'nav.signOut': 'Sign out',
18
- 'theme.dark': 'Dark mode',
19
- 'theme.light': 'Light mode',
20
- 'a11y.expandSidebar': 'Expand sidebar',
21
- 'a11y.collapseSidebar': 'Collapse sidebar',
22
- 'a11y.toLight': 'Switch to light mode',
23
- 'a11y.toDark': 'Switch to dark mode',
24
- 'a11y.contentLocale': 'Content locale',
25
- 'a11y.rowActions': 'Actions',
26
- 'lang.label': 'Language',
27
-
28
- 'account.label': 'Account',
29
- 'account.name': 'Admin',
30
-
31
- 'input.showPassword': 'Show password',
32
- 'input.hidePassword': 'Hide password',
33
-
34
- 'login.signIn': 'Sign in',
35
- 'login.password': 'Password',
36
- 'login.invalid': 'Invalid credentials',
37
- 'login.error': 'Something went wrong — please try again',
38
-
39
- 'dash.title': 'Dashboard',
40
- 'dash.lede': 'Choose a collection to manage its content.',
41
- 'dash.empty.title': 'No collections yet',
42
- 'dash.empty.desc': 'Define a collection to start managing content.',
43
- 'dash.mode.singleton': 'Singleton',
44
- 'dash.mode.collection': 'Collection',
45
-
46
- 'collection.unknown': 'Unknown collection: {name}',
47
-
48
- 'editor.back': '{collection}',
49
- 'editor.newRecord': 'New {collection}',
50
- 'editor.editRecord': 'Edit {collection} #{id}',
51
- 'editor.discardConfirm': 'Discard unsaved changes?',
52
- 'editor.fixPageFields': 'Please fix the highlighted page fields before saving.',
53
- 'editor.fixBlockContent': 'Some block content is invalid. Check the highlighted block fields.',
54
- 'editor.saveConflict': 'This conflicts with an existing record.',
55
- 'editor.saveFailed': 'Save failed.',
56
- 'editor.quarantined.title': 'Record quarantined',
57
- 'editor.quarantined.desc': 'This record no longer matches its collection’s schema and is shown read-only. It cannot be edited or saved until the underlying data is fixed.',
58
- 'toast.saved': 'Saved',
59
- 'toast.deleted': 'Deleted',
60
- 'toast.duplicated': 'Duplicated',
61
- 'toast.published': 'Published',
62
- 'toast.unpublished': 'Unpublished',
63
- 'toast.region': 'Notifications',
64
- 'toast.dismiss': 'Dismiss',
65
-
66
- 'list.translations': 'Translations',
67
- 'list.deadRefs': 'Refs',
68
- 'list.filter': 'Filter',
69
- 'list.filterPlaceholder': 'Filter {name}',
70
- 'list.filterClearAll': 'Clear all filters',
71
- 'list.removeFilter': 'Remove {name} filter',
72
- 'list.noFilters': 'No filterable columns.',
73
- // filter operators (the generic set) + datetime-specific overrides (filter.opDate.*) + boolean values
74
- 'filter.operator': 'Operator',
75
- 'filter.op.eq': 'equals',
76
- 'filter.op.ne': 'not equals',
77
- 'filter.op.lt': 'less than',
78
- 'filter.op.lte': 'less or equal',
79
- 'filter.op.gt': 'greater than',
80
- 'filter.op.gte': 'greater or equal',
81
- 'filter.op.contains': 'contains',
82
- 'filter.op.notContains': 'does not contain',
83
- 'filter.opDate.lt': 'before',
84
- 'filter.opDate.lte': 'on or before',
85
- 'filter.opDate.gt': 'after',
86
- 'filter.opDate.gte': 'on or after',
87
- 'filter.bool.true': 'Yes',
88
- 'filter.bool.false': 'No',
89
- 'list.columns': 'Columns',
90
- 'list.columnsReset': 'Reset to defaults',
91
- 'list.col.id': 'ID',
92
- 'list.col.slug': 'Slug',
93
- 'list.col.status': 'Status',
94
- 'list.col.createdAt': 'Created',
95
- 'list.col.updatedAt': 'Updated',
96
- 'list.editLocale': 'Edit {loc}',
97
- 'list.createLocale': 'Create {loc}',
98
- 'list.empty.title': 'No records yet',
99
- 'list.empty.desc': 'Nothing in {name} so far — create the first one.',
100
- 'list.noMatch.title': 'No matching records',
101
- 'list.noMatch.desc': 'No {name} match the active filters.',
102
- 'list.prev': 'Prev',
103
- 'list.page': 'Page {page} of {totalPages} · {total} total',
104
- 'list.next': 'Next',
105
- 'list.perPage': 'Per page',
106
- 'list.result': '{total} result',
107
- 'list.results': '{total} results',
108
- 'list.loadError': "Couldn't load this collection.",
109
- 'list.quarantined': 'Quarantined',
110
- 'list.quarantinedOne': '{n} quarantined record',
111
- 'list.quarantinedCount': '{n} quarantined records',
112
- 'list.selectAll': 'Select all rows on this page',
113
- 'list.selectRow': 'Select {name}',
114
- 'list.selected': '{n} selected',
115
- 'list.clearSelection': 'Clear',
116
- 'list.rowEdit': 'Edit {name}',
117
- 'list.rowDuplicate': 'Duplicate {name}',
118
- 'list.rowDelete': 'Delete {name}',
119
- 'list.bulkDelete': 'Delete',
120
- 'list.bulkPublish': 'Publish',
121
- 'list.bulkUnpublish': 'Unpublish',
122
- 'list.deleteSummary': 'Delete {n} record(s)? This cannot be undone.',
123
- 'list.deleteReferrersWarn': '{n} of these are referenced by other records, which will be left with a broken link.',
124
- 'list.deleteRefsUnverified': 'References could not be verified — some records may be left with a broken link. Proceed with caution.',
125
- 'list.opFailed': 'The action could not be completed.',
126
- 'list.refCheckFailed': 'References could not be checked.',
127
- 'list.actionConfirm': 'Run "{name}" on {n} record(s)?',
128
- 'list.actionDone': '{name} done',
129
-
130
- 'preview.ariaLabel': 'Live preview',
131
- 'preview.label': 'Preview',
132
- 'preview.deviceLabel': 'Preview size',
133
- 'preview.device.desktop': 'Desktop',
134
- 'preview.device.tablet': 'Tablet',
135
- 'preview.device.mobile': 'Mobile',
136
- 'preview.refresh': 'Refresh preview',
137
- 'preview.auto': 'Auto',
138
- 'preview.width': 'Width',
139
- 'preview.height': 'Height',
140
-
141
- 'pageSettings.slugLabel': 'Slug',
142
- 'pageSettings.slugHint': 'URL path, e.g. /about (blank = auto-generated from the title)',
143
- 'pageSettings.layoutLabel': 'Layout',
144
- 'pageSettings.layoutHint': 'Which layout renders this page.',
145
- 'pageSettings.layoutDefault': 'Standard (default)',
146
- 'pageSettings.statusLabel': 'Status',
147
- 'pageSettings.statusHint': 'Draft stays off the live site; Published renders it.',
148
- 'pageSettings.statusDraft': 'Draft',
149
- 'pageSettings.statusPublished': 'Published',
150
-
151
- 'editor.openInNewTab': 'Open in new tab',
152
- 'editor.previewUnsaved': 'Preview unsaved changes in a new tab',
153
- 'editor.previewFailed': 'Could not open the preview.',
154
- 'editor.publishFailed': 'Publishing failed.',
155
- 'editor.publishNotGenerated': 'Static output is off in this environment — nothing was written.',
156
- 'editor.publishDraft': 'A draft has no public page. Publish it by setting its status to Published.',
157
- // editor Ampel — LEFT lamp: one WORD + a details tooltip (save + publish lifecycle of this record)
158
- 'editorStatus.word.saving': 'Saving…',
159
- 'editorStatus.word.unsaved': 'Unsaved',
160
- 'editorStatus.word.draft': 'Draft',
161
- 'editorStatus.word.published': 'Published',
162
- 'editorStatus.word.saved': 'Saved',
163
- 'editorStatus.detail.saving': 'Saving your changes…',
164
- 'editorStatus.detail.unsaved': 'You have unsaved local changes.',
165
- 'editorStatus.detail.draft': 'Saved as a draft — not on the live site.',
166
- 'editorStatus.detail.published': 'Saved and published.',
167
- 'editorStatus.detail.saved': 'All changes saved.',
168
- // editor Ampel — RIGHT lamp: one WORD + a details tooltip (generated state of the static page)
169
- 'editorStatus.word.live': 'Live',
170
- 'editorStatus.word.generating': 'Generating…',
171
- 'editorStatus.word.notPublished': 'Not published',
172
- 'editorStatus.word.notBuilt': 'Not built',
173
- 'editorStatus.word.notLive': 'Not live',
174
- 'editorStatus.word.error': 'Error',
175
- 'editorStatus.word.outdated': 'Outdated',
176
- 'editorStatus.live.liveS3': 'Live — page uploaded to S3.',
177
- 'editorStatus.live.liveLocal': 'Live — page written to the static output.',
178
- 'editorStatus.live.pending': 'Publishing in progress…',
179
- 'editorStatus.live.outdated': 'Saved but not published — the live page still shows the last published version.',
180
- 'editorStatus.live.notPublished': 'Never published — press Publish to put this page on the live site.',
181
- 'editorStatus.live.notBuilt': 'Not generated in this environment — the static page is built on deploy.',
182
- 'editorStatus.live.error': 'Publishing the static page failed.',
183
- 'editorStatus.live.draft': 'Draft — not generated. It stays off the live site until published.',
184
- 'editorStatus.live.updatedAt': 'Last published {time}',
185
-
186
- 'seo.sectionLabel': 'SEO',
187
- 'seo.metaTitle': 'Meta title',
188
- 'seo.metaDescription': 'Meta description',
189
- 'seo.noindexLabel': 'Hide this page from search engines (noindex)',
190
- 'seo.untitled': '(untitled)',
191
- 'seo.noDescription': 'No meta description — search engines will choose a snippet.',
192
- 'field.boolean.yes': 'Yes',
193
- 'field.boolean.no': 'No',
194
- 'editor.unsupported': 'No editor is registered for type “{type}”.',
195
- 'seo.socialImage': 'Social share image',
196
- 'seo.socialImageHint': 'Shown as the preview image when the page is shared (og:image).',
197
- 'seo.author': 'Author',
198
- 'seo.authorHint': 'Published as the article author in the page’s structured data.',
199
- 'seo.publishedDate': 'Publication date',
200
- 'seo.publishedDateHint': 'Tells search and answer engines how current this page is.',
201
- 'seo.keywords': 'Keywords',
202
- 'seo.keywordsHint': 'Comma-separated topics for this page.',
203
-
204
- 'localeBar.fieldLabel': 'Locale',
205
- 'localeBar.groupLabel': 'Content locale',
206
- 'localeBar.editLocale': 'Edit {loc}',
207
- 'localeBar.copyInto': 'Copy {loc} into {current}',
208
- 'localeBar.createTranslation': 'Create {loc} translation',
209
- 'localeBar.copyFailed': "Couldn't copy from {locale}.",
210
-
211
- 'history.label': 'Edit history',
212
- 'history.undo': 'Undo',
213
- 'history.redo': 'Redo',
214
-
215
- 'blocks.empty': 'No blocks yet.',
216
- 'blocks.moveUp': 'Move block {n} up',
217
- 'blocks.moveDown': 'Move block {n} down',
218
- 'blocks.duplicate': 'Duplicate block {n}',
219
- 'blocks.remove': 'Remove block {n}',
220
- 'blocks.add': 'Add block',
221
- 'blocks.pickType': 'Choose a block type',
222
- 'blocks.addOfType': 'Add {type}',
223
- 'blocks.page': 'Page',
224
- 'blocks.pageFields': 'Page fields',
225
- 'blocks.invalid': 'Contains errors',
226
- 'blocks.addInto': 'Add to {slot}',
227
- 'blocks.noFields': 'This block has no editable fields.',
228
- 'blocks.fieldsLabel': 'Block fields',
229
- 'blocks.treeLabel': 'Block structure',
230
-
231
- 'deadRefs.listWarning': 'Links to a deleted or unpublished record',
232
- 'deadRefs.blockBadge': 'Broken reference',
233
- 'deadRefs.fieldNote': 'Points at a deleted or unpublished record.',
234
-
235
- // broken-references report (the reverse "what links here" view)
236
- 'refs.title': 'Broken references',
237
- 'refs.lede': 'Records that link to a deleted or unpublished target. Their published output keeps the stale link until you re-edit them.',
238
- 'refs.loadError': "Couldn't load the references report — it could not be verified.",
239
- 'refs.empty.title': 'No broken references',
240
- 'refs.empty.desc': 'Every reference points at a live, published record.',
241
- 'refs.colReferrer': 'Record',
242
- 'refs.colTarget': 'Links to',
243
- 'refs.colReason': 'Issue',
244
- 'refs.reason.missing': 'Deleted',
245
- 'refs.reason.unpublished': 'Unpublished',
246
- 'refs.dashAlert': '{n} broken reference(s) — review',
247
-
248
- 'gallery.title': 'Field gallery',
249
- 'gallery.lede.before': 'Every implemented field widget, live. The relation and internal-link pickers query ',
250
- 'gallery.lede.after': ' — create a post or two to see results.',
251
-
252
- 'media.title': 'Media',
253
- 'media.picker.titleSingle': 'Select a file',
254
- 'media.picker.titleMultiple': 'Select media',
255
- 'media.menu.cut': 'Cut',
256
- 'media.menu.copy': 'Copy',
257
- 'media.menu.paste': 'Paste',
258
- 'media.menu.pasteInto': 'Paste into folder',
259
- 'media.menu.rename': 'Rename',
260
- 'media.menu.delete': 'Delete',
261
- 'media.menu.deleteN': 'Delete {n} items',
262
- // media — error fallbacks (the server statusMessage is preferred when present)
263
- 'media.error.load': 'Failed to load the library',
264
- 'media.error.relocate': "The operation couldn't be completed.",
265
- 'media.error.relocateConflict': 'Some items could not be moved or copied.',
266
- 'media.folderEmpty': 'This folder is empty.',
267
- 'media.folderNotFound': 'That folder does not exist.',
268
- 'media.loadMore': 'Load more',
269
- 'media.clipboardItem': 'item',
270
- 'media.clipboardItems': 'items',
271
- 'media.clipboardCut': 'cut',
272
- 'media.clipboardCopied': 'copied',
273
- 'media.pasteHere': 'Paste here',
274
- 'media.clear': 'Clear',
275
- 'media.uploading': 'Uploading… ',
276
- 'media.uploadUploaded': 'uploaded',
277
- 'media.uploadFailed': 'failed',
278
- 'media.uploadSkipped': 'skipped',
279
- 'media.uploadError': '{name}: {reason}',
280
- 'media.uploadFailedReason': 'Upload failed',
281
- 'media.selected': 'selected',
282
- 'media.useSelected': 'Use selected',
283
- 'media.dropToUpload': 'Drop files to upload',
284
- 'media.conflicts.title': 'Resolve upload conflicts',
285
- 'media.conflicts.desc': '{count} file(s) already exist. Choose how to resolve each.',
286
- 'media.conflicts.applyAll': 'Apply to all:',
287
- 'media.conflicts.overwriteAll': 'Overwrite all',
288
- 'media.conflicts.renameAll': 'Rename all',
289
- 'media.conflicts.skipAll': 'Skip all',
290
- 'media.conflicts.newName': 'New name for {name}',
291
- 'media.conflicts.overwrite': 'Overwrite',
292
- 'media.conflicts.rename': 'Rename',
293
- 'media.conflicts.skip': 'Skip',
294
- 'media.newFolder': 'New folder',
295
- 'media.folderName': 'Folder name',
296
- 'media.folderNamePlaceholder': 'e.g. holiday',
297
- 'media.rename': 'Rename',
298
- 'media.newName': 'New name',
299
- 'media.deleteSummary': 'Delete {files} {filesUnit} and {folders} {foldersUnit} — {size}.',
300
- 'media.file': 'file',
301
- 'media.files': 'files',
302
- 'media.folder': 'folder',
303
- 'media.folders': 'folders',
304
- 'media.usageWarning': 'These files are used by published content and links will break:',
305
- 'media.conflictTitleMove': 'Move — conflicts',
306
- 'media.conflictTitleCopy': 'Copy — conflicts',
307
- 'media.conflictItems': '{count} item(s) already exist in "{dest}":',
308
- 'media.rootFolder': 'root',
309
- 'media.conflictFolderExists': 'folder already exists',
310
- 'media.conflictFileExists': 'file already exists',
311
- 'media.skip': 'Skip',
312
- 'media.replace': 'Replace',
313
- 'media.keepBoth': 'Keep both',
314
- 'media.colName': 'Name',
315
- 'media.colType': 'Type',
316
- 'media.colSize': 'Size',
317
- 'media.colDimensions': 'Dimensions',
318
- 'media.typeFolder': 'Folder',
319
- 'media.parentFolder': 'Go to the parent folder',
320
-
321
- 'mediaViewer.folder': 'Folder',
322
- 'mediaViewer.uploaded': 'Uploaded',
323
- 'mediaViewer.alt': 'Alt text',
324
- 'mediaViewer.altHint': 'Describes the image for screen readers and SEO.',
325
- 'mediaViewer.saveFailed': "Couldn't save the alt text.",
326
- 'mediaViewer.aiSourceTypeLabel': 'AI disclosure',
327
- 'mediaViewer.aiSourceTypeHint': 'How this asset was produced (EU AI Act Art. 50). Leave empty when nothing needs disclosing.',
328
- 'mediaViewer.aiSourceType.trainedAlgorithmicMedia': 'Fully AI-generated',
329
- 'mediaViewer.aiSourceType.compositeWithTrainedAlgorithmicMedia': 'AI content composited into real media',
330
- 'mediaViewer.aiSourceType.algorithmicallyEnhanced': 'AI-enhanced / algorithmically edited',
331
- 'mediaViewer.aiNote': 'Disclosure note',
332
- 'mediaViewer.aiNoteHint': 'Free text, e.g. the tool used. Pre-filled with any AI signals found in the file at upload — evidence only, not a verified claim.',
333
-
334
- 'richtext.bold': 'Bold',
335
- 'richtext.italic': 'Italic',
336
- 'richtext.underline': 'Underline',
337
- 'richtext.strikethrough': 'Strikethrough',
338
- 'richtext.inlineCode': 'Inline code',
339
- 'richtext.highlight': 'Highlight',
340
- 'richtext.subscript': 'Subscript',
341
- 'richtext.superscript': 'Superscript',
342
- 'richtext.bulletList': 'Bullet list',
343
- 'richtext.orderedList': 'Ordered list',
344
- 'richtext.blockquote': 'Blockquote',
345
- 'richtext.codeBlock': 'Code block',
346
- 'richtext.horizontalRule': 'Horizontal rule',
347
- 'richtext.alignLeft': 'Align left',
348
- 'richtext.alignCenter': 'Align center',
349
- 'richtext.alignRight': 'Align right',
350
- 'richtext.justify': 'Justify',
351
- 'richtext.clearFormatting': 'Clear formatting',
352
- 'richtext.undo': 'Undo',
353
- 'richtext.redo': 'Redo',
354
- 'richtext.paragraph': 'Paragraph',
355
- 'richtext.heading1': 'Heading 1',
356
- 'richtext.heading2': 'Heading 2',
357
- 'richtext.heading3': 'Heading 3',
358
- 'richtext.heading4': 'Heading 4',
359
- 'richtext.heading5': 'Heading 5',
360
- 'richtext.heading6': 'Heading 6',
361
- 'richtext.blockType': 'Block type',
362
- 'richtext.link': 'Link',
363
- 'richtext.linkInternal': 'Internal link',
364
- 'richtext.urlPlaceholder': 'https://…',
365
- 'richtext.linkUrl': 'Link URL',
366
- 'richtext.apply': 'Apply',
367
-
368
- 'mediaToolbar.searchPlaceholder': 'Search…',
369
- 'mediaToolbar.searchAriaLabel': 'Search media',
370
- 'mediaToolbar.viewGrid': 'Grid',
371
- 'mediaToolbar.viewTable': 'Table',
372
- 'mediaToolbar.viewAriaLabel': 'View',
373
- 'mediaToolbar.upload': 'Upload',
374
- 'mediaToolbar.newFolder': 'New folder',
375
-
376
- 'mediaPath.navAriaLabel': 'Path',
377
- 'mediaPath.editAriaLabel': 'Edit path',
378
- 'mediaPath.inputAriaLabel': 'Enter path',
379
-
380
- 'nav.collections': 'Collections',
381
-
382
- 'field.datetime.range_start': 'Start',
383
- 'field.datetime.range_end': 'End',
384
- 'field.link.type_internal': 'Internal',
385
- 'field.link.type_url': 'URL',
386
- 'field.link.type_email': 'Email',
387
- 'field.link.type_phone': 'Phone',
388
- 'field.link.link_type': 'Link type',
389
- 'field.link.url_placeholder': 'https://…',
390
- 'field.link.label_placeholder': 'Link text (optional)',
391
- 'field.link.hash_placeholder': 'Anchor (optional, e.g. section-id)',
392
- 'field.relation.placeholder': 'Search…',
393
- 'field.linkPicker.loadError': 'Could not load collections.',
394
- 'field.linkPicker.chooseCollection': 'Choose a collection…',
395
- 'field.linkPicker.collectionLabel': 'Collection',
396
- 'field.linkPicker.searchRecords': 'Search records…',
397
- 'field.repeater.moved': 'Moved item to position {n} of {total}',
398
- 'field.repeater.removed': 'Item {n} removed, {remaining} remaining',
399
- 'field.repeater.duplicated': 'Duplicated item {n}',
400
- 'field.repeater.inserted': 'Item inserted at position {n}',
401
- 'field.repeater.insert_label': 'Insert item at position {n}',
402
- 'field.repeater.item_label': 'Item {n}',
403
- 'field.repeater.move_up': 'Move item {n} up',
404
- 'field.repeater.move_down': 'Move item {n} down',
405
- 'field.repeater.duplicate_label': 'Duplicate item {n}',
406
- 'field.repeater.remove_label': 'Remove item {n}',
407
- 'field.repeater.empty': 'No items yet.',
408
- 'field.repeater.add': 'Add item',
409
- 'field.media.empty': 'No media selected.',
410
- 'field.media.add': 'Add media',
411
- 'field.media.replace': 'Replace',
412
- 'field.media.select': 'Select media',
413
- 'field.media.remove': 'Remove {name}',
414
- 'field.media.itemAt': 'media #{pos}',
415
- 'field.media.move_earlier': 'Move {name} earlier',
416
- 'field.media.move_later': 'Move {name} later',
417
- 'field.media.moved': 'Moved {name} to position {pos} of {total}',
418
-
419
- 'combobox.moved': 'Moved {label} to position {pos} of {total}',
420
- 'combobox.move_earlier': 'Move {label} earlier',
421
- 'combobox.move_later': 'Move {label} later',
422
- 'combobox.remove': 'Remove {label}',
423
- 'combobox.clear': 'Clear',
424
- 'combobox.toggle_options': 'Toggle options',
425
- 'combobox.loading': 'Loading…',
426
- 'combobox.no_results': 'No results',
427
-
428
- 'datePicker.openCalendar': 'Open calendar',
429
- 'datePicker.previousMonth': 'Previous month',
430
- 'datePicker.nextMonth': 'Next month',
431
- 'dateRange.openCalendar': 'Open calendar',
432
- 'dateRange.previousMonth': 'Previous month',
433
- 'dateRange.nextMonth': 'Next month',
434
- }
@@ -1,10 +0,0 @@
1
- /**
2
- * Map a ButtonGroup (single-select ToggleGroup) selection to the boolean model. A deselect — reka emits
3
- * null/undefined when the already-active option is re-clicked — keeps the current value instead of
4
- * coercing to `false`, so re-clicking the selected option is a no-op rather than a silent inversion.
5
- */
6
- export function nextBooleanValue(current: boolean | undefined, incoming: string | string[] | null): boolean | undefined {
7
- if (incoming === 'true') return true
8
- if (incoming === 'false') return false
9
- return current
10
- }
@@ -1,22 +0,0 @@
1
- import type { FieldDef } from '@michaelthielemann/kestrel-core'
2
-
3
- /** A record reference: its id plus a human label. Shared by UiCombobox and FieldRelation. */
4
- export interface FieldOption { value: number; label: string }
5
-
6
- /**
7
- * The shared prop contract every Field* widget honors (plus a v-model).
8
- *
9
- * Validity vocabulary (two intentional names, one seam): `error: string | null` is the validation
10
- * MESSAGE, carried by the wrappers (UiField/UiFieldset) which own its display + aria-describedby. A few
11
- * portaled controls that render outside the wrapper (UiCombobox, FieldLinkInternalPicker) also take an
12
- * `invalid: boolean` — just the visual ring — because they can't see the wrapper's `[data-invalid]`.
13
- * So: `error` = the message at the field boundary; `invalid` = the ring for detached/teleported controls.
14
- */
15
- export interface FieldComponentProps {
16
- field: FieldDef
17
- name: string
18
- locale: string
19
- error?: string | null
20
- disabled?: boolean
21
- id?: string
22
- }
@@ -1,21 +0,0 @@
1
- /**
2
- * Per-type blank-value registry for consumer-defined field types — consulted by the editor's form-init
3
- * (`emptyForField` in admin/edit-form). A custom array/object-backed type registers its empty here so a
4
- * NEW record / block seeds the right shape instead of `null`. Client-side + co-located with
5
- * `registerFieldComponent` (form-init is a client concern; the server descriptor can't reach it). No Vue
6
- * imports, so it is safe to import from the node-tested edit-form util.
7
- *
8
- * @example
9
- * // app/plugins/field-types.client.ts
10
- * registerFieldComponent('tags', TagsField)
11
- * registerFieldEmpty('tags', () => []) // a new record seeds [] instead of null
12
- */
13
- const fieldEmpties: Record<string, () => unknown> = {}
14
-
15
- export function registerFieldEmpty(type: string, make: () => unknown): void {
16
- fieldEmpties[type] = make
17
- }
18
-
19
- export function resolveFieldEmpty(type: string): (() => unknown) | undefined {
20
- return fieldEmpties[type]
21
- }
@@ -1,36 +0,0 @@
1
- import { defineAsyncComponent, type Component } from 'vue'
2
- import type { FieldType } from '@michaelthielemann/kestrel-core'
3
- import FieldText from '../components/field/Text.vue'
4
- import FieldNumber from '../components/field/Number.vue'
5
- import FieldBoolean from '../components/field/Boolean.vue'
6
- import FieldJson from '../components/field/Json.vue'
7
- import FieldChoice from '../components/field/Choice.vue'
8
- import FieldRelation from '../components/field/Relation.vue'
9
- import FieldLink from '../components/field/Link.vue'
10
- import FieldSlug from '../components/field/Slug.vue'
11
-
12
- /** Field types with a widget so far. Each later slice adds its entry. */
13
- export const fieldComponents: Partial<Record<FieldType, Component>> = {
14
- text: FieldText,
15
- slug: FieldSlug,
16
- number: FieldNumber,
17
- boolean: FieldBoolean,
18
- json: FieldJson,
19
- choice: FieldChoice,
20
- relation: FieldRelation,
21
- link: FieldLink,
22
- // Async-loaded so their heavy deps never enter the base editor chunk — they load only when a field of
23
- // that type actually renders. richtext pulls in all of TipTap (the single heaviest dep group); datetime
24
- // pulls reka-ui + @internationalized/date.
25
- datetime: defineAsyncComponent(() => import('../components/field/Datetime.vue')),
26
- richtext: defineAsyncComponent(() => import('../components/field/Richtext.vue')),
27
- // Async-loaded to break the registry → Repeater → Renderer → registry import cycle.
28
- repeater: defineAsyncComponent(() => import('../components/field/Repeater.vue')),
29
- }
30
-
31
- export const resolveFieldComponent = (type: FieldType): Component | undefined => fieldComponents[type]
32
-
33
- /** Register a field widget for a type (domain layers call this from a plugin). Mutates the singleton. */
34
- export function registerFieldComponent(type: FieldType, component: Component): void {
35
- fieldComponents[type] = component
36
- }
@@ -1,14 +0,0 @@
1
- /**
2
- * Turn a field key into a human label: split snake_case / kebab-case / camelCase into words and
3
- * capitalize the first. The shared fallback when a field has no explicit (localized) `label`, used by
4
- * both the editor field widgets (via the FieldRenderer) and the collection-list column headers — so the
5
- * editor label and the list header read the same.
6
- */
7
- export function humanizeFieldName(name: string): string {
8
- const spaced = name
9
- .replace(/[_-]+/g, ' ')
10
- .replace(/([a-z0-9])([A-Z])/g, '$1 $2')
11
- .replace(/\s+/g, ' ')
12
- .trim()
13
- return spaced ? spaced.charAt(0).toUpperCase() + spaced.slice(1) : name
14
- }