@elytracms/studio 0.0.92 → 0.0.94

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 (599) hide show
  1. package/convex/analytics-cost.test.ts +817 -0
  2. package/convex/asset-alt-migration.test.ts +127 -0
  3. package/convex/asset-replace.test.ts +168 -0
  4. package/convex/asset-revalidate.test.ts +6 -6
  5. package/convex/assets.ts +41 -5
  6. package/convex/auth.ts +5 -2
  7. package/convex/authority.ts +35 -11
  8. package/convex/cms.ts +25 -11
  9. package/convex/contract-parity.test.ts +25 -3
  10. package/convex/delivery.ts +12 -9
  11. package/convex/document-revalidate.test.ts +10 -12
  12. package/convex/guard.ts +9 -7
  13. package/convex/http-routes.test.ts +18 -8
  14. package/convex/http.ts +23 -17
  15. package/convex/ingest.test.ts +326 -0
  16. package/convex/ingest.ts +281 -0
  17. package/convex/invites.ts +13 -5
  18. package/convex/members.ts +10 -4
  19. package/convex/orphan-hydration.test.ts +116 -0
  20. package/convex/rail-write-parity.test.ts +11 -8
  21. package/convex/record-functions.ts +325 -0
  22. package/convex/records.test.ts +156 -0
  23. package/convex/redirect-migration.test.ts +205 -0
  24. package/convex/redirect-revalidate.test.ts +5 -1
  25. package/convex/redirects.ts +120 -79
  26. package/convex/role-policy.test.ts +315 -0
  27. package/convex/roles.ts +83 -0
  28. package/convex/schema.ts +36 -0
  29. package/convex/triggers.ts +21 -1
  30. package/dist/addon.d.ts +71 -0
  31. package/dist/addon.js +67 -0
  32. package/dist/addon.js.map +1 -0
  33. package/dist/components/account/account-settings.js +2 -2
  34. package/dist/components/account/account-settings.js.map +1 -1
  35. package/dist/components/account/credential-panel.js +2 -2
  36. package/dist/components/account/credential-panel.js.map +1 -1
  37. package/dist/components/account/self-account-schema.d.ts +6 -15
  38. package/dist/components/account/self-account-schema.js +52 -34
  39. package/dist/components/account/self-account-schema.js.map +1 -1
  40. package/dist/components/account/self-account-view-source.d.ts +1 -1
  41. package/dist/components/account/self-account-view-source.js +6 -4
  42. package/dist/components/account/self-account-view-source.js.map +1 -1
  43. package/dist/components/ai/ai-chat-panel-lazy.js +1 -1
  44. package/dist/components/ai/ai-chat-panel-lazy.js.map +1 -1
  45. package/dist/components/ai/ai-chat-panel.js +6 -6
  46. package/dist/components/ai/ai-chat-panel.js.map +1 -1
  47. package/dist/components/ai/ai-cms-panel.js +2 -2
  48. package/dist/components/ai/ai-cms-panel.js.map +1 -1
  49. package/dist/components/ai/ai-panel-toggle.js +4 -4
  50. package/dist/components/ai/ai-panel-toggle.js.map +1 -1
  51. package/dist/components/ai/chat-ui.js +2 -2
  52. package/dist/components/ai/chat-ui.js.map +1 -1
  53. package/dist/components/ai/proposal-card.d.ts +2 -2
  54. package/dist/components/ai/proposal-card.js +4 -3
  55. package/dist/components/ai/proposal-card.js.map +1 -1
  56. package/dist/components/ai/proposal-issues.js +2 -2
  57. package/dist/components/ai/proposal-issues.js.map +1 -1
  58. package/dist/components/ai/translate-document-action.js +2 -2
  59. package/dist/components/ai/translate-document-action.js.map +1 -1
  60. package/dist/components/ai/translate-document-dialog.js +10 -8
  61. package/dist/components/ai/translate-document-dialog.js.map +1 -1
  62. package/dist/components/ai/translate-skipped.d.ts +19 -0
  63. package/dist/components/ai/translate-skipped.js +46 -0
  64. package/dist/components/ai/translate-skipped.js.map +1 -0
  65. package/dist/components/app-views/default-modules.d.ts +50 -2
  66. package/dist/components/app-views/default-modules.js +65 -20
  67. package/dist/components/app-views/default-modules.js.map +1 -1
  68. package/dist/components/app-views/module.d.ts +53 -3
  69. package/dist/components/app-views/module.js +14 -7
  70. package/dist/components/app-views/module.js.map +1 -1
  71. package/dist/components/app-views/sidebar.js +1 -1
  72. package/dist/components/app-views/sidebar.js.map +1 -1
  73. package/dist/components/app-views/studio-config.d.ts +11 -2
  74. package/dist/components/app-views/studio-config.js.map +1 -1
  75. package/dist/components/assets/asset-detail.js +20 -10
  76. package/dist/components/assets/asset-detail.js.map +1 -1
  77. package/dist/components/assets/asset-grid.js +2 -2
  78. package/dist/components/assets/asset-grid.js.map +1 -1
  79. package/dist/components/assets/asset-metadata.d.ts +15 -4
  80. package/dist/components/assets/asset-metadata.js +15 -2
  81. package/dist/components/assets/asset-metadata.js.map +1 -1
  82. package/dist/components/assets/asset-search.js +4 -1
  83. package/dist/components/assets/asset-search.js.map +1 -1
  84. package/dist/components/assets/asset-selection.d.ts +0 -8
  85. package/dist/components/assets/asset-selection.js +4 -23
  86. package/dist/components/assets/asset-selection.js.map +1 -1
  87. package/dist/components/assets/asset-thumb.js +6 -5
  88. package/dist/components/assets/asset-thumb.js.map +1 -1
  89. package/dist/components/assets/assets-collection-view-source.d.ts +5 -5
  90. package/dist/components/assets/assets-collection-view-source.js +9 -5
  91. package/dist/components/assets/assets-collection-view-source.js.map +1 -1
  92. package/dist/components/assets/assets-module.js +1 -1
  93. package/dist/components/assets/assets-module.js.map +1 -1
  94. package/dist/components/assets/assets-store.d.ts +16 -2
  95. package/dist/components/assets/assets-store.js +28 -6
  96. package/dist/components/assets/assets-store.js.map +1 -1
  97. package/dist/components/assets/assets-view-preference.js +1 -1
  98. package/dist/components/assets/assets-view-preference.js.map +1 -1
  99. package/dist/components/assets/replace-file.d.ts +22 -0
  100. package/dist/components/assets/replace-file.js +59 -0
  101. package/dist/components/assets/replace-file.js.map +1 -0
  102. package/dist/components/auth-context.d.ts +1 -1
  103. package/dist/components/auth-context.js +6 -6
  104. package/dist/components/auth-context.js.map +1 -1
  105. package/dist/components/builder/blocks-model.d.ts +15 -27
  106. package/dist/components/builder/blocks-model.js +38 -44
  107. package/dist/components/builder/blocks-model.js.map +1 -1
  108. package/dist/components/builder/blocks-panel.d.ts +8 -4
  109. package/dist/components/builder/blocks-panel.js +10 -9
  110. package/dist/components/builder/blocks-panel.js.map +1 -1
  111. package/dist/components/builder/builder-store.d.ts +104 -15
  112. package/dist/components/builder/builder-store.js +157 -32
  113. package/dist/components/builder/builder-store.js.map +1 -1
  114. package/dist/components/builder/canvas-body.d.ts +30 -0
  115. package/dist/components/builder/canvas-body.js +38 -0
  116. package/dist/components/builder/canvas-body.js.map +1 -0
  117. package/dist/components/builder/canvas-breakpoints.js +1 -1
  118. package/dist/components/builder/canvas-breakpoints.js.map +1 -1
  119. package/dist/components/builder/canvas-chrome-css.js +7 -0
  120. package/dist/components/builder/canvas-chrome-css.js.map +1 -1
  121. package/dist/components/builder/canvas-dnd.d.ts +9 -9
  122. package/dist/components/builder/canvas-dnd.js +6 -6
  123. package/dist/components/builder/canvas-dnd.js.map +1 -1
  124. package/dist/components/builder/canvas-inline-editing.d.ts +1 -1
  125. package/dist/components/builder/canvas-inline-editing.js.map +1 -1
  126. package/dist/components/builder/canvas-overlay-geometry.d.ts +1 -1
  127. package/dist/components/builder/canvas-overlay-geometry.js.map +1 -1
  128. package/dist/components/builder/canvas-render-context.d.ts +28 -20
  129. package/dist/components/builder/canvas-render-context.js +46 -47
  130. package/dist/components/builder/canvas-render-context.js.map +1 -1
  131. package/dist/components/builder/canvas-runs.d.ts +45 -0
  132. package/dist/components/builder/canvas-runs.js +51 -0
  133. package/dist/components/builder/canvas-runs.js.map +1 -0
  134. package/dist/components/builder/canvas-theme-notice.js +2 -2
  135. package/dist/components/builder/canvas-theme-notice.js.map +1 -1
  136. package/dist/components/builder/canvas.js +35 -8
  137. package/dist/components/builder/canvas.js.map +1 -1
  138. package/dist/components/builder/clipboard-actions.d.ts +16 -1
  139. package/dist/components/builder/clipboard-actions.js +48 -11
  140. package/dist/components/builder/clipboard-actions.js.map +1 -1
  141. package/dist/components/builder/composition-field-editor-lazy.js +1 -1
  142. package/dist/components/builder/composition-field-editor-lazy.js.map +1 -1
  143. package/dist/components/builder/composition-field-editor.d.ts +4 -16
  144. package/dist/components/builder/composition-field-editor.js +32 -43
  145. package/dist/components/builder/composition-field-editor.js.map +1 -1
  146. package/dist/components/builder/delete-key.d.ts +5 -0
  147. package/dist/components/builder/delete-key.js +4 -0
  148. package/dist/components/builder/delete-key.js.map +1 -1
  149. package/dist/components/builder/drag-session.d.ts +1 -1
  150. package/dist/components/builder/drag-session.js.map +1 -1
  151. package/dist/components/builder/fixture-thumbnail.js +1 -1
  152. package/dist/components/builder/fixture-thumbnail.js.map +1 -1
  153. package/dist/components/builder/insert-context.d.ts +18 -26
  154. package/dist/components/builder/insert-context.js +47 -94
  155. package/dist/components/builder/insert-context.js.map +1 -1
  156. package/dist/components/builder/layout-inspector.js +1 -1
  157. package/dist/components/builder/layout-inspector.js.map +1 -1
  158. package/dist/components/builder/node-title.js +1 -1
  159. package/dist/components/builder/node-title.js.map +1 -1
  160. package/dist/components/builder/page-tree.d.ts +4 -4
  161. package/dist/components/builder/page-tree.js +8 -8
  162. package/dist/components/builder/page-tree.js.map +1 -1
  163. package/dist/components/builder/placement-refusal.d.ts +18 -0
  164. package/dist/components/builder/placement-refusal.js +46 -0
  165. package/dist/components/builder/placement-refusal.js.map +1 -0
  166. package/dist/components/builder/property-inspector.js +8 -4
  167. package/dist/components/builder/property-inspector.js.map +1 -1
  168. package/dist/components/builder/reuse-context.js +68 -30
  169. package/dist/components/builder/reuse-context.js.map +1 -1
  170. package/dist/components/builder/reuse.d.ts +79 -1
  171. package/dist/components/builder/reuse.js +70 -3
  172. package/dist/components/builder/reuse.js.map +1 -1
  173. package/dist/components/builder/rich-text-toolbar.js +1 -1
  174. package/dist/components/builder/rich-text-toolbar.js.map +1 -1
  175. package/dist/components/builder/run-inspector.d.ts +11 -0
  176. package/dist/components/builder/run-inspector.js +33 -0
  177. package/dist/components/builder/run-inspector.js.map +1 -0
  178. package/dist/components/builder/selection-overlay.js +3 -3
  179. package/dist/components/builder/selection-overlay.js.map +1 -1
  180. package/dist/components/builder/spacing-handles.d.ts +2 -2
  181. package/dist/components/builder/spacing-handles.js +3 -3
  182. package/dist/components/builder/spacing-handles.js.map +1 -1
  183. package/dist/components/cms/asset-field.d.ts +38 -1
  184. package/dist/components/cms/asset-field.js +184 -60
  185. package/dist/components/cms/asset-field.js.map +1 -1
  186. package/dist/components/cms/asset-picker-core.d.ts +16 -0
  187. package/dist/components/cms/asset-picker-core.js +20 -0
  188. package/dist/components/cms/asset-picker-core.js.map +1 -1
  189. package/dist/components/cms/asset-picker.js +14 -20
  190. package/dist/components/cms/asset-picker.js.map +1 -1
  191. package/dist/components/cms/bulk-actions.d.ts +4 -20
  192. package/dist/components/cms/bulk-actions.js +5 -26
  193. package/dist/components/cms/bulk-actions.js.map +1 -1
  194. package/dist/components/cms/bulk-bar.d.ts +2 -2
  195. package/dist/components/cms/bulk-bar.js +2 -2
  196. package/dist/components/cms/bulk-bar.js.map +1 -1
  197. package/dist/components/cms/cell-edit.d.ts +1 -1
  198. package/dist/components/cms/cell-edit.js +1 -1
  199. package/dist/components/cms/cell-edit.js.map +1 -1
  200. package/dist/components/cms/cell.d.ts +1 -1
  201. package/dist/components/cms/cell.js +3 -3
  202. package/dist/components/cms/cell.js.map +1 -1
  203. package/dist/components/cms/cms-index.js +2 -2
  204. package/dist/components/cms/cms-index.js.map +1 -1
  205. package/dist/components/cms/cms-labels.js +2 -2
  206. package/dist/components/cms/cms-labels.js.map +1 -1
  207. package/dist/components/cms/cms-store.d.ts +7 -6
  208. package/dist/components/cms/cms-store.js +23 -43
  209. package/dist/components/cms/cms-store.js.map +1 -1
  210. package/dist/components/cms/collection-table.js +7 -7
  211. package/dist/components/cms/collection-table.js.map +1 -1
  212. package/dist/components/cms/detail-editor.d.ts +5 -2
  213. package/dist/components/cms/detail-editor.js +20 -15
  214. package/dist/components/cms/detail-editor.js.map +1 -1
  215. package/dist/components/cms/details-pane.js +1 -1
  216. package/dist/components/cms/details-pane.js.map +1 -1
  217. package/dist/components/cms/doc-state.js +1 -1
  218. package/dist/components/cms/doc-state.js.map +1 -1
  219. package/dist/components/cms/document-diff-view.d.ts +3 -1
  220. package/dist/components/cms/document-diff-view.js +17 -12
  221. package/dist/components/cms/document-diff-view.js.map +1 -1
  222. package/dist/components/cms/document-editor-context.js +1 -1
  223. package/dist/components/cms/document-editor-context.js.map +1 -1
  224. package/dist/components/cms/document-staging.js +1 -1
  225. package/dist/components/cms/document-staging.js.map +1 -1
  226. package/dist/components/cms/document-url-path.js +2 -2
  227. package/dist/components/cms/document-url-path.js.map +1 -1
  228. package/dist/components/cms/duplicate-document.d.ts +1 -1
  229. package/dist/components/cms/duplicate-document.js.map +1 -1
  230. package/dist/components/cms/editable-cell.js +3 -3
  231. package/dist/components/cms/editable-cell.js.map +1 -1
  232. package/dist/components/cms/field-anchors.d.ts +7 -4
  233. package/dist/components/cms/field-anchors.js +9 -7
  234. package/dist/components/cms/field-anchors.js.map +1 -1
  235. package/dist/components/cms/field-collaboration.d.ts +1 -1
  236. package/dist/components/cms/field-collaboration.js +1 -1
  237. package/dist/components/cms/field-collaboration.js.map +1 -1
  238. package/dist/components/cms/field-connection.d.ts +1 -1
  239. package/dist/components/cms/field-connection.js +2 -2
  240. package/dist/components/cms/field-connection.js.map +1 -1
  241. package/dist/components/cms/field-control-lib.d.ts +15 -1
  242. package/dist/components/cms/field-control-lib.js +23 -4
  243. package/dist/components/cms/field-control-lib.js.map +1 -1
  244. package/dist/components/cms/field-control.js +4 -4
  245. package/dist/components/cms/field-control.js.map +1 -1
  246. package/dist/components/cms/field-renderer.d.ts +1 -1
  247. package/dist/components/cms/field-renderer.js +2 -2
  248. package/dist/components/cms/field-renderer.js.map +1 -1
  249. package/dist/components/cms/filter-builder.d.ts +1 -1
  250. package/dist/components/cms/filter-builder.js +3 -3
  251. package/dist/components/cms/filter-builder.js.map +1 -1
  252. package/dist/components/cms/gate-validation.d.ts +21 -30
  253. package/dist/components/cms/gate-validation.js +11 -32
  254. package/dist/components/cms/gate-validation.js.map +1 -1
  255. package/dist/components/cms/import-export.js +2 -2
  256. package/dist/components/cms/import-export.js.map +1 -1
  257. package/dist/components/cms/issue-copy.js +1 -1
  258. package/dist/components/cms/issue-copy.js.map +1 -1
  259. package/dist/components/cms/issues-pane.js +3 -3
  260. package/dist/components/cms/issues-pane.js.map +1 -1
  261. package/dist/components/cms/object-array-field.js +6 -6
  262. package/dist/components/cms/object-array-field.js.map +1 -1
  263. package/dist/components/cms/prop-fields.d.ts +7 -2
  264. package/dist/components/cms/prop-fields.js +14 -7
  265. package/dist/components/cms/prop-fields.js.map +1 -1
  266. package/dist/components/cms/reference-confirm.d.ts +1 -1
  267. package/dist/components/cms/reference-confirm.js +2 -2
  268. package/dist/components/cms/reference-confirm.js.map +1 -1
  269. package/dist/components/cms/relation-picker.js +2 -2
  270. package/dist/components/cms/relation-picker.js.map +1 -1
  271. package/dist/components/cms/rich-text/block-style.js +1 -1
  272. package/dist/components/cms/rich-text/block-style.js.map +1 -1
  273. package/dist/components/cms/rich-text/component-embed.js +4 -4
  274. package/dist/components/cms/rich-text/component-embed.js.map +1 -1
  275. package/dist/components/cms/rich-text/editor.js +3 -3
  276. package/dist/components/cms/rich-text/editor.js.map +1 -1
  277. package/dist/components/cms/rich-text/embed-picker.d.ts +1 -1
  278. package/dist/components/cms/rich-text/embed-picker.js +3 -3
  279. package/dist/components/cms/rich-text/embed-picker.js.map +1 -1
  280. package/dist/components/cms/rich-text/embed-props.js +3 -3
  281. package/dist/components/cms/rich-text/embed-props.js.map +1 -1
  282. package/dist/components/cms/rich-text/extensions.js +1 -1
  283. package/dist/components/cms/rich-text/extensions.js.map +1 -1
  284. package/dist/components/cms/rich-text/font-size-control.d.ts +1 -1
  285. package/dist/components/cms/rich-text/font-size-control.js +2 -2
  286. package/dist/components/cms/rich-text/font-size-control.js.map +1 -1
  287. package/dist/components/cms/rich-text/insert.d.ts +20 -9
  288. package/dist/components/cms/rich-text/insert.js +25 -17
  289. package/dist/components/cms/rich-text/insert.js.map +1 -1
  290. package/dist/components/cms/rich-text/lazy.js +1 -1
  291. package/dist/components/cms/rich-text/lazy.js.map +1 -1
  292. package/dist/components/cms/rich-text/link-control.js +2 -2
  293. package/dist/components/cms/rich-text/link-control.js.map +1 -1
  294. package/dist/components/cms/rich-text/slash-command.js +3 -3
  295. package/dist/components/cms/rich-text/slash-command.js.map +1 -1
  296. package/dist/components/cms/rich-text/toolbar.js +1 -1
  297. package/dist/components/cms/rich-text/toolbar.js.map +1 -1
  298. package/dist/components/cms/rich-text/unknown-node.js +2 -2
  299. package/dist/components/cms/rich-text/unknown-node.js.map +1 -1
  300. package/dist/components/cms/rich-text-preview.js +2 -2
  301. package/dist/components/cms/rich-text-preview.js.map +1 -1
  302. package/dist/components/cms/row-actions.d.ts +1 -1
  303. package/dist/components/cms/row-actions.js.map +1 -1
  304. package/dist/components/cms/scalar-value-editor.d.ts +1 -1
  305. package/dist/components/cms/scalar-value-editor.js +2 -2
  306. package/dist/components/cms/scalar-value-editor.js.map +1 -1
  307. package/dist/components/cms/use-discard-controller.d.ts +1 -1
  308. package/dist/components/cms/use-discard-controller.js +1 -1
  309. package/dist/components/cms/use-discard-controller.js.map +1 -1
  310. package/dist/components/cms/use-document-draft.d.ts +7 -1
  311. package/dist/components/cms/use-document-draft.js +16 -2
  312. package/dist/components/cms/use-document-draft.js.map +1 -1
  313. package/dist/components/cms/use-document-versions.js +1 -1
  314. package/dist/components/cms/use-document-versions.js.map +1 -1
  315. package/dist/components/cms/use-field-focus.d.ts +1 -1
  316. package/dist/components/cms/use-field-focus.js +2 -2
  317. package/dist/components/cms/use-field-focus.js.map +1 -1
  318. package/dist/components/cms/use-live-url.d.ts +1 -1
  319. package/dist/components/cms/use-live-url.js +3 -3
  320. package/dist/components/cms/use-live-url.js.map +1 -1
  321. package/dist/components/cms/use-publish-controller.d.ts +2 -3
  322. package/dist/components/cms/use-publish-controller.js +8 -20
  323. package/dist/components/cms/use-publish-controller.js.map +1 -1
  324. package/dist/components/cms/use-published-perspective.d.ts +1 -1
  325. package/dist/components/cms/use-published-perspective.js.map +1 -1
  326. package/dist/components/cms/use-restore-version.d.ts +1 -1
  327. package/dist/components/cms/use-restore-version.js +1 -1
  328. package/dist/components/cms/use-restore-version.js.map +1 -1
  329. package/dist/components/cms/version-compare-lazy.js +1 -1
  330. package/dist/components/cms/version-compare-lazy.js.map +1 -1
  331. package/dist/components/cms/version-compare.js +1 -1
  332. package/dist/components/cms/version-compare.js.map +1 -1
  333. package/dist/components/cms/versions-pane.js +11 -4
  334. package/dist/components/cms/versions-pane.js.map +1 -1
  335. package/dist/components/cms/view-bar.js +3 -3
  336. package/dist/components/cms/view-bar.js.map +1 -1
  337. package/dist/components/collection-view/cms-collection-view-source.d.ts +1 -1
  338. package/dist/components/collection-view/cms-collection-view-source.js +5 -3
  339. package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
  340. package/dist/components/collection-view/collection-view-context.d.ts +1 -1
  341. package/dist/components/collection-view/collection-view-context.js +1 -1
  342. package/dist/components/collection-view/collection-view-context.js.map +1 -1
  343. package/dist/components/collection-view/collection-view-surface.d.ts +13 -0
  344. package/dist/components/collection-view/collection-view-surface.js +18 -0
  345. package/dist/components/collection-view/collection-view-surface.js.map +1 -0
  346. package/dist/components/components/component-detail.js +10 -10
  347. package/dist/components/components/component-detail.js.map +1 -1
  348. package/dist/components/components/component-preview.d.ts +2 -2
  349. package/dist/components/components/component-preview.js +5 -5
  350. package/dist/components/components/component-preview.js.map +1 -1
  351. package/dist/components/components/component-status.d.ts +1 -1
  352. package/dist/components/components/component-status.js +1 -1
  353. package/dist/components/components/component-status.js.map +1 -1
  354. package/dist/components/components/components-index.js +2 -2
  355. package/dist/components/components/components-index.js.map +1 -1
  356. package/dist/components/components/field-inspector.js +1 -1
  357. package/dist/components/components/field-inspector.js.map +1 -1
  358. package/dist/components/components/registry-browser.js +3 -3
  359. package/dist/components/components/registry-browser.js.map +1 -1
  360. package/dist/components/components/taxonomy.d.ts +1 -1
  361. package/dist/components/components/taxonomy.js.map +1 -1
  362. package/dist/components/components/transfer-dialog.js +4 -3
  363. package/dist/components/components/transfer-dialog.js.map +1 -1
  364. package/dist/components/components/transfer.d.ts +10 -10
  365. package/dist/components/components/transfer.js +13 -12
  366. package/dist/components/components/transfer.js.map +1 -1
  367. package/dist/components/current-user-menu.js +1 -1
  368. package/dist/components/current-user-menu.js.map +1 -1
  369. package/dist/components/delivery-health-banner.js +2 -2
  370. package/dist/components/delivery-health-banner.js.map +1 -1
  371. package/dist/components/deployment-setup-gate.js +3 -3
  372. package/dist/components/deployment-setup-gate.js.map +1 -1
  373. package/dist/components/dev-login-badge.js +2 -2
  374. package/dist/components/dev-login-badge.js.map +1 -1
  375. package/dist/components/guards.js +1 -1
  376. package/dist/components/guards.js.map +1 -1
  377. package/dist/components/inspector/document-panes.d.ts +54 -0
  378. package/dist/components/inspector/document-panes.js +41 -0
  379. package/dist/components/inspector/document-panes.js.map +1 -0
  380. package/dist/components/inspector/inspector-sidebar.js +1 -1
  381. package/dist/components/inspector/inspector-sidebar.js.map +1 -1
  382. package/dist/components/nav-issues-registry.d.ts +53 -0
  383. package/dist/components/nav-issues-registry.js +69 -0
  384. package/dist/components/nav-issues-registry.js.map +1 -0
  385. package/dist/components/nav-issues.js +4 -4
  386. package/dist/components/nav-issues.js.map +1 -1
  387. package/dist/components/operation-error.d.ts +1 -1
  388. package/dist/components/operation-error.js +4 -4
  389. package/dist/components/operation-error.js.map +1 -1
  390. package/dist/components/playground-badge.js +2 -2
  391. package/dist/components/playground-badge.js.map +1 -1
  392. package/dist/components/project-list.js +3 -3
  393. package/dist/components/project-list.js.map +1 -1
  394. package/dist/components/project-session.d.ts +2 -2
  395. package/dist/components/project-session.js +5 -5
  396. package/dist/components/project-session.js.map +1 -1
  397. package/dist/components/project-switcher.js +2 -2
  398. package/dist/components/project-switcher.js.map +1 -1
  399. package/dist/components/rail-store-status.js +1 -1
  400. package/dist/components/rail-store-status.js.map +1 -1
  401. package/dist/components/rail-view-source.d.ts +6 -5
  402. package/dist/components/rail-view-source.js +4 -3
  403. package/dist/components/rail-view-source.js.map +1 -1
  404. package/dist/components/records/record-lens.d.ts +51 -0
  405. package/dist/components/records/record-lens.js +156 -0
  406. package/dist/components/records/record-lens.js.map +1 -0
  407. package/dist/components/records/record-rail.d.ts +86 -0
  408. package/dist/components/records/record-rail.js +241 -0
  409. package/dist/components/records/record-rail.js.map +1 -0
  410. package/dist/components/redirects/redirects-schema.js +1 -1
  411. package/dist/components/redirects/redirects-schema.js.map +1 -1
  412. package/dist/components/references/references-panel.js +2 -2
  413. package/dist/components/references/references-panel.js.map +1 -1
  414. package/dist/components/section-nav.js +27 -11
  415. package/dist/components/section-nav.js.map +1 -1
  416. package/dist/components/section-state.js +2 -2
  417. package/dist/components/section-state.js.map +1 -1
  418. package/dist/components/section-surface.js +2 -2
  419. package/dist/components/section-surface.js.map +1 -1
  420. package/dist/components/session-expired-overlay.js +3 -3
  421. package/dist/components/session-expired-overlay.js.map +1 -1
  422. package/dist/components/settings-form.js +1 -1
  423. package/dist/components/settings-form.js.map +1 -1
  424. package/dist/components/sign-in-needed-badge.js +1 -1
  425. package/dist/components/sign-in-needed-badge.js.map +1 -1
  426. package/dist/components/sign-in-view.d.ts +2 -2
  427. package/dist/components/sign-in-view.js +5 -5
  428. package/dist/components/sign-in-view.js.map +1 -1
  429. package/dist/components/studio-context.js +3 -3
  430. package/dist/components/studio-context.js.map +1 -1
  431. package/dist/components/studio-project-screen.js +30 -3
  432. package/dist/components/studio-project-screen.js.map +1 -1
  433. package/dist/components/studio-shell.js +6 -5
  434. package/dist/components/studio-shell.js.map +1 -1
  435. package/dist/components/theme-context.d.ts +1 -1
  436. package/dist/components/theme-context.js +2 -2
  437. package/dist/components/theme-context.js.map +1 -1
  438. package/dist/components/use-hydration-phase.d.ts +1 -1
  439. package/dist/components/use-hydration-phase.js +1 -1
  440. package/dist/components/use-hydration-phase.js.map +1 -1
  441. package/dist/components/users/invite-user-bar.d.ts +27 -0
  442. package/dist/components/users/invite-user-bar.js +25 -9
  443. package/dist/components/users/invite-user-bar.js.map +1 -1
  444. package/dist/components/users/role-policy-drift-issues.d.ts +38 -0
  445. package/dist/components/users/role-policy-drift-issues.js +71 -0
  446. package/dist/components/users/role-policy-drift-issues.js.map +1 -0
  447. package/dist/components/users/users-collection-view-source.d.ts +1 -1
  448. package/dist/components/users/users-collection-view-source.js +4 -2
  449. package/dist/components/users/users-collection-view-source.js.map +1 -1
  450. package/dist/components/users/users-module.js +1 -1
  451. package/dist/components/users/users-module.js.map +1 -1
  452. package/dist/components/users/users-schema.d.ts +10 -1
  453. package/dist/components/users/users-schema.js +45 -25
  454. package/dist/components/users/users-schema.js.map +1 -1
  455. package/dist/components/users/users-store.js +3 -3
  456. package/dist/components/users/users-store.js.map +1 -1
  457. package/dist/components/workspace-projects.d.ts +1 -1
  458. package/dist/components/workspace-projects.js +1 -1
  459. package/dist/components/workspace-projects.js.map +1 -1
  460. package/dist/lib/ai/apply-content.js +56 -116
  461. package/dist/lib/ai/apply-content.js.map +1 -1
  462. package/dist/lib/ai/chat-context.d.ts +8 -0
  463. package/dist/lib/ai/chat-context.js +37 -6
  464. package/dist/lib/ai/chat-context.js.map +1 -1
  465. package/dist/lib/ai/chat-state.d.ts +6 -0
  466. package/dist/lib/ai/chat-state.js.map +1 -1
  467. package/dist/lib/ai/constraints.d.ts +20 -5
  468. package/dist/lib/ai/constraints.js +125 -33
  469. package/dist/lib/ai/constraints.js.map +1 -1
  470. package/dist/lib/ai/fake-provider.d.ts +16 -3
  471. package/dist/lib/ai/fake-provider.js +22 -6
  472. package/dist/lib/ai/fake-provider.js.map +1 -1
  473. package/dist/lib/ai/index.d.ts +3 -1
  474. package/dist/lib/ai/index.js +3 -1
  475. package/dist/lib/ai/index.js.map +1 -1
  476. package/dist/lib/ai/leash.d.ts +34 -0
  477. package/dist/lib/ai/leash.js +28 -0
  478. package/dist/lib/ai/leash.js.map +1 -0
  479. package/dist/lib/ai/node-handler.d.ts +1 -1
  480. package/dist/lib/ai/node-handler.js.map +1 -1
  481. package/dist/lib/ai/rich-text-input.d.ts +8 -8
  482. package/dist/lib/ai/rich-text-input.js +2 -1
  483. package/dist/lib/ai/rich-text-input.js.map +1 -1
  484. package/dist/lib/ai/rich-text-translate.d.ts +27 -4
  485. package/dist/lib/ai/rich-text-translate.js +28 -10
  486. package/dist/lib/ai/rich-text-translate.js.map +1 -1
  487. package/dist/lib/ai/shape.d.ts +13 -13
  488. package/dist/lib/ai/shape.js +69 -93
  489. package/dist/lib/ai/shape.js.map +1 -1
  490. package/dist/lib/ai/tools.d.ts +36 -41
  491. package/dist/lib/ai/tools.js +83 -87
  492. package/dist/lib/ai/tools.js.map +1 -1
  493. package/dist/lib/ai/translate-document.d.ts +32 -4
  494. package/dist/lib/ai/translate-document.js +145 -47
  495. package/dist/lib/ai/translate-document.js.map +1 -1
  496. package/dist/lib/ai/types.d.ts +34 -23
  497. package/dist/lib/ai/types.js.map +1 -1
  498. package/dist/lib/ai/update-fields.d.ts +15 -12
  499. package/dist/lib/ai/update-fields.js +112 -188
  500. package/dist/lib/ai/update-fields.js.map +1 -1
  501. package/dist/lib/ai/writer-form.d.ts +116 -0
  502. package/dist/lib/ai/writer-form.js +429 -0
  503. package/dist/lib/ai/writer-form.js.map +1 -0
  504. package/dist/lib/assets/upload.d.ts +31 -2
  505. package/dist/lib/assets/upload.js +61 -6
  506. package/dist/lib/assets/upload.js.map +1 -1
  507. package/dist/lib/clipboard/os-clipboard.d.ts +10 -2
  508. package/dist/lib/clipboard/os-clipboard.js +8 -4
  509. package/dist/lib/clipboard/os-clipboard.js.map +1 -1
  510. package/dist/lib/clipboard/paste-issues.js +1 -1
  511. package/dist/lib/clipboard/paste-issues.js.map +1 -1
  512. package/dist/lib/clipboard/paste-target.d.ts +18 -9
  513. package/dist/lib/clipboard/paste-target.js +10 -9
  514. package/dist/lib/clipboard/paste-target.js.map +1 -1
  515. package/dist/lib/cms/field-patch.d.ts +0 -10
  516. package/dist/lib/cms/field-patch.js +4 -30
  517. package/dist/lib/cms/field-patch.js.map +1 -1
  518. package/dist/lib/cms/published-documents.js +1 -1
  519. package/dist/lib/cms/published-documents.js.map +1 -1
  520. package/dist/lib/cms-views/view-model.d.ts +9 -9
  521. package/dist/lib/cms-views/view-model.js +2 -2
  522. package/dist/lib/cms-views/view-model.js.map +1 -1
  523. package/dist/lib/collection-view/collection-view-source.d.ts +14 -5
  524. package/dist/lib/collection-view/collection-view-source.js.map +1 -1
  525. package/dist/lib/data/collection-content.js +3 -2
  526. package/dist/lib/data/collection-content.js.map +1 -1
  527. package/dist/lib/data/content-session-refresh.d.ts +1 -1
  528. package/dist/lib/data/content-session-refresh.js.map +1 -1
  529. package/dist/lib/data/playground-unload-guard.d.ts +1 -1
  530. package/dist/lib/data/playground-unload-guard.js +1 -1
  531. package/dist/lib/data/playground-unload-guard.js.map +1 -1
  532. package/dist/lib/dnd/drop-rules.d.ts +25 -31
  533. package/dist/lib/dnd/drop-rules.js +53 -59
  534. package/dist/lib/dnd/drop-rules.js.map +1 -1
  535. package/dist/lib/engine-version.d.ts +1 -1
  536. package/dist/lib/engine-version.js +1 -1
  537. package/dist/lib/engine-version.js.map +1 -1
  538. package/dist/lib/i18n/i18n.js +1 -1
  539. package/dist/lib/i18n/i18n.js.map +1 -1
  540. package/dist/lib/i18n/messages.de.js +44 -3
  541. package/dist/lib/i18n/messages.de.js.map +1 -1
  542. package/dist/lib/i18n/messages.en.d.ts +38 -2
  543. package/dist/lib/i18n/messages.en.js +51 -3
  544. package/dist/lib/i18n/messages.en.js.map +1 -1
  545. package/dist/lib/operations/project-runtime-config.d.ts +34 -6
  546. package/dist/lib/operations/project-runtime-config.js +50 -10
  547. package/dist/lib/operations/project-runtime-config.js.map +1 -1
  548. package/dist/lib/operations/publish-with-revision.d.ts +33 -1
  549. package/dist/lib/operations/publish-with-revision.js +32 -0
  550. package/dist/lib/operations/publish-with-revision.js.map +1 -1
  551. package/dist/lib/operations/runtime-validator.d.ts +19 -68
  552. package/dist/lib/operations/runtime-validator.js +12 -138
  553. package/dist/lib/operations/runtime-validator.js.map +1 -1
  554. package/dist/lib/operations/studio-operations.d.ts +17 -2
  555. package/dist/lib/operations/studio-operations.js +18 -11
  556. package/dist/lib/operations/studio-operations.js.map +1 -1
  557. package/dist/lib/persistence/convex-adapter.d.ts +16 -3
  558. package/dist/lib/persistence/convex-adapter.js +83 -47
  559. package/dist/lib/persistence/convex-adapter.js.map +1 -1
  560. package/dist/lib/persistence/index.js +14 -1
  561. package/dist/lib/persistence/index.js.map +1 -1
  562. package/dist/lib/persona/labels.js +4 -2
  563. package/dist/lib/persona/labels.js.map +1 -1
  564. package/dist/lib/query/operations-query.d.ts +1 -1
  565. package/dist/lib/query/operations-query.js +1 -1
  566. package/dist/lib/query/operations-query.js.map +1 -1
  567. package/dist/lib/references/reference-model.js +1 -1
  568. package/dist/lib/references/reference-model.js.map +1 -1
  569. package/dist/lib/references/references-store.js +1 -1
  570. package/dist/lib/references/references-store.js.map +1 -1
  571. package/dist/lib/workspace/index.d.ts +14 -11
  572. package/dist/lib/workspace/index.js +20 -24
  573. package/dist/lib/workspace/index.js.map +1 -1
  574. package/dist/mount.d.ts +28 -0
  575. package/dist/mount.js +27 -0
  576. package/dist/mount.js.map +1 -0
  577. package/dist/router/root.js +10 -10
  578. package/dist/router/root.js.map +1 -1
  579. package/dist/ui/badge.d.ts +1 -1
  580. package/dist/ui/button.d.ts +2 -2
  581. package/package.json +15 -11
  582. package/dist/components/cms/cms-composition-validators.d.ts +0 -16
  583. package/dist/components/cms/cms-composition-validators.js +0 -133
  584. package/dist/components/cms/cms-composition-validators.js.map +0 -1
  585. package/dist/components/cms/publish-clean.d.ts +0 -28
  586. package/dist/components/cms/publish-clean.js +0 -38
  587. package/dist/components/cms/publish-clean.js.map +0 -1
  588. package/dist/components/redirects/redirects-collection-view-source.d.ts +0 -53
  589. package/dist/components/redirects/redirects-collection-view-source.js +0 -146
  590. package/dist/components/redirects/redirects-collection-view-source.js.map +0 -1
  591. package/dist/components/redirects/redirects-module.d.ts +0 -21
  592. package/dist/components/redirects/redirects-module.js +0 -40
  593. package/dist/components/redirects/redirects-module.js.map +0 -1
  594. package/dist/components/redirects/redirects-store.d.ts +0 -68
  595. package/dist/components/redirects/redirects-store.js +0 -132
  596. package/dist/components/redirects/redirects-store.js.map +0 -1
  597. package/dist/lib/assets/asset-placements.d.ts +0 -28
  598. package/dist/lib/assets/asset-placements.js +0 -83
  599. package/dist/lib/assets/asset-placements.js.map +0 -1
package/dist/mount.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * `@elytracms/studio/mount` — the screens a studio's ROUTE FILES mount (EC-616).
3
+ *
4
+ * The scaffold's studio is a handful of TanStack route files that each mount one engine
5
+ * screen; this entry is exactly those screens, and nothing else:
6
+ *
7
+ * ```tsx
8
+ * // studio/src/routes/index.tsx — the project launcher (and its forced `?state=`)
9
+ * import { ProjectLauncher, parseSectionState } from '@elytracms/studio/mount'
10
+ * // studio/src/routes/$projectId.$.tsx — every per-project surface, resolved from the URL
11
+ * import { StudioProjectScreen } from '@elytracms/studio/mount'
12
+ * // studio/src/routes/sign-in.tsx — the sign-in screen
13
+ * import { SignInView } from '@elytracms/studio/mount'
14
+ * ```
15
+ *
16
+ * It is NOT the addon contract (that is `@elytracms/studio/addon`) and not the
17
+ * customization API (`@elytracms/studio/customization`): a mount is where the scaffold
18
+ * puts the engine's screens, so it gets its own declared entry instead of four per-file
19
+ * keys that would freeze internal file paths as public API. Before EC-616 these four were
20
+ * reachable only through the `./components/*` wildcard, which the published package no
21
+ * longer has.
22
+ */
23
+ export { ProjectLauncher } from './components/project-list.js';
24
+ export { parseSectionState } from './components/section-surface.js';
25
+ export { StudioProjectScreen } from './components/studio-project-screen.js';
26
+ export { SignInView } from './components/sign-in-view.js';
27
+ //# sourceMappingURL=mount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mount.js","sourceRoot":"","sources":["../src/mount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAA;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAA","sourcesContent":["/**\n * `@elytracms/studio/mount` — the screens a studio's ROUTE FILES mount (EC-616).\n *\n * The scaffold's studio is a handful of TanStack route files that each mount one engine\n * screen; this entry is exactly those screens, and nothing else:\n *\n * ```tsx\n * // studio/src/routes/index.tsx — the project launcher (and its forced `?state=`)\n * import { ProjectLauncher, parseSectionState } from '@elytracms/studio/mount'\n * // studio/src/routes/$projectId.$.tsx — every per-project surface, resolved from the URL\n * import { StudioProjectScreen } from '@elytracms/studio/mount'\n * // studio/src/routes/sign-in.tsx — the sign-in screen\n * import { SignInView } from '@elytracms/studio/mount'\n * ```\n *\n * It is NOT the addon contract (that is `@elytracms/studio/addon`) and not the\n * customization API (`@elytracms/studio/customization`): a mount is where the scaffold\n * puts the engine's screens, so it gets its own declared entry instead of four per-file\n * keys that would freeze internal file paths as public API. Before EC-616 these four were\n * reachable only through the `./components/*` wildcard, which the published package no\n * longer has.\n */\nexport { ProjectLauncher } from './components/project-list'\nexport type { ProjectLauncherProps } from './components/project-list'\nexport { parseSectionState } from './components/section-surface'\nexport { StudioProjectScreen } from './components/studio-project-screen'\nexport { SignInView } from './components/sign-in-view'\nexport type { SignInViewProps } from './components/sign-in-view'\n"]}
@@ -1,17 +1,17 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createRootRoute, HeadContent, Outlet, Scripts, useLocation, } from '@tanstack/react-router';
3
3
  import { NavigateOnce } from './navigate-once.js';
4
- import { AuthProvider, useAuth } from '@elytracms/studio/components/auth-context';
5
- import { DeploymentSetupGate } from '@elytracms/studio/components/deployment-setup-gate';
6
- import { SessionExpiredOverlay } from '@elytracms/studio/components/session-expired-overlay';
7
- import { StudioProvider } from '@elytracms/studio/components/studio-context';
8
- import { ThemeProvider } from '@elytracms/studio/components/theme-context';
4
+ import { AuthProvider, useAuth } from '../components/auth-context.js';
5
+ import { DeploymentSetupGate } from '../components/deployment-setup-gate.js';
6
+ import { SessionExpiredOverlay } from '../components/session-expired-overlay.js';
7
+ import { StudioProvider } from '../components/studio-context.js';
8
+ import { ThemeProvider } from '../components/theme-context.js';
9
9
  import { Loader2 } from 'lucide-react';
10
- import { SIGN_IN_PATH, resolveRouteGuard } from '@elytracms/studio/lib/auth';
11
- import { useHydrated, useT, useUiLocale } from '@elytracms/studio/lib/i18n';
12
- import { setStudioBaseTitle } from '@elytracms/studio/lib/tab-title';
13
- import { activeSlugForLocation, setActiveProjectSlug } from '@elytracms/studio/lib/workspace';
14
- import { THEME_INIT_SCRIPT } from '@elytracms/studio/lib/theme';
10
+ import { SIGN_IN_PATH, resolveRouteGuard } from '../lib/auth/index.js';
11
+ import { useHydrated, useT, useUiLocale } from '../lib/i18n/index.js';
12
+ import { setStudioBaseTitle } from '../lib/tab-title.js';
13
+ import { activeSlugForLocation, setActiveProjectSlug } from '../lib/workspace/index.js';
14
+ import { THEME_INIT_SCRIPT } from '../lib/theme.js';
15
15
  export function createStudioRootRoute(options) {
16
16
  const { appCssUrl, title = 'Elytra', htmlLang, meta = [], links = [], providers } = options;
17
17
  // EC-402: register the base title for the shell's per-view tab-title effect
@@ -1 +1 @@
1
- {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/router/root.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from 'react'\nimport {\n createRootRoute,\n HeadContent,\n Outlet,\n Scripts,\n useLocation,\n} from '@tanstack/react-router'\nimport { NavigateOnce } from './navigate-once'\nimport { AuthProvider, useAuth } from '@elytracms/studio/components/auth-context'\nimport { DeploymentSetupGate } from '@elytracms/studio/components/deployment-setup-gate'\nimport { SessionExpiredOverlay } from '@elytracms/studio/components/session-expired-overlay'\nimport { StudioProvider } from '@elytracms/studio/components/studio-context'\nimport { ThemeProvider } from '@elytracms/studio/components/theme-context'\nimport { Loader2 } from 'lucide-react'\nimport { SIGN_IN_PATH, resolveRouteGuard } from '@elytracms/studio/lib/auth'\nimport { useHydrated, useT, useUiLocale } from '@elytracms/studio/lib/i18n'\nimport { setStudioBaseTitle } from '@elytracms/studio/lib/tab-title'\nimport { activeSlugForLocation, setActiveProjectSlug } from '@elytracms/studio/lib/workspace'\nimport { THEME_INIT_SCRIPT } from '@elytracms/studio/lib/theme'\n\n/**\n * Studio root-route boot factory (EC-375; consolidated from the copy-pasted\n * consumer `__root.tsx` by EC-369 finding #7). It assembles the ONE canonical\n * provider/gate stack — ThemeProvider → DeploymentSetupGate → AuthProvider(keyed)\n * → AuthGate → StudioProvider → Outlet — plus the `RootDocument` shell\n * (html/head with the pre-hydration theme script + the chrome stylesheet).\n *\n * Its whole purpose is to make the NEXT required-gate addition automatic on\n * package upgrade: when EC-258 added `DeploymentSetupGate`, every hand-copied\n * `__root.tsx` had to be manually re-synced, and Konditorei's silently missed\n * it for five releases (EC-367). Owning the composition here means a consumer's\n * `__root.tsx` shrinks to a thin shell and picks up new gates for free.\n *\n * The consumer re-exports the returned route as `Route` (the generated route\n * tree imports `Route` from `./routes/__root`):\n *\n * ```tsx\n * import { createStudioRootRoute } from '@elytracms/studio/router/root'\n * import appCss from '../styles/app.css?url'\n * export const Route = createStudioRootRoute({ appCssUrl: appCss })\n * ```\n */\nexport interface StudioRootRouteOptions {\n /**\n * URL of the studio chrome stylesheet, from the consumer's Vite `?url` import\n * (`import appCss from '../styles/app.css?url'`). The one option every consumer\n * must pass — the sheet is project-owned (it carries the delivery theme).\n */\n appCssUrl: string\n /** Document `<title>`. Default: `'Elytra'`. */\n title?: string\n /**\n * `<html lang>`. Defaults to the **resolved studio-UI locale** (EC-513): the\n * config-pinned `i18n.locale` if there is one, otherwise the default locale on the\n * server and, once browser detection takes over after hydration, the visitor's\n * preferred locale. Pass a value only to fix `lang` to something the chrome is not\n * actually rendered in.\n */\n htmlLang?: string\n /**\n * Extra `<head>` meta entries appended after the defaults (charset, viewport,\n * title). Same shape TanStack Router's `head().meta` takes.\n */\n meta?: Array<Record<string, string>>\n /** Extra `<head>` link entries appended after the app stylesheet. */\n links?: Array<Record<string, string>>\n /**\n * Escape hatch: wrap additional project-specific providers around the routed\n * subtree. Rendered INSIDE `StudioProvider` and around `<Outlet />`, so nested\n * providers see the full studio/auth/theme context and remount with the active\n * project. Return the passed `children` wrapped in your providers.\n */\n providers?: (children: ReactNode) => ReactNode\n}\n\nexport function createStudioRootRoute(options: StudioRootRouteOptions) {\n const { appCssUrl, title = 'Elytra', htmlLang, meta = [], links = [], providers } = options\n\n // EC-402: register the base title for the shell's per-view tab-title effect\n // (`StudioTabTitle` composes `deepest crumb · view · project · <this title>`\n // and restores exactly this value when leaving a project view). Module-holder\n // seam — same pattern as `setActiveProjectSlug` — so the shell never has to\n // capture `document.title` and race the router's own head effect.\n setStudioBaseTitle(title)\n\n function RootComponent() {\n const location = useLocation()\n // EC-513: locale resolution is client-side, so the studio boots in the server's\n // locale (default, or the `i18n.locale` pin) and hands over to the browser's\n // preference AFTER hydration — the hydration render has to reproduce the server's\n // markup or React discards the tree with a mismatch error. Subscribing HERE, at the\n // one root above the whole chrome, is what makes the handover visible everywhere:\n // ~948 of the studio's localized render sites call the non-hook `translate()` and\n // would otherwise never re-render for it. It also keeps `<html lang>` honest —\n // it names the language the chrome is actually rendered in, at every moment.\n const uiLocale = useUiLocale()\n // EC-179: the active project selects its Convex backend. Resolve it from the\n // URL (or the sign-in redirect target) and bind it *before* the auth and\n // persistence adapters are selected, so the initial sign-in authenticates\n // against the project the user is heading for. Keying the auth/studio subtree\n // by the active project remounts it on a project switch, so the adapters\n // re-select against the new backend and the session is restored per-backend.\n const activeSlug = activeSlugForLocation(\n location.pathname,\n (location.search as { redirect?: string }).redirect,\n )\n setActiveProjectSlug(activeSlug)\n\n return (\n <RootDocument htmlLang={htmlLang ?? uiLocale}>\n <ThemeProvider>\n {/* EC-258: one deployment-setup gate runs before auth — a misconfigured or\n unreachable backend, an invalid workspace config, or any failing readiness\n precondition (missing auth signing key, required collections, …) is a\n single visible boot screen with copy-pasteable fixes, never a silent\n in-memory fallback or a misleading downstream error. All checks passing\n renders children as before. */}\n <DeploymentSetupGate>\n <AuthProvider key={activeSlug ?? '__launcher__'}>\n <AuthGate>\n <StudioProvider>\n {providers ? providers(<Outlet />) : <Outlet />}\n {/* EC-403: the blocking in-place re-auth overlay — mounted over\n every route, INSIDE StudioProvider (it invalidates the studio\n query cache on re-auth) and inside AuthProvider (it reads the\n sessionExpired state). Renders null unless the session died. */}\n <SessionExpiredOverlay />\n </StudioProvider>\n </AuthGate>\n </AuthProvider>\n </DeploymentSetupGate>\n </ThemeProvider>\n </RootDocument>\n )\n }\n\n return createRootRoute({\n head: () => ({\n meta: [\n { charSet: 'utf-8' },\n { name: 'viewport', content: 'width=device-width, initial-scale=1' },\n { title },\n ...meta,\n ],\n links: [{ rel: 'stylesheet', href: appCssUrl }, ...links],\n }),\n component: RootComponent,\n })\n}\n\n/**\n * Route guard (EC-150): one chokepoint in the root layout. Unauthenticated\n * visitors on protected paths are redirected to the sign-in screen (with the\n * intended target preserved); signed-in users never see the sign-in screen.\n * The decision logic is the pure, unit-tested `resolveRouteGuard`.\n */\nfunction AuthGate({ children }: { children: ReactNode }) {\n const { status } = useAuth()\n const location = useLocation()\n // EC-451: feed the still-pending `?redirect` search param into the decision.\n // Dev auto-login (or any fast real sign-in — SSO return, password-manager\n // autofill) can flip the session to signed-in while the location is still\n // `/sign-in?redirect=…`, BEFORE `SignInView`'s own post-sign-in navigation\n // runs; the gate's bounce then fires first and must consume the target\n // instead of dropping it on an unconditional `/`. The target is validated\n // by `postSignInTarget` inside `resolveRouteGuard` (same-origin relative\n // paths only — redirect is an attacker-suppliable search param).\n const rawRedirect = (location.search as { redirect?: unknown }).redirect\n const redirect = typeof rawRedirect === 'string' ? rawRedirect : undefined\n const decision = resolveRouteGuard(location.pathname, status, redirect)\n\n if (decision.kind === 'pending') return <SessionLoading />\n if (decision.kind === 'redirect-to-sign-in') {\n // EC-441: `NavigateOnce`, not `<Navigate>` — the gate stays mounted while\n // the sign-in transition is pending, and a per-render re-navigate spirals\n // into the router's update-depth rejection.\n return <NavigateOnce to={SIGN_IN_PATH} search={{ redirect: decision.redirect }} replace />\n }\n if (decision.kind === 'redirect-home') return <NavigateOnce to={decision.target} replace />\n return children\n}\n\n/**\n * The studio's boot screen: the deterministic session-restore state and — because a\n * request-less render always finds the auth gate `pending` — the entire body of the\n * build-time prerendered SPA shell (`dist/client/_shell.html`).\n *\n * **It is deliberately wordless** (EC-523; owner-ratified 2026-08-01: *\"remove the text\n * — if we really need something while loading, add a simple spinner, but not mandatory —\n * the shell should stay free of side-effects\"*). A build-time prerender has no request,\n * hence no `Accept-Language` and no session, so it cannot know the visitor's language.\n * EC-513 fixed the one string that flipped after hydration; removing the words removes\n * the possibility of the next one.\n *\n * **Accessibility**, because \"no words\" must not mean \"no accessible name\": moving the\n * text into an `aria-label` bakes the very same wrong-language string into the shell,\n * only somewhere a screen-reader user cannot notice it flip. So the shell ships an\n * **empty** `role=\"status\"` region — the correct live-region shape in any case, since a\n * region must already exist in the DOM for a later insertion to be announced — and\n * `useHydrated` fills it once hydration is done, in the visitor's actual locale. The\n * unannounced window is bounded by hydration, i.e. exactly the window in which no\n * announcement could have been correct.\n *\n * Do **not** add `aria-busy` here: on a live region it tells assistive tech to withhold\n * updates, which would suppress the very announcement this shape exists to deliver.\n *\n * Exported so the shell's pre-hydration markup is pinnable with `renderToStaticMarkup`\n * (`root.test.tsx`) — the built artefact is the real proof, but nothing else in the\n * node test pattern can reach this render.\n */\nexport function SessionLoading() {\n const hydrated = useHydrated()\n const t = useT()\n return (\n <div className=\"grid min-h-dvh place-items-center bg-background\" role=\"status\">\n <Loader2 className=\"size-6 animate-spin text-muted-foreground\" aria-hidden=\"true\" />\n {hydrated ? <span className=\"sr-only\">{t('auth.boot.checkingSession')}</span> : null}\n </div>\n )\n}\n\nfunction RootDocument({ children, htmlLang }: { children: ReactNode; htmlLang: string }) {\n // Dark-first SSR baseline; THEME_INIT_SCRIPT flips the class pre-hydration\n // from the stored preference, and ThemeProvider keeps it reactive thereafter.\n // suppressHydrationWarning: the script intentionally mutates the class before\n // React hydrates, so a className mismatch on <html> is expected, not a bug.\n // The app stylesheet is emitted via head().links and rendered by <HeadContent />.\n //\n // EC-523: `lang` is the ONE locale-dependent value that stays in the prerendered\n // shell, and it must. There is no locale-free value for it, and dropping it is a real\n // accessibility regression (a screen reader picks its voice from the document\n // language). It is baked as the build's default locale and flips to the visitor's\n // after hydration — honest at every moment, since EC-513 made it name the language the\n // chrome is actually rendered in. The mismatch it would otherwise raise is covered by\n // the same `suppressHydrationWarning` the theme script needs. Do not \"fix\" it by\n // hard-coding a value: that trades an attribute that is briefly stale for one that is\n // permanently wrong.\n return (\n <html lang={htmlLang} className=\"dark\" suppressHydrationWarning>\n <head>\n <HeadContent />\n <script dangerouslySetInnerHTML={{ __html: THEME_INIT_SCRIPT }} />\n </head>\n <body className=\"min-h-screen bg-background font-sans text-foreground antialiased\">\n {children}\n <Scripts />\n </body>\n </html>\n )\n}\n"]}
1
+ {"version":3,"file":"root.js","sourceRoot":"","sources":["../../src/router/root.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from 'react'\nimport {\n createRootRoute,\n HeadContent,\n Outlet,\n Scripts,\n useLocation,\n} from '@tanstack/react-router'\nimport { NavigateOnce } from './navigate-once'\nimport { AuthProvider, useAuth } from '../components/auth-context'\nimport { DeploymentSetupGate } from '../components/deployment-setup-gate'\nimport { SessionExpiredOverlay } from '../components/session-expired-overlay'\nimport { StudioProvider } from '../components/studio-context'\nimport { ThemeProvider } from '../components/theme-context'\nimport { Loader2 } from 'lucide-react'\nimport { SIGN_IN_PATH, resolveRouteGuard } from '../lib/auth'\nimport { useHydrated, useT, useUiLocale } from '../lib/i18n'\nimport { setStudioBaseTitle } from '../lib/tab-title'\nimport { activeSlugForLocation, setActiveProjectSlug } from '../lib/workspace'\nimport { THEME_INIT_SCRIPT } from '../lib/theme'\n\n/**\n * Studio root-route boot factory (EC-375; consolidated from the copy-pasted\n * consumer `__root.tsx` by EC-369 finding #7). It assembles the ONE canonical\n * provider/gate stack — ThemeProvider → DeploymentSetupGate → AuthProvider(keyed)\n * → AuthGate → StudioProvider → Outlet — plus the `RootDocument` shell\n * (html/head with the pre-hydration theme script + the chrome stylesheet).\n *\n * Its whole purpose is to make the NEXT required-gate addition automatic on\n * package upgrade: when EC-258 added `DeploymentSetupGate`, every hand-copied\n * `__root.tsx` had to be manually re-synced, and Konditorei's silently missed\n * it for five releases (EC-367). Owning the composition here means a consumer's\n * `__root.tsx` shrinks to a thin shell and picks up new gates for free.\n *\n * The consumer re-exports the returned route as `Route` (the generated route\n * tree imports `Route` from `./routes/__root`):\n *\n * ```tsx\n * import { createStudioRootRoute } from '@elytracms/studio/router/root'\n * import appCss from '../styles/app.css?url'\n * export const Route = createStudioRootRoute({ appCssUrl: appCss })\n * ```\n */\nexport interface StudioRootRouteOptions {\n /**\n * URL of the studio chrome stylesheet, from the consumer's Vite `?url` import\n * (`import appCss from '../styles/app.css?url'`). The one option every consumer\n * must pass — the sheet is project-owned (it carries the delivery theme).\n */\n appCssUrl: string\n /** Document `<title>`. Default: `'Elytra'`. */\n title?: string\n /**\n * `<html lang>`. Defaults to the **resolved studio-UI locale** (EC-513): the\n * config-pinned `i18n.locale` if there is one, otherwise the default locale on the\n * server and, once browser detection takes over after hydration, the visitor's\n * preferred locale. Pass a value only to fix `lang` to something the chrome is not\n * actually rendered in.\n */\n htmlLang?: string\n /**\n * Extra `<head>` meta entries appended after the defaults (charset, viewport,\n * title). Same shape TanStack Router's `head().meta` takes.\n */\n meta?: Array<Record<string, string>>\n /** Extra `<head>` link entries appended after the app stylesheet. */\n links?: Array<Record<string, string>>\n /**\n * Escape hatch: wrap additional project-specific providers around the routed\n * subtree. Rendered INSIDE `StudioProvider` and around `<Outlet />`, so nested\n * providers see the full studio/auth/theme context and remount with the active\n * project. Return the passed `children` wrapped in your providers.\n */\n providers?: (children: ReactNode) => ReactNode\n}\n\nexport function createStudioRootRoute(options: StudioRootRouteOptions) {\n const { appCssUrl, title = 'Elytra', htmlLang, meta = [], links = [], providers } = options\n\n // EC-402: register the base title for the shell's per-view tab-title effect\n // (`StudioTabTitle` composes `deepest crumb · view · project · <this title>`\n // and restores exactly this value when leaving a project view). Module-holder\n // seam — same pattern as `setActiveProjectSlug` — so the shell never has to\n // capture `document.title` and race the router's own head effect.\n setStudioBaseTitle(title)\n\n function RootComponent() {\n const location = useLocation()\n // EC-513: locale resolution is client-side, so the studio boots in the server's\n // locale (default, or the `i18n.locale` pin) and hands over to the browser's\n // preference AFTER hydration — the hydration render has to reproduce the server's\n // markup or React discards the tree with a mismatch error. Subscribing HERE, at the\n // one root above the whole chrome, is what makes the handover visible everywhere:\n // ~948 of the studio's localized render sites call the non-hook `translate()` and\n // would otherwise never re-render for it. It also keeps `<html lang>` honest —\n // it names the language the chrome is actually rendered in, at every moment.\n const uiLocale = useUiLocale()\n // EC-179: the active project selects its Convex backend. Resolve it from the\n // URL (or the sign-in redirect target) and bind it *before* the auth and\n // persistence adapters are selected, so the initial sign-in authenticates\n // against the project the user is heading for. Keying the auth/studio subtree\n // by the active project remounts it on a project switch, so the adapters\n // re-select against the new backend and the session is restored per-backend.\n const activeSlug = activeSlugForLocation(\n location.pathname,\n (location.search as { redirect?: string }).redirect,\n )\n setActiveProjectSlug(activeSlug)\n\n return (\n <RootDocument htmlLang={htmlLang ?? uiLocale}>\n <ThemeProvider>\n {/* EC-258: one deployment-setup gate runs before auth — a misconfigured or\n unreachable backend, an invalid workspace config, or any failing readiness\n precondition (missing auth signing key, required collections, …) is a\n single visible boot screen with copy-pasteable fixes, never a silent\n in-memory fallback or a misleading downstream error. All checks passing\n renders children as before. */}\n <DeploymentSetupGate>\n <AuthProvider key={activeSlug ?? '__launcher__'}>\n <AuthGate>\n <StudioProvider>\n {providers ? providers(<Outlet />) : <Outlet />}\n {/* EC-403: the blocking in-place re-auth overlay — mounted over\n every route, INSIDE StudioProvider (it invalidates the studio\n query cache on re-auth) and inside AuthProvider (it reads the\n sessionExpired state). Renders null unless the session died. */}\n <SessionExpiredOverlay />\n </StudioProvider>\n </AuthGate>\n </AuthProvider>\n </DeploymentSetupGate>\n </ThemeProvider>\n </RootDocument>\n )\n }\n\n return createRootRoute({\n head: () => ({\n meta: [\n { charSet: 'utf-8' },\n { name: 'viewport', content: 'width=device-width, initial-scale=1' },\n { title },\n ...meta,\n ],\n links: [{ rel: 'stylesheet', href: appCssUrl }, ...links],\n }),\n component: RootComponent,\n })\n}\n\n/**\n * Route guard (EC-150): one chokepoint in the root layout. Unauthenticated\n * visitors on protected paths are redirected to the sign-in screen (with the\n * intended target preserved); signed-in users never see the sign-in screen.\n * The decision logic is the pure, unit-tested `resolveRouteGuard`.\n */\nfunction AuthGate({ children }: { children: ReactNode }) {\n const { status } = useAuth()\n const location = useLocation()\n // EC-451: feed the still-pending `?redirect` search param into the decision.\n // Dev auto-login (or any fast real sign-in — SSO return, password-manager\n // autofill) can flip the session to signed-in while the location is still\n // `/sign-in?redirect=…`, BEFORE `SignInView`'s own post-sign-in navigation\n // runs; the gate's bounce then fires first and must consume the target\n // instead of dropping it on an unconditional `/`. The target is validated\n // by `postSignInTarget` inside `resolveRouteGuard` (same-origin relative\n // paths only — redirect is an attacker-suppliable search param).\n const rawRedirect = (location.search as { redirect?: unknown }).redirect\n const redirect = typeof rawRedirect === 'string' ? rawRedirect : undefined\n const decision = resolveRouteGuard(location.pathname, status, redirect)\n\n if (decision.kind === 'pending') return <SessionLoading />\n if (decision.kind === 'redirect-to-sign-in') {\n // EC-441: `NavigateOnce`, not `<Navigate>` — the gate stays mounted while\n // the sign-in transition is pending, and a per-render re-navigate spirals\n // into the router's update-depth rejection.\n return <NavigateOnce to={SIGN_IN_PATH} search={{ redirect: decision.redirect }} replace />\n }\n if (decision.kind === 'redirect-home') return <NavigateOnce to={decision.target} replace />\n return children\n}\n\n/**\n * The studio's boot screen: the deterministic session-restore state and — because a\n * request-less render always finds the auth gate `pending` — the entire body of the\n * build-time prerendered SPA shell (`dist/client/_shell.html`).\n *\n * **It is deliberately wordless** (EC-523; owner-ratified 2026-08-01: *\"remove the text\n * — if we really need something while loading, add a simple spinner, but not mandatory —\n * the shell should stay free of side-effects\"*). A build-time prerender has no request,\n * hence no `Accept-Language` and no session, so it cannot know the visitor's language.\n * EC-513 fixed the one string that flipped after hydration; removing the words removes\n * the possibility of the next one.\n *\n * **Accessibility**, because \"no words\" must not mean \"no accessible name\": moving the\n * text into an `aria-label` bakes the very same wrong-language string into the shell,\n * only somewhere a screen-reader user cannot notice it flip. So the shell ships an\n * **empty** `role=\"status\"` region — the correct live-region shape in any case, since a\n * region must already exist in the DOM for a later insertion to be announced — and\n * `useHydrated` fills it once hydration is done, in the visitor's actual locale. The\n * unannounced window is bounded by hydration, i.e. exactly the window in which no\n * announcement could have been correct.\n *\n * Do **not** add `aria-busy` here: on a live region it tells assistive tech to withhold\n * updates, which would suppress the very announcement this shape exists to deliver.\n *\n * Exported so the shell's pre-hydration markup is pinnable with `renderToStaticMarkup`\n * (`root.test.tsx`) — the built artefact is the real proof, but nothing else in the\n * node test pattern can reach this render.\n */\nexport function SessionLoading() {\n const hydrated = useHydrated()\n const t = useT()\n return (\n <div className=\"grid min-h-dvh place-items-center bg-background\" role=\"status\">\n <Loader2 className=\"size-6 animate-spin text-muted-foreground\" aria-hidden=\"true\" />\n {hydrated ? <span className=\"sr-only\">{t('auth.boot.checkingSession')}</span> : null}\n </div>\n )\n}\n\nfunction RootDocument({ children, htmlLang }: { children: ReactNode; htmlLang: string }) {\n // Dark-first SSR baseline; THEME_INIT_SCRIPT flips the class pre-hydration\n // from the stored preference, and ThemeProvider keeps it reactive thereafter.\n // suppressHydrationWarning: the script intentionally mutates the class before\n // React hydrates, so a className mismatch on <html> is expected, not a bug.\n // The app stylesheet is emitted via head().links and rendered by <HeadContent />.\n //\n // EC-523: `lang` is the ONE locale-dependent value that stays in the prerendered\n // shell, and it must. There is no locale-free value for it, and dropping it is a real\n // accessibility regression (a screen reader picks its voice from the document\n // language). It is baked as the build's default locale and flips to the visitor's\n // after hydration — honest at every moment, since EC-513 made it name the language the\n // chrome is actually rendered in. The mismatch it would otherwise raise is covered by\n // the same `suppressHydrationWarning` the theme script needs. Do not \"fix\" it by\n // hard-coding a value: that trades an attribute that is briefly stale for one that is\n // permanently wrong.\n return (\n <html lang={htmlLang} className=\"dark\" suppressHydrationWarning>\n <head>\n <HeadContent />\n <script dangerouslySetInnerHTML={{ __html: THEME_INIT_SCRIPT }} />\n </head>\n <body className=\"min-h-screen bg-background font-sans text-foreground antialiased\">\n {children}\n <Scripts />\n </body>\n </html>\n )\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  import { type VariantProps } from 'class-variance-authority';
2
2
  import type { HTMLAttributes } from 'react';
3
3
  export declare const badgeVariants: (props?: ({
4
- variant?: "error" | "default" | "warning" | "success" | "primary" | "outline" | "info" | null | undefined;
4
+ variant?: "default" | "primary" | "error" | "outline" | "success" | "warning" | "info" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  export interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
7
7
  }
@@ -1,8 +1,8 @@
1
1
  import { type VariantProps } from 'class-variance-authority';
2
2
  import type { ButtonHTMLAttributes } from 'react';
3
3
  export declare const buttonVariants: (props?: ({
4
- variant?: "default" | "link" | "secondary" | "outline" | "ghost" | "destructive" | null | undefined;
5
- size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | null | undefined;
4
+ variant?: "link" | "default" | "secondary" | "outline" | "ghost" | "destructive" | null | undefined;
5
+ size?: "sm" | "lg" | "default" | "icon" | "icon-sm" | null | undefined;
6
6
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
7
  export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
8
8
  asChild?: boolean;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elytracms/studio",
3
3
  "author": "finaldream <hi@finaldream.de>",
4
- "version": "0.0.92",
4
+ "version": "0.0.94",
5
5
  "engines": {
6
6
  "node": ">=22.18.0"
7
7
  },
@@ -15,6 +15,14 @@
15
15
  "types": "./dist/customization.d.ts",
16
16
  "default": "./dist/customization.js"
17
17
  },
18
+ "./addon": {
19
+ "types": "./dist/addon.d.ts",
20
+ "default": "./dist/addon.js"
21
+ },
22
+ "./mount": {
23
+ "types": "./dist/mount.d.ts",
24
+ "default": "./dist/mount.js"
25
+ },
18
26
  "./ui": {
19
27
  "types": "./dist/ui/index.d.ts",
20
28
  "default": "./dist/ui/index.js"
@@ -35,10 +43,6 @@
35
43
  "types": "./dist/components/builder/canvas-stylesheet.d.ts",
36
44
  "default": "./dist/components/builder/canvas-stylesheet.js"
37
45
  },
38
- "./components/*": {
39
- "types": "./dist/components/*.d.ts",
40
- "default": "./dist/components/*.js"
41
- },
42
46
  "./lib/assets": {
43
47
  "types": "./dist/lib/assets/index.d.ts",
44
48
  "default": "./dist/lib/assets/index.js"
@@ -63,6 +67,10 @@
63
67
  "types": "./dist/lib/ai/index.d.ts",
64
68
  "default": "./dist/lib/ai/index.js"
65
69
  },
70
+ "./lib/ai/vite": {
71
+ "types": "./dist/lib/ai/vite.d.ts",
72
+ "default": "./dist/lib/ai/vite.js"
73
+ },
66
74
  "./lib/registry": {
67
75
  "types": "./dist/lib/registry/index.d.ts",
68
76
  "default": "./dist/lib/registry/index.js"
@@ -99,10 +107,6 @@
99
107
  "types": "./dist/lib/auth/index.d.ts",
100
108
  "default": "./dist/lib/auth/index.js"
101
109
  },
102
- "./lib/*": {
103
- "types": "./dist/lib/*.d.ts",
104
- "default": "./dist/lib/*.js"
105
- },
106
110
  "./previews/enumerate": {
107
111
  "types": "./dist/previews/enumerate.d.ts",
108
112
  "default": "./dist/previews/enumerate.js"
@@ -149,7 +153,7 @@
149
153
  "lucide-react": "^1.23.0",
150
154
  "tailwind-merge": "^3.6.0",
151
155
  "zod": "^4.4.3",
152
- "@elytracms/core": "^0.0.92"
156
+ "@elytracms/core": "^0.0.94"
153
157
  },
154
158
  "peerDependencies": {
155
159
  "@tanstack/react-router": "^1.170.0",
@@ -173,7 +177,7 @@
173
177
  "react-dom": "^19.2.7",
174
178
  "typescript": "^6.0.3",
175
179
  "vite": "^8.1.3",
176
- "@elytracms/components": "^0.0.92"
180
+ "@elytracms/components": "^0.0.94"
177
181
  },
178
182
  "scripts": {
179
183
  "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && node ../../scripts/fix-esm-extensions.mjs dist && node ../../scripts/check-esm-extensions.mjs dist",
@@ -1,16 +0,0 @@
1
- import type { BlocksFieldDef, CompositionIssue, RichTextFieldDef } from '@elytracms/core/cms-core';
2
- /**
3
- * EC-188: validate a `blocks` composition field value against the field's `allow`
4
- * vocabulary + the code-owned component registry (the leash), mapping graph
5
- * issues into plain CMS findings. Never throws — a malformed value degrades to
6
- * a single finding, matching the "validation is first-class, never a crash"
7
- * rule.
8
- */
9
- export declare function validateComposition(value: unknown, field: BlocksFieldDef): CompositionIssue[];
10
- /**
11
- * EC-189: validate the composition nodes inside a `richText` field value with
12
- * the SAME leash a `blocks` field uses — since EC-547 literally the same walk
13
- * over the same shape: the value's `elytra/component` nodes ARE sequence
14
- * citizens, at the top level and nested in typography content.
15
- */
16
- export declare function validateRichTextEmbeds(value: unknown, field: RichTextFieldDef): CompositionIssue[];
@@ -1,133 +0,0 @@
1
- import { legacyNodeMemberIssues, validateCompositionValue } from '@elytracms/core/project-graph';
2
- import { BLOCK_SEQUENCE_VERSION, classifyBlockNode, isBlockSequenceValueShape, parseBlockSequenceValue, } from '@elytracms/core/rich-text';
3
- import { getStudioRegistry } from '@elytracms/studio/lib/registry';
4
- /**
5
- * Composition validator adapters (EC-326, extracted from `cms-store.tsx`) —
6
- * injected into `validateDocument`'s `validateComposition`/`validateRichTextEmbeds`
7
- * options so `@elytracms/core/cms-core` stays free of `@elytracms/core/project-graph`
8
- * and `@elytracms/core/rich-text`.
9
- *
10
- * EC-547 (EC-500 D1/D4): both field types now share ONE stored shape — the v2
11
- * block sequence `{ version: 2, content: BlockNode[] }` — and therefore ONE
12
- * validation walk: unwrap the envelope, validate the sequence's component nodes
13
- * (top-level roots AND nodes nested inside typography content) against the
14
- * field's `allow` vocabulary + the code-owned component registry. "`allow`
15
- * means component ids insertable at this position" is now literally the same
16
- * check on the same shape for `blocks` and `richText`.
17
- *
18
- * Pre-convergence shapes (the v1 `{ version, doc }` envelope, bare node lists)
19
- * never reach these adapters: `validateDocument`'s shape pass reports them as
20
- * the explicit pre-convergence issue and skips the deeper validators (EC-548
21
- * removed the legacy walks). A retired `componentEmbed` node riding in v2
22
- * content is a foreign typography node — not rendered, not validated, surfaced
23
- * by the renderer's unknown-node fallback (render/validate parity, EC-497).
24
- */
25
- /**
26
- * Validate the component nodes of a v2 block sequence against the field leash.
27
- *
28
- * - Top-level component roots validate in ONE `validateCompositionValue` call,
29
- * so cross-root checks (duplicate node ids) see the whole sequence. Their
30
- * `root/<k>` issue paths are re-keyed to the node's actual sequence index
31
- * (`content/<i>/…`).
32
- * - A component nested in typography content validates per-node with the SAME
33
- * leash, its findings prefixed with the typography path
34
- * (`content/<i>/content/<j>/…`).
35
- * - A malformed value degrades to a single finding, never a crash.
36
- */
37
- function validateBlockSequence(value, allow) {
38
- // Structural gate FIRST: only the stored `{ version: 2, content }` object is a
39
- // sequence here. The parser alone would also accept a JSON-string encoding of
40
- // one — which no delivery reader accepts — and validating that clean would be
41
- // the invisible divergence EC-390 exists to prevent.
42
- if (!isBlockSequenceValueShape(value)) {
43
- return [
44
- {
45
- message: `is not a valid block sequence (version ${BLOCK_SEQUENCE_VERSION})`,
46
- severity: 'error',
47
- },
48
- ];
49
- }
50
- // EC-574: retired node members (a render `condition`, a `kind: 'binding'` prop)
51
- // are judged on the value AS STORED, before the parse below — the parser strips
52
- // a stray `condition` silently and rejects a binding prop only generically, so
53
- // this is the one place the stored shape is still visible to name precisely.
54
- const out = legacyNodeMemberIssues(value).map((issue) => ({
55
- message: issue.message,
56
- severity: issue.severity,
57
- nodePath: issue.path.join('/'),
58
- }));
59
- const parsed = parseBlockSequenceValue(value);
60
- if (!parsed.ok) {
61
- return [
62
- ...out,
63
- {
64
- message: `is not a valid block sequence (version ${BLOCK_SEQUENCE_VERSION})`,
65
- severity: 'error',
66
- },
67
- ];
68
- }
69
- const components = getStudioRegistry().registry.lookup;
70
- const opts = { ...(allow ? { allow } : {}), components };
71
- /** `root/0/<rest>` from a single-node validation call → `<base>/<rest>`. */
72
- const nestedPath = (base, path) => {
73
- const rest = path.slice(2);
74
- return rest.length > 0 ? `${base}/${rest.join('/')}` : base;
75
- };
76
- const walkTypography = (nodes, base) => {
77
- nodes?.forEach((child, i) => {
78
- const here = `${base}/content/${i}`;
79
- const kind = classifyBlockNode(child);
80
- if (kind.kind === 'component') {
81
- for (const issue of validateCompositionValue(kind.node, opts)) {
82
- out.push({ message: issue.message, severity: issue.severity, nodePath: nestedPath(here, issue.path) });
83
- }
84
- }
85
- else {
86
- walkTypography(kind.node.content, here);
87
- }
88
- });
89
- };
90
- const roots = [];
91
- parsed.value.content.forEach((node, index) => {
92
- const kind = classifyBlockNode(node);
93
- if (kind.kind === 'component')
94
- roots.push({ node: kind.node, index });
95
- else
96
- walkTypography(kind.node.content, `content/${index}`);
97
- });
98
- for (const issue of validateCompositionValue(roots.map((r) => r.node), opts)) {
99
- // path is `['root', <k>, ...rest]` — re-key <k> to the sequence index.
100
- const [, k, ...rest] = issue.path;
101
- const index = typeof k === 'number' ? (roots[k]?.index ?? k) : k;
102
- out.push({
103
- message: issue.message,
104
- severity: issue.severity,
105
- nodePath: ['content', ...(index === undefined ? [] : [index]), ...rest].join('/'),
106
- });
107
- }
108
- return out;
109
- }
110
- /**
111
- * EC-188: validate a `blocks` composition field value against the field's `allow`
112
- * vocabulary + the code-owned component registry (the leash), mapping graph
113
- * issues into plain CMS findings. Never throws — a malformed value degrades to
114
- * a single finding, matching the "validation is first-class, never a crash"
115
- * rule.
116
- */
117
- export function validateComposition(value, field) {
118
- if (value == null)
119
- return [];
120
- return validateBlockSequence(value, field.allow);
121
- }
122
- /**
123
- * EC-189: validate the composition nodes inside a `richText` field value with
124
- * the SAME leash a `blocks` field uses — since EC-547 literally the same walk
125
- * over the same shape: the value's `elytra/component` nodes ARE sequence
126
- * citizens, at the top level and nested in typography content.
127
- */
128
- export function validateRichTextEmbeds(value, field) {
129
- if (value == null)
130
- return [];
131
- return validateBlockSequence(value, field.allow);
132
- }
133
- //# sourceMappingURL=cms-composition-validators.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cms-composition-validators.js","sourceRoot":"","sources":["../../../src/components/cms/cms-composition-validators.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BlocksFieldDef, CompositionIssue, RichTextFieldDef } from '@elytracms/core/cms-core'\nimport { legacyNodeMemberIssues, validateCompositionValue } from '@elytracms/core/project-graph'\nimport type { ComponentNode } from '@elytracms/core/project-graph'\nimport {\n BLOCK_SEQUENCE_VERSION,\n classifyBlockNode,\n isBlockSequenceValueShape,\n parseBlockSequenceValue,\n} from '@elytracms/core/rich-text'\nimport type { BlockNode } from '@elytracms/core/rich-text'\nimport { getStudioRegistry } from '@elytracms/studio/lib/registry'\n\n/**\n * Composition validator adapters (EC-326, extracted from `cms-store.tsx`) —\n * injected into `validateDocument`'s `validateComposition`/`validateRichTextEmbeds`\n * options so `@elytracms/core/cms-core` stays free of `@elytracms/core/project-graph`\n * and `@elytracms/core/rich-text`.\n *\n * EC-547 (EC-500 D1/D4): both field types now share ONE stored shape — the v2\n * block sequence `{ version: 2, content: BlockNode[] }` — and therefore ONE\n * validation walk: unwrap the envelope, validate the sequence's component nodes\n * (top-level roots AND nodes nested inside typography content) against the\n * field's `allow` vocabulary + the code-owned component registry. \"`allow`\n * means component ids insertable at this position\" is now literally the same\n * check on the same shape for `blocks` and `richText`.\n *\n * Pre-convergence shapes (the v1 `{ version, doc }` envelope, bare node lists)\n * never reach these adapters: `validateDocument`'s shape pass reports them as\n * the explicit pre-convergence issue and skips the deeper validators (EC-548\n * removed the legacy walks). A retired `componentEmbed` node riding in v2\n * content is a foreign typography node — not rendered, not validated, surfaced\n * by the renderer's unknown-node fallback (render/validate parity, EC-497).\n */\n\n/**\n * Validate the component nodes of a v2 block sequence against the field leash.\n *\n * - Top-level component roots validate in ONE `validateCompositionValue` call,\n * so cross-root checks (duplicate node ids) see the whole sequence. Their\n * `root/<k>` issue paths are re-keyed to the node's actual sequence index\n * (`content/<i>/…`).\n * - A component nested in typography content validates per-node with the SAME\n * leash, its findings prefixed with the typography path\n * (`content/<i>/content/<j>/…`).\n * - A malformed value degrades to a single finding, never a crash.\n */\nfunction validateBlockSequence(\n value: unknown,\n allow: readonly string[] | undefined,\n): CompositionIssue[] {\n // Structural gate FIRST: only the stored `{ version: 2, content }` object is a\n // sequence here. The parser alone would also accept a JSON-string encoding of\n // one — which no delivery reader accepts — and validating that clean would be\n // the invisible divergence EC-390 exists to prevent.\n if (!isBlockSequenceValueShape(value)) {\n return [\n {\n message: `is not a valid block sequence (version ${BLOCK_SEQUENCE_VERSION})`,\n severity: 'error',\n },\n ]\n }\n // EC-574: retired node members (a render `condition`, a `kind: 'binding'` prop)\n // are judged on the value AS STORED, before the parse below — the parser strips\n // a stray `condition` silently and rejects a binding prop only generically, so\n // this is the one place the stored shape is still visible to name precisely.\n const out: CompositionIssue[] = legacyNodeMemberIssues(value).map((issue) => ({\n message: issue.message,\n severity: issue.severity,\n nodePath: issue.path.join('/'),\n }))\n const parsed = parseBlockSequenceValue(value)\n if (!parsed.ok) {\n return [\n ...out,\n {\n message: `is not a valid block sequence (version ${BLOCK_SEQUENCE_VERSION})`,\n severity: 'error',\n },\n ]\n }\n const components = getStudioRegistry().registry.lookup\n const opts = { ...(allow ? { allow } : {}), components }\n\n /** `root/0/<rest>` from a single-node validation call → `<base>/<rest>`. */\n const nestedPath = (base: string, path: ReadonlyArray<string | number>): string => {\n const rest = path.slice(2)\n return rest.length > 0 ? `${base}/${rest.join('/')}` : base\n }\n\n const walkTypography = (nodes: readonly BlockNode[] | undefined, base: string): void => {\n nodes?.forEach((child, i) => {\n const here = `${base}/content/${i}`\n const kind = classifyBlockNode(child)\n if (kind.kind === 'component') {\n for (const issue of validateCompositionValue(kind.node, opts)) {\n out.push({ message: issue.message, severity: issue.severity, nodePath: nestedPath(here, issue.path) })\n }\n } else {\n walkTypography(kind.node.content, here)\n }\n })\n }\n\n const roots: { node: ComponentNode; index: number }[] = []\n parsed.value.content.forEach((node, index) => {\n const kind = classifyBlockNode(node)\n if (kind.kind === 'component') roots.push({ node: kind.node, index })\n else walkTypography(kind.node.content, `content/${index}`)\n })\n\n for (const issue of validateCompositionValue(roots.map((r) => r.node), opts)) {\n // path is `['root', <k>, ...rest]` — re-key <k> to the sequence index.\n const [, k, ...rest] = issue.path\n const index = typeof k === 'number' ? (roots[k]?.index ?? k) : k\n out.push({\n message: issue.message,\n severity: issue.severity,\n nodePath: ['content', ...(index === undefined ? [] : [index]), ...rest].join('/'),\n })\n }\n return out\n}\n\n/**\n * EC-188: validate a `blocks` composition field value against the field's `allow`\n * vocabulary + the code-owned component registry (the leash), mapping graph\n * issues into plain CMS findings. Never throws — a malformed value degrades to\n * a single finding, matching the \"validation is first-class, never a crash\"\n * rule.\n */\nexport function validateComposition(value: unknown, field: BlocksFieldDef): CompositionIssue[] {\n if (value == null) return []\n return validateBlockSequence(value, field.allow)\n}\n\n/**\n * EC-189: validate the composition nodes inside a `richText` field value with\n * the SAME leash a `blocks` field uses — since EC-547 literally the same walk\n * over the same shape: the value's `elytra/component` nodes ARE sequence\n * citizens, at the top level and nested in typography content.\n */\nexport function validateRichTextEmbeds(value: unknown, field: RichTextFieldDef): CompositionIssue[] {\n if (value == null) return []\n return validateBlockSequence(value, field.allow)\n}\n"]}
@@ -1,28 +0,0 @@
1
- import type { CmsDocument, CollectionDef, LocaleConfig } from '@elytracms/core/cms-core';
2
- import type { ManifestResolver } from '@elytracms/core/component-registry';
3
- /**
4
- * EC-425 — THE publish-time hidden-strip, extracted so single-document publish
5
- * (`doPublish`, use-publish-controller) and bulk publish (`runBulk`, cms-store)
6
- * share ONE clean step instead of the bulk bar bypassing it:
7
- *
8
- * - EC-273 `clearHiddenValues`: drop conditionally-hidden document field values
9
- * (predicate-hidden, non-`retainWhenHidden`) from `values`/`localized`, each
10
- * judged in the locale view the editor displayed (EC-580 — the strip sees what
11
- * the editor saw, so it needs the project's `LocaleConfig`).
12
- * - EC-394 `clearHiddenProps`: the same strip for component props across every
13
- * `blocks`/canvas composition, so a hidden relation/asset prop's ref leaves
14
- * the EC-277 reference index (derived from the stored draft at the EC-286
15
- * write chokepoint) and stops blocking its target's delete/unpublish.
16
- *
17
- * This is the projection point for "hidden means not delivered" (EC-565 Q3):
18
- * delivery stays predicate-free because the values are gone from the snapshot.
19
- *
20
- * The manifests AND the locale config resolve through the SESSION by default
21
- * (client-side-with-user-session, the ratified trust boundary — the registry
22
- * binding `doPublish` used inline since EC-394, and the project locales the CMS
23
- * session installs, EC-479). Both production callers pass the session's
24
- * `localeConfig` explicitly; tests inject a resolver to pin behaviour against
25
- * fixture manifests. Identity-preserving: returns the input document when
26
- * nothing clears, so callers can save-if-changed.
27
- */
28
- export declare function cleanHiddenForPublish(collection: CollectionDef, doc: CmsDocument, resolveManifest?: ManifestResolver, localeConfig?: LocaleConfig | undefined): CmsDocument;
@@ -1,38 +0,0 @@
1
- import { clearHiddenValues } from '@elytracms/core/cms-core';
2
- import { clearHiddenProps } from '@elytracms/core/component-registry';
3
- import { getStudioRegistry } from '@elytracms/studio/lib/registry';
4
- import { getStudioLocaleConfig } from '@elytracms/studio/lib/locale';
5
- /**
6
- * EC-425 — THE publish-time hidden-strip, extracted so single-document publish
7
- * (`doPublish`, use-publish-controller) and bulk publish (`runBulk`, cms-store)
8
- * share ONE clean step instead of the bulk bar bypassing it:
9
- *
10
- * - EC-273 `clearHiddenValues`: drop conditionally-hidden document field values
11
- * (predicate-hidden, non-`retainWhenHidden`) from `values`/`localized`, each
12
- * judged in the locale view the editor displayed (EC-580 — the strip sees what
13
- * the editor saw, so it needs the project's `LocaleConfig`).
14
- * - EC-394 `clearHiddenProps`: the same strip for component props across every
15
- * `blocks`/canvas composition, so a hidden relation/asset prop's ref leaves
16
- * the EC-277 reference index (derived from the stored draft at the EC-286
17
- * write chokepoint) and stops blocking its target's delete/unpublish.
18
- *
19
- * This is the projection point for "hidden means not delivered" (EC-565 Q3):
20
- * delivery stays predicate-free because the values are gone from the snapshot.
21
- *
22
- * The manifests AND the locale config resolve through the SESSION by default
23
- * (client-side-with-user-session, the ratified trust boundary — the registry
24
- * binding `doPublish` used inline since EC-394, and the project locales the CMS
25
- * session installs, EC-479). Both production callers pass the session's
26
- * `localeConfig` explicitly; tests inject a resolver to pin behaviour against
27
- * fixture manifests. Identity-preserving: returns the input document when
28
- * nothing clears, so callers can save-if-changed.
29
- */
30
- export function cleanHiddenForPublish(collection, doc, resolveManifest = sessionManifestResolver(), localeConfig = getStudioLocaleConfig() ?? undefined) {
31
- return clearHiddenProps(collection, clearHiddenValues(collection, doc, localeConfig), resolveManifest);
32
- }
33
- /** The session component registry as a {@link ManifestResolver}. */
34
- function sessionManifestResolver() {
35
- const { registry } = getStudioRegistry();
36
- return (id) => registry.getManifest(id);
37
- }
38
- //# sourceMappingURL=publish-clean.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"publish-clean.js","sourceRoot":"","sources":["../../../src/components/cms/publish-clean.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAA;AAErE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAEpE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,qBAAqB,CACnC,UAAyB,EACzB,GAAgB,EAChB,kBAAoC,uBAAuB,EAAE,EAC7D,eAAyC,qBAAqB,EAAE,IAAI,SAAS;IAE7E,OAAO,gBAAgB,CAAC,UAAU,EAAE,iBAAiB,CAAC,UAAU,EAAE,GAAG,EAAE,YAAY,CAAC,EAAE,eAAe,CAAC,CAAA;AACxG,CAAC;AAED,oEAAoE;AACpE,SAAS,uBAAuB;IAC9B,MAAM,EAAE,QAAQ,EAAE,GAAG,iBAAiB,EAAE,CAAA;IACxC,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,CAAA;AACzC,CAAC","sourcesContent":["import { clearHiddenValues } from '@elytracms/core/cms-core'\nimport type { CmsDocument, CollectionDef, LocaleConfig } from '@elytracms/core/cms-core'\nimport { clearHiddenProps } from '@elytracms/core/component-registry'\nimport type { ManifestResolver } from '@elytracms/core/component-registry'\nimport { getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport { getStudioLocaleConfig } from '@elytracms/studio/lib/locale'\n\n/**\n * EC-425 — THE publish-time hidden-strip, extracted so single-document publish\n * (`doPublish`, use-publish-controller) and bulk publish (`runBulk`, cms-store)\n * share ONE clean step instead of the bulk bar bypassing it:\n *\n * - EC-273 `clearHiddenValues`: drop conditionally-hidden document field values\n * (predicate-hidden, non-`retainWhenHidden`) from `values`/`localized`, each\n * judged in the locale view the editor displayed (EC-580 — the strip sees what\n * the editor saw, so it needs the project's `LocaleConfig`).\n * - EC-394 `clearHiddenProps`: the same strip for component props across every\n * `blocks`/canvas composition, so a hidden relation/asset prop's ref leaves\n * the EC-277 reference index (derived from the stored draft at the EC-286\n * write chokepoint) and stops blocking its target's delete/unpublish.\n *\n * This is the projection point for \"hidden means not delivered\" (EC-565 Q3):\n * delivery stays predicate-free because the values are gone from the snapshot.\n *\n * The manifests AND the locale config resolve through the SESSION by default\n * (client-side-with-user-session, the ratified trust boundary — the registry\n * binding `doPublish` used inline since EC-394, and the project locales the CMS\n * session installs, EC-479). Both production callers pass the session's\n * `localeConfig` explicitly; tests inject a resolver to pin behaviour against\n * fixture manifests. Identity-preserving: returns the input document when\n * nothing clears, so callers can save-if-changed.\n */\nexport function cleanHiddenForPublish(\n collection: CollectionDef,\n doc: CmsDocument,\n resolveManifest: ManifestResolver = sessionManifestResolver(),\n localeConfig: LocaleConfig | undefined = getStudioLocaleConfig() ?? undefined,\n): CmsDocument {\n return clearHiddenProps(collection, clearHiddenValues(collection, doc, localeConfig), resolveManifest)\n}\n\n/** The session component registry as a {@link ManifestResolver}. */\nfunction sessionManifestResolver(): ManifestResolver {\n const { registry } = getStudioRegistry()\n return (id) => registry.getManifest(id)\n}\n"]}
@@ -1,53 +0,0 @@
1
- import type { CmsDocument, CollectionDef } from '@elytracms/core/cms-core';
2
- import type { RedirectEntry, SaveRedirectInput } from '@elytracms/core/persistence';
3
- import type { CollectionViewCapabilities, CollectionViewSource } from '@elytracms/studio/lib/collection-view/collection-view-source';
4
- /**
5
- * The capability profile of the redirects rail (EC-303): content-gated, create
6
- * + remove, no publish/versions/locales — redirects are CONTENT (an editor
7
- * owns them), so unlike the users rail this source allows `create`, is NOT
8
- * admin-only, and needs no principal field-access policy. Hoisted to a
9
- * module-level constant (EC-327), mirroring `ASSET_COLLECTION_CAPABILITIES`.
10
- */
11
- export declare const REDIRECT_COLLECTION_CAPABILITIES: CollectionViewCapabilities;
12
- /**
13
- * Project a stored redirect into the lens's `values` shape. EC-311 Tier 2:
14
- * additive schema fields round-trip through the open meta bag, spread FIRST so a
15
- * canonical column always wins over a same-named meta key (RESIDUE-3c, EC-577):
16
- * spread last, a stored `meta.to` displayed as the redirect's target and a
17
- * re-save wrote it into the canonical `to`. The record schema now refuses such a
18
- * key on write; this order keeps a row stored before that harmless.
19
- */
20
- export declare function redirectToDocument(entry: RedirectEntry): CmsDocument;
21
- /**
22
- * Map an edited lens document back to the redirect write (EC-577). A column the
23
- * document does not carry is left out of the write, so the stored value is kept:
24
- * `permanent`/`enabled` get their defaults only when the save CREATES the
25
- * redirect, applied once inside the adapter's transaction — this lens no longer
26
- * restates them (`?? true` here was the third copy of the default, RESIDUE-3b).
27
- * `from`/`to` are always sent: the editor owns them, and an empty one is refused
28
- * visibly by the write's validation rather than kept silently.
29
- */
30
- export declare function documentToSaveRedirect(doc: CmsDocument): SaveRedirectInput;
31
- /**
32
- * Assemble a {@link CollectionViewSource} for the **redirects rail** (EC-303) —
33
- * the portable list/edit surfaces over the editorial redirects store instead of
34
- * the CMS store. Redirects are CONTENT (an editor owns them), so unlike the users
35
- * rail this source allows `create`, is NOT admin-only, and needs no principal
36
- * field-access policy. No publish/versions/locales/inline/import — a redirect
37
- * is a small record saved explicitly (a saved+enabled one is live); bulk
38
- * delete rides the shared rail runner (EC-433).
39
- *
40
- * Must be mounted under a `RedirectsProvider` (for {@link useRedirects}).
41
- *
42
- * `schema` defaults to the engine-owned {@link redirectsCollectionDef}; a mount may
43
- * pass a customized def (EC-311 — built-in fields overridden by equal name via
44
- * `nav.redirects({ fields })`). The canonical `from`/`to`/`permanent`/`enabled`
45
- * names+types are contract-locked, so the projection helpers still read the same
46
- * canonical values; a mount's *additive* fields (Tier 2) round-trip through the
47
- * record's open `meta` bag ({@link documentToSaveRedirect}/{@link redirectToDocument}).
48
- *
49
- * The shared scaffold (`useRailViewSource`, EC-327) owns `viewState`/`lastError`
50
- * plumbing and the assembled source; this hook supplies only the redirects-store
51
- * reads/writes, the capability profile, and the registry-driven `validate`.
52
- */
53
- export declare function useRedirectsCollectionViewSource(projectId: string, schema?: CollectionDef): CollectionViewSource;