@aphexcms/cms-core 9.4.0 → 9.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (408) hide show
  1. package/dist/admin/block-previews.svelte.d.ts +46 -0
  2. package/dist/admin/block-previews.svelte.d.ts.map +1 -0
  3. package/dist/admin/block-previews.svelte.js +26 -0
  4. package/dist/admin/field-components.svelte.d.ts +16 -0
  5. package/dist/admin/field-components.svelte.d.ts.map +1 -0
  6. package/dist/admin/field-components.svelte.js +18 -0
  7. package/dist/admin/nav.svelte.d.ts +34 -0
  8. package/dist/admin/nav.svelte.d.ts.map +1 -0
  9. package/dist/admin/nav.svelte.js +78 -0
  10. package/dist/admin/slots.svelte.d.ts +50 -0
  11. package/dist/admin/slots.svelte.d.ts.map +1 -0
  12. package/dist/admin/slots.svelte.js +67 -0
  13. package/dist/admin/types.d.ts +7 -0
  14. package/dist/admin/types.d.ts.map +1 -0
  15. package/dist/admin/types.js +1 -0
  16. package/dist/api/schemas/api-keys.d.ts +4 -37
  17. package/dist/api/schemas/api-keys.d.ts.map +1 -1
  18. package/dist/api/schemas/api-keys.js +5 -2
  19. package/dist/api/schemas/assets.d.ts +4 -0
  20. package/dist/api/schemas/assets.d.ts.map +1 -1
  21. package/dist/api/schemas/assets.js +3 -0
  22. package/dist/api/schemas/plugin-settings.d.ts +6 -0
  23. package/dist/api/schemas/plugin-settings.d.ts.map +1 -0
  24. package/dist/api/schemas/plugin-settings.js +8 -0
  25. package/dist/api/schemas/roles.d.ts +7 -56
  26. package/dist/api/schemas/roles.d.ts.map +1 -1
  27. package/dist/api/schemas/roles.js +11 -6
  28. package/dist/api/schemas/user.d.ts +2 -1
  29. package/dist/api/schemas/user.d.ts.map +1 -1
  30. package/dist/api/schemas/user.js +7 -2
  31. package/dist/app-augment.d.ts +11 -0
  32. package/dist/app-augment.d.ts.map +1 -1
  33. package/dist/app.d.ts +2 -0
  34. package/dist/auth/provider.d.ts +3 -0
  35. package/dist/auth/provider.d.ts.map +1 -1
  36. package/dist/cli/index.js +4 -4
  37. package/dist/cli/index.js.map +1 -1
  38. package/dist/client/index.d.ts +6 -0
  39. package/dist/client/index.d.ts.map +1 -1
  40. package/dist/client/index.js +9 -0
  41. package/dist/components/AdminApp.svelte +259 -113
  42. package/dist/components/AdminApp.svelte.d.ts +18 -2
  43. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  44. package/dist/components/admin/AdminSlot.svelte +18 -0
  45. package/dist/components/admin/AdminSlot.svelte.d.ts +12 -0
  46. package/dist/components/admin/AdminSlot.svelte.d.ts.map +1 -0
  47. package/dist/components/admin/DocumentEditor.svelte +646 -385
  48. package/dist/components/admin/DocumentEditor.svelte.d.ts +13 -0
  49. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  50. package/dist/components/admin/MediaBrowser.svelte +13 -3
  51. package/dist/components/admin/MediaBrowser.svelte.d.ts.map +1 -1
  52. package/dist/components/admin/PluginSettingsPanel.svelte +231 -0
  53. package/dist/components/admin/PluginSettingsPanel.svelte.d.ts +8 -0
  54. package/dist/components/admin/PluginSettingsPanel.svelte.d.ts.map +1 -0
  55. package/dist/components/admin/SchemaField.svelte +76 -95
  56. package/dist/components/admin/SchemaField.svelte.d.ts +7 -0
  57. package/dist/components/admin/SchemaField.svelte.d.ts.map +1 -1
  58. package/dist/components/admin/fields/ArrayField.svelte +24 -2
  59. package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
  60. package/dist/components/admin/fields/FieldInput.svelte +109 -0
  61. package/dist/components/admin/fields/FieldInput.svelte.d.ts +17 -0
  62. package/dist/components/admin/fields/FieldInput.svelte.d.ts.map +1 -0
  63. package/dist/components/admin/fields/richtext/PortableTextImageView.svelte +5 -12
  64. package/dist/components/admin/fields/richtext/PortableTextImageView.svelte.d.ts +2 -9
  65. package/dist/components/admin/fields/richtext/PortableTextImageView.svelte.d.ts.map +1 -1
  66. package/dist/components/admin/fields/richtext/PortableTextObjectView.svelte +18 -17
  67. package/dist/components/admin/fields/richtext/PortableTextObjectView.svelte.d.ts +2 -9
  68. package/dist/components/admin/fields/richtext/PortableTextObjectView.svelte.d.ts.map +1 -1
  69. package/dist/components/admin/fields/richtext/RichtextField.svelte +55 -2
  70. package/dist/components/admin/fields/richtext/RichtextField.svelte.d.ts.map +1 -1
  71. package/dist/components/admin/fields/richtext/portable-text-object-node.d.ts +7 -0
  72. package/dist/components/admin/fields/richtext/portable-text-object-node.d.ts.map +1 -1
  73. package/dist/components/admin/fields/richtext/portable-text-object-node.js +4 -2
  74. package/dist/components/admin/fields/richtext/svelte-node-view.d.ts +16 -1
  75. package/dist/components/admin/fields/richtext/svelte-node-view.d.ts.map +1 -1
  76. package/dist/components/admin/fields/richtext/svelte-node-view.js +20 -1
  77. package/dist/components/layout/OrganizationSwitcher.svelte +31 -10
  78. package/dist/components/layout/OrganizationSwitcher.svelte.d.ts.map +1 -1
  79. package/dist/components/layout/Sidebar.svelte +49 -11
  80. package/dist/components/layout/Sidebar.svelte.d.ts +5 -1
  81. package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -1
  82. package/dist/components/layout/sidebar/AppSidebar.svelte +66 -3
  83. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts +5 -0
  84. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts.map +1 -1
  85. package/dist/components/layout/sidebar/NavMain.svelte +3 -2
  86. package/dist/components/layout/sidebar/NavMain.svelte.d.ts +4 -3
  87. package/dist/components/layout/sidebar/NavMain.svelte.d.ts.map +1 -1
  88. package/dist/components/layout/sidebar/NavUser.svelte +5 -1
  89. package/dist/config.d.ts.map +1 -1
  90. package/dist/config.js +11 -0
  91. package/dist/db/interfaces/asset.d.ts +1 -0
  92. package/dist/db/interfaces/asset.d.ts.map +1 -1
  93. package/dist/db/interfaces/index.d.ts +3 -1
  94. package/dist/db/interfaces/index.d.ts.map +1 -1
  95. package/dist/db/interfaces/plugin-settings.d.ts +23 -0
  96. package/dist/db/interfaces/plugin-settings.d.ts.map +1 -0
  97. package/dist/db/interfaces/plugin-settings.js +13 -0
  98. package/dist/db/interfaces/role.d.ts +14 -5
  99. package/dist/db/interfaces/role.d.ts.map +1 -1
  100. package/dist/engine.d.ts +28 -0
  101. package/dist/engine.d.ts.map +1 -1
  102. package/dist/engine.js +44 -0
  103. package/dist/hooks.d.ts +6 -0
  104. package/dist/hooks.d.ts.map +1 -1
  105. package/dist/hooks.js +59 -2
  106. package/dist/index.d.ts +2 -0
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +5 -0
  109. package/dist/lib/admin/block-previews.svelte.d.ts +46 -0
  110. package/dist/lib/admin/block-previews.svelte.d.ts.map +1 -0
  111. package/dist/lib/admin/block-previews.svelte.js +27 -0
  112. package/dist/lib/admin/block-previews.svelte.js.map +1 -0
  113. package/dist/lib/admin/field-components.svelte.d.ts +16 -0
  114. package/dist/lib/admin/field-components.svelte.d.ts.map +1 -0
  115. package/dist/lib/admin/field-components.svelte.js +19 -0
  116. package/dist/lib/admin/field-components.svelte.js.map +1 -0
  117. package/dist/lib/admin/nav.svelte.d.ts +34 -0
  118. package/dist/lib/admin/nav.svelte.d.ts.map +1 -0
  119. package/dist/lib/admin/nav.svelte.js +79 -0
  120. package/dist/lib/admin/nav.svelte.js.map +1 -0
  121. package/dist/lib/admin/slots.svelte.d.ts +50 -0
  122. package/dist/lib/admin/slots.svelte.d.ts.map +1 -0
  123. package/dist/lib/admin/slots.svelte.js +68 -0
  124. package/dist/lib/admin/slots.svelte.js.map +1 -0
  125. package/dist/lib/admin/types.d.ts +7 -0
  126. package/dist/lib/admin/types.d.ts.map +1 -0
  127. package/dist/lib/admin/types.js +2 -0
  128. package/dist/lib/admin/types.js.map +1 -0
  129. package/dist/lib/api/schemas/api-keys.d.ts +4 -37
  130. package/dist/lib/api/schemas/api-keys.d.ts.map +1 -1
  131. package/dist/lib/api/schemas/api-keys.js +5 -2
  132. package/dist/lib/api/schemas/api-keys.js.map +1 -1
  133. package/dist/lib/api/schemas/assets.d.ts +4 -0
  134. package/dist/lib/api/schemas/assets.d.ts.map +1 -1
  135. package/dist/lib/api/schemas/assets.js +3 -0
  136. package/dist/lib/api/schemas/assets.js.map +1 -1
  137. package/dist/lib/api/schemas/plugin-settings.d.ts +6 -0
  138. package/dist/lib/api/schemas/plugin-settings.d.ts.map +1 -0
  139. package/dist/lib/api/schemas/plugin-settings.js +9 -0
  140. package/dist/lib/api/schemas/plugin-settings.js.map +1 -0
  141. package/dist/lib/api/schemas/roles.d.ts +7 -56
  142. package/dist/lib/api/schemas/roles.d.ts.map +1 -1
  143. package/dist/lib/api/schemas/roles.js +11 -6
  144. package/dist/lib/api/schemas/roles.js.map +1 -1
  145. package/dist/lib/api/schemas/user.d.ts +2 -1
  146. package/dist/lib/api/schemas/user.d.ts.map +1 -1
  147. package/dist/lib/api/schemas/user.js +7 -2
  148. package/dist/lib/api/schemas/user.js.map +1 -1
  149. package/dist/lib/app-augment.d.ts +11 -0
  150. package/dist/lib/app-augment.d.ts.map +1 -1
  151. package/dist/lib/auth/provider.d.ts +3 -0
  152. package/dist/lib/auth/provider.d.ts.map +1 -1
  153. package/dist/lib/client/index.d.ts +6 -0
  154. package/dist/lib/client/index.d.ts.map +1 -1
  155. package/dist/lib/client/index.js +9 -0
  156. package/dist/lib/client/index.js.map +1 -1
  157. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.d.ts +7 -0
  158. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.d.ts.map +1 -1
  159. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.js +4 -2
  160. package/dist/lib/components/admin/fields/richtext/portable-text-object-node.js.map +1 -1
  161. package/dist/lib/components/admin/fields/richtext/svelte-node-view.d.ts +16 -1
  162. package/dist/lib/components/admin/fields/richtext/svelte-node-view.d.ts.map +1 -1
  163. package/dist/lib/components/admin/fields/richtext/svelte-node-view.js +20 -1
  164. package/dist/lib/components/admin/fields/richtext/svelte-node-view.js.map +1 -1
  165. package/dist/lib/config.d.ts.map +1 -1
  166. package/dist/lib/config.js +11 -0
  167. package/dist/lib/config.js.map +1 -1
  168. package/dist/lib/db/interfaces/asset.d.ts +1 -0
  169. package/dist/lib/db/interfaces/asset.d.ts.map +1 -1
  170. package/dist/lib/db/interfaces/index.d.ts +3 -1
  171. package/dist/lib/db/interfaces/index.d.ts.map +1 -1
  172. package/dist/lib/db/interfaces/plugin-settings.d.ts +23 -0
  173. package/dist/lib/db/interfaces/plugin-settings.d.ts.map +1 -0
  174. package/dist/lib/db/interfaces/plugin-settings.js +14 -0
  175. package/dist/lib/db/interfaces/plugin-settings.js.map +1 -0
  176. package/dist/lib/db/interfaces/role.d.ts +14 -5
  177. package/dist/lib/db/interfaces/role.d.ts.map +1 -1
  178. package/dist/lib/engine.d.ts +28 -0
  179. package/dist/lib/engine.d.ts.map +1 -1
  180. package/dist/lib/engine.js +44 -0
  181. package/dist/lib/engine.js.map +1 -1
  182. package/dist/lib/hooks.d.ts +6 -0
  183. package/dist/lib/hooks.d.ts.map +1 -1
  184. package/dist/lib/hooks.js +59 -2
  185. package/dist/lib/hooks.js.map +1 -1
  186. package/dist/lib/index.d.ts +2 -0
  187. package/dist/lib/index.d.ts.map +1 -1
  188. package/dist/lib/index.js +5 -0
  189. package/dist/lib/index.js.map +1 -1
  190. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  191. package/dist/lib/local-api/collection-api.js +4 -2
  192. package/dist/lib/local-api/collection-api.js.map +1 -1
  193. package/dist/lib/local-api/types.d.ts +8 -0
  194. package/dist/lib/local-api/types.d.ts.map +1 -1
  195. package/dist/lib/mcp/tools.d.ts.map +1 -1
  196. package/dist/lib/mcp/tools.js +69 -1
  197. package/dist/lib/mcp/tools.js.map +1 -1
  198. package/dist/lib/permissions-context.svelte.d.ts +7 -4
  199. package/dist/lib/permissions-context.svelte.d.ts.map +1 -1
  200. package/dist/lib/permissions-context.svelte.js.map +1 -1
  201. package/dist/lib/plugins/index.d.ts +3 -0
  202. package/dist/lib/plugins/index.d.ts.map +1 -0
  203. package/dist/lib/plugins/index.js +3 -0
  204. package/dist/lib/plugins/index.js.map +1 -0
  205. package/dist/lib/plugins/resolver.d.ts +49 -0
  206. package/dist/lib/plugins/resolver.d.ts.map +1 -0
  207. package/dist/lib/plugins/resolver.js +66 -0
  208. package/dist/lib/plugins/resolver.js.map +1 -0
  209. package/dist/lib/plugins/types.d.ts +233 -0
  210. package/dist/lib/plugins/types.d.ts.map +1 -0
  211. package/dist/lib/plugins/types.js +9 -0
  212. package/dist/lib/plugins/types.js.map +1 -0
  213. package/dist/lib/schema-utils/desugar.d.ts +27 -0
  214. package/dist/lib/schema-utils/desugar.d.ts.map +1 -0
  215. package/dist/lib/schema-utils/desugar.js +102 -0
  216. package/dist/lib/schema-utils/desugar.js.map +1 -0
  217. package/dist/lib/schema-utils/index.d.ts +2 -0
  218. package/dist/lib/schema-utils/index.d.ts.map +1 -1
  219. package/dist/lib/schema-utils/index.js +2 -0
  220. package/dist/lib/schema-utils/index.js.map +1 -1
  221. package/dist/lib/schema-utils/settings.d.ts +17 -0
  222. package/dist/lib/schema-utils/settings.d.ts.map +1 -0
  223. package/dist/lib/schema-utils/settings.js +23 -0
  224. package/dist/lib/schema-utils/settings.js.map +1 -0
  225. package/dist/lib/schema-utils/validator.d.ts.map +1 -1
  226. package/dist/lib/schema-utils/validator.js +11 -0
  227. package/dist/lib/schema-utils/validator.js.map +1 -1
  228. package/dist/lib/security/secret-crypto.d.ts +18 -0
  229. package/dist/lib/security/secret-crypto.d.ts.map +1 -0
  230. package/dist/lib/security/secret-crypto.js +71 -0
  231. package/dist/lib/security/secret-crypto.js.map +1 -0
  232. package/dist/lib/server/api/index.d.ts.map +1 -1
  233. package/dist/lib/server/api/index.js +3 -0
  234. package/dist/lib/server/api/index.js.map +1 -1
  235. package/dist/lib/server/api/routes/assets.d.ts.map +1 -1
  236. package/dist/lib/server/api/routes/assets.js +8 -2
  237. package/dist/lib/server/api/routes/assets.js.map +1 -1
  238. package/dist/lib/server/api/routes/organizations.d.ts.map +1 -1
  239. package/dist/lib/server/api/routes/organizations.js +4 -1
  240. package/dist/lib/server/api/routes/organizations.js.map +1 -1
  241. package/dist/lib/server/api/routes/plugin-settings.d.ts +4 -0
  242. package/dist/lib/server/api/routes/plugin-settings.d.ts.map +1 -0
  243. package/dist/lib/server/api/routes/plugin-settings.js +109 -0
  244. package/dist/lib/server/api/routes/plugin-settings.js.map +1 -0
  245. package/dist/lib/server/api/routes/roles.d.ts.map +1 -1
  246. package/dist/lib/server/api/routes/roles.js +37 -0
  247. package/dist/lib/server/api/routes/roles.js.map +1 -1
  248. package/dist/lib/server/api/routes/user.d.ts.map +1 -1
  249. package/dist/lib/server/api/routes/user.js +14 -3
  250. package/dist/lib/server/api/routes/user.js.map +1 -1
  251. package/dist/lib/services/asset-service.d.ts +1 -0
  252. package/dist/lib/services/asset-service.d.ts.map +1 -1
  253. package/dist/lib/services/asset-service.js.map +1 -1
  254. package/dist/lib/services/index.d.ts +2 -0
  255. package/dist/lib/services/index.d.ts.map +1 -1
  256. package/dist/lib/services/index.js +1 -0
  257. package/dist/lib/services/index.js.map +1 -1
  258. package/dist/lib/services/plugin-settings-service.d.ts +76 -0
  259. package/dist/lib/services/plugin-settings-service.d.ts.map +1 -0
  260. package/dist/lib/services/plugin-settings-service.js +236 -0
  261. package/dist/lib/services/plugin-settings-service.js.map +1 -0
  262. package/dist/lib/services/roles-service.d.ts +2 -2
  263. package/dist/lib/services/roles-service.d.ts.map +1 -1
  264. package/dist/lib/services/roles-service.js.map +1 -1
  265. package/dist/lib/theme/css.d.ts +30 -0
  266. package/dist/lib/theme/css.d.ts.map +1 -0
  267. package/dist/lib/theme/css.js +54 -0
  268. package/dist/lib/theme/css.js.map +1 -0
  269. package/dist/lib/theme/derive.d.ts +27 -0
  270. package/dist/lib/theme/derive.d.ts.map +1 -0
  271. package/dist/lib/theme/derive.js +108 -0
  272. package/dist/lib/theme/derive.js.map +1 -0
  273. package/dist/lib/theme/index.d.ts +5 -0
  274. package/dist/lib/theme/index.d.ts.map +1 -0
  275. package/dist/lib/theme/index.js +5 -0
  276. package/dist/lib/theme/index.js.map +1 -0
  277. package/dist/lib/theme/schemes.d.ts +60 -0
  278. package/dist/lib/theme/schemes.d.ts.map +1 -0
  279. package/dist/lib/theme/schemes.js +150 -0
  280. package/dist/lib/theme/schemes.js.map +1 -0
  281. package/dist/lib/theme/tokens.d.ts +57 -0
  282. package/dist/lib/theme/tokens.d.ts.map +1 -0
  283. package/dist/lib/theme/tokens.js +11 -0
  284. package/dist/lib/theme/tokens.js.map +1 -0
  285. package/dist/{cli/generate-types.d.ts → lib/type-gen.d.ts} +3 -6
  286. package/dist/lib/type-gen.d.ts.map +1 -0
  287. package/dist/lib/type-gen.js +658 -0
  288. package/dist/lib/type-gen.js.map +1 -0
  289. package/dist/lib/types/auth.d.ts +10 -10
  290. package/dist/lib/types/auth.d.ts.map +1 -1
  291. package/dist/lib/types/capabilities.d.ts +50 -9
  292. package/dist/lib/types/capabilities.d.ts.map +1 -1
  293. package/dist/lib/types/capabilities.js +147 -5
  294. package/dist/lib/types/capabilities.js.map +1 -1
  295. package/dist/lib/types/config.d.ts +30 -1
  296. package/dist/lib/types/config.d.ts.map +1 -1
  297. package/dist/lib/types/schemas.d.ts +90 -2
  298. package/dist/lib/types/schemas.d.ts.map +1 -1
  299. package/dist/lib/types/schemas.js.map +1 -1
  300. package/dist/lib/types/sidebar.d.ts +3 -1
  301. package/dist/lib/types/sidebar.d.ts.map +1 -1
  302. package/dist/lib/utils/index.d.ts +1 -0
  303. package/dist/lib/utils/index.d.ts.map +1 -1
  304. package/dist/lib/utils/index.js +1 -0
  305. package/dist/lib/utils/index.js.map +1 -1
  306. package/dist/lib/utils/preview.d.ts +16 -5
  307. package/dist/lib/utils/preview.d.ts.map +1 -1
  308. package/dist/lib/utils/preview.js +7 -2
  309. package/dist/lib/utils/preview.js.map +1 -1
  310. package/dist/lib/vite/index.d.ts +7 -0
  311. package/dist/lib/vite/index.d.ts.map +1 -1
  312. package/dist/lib/vite/index.js +37 -6
  313. package/dist/lib/vite/index.js.map +1 -1
  314. package/dist/local-api/collection-api.d.ts.map +1 -1
  315. package/dist/local-api/collection-api.js +4 -2
  316. package/dist/local-api/types.d.ts +8 -0
  317. package/dist/local-api/types.d.ts.map +1 -1
  318. package/dist/mcp/tools.d.ts.map +1 -1
  319. package/dist/mcp/tools.js +69 -1
  320. package/dist/permissions-context.svelte.d.ts +7 -4
  321. package/dist/permissions-context.svelte.d.ts.map +1 -1
  322. package/dist/plugins/index.d.ts +3 -0
  323. package/dist/plugins/index.d.ts.map +1 -0
  324. package/dist/plugins/index.js +2 -0
  325. package/dist/plugins/resolver.d.ts +49 -0
  326. package/dist/plugins/resolver.d.ts.map +1 -0
  327. package/dist/plugins/resolver.js +65 -0
  328. package/dist/plugins/types.d.ts +233 -0
  329. package/dist/plugins/types.d.ts.map +1 -0
  330. package/dist/plugins/types.js +8 -0
  331. package/dist/schema-utils/desugar.d.ts +27 -0
  332. package/dist/schema-utils/desugar.d.ts.map +1 -0
  333. package/dist/schema-utils/desugar.js +101 -0
  334. package/dist/schema-utils/index.d.ts +2 -0
  335. package/dist/schema-utils/index.d.ts.map +1 -1
  336. package/dist/schema-utils/index.js +2 -0
  337. package/dist/schema-utils/settings.d.ts +17 -0
  338. package/dist/schema-utils/settings.d.ts.map +1 -0
  339. package/dist/schema-utils/settings.js +22 -0
  340. package/dist/schema-utils/validator.d.ts.map +1 -1
  341. package/dist/schema-utils/validator.js +11 -0
  342. package/dist/security/secret-crypto.d.ts +18 -0
  343. package/dist/security/secret-crypto.d.ts.map +1 -0
  344. package/dist/security/secret-crypto.js +70 -0
  345. package/dist/server/api/index.d.ts.map +1 -1
  346. package/dist/server/api/index.js +3 -0
  347. package/dist/server/api/routes/assets.d.ts.map +1 -1
  348. package/dist/server/api/routes/assets.js +8 -2
  349. package/dist/server/api/routes/organizations.d.ts.map +1 -1
  350. package/dist/server/api/routes/organizations.js +4 -1
  351. package/dist/server/api/routes/plugin-settings.d.ts +4 -0
  352. package/dist/server/api/routes/plugin-settings.d.ts.map +1 -0
  353. package/dist/server/api/routes/plugin-settings.js +108 -0
  354. package/dist/server/api/routes/roles.d.ts.map +1 -1
  355. package/dist/server/api/routes/roles.js +37 -0
  356. package/dist/server/api/routes/user.d.ts.map +1 -1
  357. package/dist/server/api/routes/user.js +14 -3
  358. package/dist/services/asset-service.d.ts +1 -0
  359. package/dist/services/asset-service.d.ts.map +1 -1
  360. package/dist/services/index.d.ts +2 -0
  361. package/dist/services/index.d.ts.map +1 -1
  362. package/dist/services/index.js +1 -0
  363. package/dist/services/plugin-settings-service.d.ts +76 -0
  364. package/dist/services/plugin-settings-service.d.ts.map +1 -0
  365. package/dist/services/plugin-settings-service.js +235 -0
  366. package/dist/services/roles-service.d.ts +2 -2
  367. package/dist/services/roles-service.d.ts.map +1 -1
  368. package/dist/theme/css.d.ts +30 -0
  369. package/dist/theme/css.d.ts.map +1 -0
  370. package/dist/theme/css.js +53 -0
  371. package/dist/theme/derive.d.ts +27 -0
  372. package/dist/theme/derive.d.ts.map +1 -0
  373. package/dist/theme/derive.js +107 -0
  374. package/dist/theme/index.d.ts +5 -0
  375. package/dist/theme/index.d.ts.map +1 -0
  376. package/dist/theme/index.js +4 -0
  377. package/dist/theme/schemes.d.ts +60 -0
  378. package/dist/theme/schemes.d.ts.map +1 -0
  379. package/dist/theme/schemes.js +149 -0
  380. package/dist/theme/tokens.d.ts +57 -0
  381. package/dist/theme/tokens.d.ts.map +1 -0
  382. package/dist/theme/tokens.js +10 -0
  383. package/dist/type-gen.d.ts +19 -0
  384. package/dist/type-gen.d.ts.map +1 -0
  385. package/dist/{cli/generate-types.js → type-gen.js} +101 -68
  386. package/dist/types/auth.d.ts +10 -10
  387. package/dist/types/auth.d.ts.map +1 -1
  388. package/dist/types/capabilities.d.ts +50 -9
  389. package/dist/types/capabilities.d.ts.map +1 -1
  390. package/dist/types/capabilities.js +147 -5
  391. package/dist/types/config.d.ts +30 -1
  392. package/dist/types/config.d.ts.map +1 -1
  393. package/dist/types/schemas.d.ts +90 -2
  394. package/dist/types/schemas.d.ts.map +1 -1
  395. package/dist/types/sidebar.d.ts +3 -1
  396. package/dist/types/sidebar.d.ts.map +1 -1
  397. package/dist/utils/index.d.ts +1 -0
  398. package/dist/utils/index.d.ts.map +1 -1
  399. package/dist/utils/index.js +1 -0
  400. package/dist/utils/preview.d.ts +16 -5
  401. package/dist/utils/preview.d.ts.map +1 -1
  402. package/dist/utils/preview.js +7 -2
  403. package/dist/vite/index.d.ts +7 -0
  404. package/dist/vite/index.d.ts.map +1 -1
  405. package/dist/vite/index.js +37 -6
  406. package/package.json +6 -4
  407. package/dist/cli/generate-types.d.ts.map +0 -1
  408. package/dist/cli/generate-types.js.map +0 -1
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { Alert, AlertDescription, AlertTitle } from '@aphexcms/ui/shadcn/alert';
7
7
  import { Button } from '@aphexcms/ui/shadcn/button';
8
+ import { useSidebar } from '@aphexcms/ui/shadcn/sidebar';
8
9
  import * as Tabs from '@aphexcms/ui/shadcn/tabs';
9
10
  import * as Popover from '@aphexcms/ui/shadcn/popover';
10
11
  import * as Select from '@aphexcms/ui/shadcn/select';
@@ -12,6 +13,14 @@
12
13
  import { goto } from '$app/navigation';
13
14
  import { SvelteURLSearchParams } from 'svelte/reactivity';
14
15
  import type { SchemaType } from '../types/index';
16
+ import type { CMSPlugin, AdminToolProps } from '../plugins/types';
17
+ import { createPartResolver } from '../plugins/resolver';
18
+ import type { AdminArea } from '../admin/types';
19
+ import { setAdminNav } from '../admin/nav.svelte';
20
+ import type { Component } from 'svelte';
21
+ import { setFieldComponents } from '../admin/field-components.svelte';
22
+ import { setBlockPreviews, type BlockPreviewProps } from '../admin/block-previews.svelte';
23
+ import AdminSlot from './admin/AdminSlot.svelte';
15
24
  import type { UserSessionPreferences } from '../types/organization';
16
25
  import { resolvePreviewTitle, resolvePreviewSubtitle } from '../utils/preview';
17
26
  import DocumentEditor from './admin/DocumentEditor.svelte';
@@ -53,13 +62,25 @@
53
62
  capabilities?: string[];
54
63
  /** Effective organization role name, for role-list style checks. */
55
64
  rbacRole?: string | null;
56
- activeTab?: { value: 'structure' | 'vision' | 'media' };
65
+ activeTab?: { value: AdminArea };
57
66
  handleTabChange: (value: string) => void;
58
67
  userPreferences?: UserSessionPreferences | null;
68
+ /**
69
+ * Build-time plugins, imported client-side (component parts can't cross
70
+ * SvelteKit `load`). Their document-action parts render in the editor toolbar.
71
+ */
72
+ plugins?: CMSPlugin[];
73
+ /**
74
+ * Inline editor previews for custom rich-text block types, keyed by `_type`.
75
+ * Without one, a block renders as a generic card (title/subtitle from its
76
+ * `preview` config); with one, the real block renders inline as you write.
77
+ * App-owned on purpose — the app owns presentation.
78
+ */
79
+ blockPreviews?: Record<string, Component<BlockPreviewProps>>;
59
80
  }
60
81
 
61
82
  let {
62
- schemas,
83
+ schemas: appSchemas,
63
84
  documentTypes: documentTypesFromServer,
64
85
  schemaError = null,
65
86
  title = 'Aphex CMS',
@@ -67,11 +88,49 @@
67
88
  isReadOnly = false,
68
89
  capabilities = [],
69
90
  rbacRole = null,
70
- activeTab = { value: 'structure' } as { value: 'structure' | 'vision' | 'media' },
91
+ activeTab = { value: 'structure' } as { value: AdminArea },
71
92
  handleTabChange = () => {},
72
- userPreferences = null
93
+ userPreferences = null,
94
+ plugins = [],
95
+ blockPreviews = {}
73
96
  }: Props = $props();
74
97
 
98
+ // One resolver over the (client-side) plugins, reused for every part kind.
99
+ const partResolver = $derived(createPartResolver(plugins));
100
+
101
+ // Plugin-inclusive schema list: app schemas plus any `aphex/schema` parts, then
102
+ // any `aphex/schema/transform` parts applied — the same pipeline the server engine
103
+ // runs in createCMSConfig, so the editor and the engine agree. The plugins are
104
+ // already client-side here (we hold them for component parts), so the admin
105
+ // resolves this itself — no app wiring. Everything downstream references `schemas`.
106
+ const schemas = $derived(
107
+ partResolver.applySchemaTransforms([...appSchemas, ...partResolver.schemaTypes()])
108
+ );
109
+
110
+ // Publish plugin field-input widgets so SchemaField can swap them in for a
111
+ // field's `input` key (falling back to the built-in renderer).
112
+ setFieldComponents((input) => partResolver.fieldComponent(input)?.component);
113
+ // Inline block previews come from the app (presentation is app-owned).
114
+ setBlockPreviews((type) => blockPreviews[type]);
115
+
116
+ // Plane-split guard: a plugin's `aphex/schema` document types must also reach the
117
+ // server engine (register the plugin in aphex.config). If one is present on the
118
+ // client but absent from the server's document-type list, the editor would render
119
+ // a type the engine can't validate or persist — warn loudly in dev.
120
+ $effect(() => {
121
+ const serverTypes = new Set(documentTypesFromServer.map((t) => t.name));
122
+ for (const s of partResolver.schemaTypes()) {
123
+ if (s.type === 'document' && !serverTypes.has(s.name)) {
124
+ cmsLogger.warn(
125
+ '[plugins]',
126
+ `Schema type "${s.name}" is contributed by a plugin on the client, but the server ` +
127
+ `engine doesn't know it. Register the plugin in aphex.config.ts (plugins: [...]) too, ` +
128
+ `or documents of this type can't be validated or saved.`
129
+ );
130
+ }
131
+ }
132
+ });
133
+
75
134
  // Publish capabilities to every descendant (DocumentEditor, fields, etc)
76
135
  // via Svelte context. Using a getter closure so prop reactivity propagates:
77
136
  // if the parent swaps the capabilities array (e.g. role change mid-session)
@@ -81,9 +140,60 @@
81
140
  () => rbacRole
82
141
  );
83
142
 
143
+ // Plugin admin tools contributed by plugins. Capability-gated (privileged roles
144
+ // bypass). Each becomes a `plugin:<id>` area. `placement` decides where the
145
+ // trigger renders: `'tab'` (default) in the top tab strip, `'sidebar'` in the
146
+ // left sidebar nav — the latter keeps the tab strip short once several plugins
147
+ // are installed.
148
+ const adminTools = $derived(
149
+ partResolver.adminTools({
150
+ capabilities: [...capabilities],
151
+ overrideAccess: rbacRole === 'super_admin' || rbacRole === 'admin'
152
+ })
153
+ );
154
+ // Tab-placed tools render into the top strip here; sidebar-placed tools are
155
+ // rendered by AppSidebar from the plugin list (persistent across admin pages).
156
+ const tabTools = $derived(adminTools.filter((t) => (t.placement ?? 'tab') === 'tab'));
157
+ // Centralized admin URL navigation — intents own which params they set/clear.
158
+ // Published to descendants (editor, plugin tools) so they navigate the same way.
159
+ const nav = setAdminNav();
160
+
161
+ function openAdminTool(id: string) {
162
+ activeTab.value = `plugin:${id}`;
163
+ nav.openArea(`plugin:${id}`);
164
+ }
165
+
84
166
  // Keep a state of the organization id
85
167
  let currentOrgId = $state<string | null>(page.url.searchParams.get('orgId'));
86
168
 
169
+ // Stable context handed to every plugin admin-tool component.
170
+ const adminToolContext = $derived<AdminToolProps>({
171
+ organizationId: currentOrgId,
172
+ capabilities,
173
+ role: rbacRole,
174
+ can: (capability) =>
175
+ rbacRole === 'super_admin' || rbacRole === 'admin' || capabilities.includes(capability),
176
+ schemas,
177
+ navigate: (area) => {
178
+ activeTab.value = area;
179
+ },
180
+ openDocument: (documentType, documentId) => {
181
+ // Guard: without a type the editor can't resolve a schema ("No schema found").
182
+ if (!documentType || !documentId) {
183
+ cmsLogger.warn('[AdminApp]', 'openDocument called without type/id', {
184
+ documentType,
185
+ documentId
186
+ });
187
+ return;
188
+ }
189
+ // The editor lives in the structure area — switch to it first (like
190
+ // navigateToDocumentType does) so opening a doc from a plugin tab actually
191
+ // shows the editor instead of leaving state stranded on the plugin tab.
192
+ if (activeTab.value !== 'structure') handleTabChange('structure');
193
+ navigateToEditDocument(documentId, documentType);
194
+ }
195
+ });
196
+
87
197
  // Merge document types with schema icons (schemas have icons, server data doesn't),
88
198
  // then filter out any schemas the caller can't read. Mirrors the server check:
89
199
  // an `access.read` list on a schema is an allowlist of role names (built-in
@@ -166,21 +276,13 @@
166
276
 
167
277
  function toggleFocusMode() {
168
278
  focusModeOn = !focusModeOn;
169
- const params = new SvelteURLSearchParams(page.url.searchParams);
170
- if (focusModeOn) {
171
- params.set('focus', '1');
172
- } else {
173
- params.delete('focus');
174
- }
175
- goto(`/admin?${params.toString()}`, { replaceState: true });
279
+ nav.patch({ focus: focusModeOn ? '1' : null });
176
280
  }
177
281
 
178
282
  function exitFocusMode() {
179
283
  if (!focusModeOn) return;
180
284
  focusModeOn = false;
181
- const params = new SvelteURLSearchParams(page.url.searchParams);
182
- params.delete('focus');
183
- goto(`/admin?${params.toString()}`, { replaceState: true });
285
+ nav.patch({ focus: null });
184
286
  }
185
287
 
186
288
  // Sync focus state from URL — covers refresh, deep links, back button.
@@ -195,8 +297,14 @@
195
297
  // live preview iframe. Independent from focus mode; Esc also exits.
196
298
  let presentationModeOn = $state(false);
197
299
 
300
+ // Sidebar context (set by the SidebarProvider ancestor). Used to reclaim screen
301
+ // real estate for the preview canvas when presentation mode opens.
302
+ const sidebar = useSidebar();
303
+
198
304
  function togglePresentationMode() {
199
305
  presentationModeOn = !presentationModeOn;
306
+ // Entering presentation mode: collapse the nav rail so the preview gets the room.
307
+ if (presentationModeOn) sidebar?.setOpen(false);
200
308
  }
201
309
 
202
310
  function exitPresentationMode() {
@@ -295,6 +403,18 @@
295
403
  }
296
404
  let editorStack = $state<EditorStackItem[]>([]);
297
405
 
406
+ // Bumped to ask the base (primary) editor's preview to re-fetch — e.g. after a
407
+ // referenced doc autosaves, so the base preview reflects the change.
408
+ let baseRefreshToken = $state(0);
409
+
410
+ // Human label for a document type: the schema's `title` (e.g. "Blog Post"),
411
+ // falling back to a prettified name so `blog_post` never surfaces as "Blog_post".
412
+ function typeLabel(name: string | null | undefined): string {
413
+ if (!name) return '';
414
+ const title = schemas.find((s) => s.name === name)?.title;
415
+ return title ?? name.charAt(0).toUpperCase() + name.slice(1).replace(/_/g, ' ');
416
+ }
417
+
298
418
  // Track which editor is currently active/focused (0 = primary, 1+ = stacked)
299
419
  let activeEditorIndex = $state<number>(0);
300
420
 
@@ -627,35 +747,17 @@
627
747
  // at least sees an error surface rather than a stuck sidebar click.
628
748
  }
629
749
 
630
- const params = new SvelteURLSearchParams(page.url.searchParams);
631
- params.set('docType', docType);
632
- params.delete('docId');
633
- params.delete('action');
634
- params.delete('stack');
635
- params.delete('history');
636
- await goto(`/admin?${params.toString()}`, { replaceState: false });
750
+ await nav.openType(docType);
637
751
  mobileView = 'documents';
638
752
  }
639
753
 
640
754
  async function navigateToCreateDocument(docType: string) {
641
- const params = new SvelteURLSearchParams(page.url.searchParams);
642
- params.set('docType', docType);
643
- params.set('action', 'create');
644
- params.delete('docId');
645
- params.delete('stack');
646
- params.delete('history');
647
- await goto(`/admin?${params.toString()}`, { replaceState: false });
755
+ await nav.createDocument(docType);
648
756
  mobileView = 'editor';
649
757
  }
650
758
 
651
759
  async function navigateToEditDocument(docId: string, docType?: string, replace: boolean = false) {
652
- const params = new SvelteURLSearchParams(page.url.searchParams);
653
- params.set('docId', docId);
654
- if (docType) params.set('docType', docType);
655
- params.delete('action');
656
- params.delete('fromDocId');
657
- params.delete('fromDocType');
658
- await goto(`/admin?${params.toString()}`, { replaceState: replace });
760
+ await nav.openDocument(docId, docType, { replace });
659
761
  mobileView = 'editor';
660
762
  }
661
763
 
@@ -673,26 +775,12 @@
673
775
  // Navigate back to the document we came from
674
776
  await navigateToEditDocument(fromDocId, fromDocType, false);
675
777
  } else if (selectedDocumentType && !currentTypeIsSingleton) {
676
- // Navigate back to document list
677
- const params = new SvelteURLSearchParams(page.url.searchParams);
678
- params.set('docType', selectedDocumentType);
679
- params.delete('docId');
680
- params.delete('action');
681
- params.delete('stack');
682
- params.delete('focus');
683
- params.delete('history');
684
- await goto(`/admin?${params.toString()}`, { replaceState: false });
778
+ // Back to the document list for the current type
779
+ await nav.closeToType(selectedDocumentType);
685
780
  mobileView = 'documents';
686
781
  } else {
687
- // Navigate back to home
688
- const params = new SvelteURLSearchParams(page.url.searchParams);
689
- params.delete('docType');
690
- params.delete('docId');
691
- params.delete('action');
692
- params.delete('stack');
693
- params.delete('focus');
694
- params.delete('history');
695
- await goto(`/admin?${params.toString()}`, { replaceState: false });
782
+ // Back to the dashboard
783
+ await nav.goHome();
696
784
  mobileView = 'types';
697
785
  }
698
786
  }
@@ -700,18 +788,14 @@
700
788
  function handleOpenVersionHistory(docId: string) {
701
789
  showVersionPanel = true;
702
790
  versionPanelDocId = docId;
703
- const params = new SvelteURLSearchParams(page.url.searchParams);
704
- params.set('history', '1');
705
- goto(`/admin?${params.toString()}`, { replaceState: true });
791
+ nav.patch({ history: '1' });
706
792
  }
707
793
 
708
794
  function handleCloseVersionPanel() {
709
795
  showVersionPanel = false;
710
796
  versionPanelDocId = null;
711
797
  versionPreviewData = null;
712
- const params = new SvelteURLSearchParams(page.url.searchParams);
713
- params.delete('history');
714
- goto(`/admin?${params.toString()}`, { replaceState: true });
798
+ nav.patch({ history: null });
715
799
  }
716
800
 
717
801
  // Close version panel when navigating away
@@ -827,6 +911,11 @@
827
911
  if (showVersionPanel && versionPanelDocId === documentId) {
828
912
  versionPanelRef?.refresh();
829
913
  }
914
+ // A referenced doc (open in the reference panel) autosaved — nudge the base
915
+ // preview to re-fetch, so its server-loaded view (e.g. a list that includes
916
+ // this doc) reflects the edit. Not fired for the base doc itself, which already
917
+ // live-updates via the data push.
918
+ if (editorStack.some((e) => e.documentId === documentId)) baseRefreshToken++;
830
919
  }
831
920
 
832
921
  function handleDocumentPublished(documentId: string) {
@@ -863,6 +952,10 @@
863
952
  }
864
953
 
865
954
  async function fetchDocuments(docType: string) {
955
+ // No type = nothing to list (e.g. mid-navigation from a plugin tab before a
956
+ // type is selected). Bail quietly rather than hitting the API and toasting
957
+ // "Document type is required".
958
+ if (!docType) return;
866
959
  cmsLogger.debug('[AdminApp]', 'FETCHING DOCUMENTS', { sort: sortString });
867
960
  loading = true;
868
961
  error = null;
@@ -926,6 +1019,34 @@
926
1019
  }
927
1020
  </script>
928
1021
 
1022
+ <!-- Plugin admin-tool tabs (placement: 'tab') — registered into the Sidebar's tab strip. -->
1023
+ {#if tabTools.length > 0}
1024
+ <AdminSlot name="admin-tabs" id="plugin-admin-tools">
1025
+ {#each tabTools as tool (tool.id)}
1026
+ <button
1027
+ onclick={() => openAdminTool(tool.id)}
1028
+ class="{activeTab.value === `plugin:${tool.id}`
1029
+ ? 'bg-background text-foreground shadow'
1030
+ : 'text-muted-foreground'} ring-offset-background focus-visible:ring-ring inline-flex cursor-pointer items-center justify-center gap-1.5 rounded-md px-3 py-1 text-sm font-medium whitespace-nowrap transition-all focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none"
1031
+ >
1032
+ {#if tool.icon}
1033
+ {@const Icon = tool.icon}
1034
+ <Icon class="h-4 w-4" />
1035
+ {/if}
1036
+ {tool.title}
1037
+ </button>
1038
+ {/each}
1039
+ </AdminSlot>
1040
+ {/if}
1041
+
1042
+ <!--
1043
+ Sidebar-placed plugin tools (placement: 'sidebar') are rendered by AppSidebar
1044
+ directly from the plugin list, at the persistent layout level — not here — so
1045
+ the Tools nav survives on every admin page (settings included), where AdminApp
1046
+ isn't mounted. AdminApp still owns the tab-placed tools (above) and renders each
1047
+ tool's `plugin:<id>` content area (below).
1048
+ -->
1049
+
929
1050
  <svelte:head>
930
1051
  <title
931
1052
  >{activeTab.value === 'structure'
@@ -938,7 +1059,7 @@
938
1059
 
939
1060
  <div class="flex h-full flex-col overflow-hidden">
940
1061
  <!-- Breadcrumb navigation: mobile (< 620px) or focus mode on any width -->
941
- {#if (windowWidth < 620 || focusModeOn || presentationModeOn) && activeTab.value === 'structure'}
1062
+ {#if (windowWidth < 620 || focusModeOn) && activeTab.value === 'structure'}
942
1063
  <div class="border-border bg-background border-b">
943
1064
  <div class="flex h-12 items-center px-4">
944
1065
  {#if mobileView === 'documents' && selectedDocumentType}
@@ -1482,7 +1603,7 @@
1482
1603
  <!-- Primary Editor Panel -->
1483
1604
  {#if primaryEditorState.visible}
1484
1605
  <div
1485
- class="transition-all duration-200 {windowWidth < 620
1606
+ class="relative transition-all duration-200 {windowWidth < 620
1486
1607
  ? 'w-screen'
1487
1608
  : 'flex-1'} h-full overflow-x-hidden overflow-y-auto {primaryEditorState.expanded
1488
1609
  ? ''
@@ -1491,6 +1612,7 @@
1491
1612
  >
1492
1613
  <DocumentEditor
1493
1614
  {schemas}
1615
+ {plugins}
1494
1616
  documentType={selectedDocumentType!}
1495
1617
  documentId={editingDocumentId}
1496
1618
  isCreating={isCreatingDocument}
@@ -1498,6 +1620,7 @@
1498
1620
  onToggleFocus={toggleFocusMode}
1499
1621
  presentationMode={presentationModeOn}
1500
1622
  onTogglePresentation={togglePresentationMode}
1623
+ refreshToken={baseRefreshToken}
1501
1624
  organizationId={currentOrgId}
1502
1625
  onBack={navigateBack}
1503
1626
  onOpenReference={handleOpenReference}
@@ -1571,32 +1694,44 @@
1571
1694
  }}
1572
1695
  {isReadOnly}
1573
1696
  />
1697
+
1698
+ <!-- Presentation-mode reference: a left-anchored panel over the fields
1699
+ column only (no dimming backdrop), so the base editor's live
1700
+ preview stays fully visible and interactive on the right. Close
1701
+ with the panel's Back button. -->
1702
+ {#if presentationModeOn && editorStack.length > 0}
1703
+ {@const currentRef = editorStack[editorStack.length - 1]!}
1704
+ <div
1705
+ class="border-rule bg-background absolute inset-y-0 left-0 z-40 flex w-full max-w-[520px] flex-col border-r shadow-2xl"
1706
+ >
1707
+ {@render referenceEditorBody(currentRef)}
1708
+ </div>
1709
+ {/if}
1574
1710
  </div>
1575
1711
  {#if !primaryEditorState.expanded && !focusModeOn && !presentationModeOn}
1576
1712
  <!-- Collapsed Primary Editor Strip -->
1577
1713
  <button
1578
1714
  onclick={() => setActiveEditor(0)}
1579
1715
  class="border-rule hover:bg-muted/50 flex h-full w-[60px] cursor-pointer flex-col border-l transition-colors"
1580
- title="Click to expand {selectedDocumentType}"
1716
+ title="Click to expand {typeLabel(selectedDocumentType)}"
1581
1717
  >
1582
1718
  <div class="flex flex-1 items-start justify-center p-2 pt-8 text-left">
1583
1719
  <div
1584
1720
  class="text-foreground -mt-2 text-sm font-medium whitespace-nowrap [writing-mode:vertical-rl]"
1585
1721
  >
1586
- {selectedDocumentType
1587
- ? selectedDocumentType.charAt(0).toUpperCase() +
1588
- selectedDocumentType.slice(1)
1589
- : ''}
1722
+ {typeLabel(selectedDocumentType)}
1590
1723
  </div>
1591
1724
  </div>
1592
1725
  </button>
1593
1726
  {/if}
1594
1727
  {/if}
1595
1728
 
1596
- <!-- Stacked Reference Panel — only the last entry in the stack
1597
- is rendered. Back button pops the stack (walks back through
1598
- the ref chain); closing entirely on the last pop. -->
1599
- {#if editorStack.length > 0}
1729
+ <!-- Stacked Reference Panel — only the last entry in the stack is
1730
+ rendered. In presentation mode it opens as a modal over the
1731
+ current editor (so you stay anchored to the document + preview
1732
+ you were editing); otherwise it's a side panel. Back pops the
1733
+ stack (walks the ref chain); closing clears it. -->
1734
+ {#if editorStack.length > 0 && !presentationModeOn}
1600
1735
  {@const currentRef = editorStack[editorStack.length - 1]!}
1601
1736
  {@const isExpanded = focusModeOn
1602
1737
  ? activeEditorIndex === 1
@@ -1607,60 +1742,20 @@
1607
1742
  class="border-rule h-full flex-1 overflow-x-hidden overflow-y-auto border-l transition-all duration-200"
1608
1743
  style="min-width: 0;"
1609
1744
  >
1610
- <DocumentEditor
1611
- {schemas}
1612
- documentType={currentRef.documentType}
1613
- documentId={currentRef.documentId}
1614
- isCreating={currentRef.isCreating}
1615
- onBack={handleStackedEditorBack}
1616
- onOpenReference={handleOpenReference}
1617
- onOpenVersionHistory={handleOpenVersionHistory}
1618
- onToggleFocus={() => {
1619
- activeEditorIndex = 1;
1620
- toggleFocusMode();
1621
- }}
1622
- externalVersionPreview={versionPanelDocId === currentRef.documentId
1623
- ? versionPreviewData
1624
- : null}
1625
- onSaved={async () => {}}
1626
- onAutoSaved={handleAutoSave}
1627
- onPublished={async (docId) => {
1628
- handleDocumentPublished(docId);
1629
- if (selectedDocumentType) {
1630
- await fetchDocuments(selectedDocumentType);
1631
- }
1632
- }}
1633
- onUnpublished={async (docId) => {
1634
- handleDocumentPublished(docId);
1635
- if (selectedDocumentType) {
1636
- await fetchDocuments(selectedDocumentType);
1637
- }
1638
- }}
1639
- onRestored={async (docId) => {
1640
- handleDocumentPublished(docId);
1641
- if (selectedDocumentType) {
1642
- await fetchDocuments(selectedDocumentType);
1643
- }
1644
- }}
1645
- onDeleted={async () => {
1646
- handleCloseStackedEditor(0);
1647
- }}
1648
- {isReadOnly}
1649
- />
1745
+ {@render referenceEditorBody(currentRef)}
1650
1746
  </div>
1651
1747
  {:else if !focusModeOn}
1652
1748
  <!-- Collapsed Stacked Editor Strip -->
1653
1749
  <button
1654
1750
  onclick={() => setActiveEditor(1)}
1655
1751
  class="border-rule hover:bg-muted/50 flex h-full w-[60px] cursor-pointer flex-col border-l transition-colors"
1656
- title="Click to expand {currentRef.documentType}"
1752
+ title="Click to expand {typeLabel(currentRef.documentType)}"
1657
1753
  >
1658
1754
  <div class="flex h-full flex-1 items-start justify-center p-2 pt-8 text-left">
1659
1755
  <div
1660
1756
  class="text-foreground text-sm font-medium whitespace-nowrap [writing-mode:vertical-rl]"
1661
1757
  >
1662
- {currentRef.documentType.charAt(0).toUpperCase() +
1663
- currentRef.documentType.slice(1)}
1758
+ {typeLabel(currentRef.documentType)}
1664
1759
  </div>
1665
1760
  </div>
1666
1761
  </button>
@@ -1745,8 +1840,59 @@
1745
1840
  <Tabs.Content value="media" class="m-0 h-full p-0">
1746
1841
  <MediaBrowser active={activeTab.value === 'media'} />
1747
1842
  </Tabs.Content>
1843
+
1844
+ <!-- Plugin admin tools — each rendered as its own top-level area. -->
1845
+ {#each adminTools as tool (tool.id)}
1846
+ {@const Tool = tool.component}
1847
+ <Tabs.Content value={`plugin:${tool.id}`} class="m-0 h-full overflow-auto p-0">
1848
+ <Tool tool={adminToolContext} />
1849
+ </Tabs.Content>
1850
+ {/each}
1748
1851
  </Tabs.Root>
1749
1852
  </div>
1750
1853
  </div>
1751
1854
 
1752
1855
  <ConfirmDialogHost />
1856
+
1857
+ <!-- Shared body for a stacked reference editor — always form-only (no nested preview
1858
+ iframe). In presentation mode it renders inside a modal over the base editor, whose
1859
+ live preview stays visible behind it; otherwise it's the side panel. -->
1860
+ {#snippet referenceEditorBody(currentRef: EditorStackItem)}
1861
+ <DocumentEditor
1862
+ {schemas}
1863
+ {plugins}
1864
+ documentType={currentRef.documentType}
1865
+ documentId={currentRef.documentId}
1866
+ isCreating={currentRef.isCreating}
1867
+ organizationId={currentOrgId}
1868
+ onBack={handleStackedEditorBack}
1869
+ backLabel="Back"
1870
+ onOpenReference={handleOpenReference}
1871
+ onOpenVersionHistory={handleOpenVersionHistory}
1872
+ externalVersionPreview={versionPanelDocId === currentRef.documentId ? versionPreviewData : null}
1873
+ onSaved={async () => {}}
1874
+ onAutoSaved={handleAutoSave}
1875
+ onPublished={async (docId) => {
1876
+ handleDocumentPublished(docId);
1877
+ if (selectedDocumentType) {
1878
+ await fetchDocuments(selectedDocumentType);
1879
+ }
1880
+ }}
1881
+ onUnpublished={async (docId) => {
1882
+ handleDocumentPublished(docId);
1883
+ if (selectedDocumentType) {
1884
+ await fetchDocuments(selectedDocumentType);
1885
+ }
1886
+ }}
1887
+ onRestored={async (docId) => {
1888
+ handleDocumentPublished(docId);
1889
+ if (selectedDocumentType) {
1890
+ await fetchDocuments(selectedDocumentType);
1891
+ }
1892
+ }}
1893
+ onDeleted={async () => {
1894
+ handleCloseStackedEditor(0);
1895
+ }}
1896
+ {isReadOnly}
1897
+ />
1898
+ {/snippet}
@@ -1,4 +1,8 @@
1
1
  import type { SchemaType } from '../types/index.js';
2
+ import type { CMSPlugin } from '../plugins/types.js';
3
+ import type { AdminArea } from '../admin/types.js';
4
+ import type { Component } from 'svelte';
5
+ import { type BlockPreviewProps } from '../admin/block-previews.svelte.js';
2
6
  import type { UserSessionPreferences } from '../types/organization.js';
3
7
  interface Props {
4
8
  schemas: SchemaType[];
@@ -25,12 +29,24 @@ interface Props {
25
29
  /** Effective organization role name, for role-list style checks. */
26
30
  rbacRole?: string | null;
27
31
  activeTab?: {
28
- value: 'structure' | 'vision' | 'media';
32
+ value: AdminArea;
29
33
  };
30
34
  handleTabChange: (value: string) => void;
31
35
  userPreferences?: UserSessionPreferences | null;
36
+ /**
37
+ * Build-time plugins, imported client-side (component parts can't cross
38
+ * SvelteKit `load`). Their document-action parts render in the editor toolbar.
39
+ */
40
+ plugins?: CMSPlugin[];
41
+ /**
42
+ * Inline editor previews for custom rich-text block types, keyed by `_type`.
43
+ * Without one, a block renders as a generic card (title/subtitle from its
44
+ * `preview` config); with one, the real block renders inline as you write.
45
+ * App-owned on purpose — the app owns presentation.
46
+ */
47
+ blockPreviews?: Record<string, Component<BlockPreviewProps>>;
32
48
  }
33
- declare const AdminApp: import("svelte").Component<Props, {}, "">;
49
+ declare const AdminApp: Component<Props, {}, "">;
34
50
  type AdminApp = ReturnType<typeof AdminApp>;
35
51
  export default AdminApp;
36
52
  //# sourceMappingURL=AdminApp.svelte.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AdminApp.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/AdminApp.svelte.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AA2BnE,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAA;KAAE,CAAC;IACxD,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAChD;AAw+CF,QAAA,MAAM,QAAQ,2CAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"AdminApp.svelte.d.ts","sourceRoot":"","sources":["../../src/lib/components/AdminApp.svelte.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAkB,MAAM,kBAAkB,CAAC;AAElE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,OAAO,EAAoB,KAAK,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAE1F,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AA2BnE,UAAU,KAAK;IACd,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,aAAa,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5E,WAAW,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IACvE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,SAAS,CAAA;KAAE,CAAC;IACjC,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAChD;;;OAGG;IACH,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;IACtB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC;CAC7D;AAwlDF,QAAA,MAAM,QAAQ,0BAAwC,CAAC;AACvD,KAAK,QAAQ,GAAG,UAAU,CAAC,OAAO,QAAQ,CAAC,CAAC;AAC5C,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,18 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+ import { useAdminSlots, type AdminSlotName } from '../../admin/slots.svelte';
4
+
5
+ type Props = {
6
+ name: AdminSlotName;
7
+ id: string;
8
+ order?: number;
9
+ children: Snippet;
10
+ };
11
+
12
+ let { name, id, order = 0, children }: Props = $props();
13
+ const slots = useAdminSlots();
14
+
15
+ $effect(() => {
16
+ return slots?.register(name, { id, order, snippet: children });
17
+ });
18
+ </script>
@@ -0,0 +1,12 @@
1
+ import type { Snippet } from 'svelte';
2
+ import { type AdminSlotName } from '../../admin/slots.svelte.js';
3
+ type Props = {
4
+ name: AdminSlotName;
5
+ id: string;
6
+ order?: number;
7
+ children: Snippet;
8
+ };
9
+ declare const AdminSlot: import("svelte").Component<Props, {}, "">;
10
+ type AdminSlot = ReturnType<typeof AdminSlot>;
11
+ export default AdminSlot;
12
+ //# sourceMappingURL=AdminSlot.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdminSlot.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/admin/AdminSlot.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAiB,KAAK,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAG5E,KAAK,KAAK,GAAG;IACZ,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CAClB,CAAC;AAgBH,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}