@aphexcms/cms-core 2.0.9 → 2.0.11

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 (381) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api/api-keys.d.ts +8 -7
  3. package/dist/api/api-keys.d.ts.map +1 -1
  4. package/dist/api/assets.d.ts +7 -22
  5. package/dist/api/assets.d.ts.map +1 -1
  6. package/dist/api/assets.js +1 -10
  7. package/dist/api/documents.d.ts +17 -16
  8. package/dist/api/documents.d.ts.map +1 -1
  9. package/dist/api/documents.js +2 -2
  10. package/dist/api/index.d.ts +1 -0
  11. package/dist/api/index.d.ts.map +1 -1
  12. package/dist/api/index.js +1 -0
  13. package/dist/api/organizations.d.ts +15 -35
  14. package/dist/api/organizations.d.ts.map +1 -1
  15. package/dist/api/roles.d.ts +22 -0
  16. package/dist/api/roles.d.ts.map +1 -0
  17. package/dist/api/roles.js +26 -0
  18. package/dist/api/schemas/api-keys.d.ts +62 -0
  19. package/dist/api/schemas/api-keys.d.ts.map +1 -0
  20. package/dist/api/schemas/api-keys.js +28 -0
  21. package/dist/api/schemas/assets.d.ts +174 -0
  22. package/dist/api/schemas/assets.d.ts.map +1 -0
  23. package/dist/api/schemas/assets.js +99 -0
  24. package/dist/api/schemas/documents.d.ts +325 -0
  25. package/dist/api/schemas/documents.d.ts.map +1 -0
  26. package/dist/api/schemas/documents.js +161 -0
  27. package/dist/api/schemas/organizations.d.ts +41 -0
  28. package/dist/api/schemas/organizations.d.ts.map +1 -0
  29. package/dist/api/schemas/organizations.js +56 -0
  30. package/dist/api/schemas/roles.d.ts +77 -0
  31. package/dist/api/schemas/roles.d.ts.map +1 -0
  32. package/dist/api/schemas/roles.js +42 -0
  33. package/dist/api/schemas/user.d.ts +10 -0
  34. package/dist/api/schemas/user.d.ts.map +1 -0
  35. package/dist/api/schemas/user.js +11 -0
  36. package/dist/api/user.d.ts +4 -6
  37. package/dist/api/user.d.ts.map +1 -1
  38. package/dist/app-augment.d.ts +32 -0
  39. package/dist/app-augment.d.ts.map +1 -0
  40. package/dist/app-augment.js +18 -0
  41. package/dist/auth/auth-hooks.d.ts +2 -1
  42. package/dist/auth/auth-hooks.d.ts.map +1 -1
  43. package/dist/auth/auth-hooks.js +22 -2
  44. package/dist/auth/provider.d.ts +5 -0
  45. package/dist/auth/provider.d.ts.map +1 -1
  46. package/dist/cli/index.js +0 -0
  47. package/dist/client/index.d.ts +4 -0
  48. package/dist/client/index.d.ts.map +1 -1
  49. package/dist/client/index.js +7 -0
  50. package/dist/components/AdminApp.svelte +306 -142
  51. package/dist/components/AdminApp.svelte.d.ts +8 -0
  52. package/dist/components/AdminApp.svelte.d.ts.map +1 -1
  53. package/dist/components/admin/DocumentEditor.svelte +653 -365
  54. package/dist/components/admin/DocumentEditor.svelte.d.ts +2 -0
  55. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -1
  56. package/dist/components/admin/DocumentVersionPanel.svelte +57 -44
  57. package/dist/components/admin/DocumentVersionPanel.svelte.d.ts.map +1 -1
  58. package/dist/components/admin/MediaBrowser.svelte +70 -30
  59. package/dist/components/admin/MediaBrowser.svelte.d.ts.map +1 -1
  60. package/dist/components/admin/ObjectModal.svelte +70 -95
  61. package/dist/components/admin/ObjectModal.svelte.d.ts +1 -2
  62. package/dist/components/admin/ObjectModal.svelte.d.ts.map +1 -1
  63. package/dist/components/admin/PermissionsDebug.svelte +119 -0
  64. package/dist/components/admin/PermissionsDebug.svelte.d.ts +4 -0
  65. package/dist/components/admin/PermissionsDebug.svelte.d.ts.map +1 -0
  66. package/dist/components/admin/SchemaField.svelte +3 -1
  67. package/dist/components/admin/SchemaField.svelte.d.ts.map +1 -1
  68. package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte +35 -0
  69. package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte.d.ts +19 -0
  70. package/dist/components/admin/confirm-dialog/ConfirmDialogHost.svelte.d.ts.map +1 -0
  71. package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts +16 -0
  72. package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts.map +1 -0
  73. package/dist/components/admin/confirm-dialog/confirm-dialog.svelte.js +29 -0
  74. package/dist/components/admin/fields/ArrayField.svelte +104 -108
  75. package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -1
  76. package/dist/components/admin/fields/FileField.svelte +22 -17
  77. package/dist/components/admin/fields/FileField.svelte.d.ts.map +1 -1
  78. package/dist/components/admin/fields/ImageField.svelte +21 -15
  79. package/dist/components/admin/fields/ImageField.svelte.d.ts.map +1 -1
  80. package/dist/components/admin/fields/ReferenceField.svelte +142 -112
  81. package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -1
  82. package/dist/components/admin/fields/TextareaField.svelte +4 -3
  83. package/dist/components/admin/fields/TextareaField.svelte.d.ts +2 -2
  84. package/dist/components/admin/fields/TextareaField.svelte.d.ts.map +1 -1
  85. package/dist/components/layout/Sidebar.svelte +21 -11
  86. package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -1
  87. package/dist/components/layout/sidebar/NavMain.svelte +1 -0
  88. package/dist/db/interfaces/document.d.ts.map +1 -1
  89. package/dist/db/interfaces/index.d.ts +3 -1
  90. package/dist/db/interfaces/index.d.ts.map +1 -1
  91. package/dist/db/interfaces/organization.d.ts +1 -1
  92. package/dist/db/interfaces/organization.d.ts.map +1 -1
  93. package/dist/db/interfaces/role.d.ts +25 -0
  94. package/dist/db/interfaces/role.d.ts.map +1 -0
  95. package/dist/db/interfaces/role.js +1 -0
  96. package/dist/engine.d.ts.map +1 -1
  97. package/dist/engine.js +5 -0
  98. package/dist/field-access.d.ts +30 -0
  99. package/dist/field-access.d.ts.map +1 -0
  100. package/dist/field-access.js +79 -0
  101. package/dist/hooks.d.ts +2 -0
  102. package/dist/hooks.d.ts.map +1 -1
  103. package/dist/hooks.js +23 -13
  104. package/dist/lib/api/api-keys.d.ts +8 -7
  105. package/dist/lib/api/api-keys.d.ts.map +1 -1
  106. package/dist/lib/api/api-keys.js.map +1 -1
  107. package/dist/lib/api/assets.d.ts +7 -22
  108. package/dist/lib/api/assets.d.ts.map +1 -1
  109. package/dist/lib/api/assets.js +1 -10
  110. package/dist/lib/api/assets.js.map +1 -1
  111. package/dist/lib/api/documents.d.ts +17 -16
  112. package/dist/lib/api/documents.d.ts.map +1 -1
  113. package/dist/lib/api/documents.js +2 -2
  114. package/dist/lib/api/documents.js.map +1 -1
  115. package/dist/lib/api/index.d.ts +1 -0
  116. package/dist/lib/api/index.d.ts.map +1 -1
  117. package/dist/lib/api/index.js +1 -0
  118. package/dist/lib/api/index.js.map +1 -1
  119. package/dist/lib/api/organizations.d.ts +15 -35
  120. package/dist/lib/api/organizations.d.ts.map +1 -1
  121. package/dist/lib/api/organizations.js.map +1 -1
  122. package/dist/lib/api/roles.d.ts +22 -0
  123. package/dist/lib/api/roles.d.ts.map +1 -0
  124. package/dist/lib/api/roles.js +27 -0
  125. package/dist/lib/api/roles.js.map +1 -0
  126. package/dist/lib/api/schemas/api-keys.d.ts +62 -0
  127. package/dist/lib/api/schemas/api-keys.d.ts.map +1 -0
  128. package/dist/lib/api/schemas/api-keys.js +29 -0
  129. package/dist/lib/api/schemas/api-keys.js.map +1 -0
  130. package/dist/lib/api/schemas/assets.d.ts +174 -0
  131. package/dist/lib/api/schemas/assets.d.ts.map +1 -0
  132. package/dist/lib/api/schemas/assets.js +100 -0
  133. package/dist/lib/api/schemas/assets.js.map +1 -0
  134. package/dist/lib/api/schemas/documents.d.ts +325 -0
  135. package/dist/lib/api/schemas/documents.d.ts.map +1 -0
  136. package/dist/lib/api/schemas/documents.js +162 -0
  137. package/dist/lib/api/schemas/documents.js.map +1 -0
  138. package/dist/lib/api/schemas/organizations.d.ts +41 -0
  139. package/dist/lib/api/schemas/organizations.d.ts.map +1 -0
  140. package/dist/lib/api/schemas/organizations.js +57 -0
  141. package/dist/lib/api/schemas/organizations.js.map +1 -0
  142. package/dist/lib/api/schemas/roles.d.ts +77 -0
  143. package/dist/lib/api/schemas/roles.d.ts.map +1 -0
  144. package/dist/lib/api/schemas/roles.js +43 -0
  145. package/dist/lib/api/schemas/roles.js.map +1 -0
  146. package/dist/lib/api/schemas/user.d.ts +10 -0
  147. package/dist/lib/api/schemas/user.d.ts.map +1 -0
  148. package/dist/lib/api/schemas/user.js +12 -0
  149. package/dist/lib/api/schemas/user.js.map +1 -0
  150. package/dist/lib/api/user.d.ts +4 -6
  151. package/dist/lib/api/user.d.ts.map +1 -1
  152. package/dist/lib/api/user.js.map +1 -1
  153. package/dist/lib/app-augment.d.ts +32 -0
  154. package/dist/lib/app-augment.d.ts.map +1 -0
  155. package/dist/lib/app-augment.js +19 -0
  156. package/dist/lib/app-augment.js.map +1 -0
  157. package/dist/lib/auth/auth-hooks.d.ts +2 -1
  158. package/dist/lib/auth/auth-hooks.d.ts.map +1 -1
  159. package/dist/lib/auth/auth-hooks.js +22 -2
  160. package/dist/lib/auth/auth-hooks.js.map +1 -1
  161. package/dist/lib/auth/provider.d.ts +5 -0
  162. package/dist/lib/auth/provider.d.ts.map +1 -1
  163. package/dist/lib/client/index.d.ts +4 -0
  164. package/dist/lib/client/index.d.ts.map +1 -1
  165. package/dist/lib/client/index.js +7 -0
  166. package/dist/lib/client/index.js.map +1 -1
  167. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts +16 -0
  168. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.d.ts.map +1 -0
  169. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.js +30 -0
  170. package/dist/lib/components/admin/confirm-dialog/confirm-dialog.svelte.js.map +1 -0
  171. package/dist/lib/db/interfaces/document.d.ts.map +1 -1
  172. package/dist/lib/db/interfaces/index.d.ts +3 -1
  173. package/dist/lib/db/interfaces/index.d.ts.map +1 -1
  174. package/dist/lib/db/interfaces/organization.d.ts +1 -1
  175. package/dist/lib/db/interfaces/organization.d.ts.map +1 -1
  176. package/dist/lib/db/interfaces/role.d.ts +25 -0
  177. package/dist/lib/db/interfaces/role.d.ts.map +1 -0
  178. package/dist/lib/db/interfaces/role.js +2 -0
  179. package/dist/lib/db/interfaces/role.js.map +1 -0
  180. package/dist/lib/engine.d.ts.map +1 -1
  181. package/dist/lib/engine.js +5 -0
  182. package/dist/lib/engine.js.map +1 -1
  183. package/dist/lib/field-access.d.ts +30 -0
  184. package/dist/lib/field-access.d.ts.map +1 -0
  185. package/dist/lib/field-access.js +80 -0
  186. package/dist/lib/field-access.js.map +1 -0
  187. package/dist/lib/hooks.d.ts +2 -0
  188. package/dist/lib/hooks.d.ts.map +1 -1
  189. package/dist/lib/hooks.js +23 -13
  190. package/dist/lib/hooks.js.map +1 -1
  191. package/dist/lib/local-api/collection-api.d.ts +2 -0
  192. package/dist/lib/local-api/collection-api.d.ts.map +1 -1
  193. package/dist/lib/local-api/collection-api.js +98 -30
  194. package/dist/lib/local-api/collection-api.js.map +1 -1
  195. package/dist/lib/local-api/index.d.ts.map +1 -1
  196. package/dist/lib/local-api/index.js.map +1 -1
  197. package/dist/lib/local-api/permissions.d.ts +26 -26
  198. package/dist/lib/local-api/permissions.d.ts.map +1 -1
  199. package/dist/lib/local-api/permissions.js +122 -80
  200. package/dist/lib/local-api/permissions.js.map +1 -1
  201. package/dist/lib/permissions-context.svelte.d.ts +44 -0
  202. package/dist/lib/permissions-context.svelte.d.ts.map +1 -0
  203. package/dist/lib/permissions-context.svelte.js +80 -0
  204. package/dist/lib/permissions-context.svelte.js.map +1 -0
  205. package/dist/lib/routes/assets-bulk.d.ts.map +1 -1
  206. package/dist/lib/routes/assets-bulk.js +10 -3
  207. package/dist/lib/routes/assets-bulk.js.map +1 -1
  208. package/dist/lib/routes/assets-by-id.d.ts.map +1 -1
  209. package/dist/lib/routes/assets-by-id.js +11 -1
  210. package/dist/lib/routes/assets-by-id.js.map +1 -1
  211. package/dist/lib/routes/assets-references-counts.d.ts.map +1 -1
  212. package/dist/lib/routes/assets-references-counts.js +12 -2
  213. package/dist/lib/routes/assets-references-counts.js.map +1 -1
  214. package/dist/lib/routes/assets.d.ts.map +1 -1
  215. package/dist/lib/routes/assets.js +14 -13
  216. package/dist/lib/routes/assets.js.map +1 -1
  217. package/dist/lib/routes/document-versions.d.ts.map +1 -1
  218. package/dist/lib/routes/document-versions.js +16 -2
  219. package/dist/lib/routes/document-versions.js.map +1 -1
  220. package/dist/lib/routes/documents-by-id.d.ts.map +1 -1
  221. package/dist/lib/routes/documents-by-id.js +15 -3
  222. package/dist/lib/routes/documents-by-id.js.map +1 -1
  223. package/dist/lib/routes/documents-query.d.ts.map +1 -1
  224. package/dist/lib/routes/documents-query.js +13 -10
  225. package/dist/lib/routes/documents-query.js.map +1 -1
  226. package/dist/lib/routes/documents.d.ts.map +1 -1
  227. package/dist/lib/routes/documents.js +29 -26
  228. package/dist/lib/routes/documents.js.map +1 -1
  229. package/dist/lib/routes/organizations-by-id.d.ts.map +1 -1
  230. package/dist/lib/routes/organizations-by-id.js +17 -4
  231. package/dist/lib/routes/organizations-by-id.js.map +1 -1
  232. package/dist/lib/routes/organizations-invitations.d.ts.map +1 -1
  233. package/dist/lib/routes/organizations-invitations.js +48 -18
  234. package/dist/lib/routes/organizations-invitations.js.map +1 -1
  235. package/dist/lib/routes/organizations-members.d.ts.map +1 -1
  236. package/dist/lib/routes/organizations-members.js +24 -18
  237. package/dist/lib/routes/organizations-members.js.map +1 -1
  238. package/dist/lib/routes/organizations-switch.d.ts.map +1 -1
  239. package/dist/lib/routes/organizations-switch.js +7 -3
  240. package/dist/lib/routes/organizations-switch.js.map +1 -1
  241. package/dist/lib/routes/organizations.d.ts.map +1 -1
  242. package/dist/lib/routes/organizations.js +11 -5
  243. package/dist/lib/routes/organizations.js.map +1 -1
  244. package/dist/lib/routes/roles-by-name.d.ts +4 -0
  245. package/dist/lib/routes/roles-by-name.d.ts.map +1 -0
  246. package/dist/lib/routes/roles-by-name.js +112 -0
  247. package/dist/lib/routes/roles-by-name.js.map +1 -0
  248. package/dist/lib/routes/roles.d.ts +4 -0
  249. package/dist/lib/routes/roles.d.ts.map +1 -0
  250. package/dist/lib/routes/roles.js +91 -0
  251. package/dist/lib/routes/roles.js.map +1 -0
  252. package/dist/lib/routes/user-preferences.d.ts.map +1 -1
  253. package/dist/lib/routes/user-preferences.js +7 -13
  254. package/dist/lib/routes/user-preferences.js.map +1 -1
  255. package/dist/lib/routes-exports.d.ts +2 -0
  256. package/dist/lib/routes-exports.d.ts.map +1 -1
  257. package/dist/lib/routes-exports.js +3 -0
  258. package/dist/lib/routes-exports.js.map +1 -1
  259. package/dist/lib/save-state-context.svelte.d.ts +8 -0
  260. package/dist/lib/save-state-context.svelte.d.ts.map +1 -0
  261. package/dist/lib/save-state-context.svelte.js +9 -0
  262. package/dist/lib/save-state-context.svelte.js.map +1 -0
  263. package/dist/lib/schema-utils/validator.d.ts.map +1 -1
  264. package/dist/lib/schema-utils/validator.js +14 -0
  265. package/dist/lib/schema-utils/validator.js.map +1 -1
  266. package/dist/lib/server/index.d.ts +1 -0
  267. package/dist/lib/server/index.d.ts.map +1 -1
  268. package/dist/lib/server/index.js +1 -0
  269. package/dist/lib/server/index.js.map +1 -1
  270. package/dist/lib/services/index.d.ts +1 -0
  271. package/dist/lib/services/index.d.ts.map +1 -1
  272. package/dist/lib/services/index.js +1 -0
  273. package/dist/lib/services/index.js.map +1 -1
  274. package/dist/lib/services/roles-service.d.ts +35 -0
  275. package/dist/lib/services/roles-service.d.ts.map +1 -0
  276. package/dist/lib/services/roles-service.js +91 -0
  277. package/dist/lib/services/roles-service.js.map +1 -0
  278. package/dist/lib/services/version-service.d.ts.map +1 -1
  279. package/dist/lib/services/version-service.js.map +1 -1
  280. package/dist/lib/types/auth.d.ts +43 -9
  281. package/dist/lib/types/auth.d.ts.map +1 -1
  282. package/dist/lib/types/auth.js +31 -26
  283. package/dist/lib/types/auth.js.map +1 -1
  284. package/dist/lib/types/capabilities.d.ts +104 -0
  285. package/dist/lib/types/capabilities.d.ts.map +1 -0
  286. package/dist/lib/types/capabilities.js +217 -0
  287. package/dist/lib/types/capabilities.js.map +1 -0
  288. package/dist/lib/types/index.d.ts +1 -0
  289. package/dist/lib/types/index.d.ts.map +1 -1
  290. package/dist/lib/types/index.js +1 -0
  291. package/dist/lib/types/index.js.map +1 -1
  292. package/dist/lib/types/organization.d.ts +13 -4
  293. package/dist/lib/types/organization.d.ts.map +1 -1
  294. package/dist/lib/types/schemas.d.ts +71 -0
  295. package/dist/lib/types/schemas.d.ts.map +1 -1
  296. package/dist/lib/types/sidebar.d.ts +1 -1
  297. package/dist/lib/types/sidebar.d.ts.map +1 -1
  298. package/dist/lib/utils/mime-detect.d.ts.map +1 -1
  299. package/dist/lib/utils/mime-detect.js +28 -6
  300. package/dist/lib/utils/mime-detect.js.map +1 -1
  301. package/dist/local-api/collection-api.d.ts +2 -0
  302. package/dist/local-api/collection-api.d.ts.map +1 -1
  303. package/dist/local-api/collection-api.js +98 -30
  304. package/dist/local-api/index.d.ts.map +1 -1
  305. package/dist/local-api/permissions.d.ts +26 -26
  306. package/dist/local-api/permissions.d.ts.map +1 -1
  307. package/dist/local-api/permissions.js +122 -80
  308. package/dist/permissions-context.svelte.d.ts +44 -0
  309. package/dist/permissions-context.svelte.d.ts.map +1 -0
  310. package/dist/permissions-context.svelte.js +79 -0
  311. package/dist/plugins/README.md +20 -20
  312. package/dist/routes/assets-bulk.d.ts.map +1 -1
  313. package/dist/routes/assets-bulk.js +10 -3
  314. package/dist/routes/assets-by-id.d.ts.map +1 -1
  315. package/dist/routes/assets-by-id.js +11 -1
  316. package/dist/routes/assets-references-counts.d.ts.map +1 -1
  317. package/dist/routes/assets-references-counts.js +12 -2
  318. package/dist/routes/assets.d.ts.map +1 -1
  319. package/dist/routes/assets.js +14 -13
  320. package/dist/routes/document-versions.d.ts.map +1 -1
  321. package/dist/routes/document-versions.js +16 -2
  322. package/dist/routes/documents-by-id.d.ts.map +1 -1
  323. package/dist/routes/documents-by-id.js +15 -3
  324. package/dist/routes/documents-query.d.ts.map +1 -1
  325. package/dist/routes/documents-query.js +13 -10
  326. package/dist/routes/documents.d.ts.map +1 -1
  327. package/dist/routes/documents.js +29 -26
  328. package/dist/routes/organizations-by-id.d.ts.map +1 -1
  329. package/dist/routes/organizations-by-id.js +17 -4
  330. package/dist/routes/organizations-invitations.d.ts.map +1 -1
  331. package/dist/routes/organizations-invitations.js +48 -18
  332. package/dist/routes/organizations-members.d.ts.map +1 -1
  333. package/dist/routes/organizations-members.js +24 -18
  334. package/dist/routes/organizations-switch.d.ts.map +1 -1
  335. package/dist/routes/organizations-switch.js +7 -3
  336. package/dist/routes/organizations.d.ts.map +1 -1
  337. package/dist/routes/organizations.js +11 -5
  338. package/dist/routes/roles-by-name.d.ts +4 -0
  339. package/dist/routes/roles-by-name.d.ts.map +1 -0
  340. package/dist/routes/roles-by-name.js +111 -0
  341. package/dist/routes/roles.d.ts +4 -0
  342. package/dist/routes/roles.d.ts.map +1 -0
  343. package/dist/routes/roles.js +90 -0
  344. package/dist/routes/user-preferences.d.ts.map +1 -1
  345. package/dist/routes/user-preferences.js +7 -13
  346. package/dist/routes-exports.d.ts +2 -0
  347. package/dist/routes-exports.d.ts.map +1 -1
  348. package/dist/routes-exports.js +3 -0
  349. package/dist/save-state-context.svelte.d.ts +8 -0
  350. package/dist/save-state-context.svelte.d.ts.map +1 -0
  351. package/dist/save-state-context.svelte.js +8 -0
  352. package/dist/schema-utils/validator.d.ts.map +1 -1
  353. package/dist/schema-utils/validator.js +14 -0
  354. package/dist/server/index.d.ts +1 -0
  355. package/dist/server/index.d.ts.map +1 -1
  356. package/dist/server/index.js +1 -0
  357. package/dist/services/index.d.ts +1 -0
  358. package/dist/services/index.d.ts.map +1 -1
  359. package/dist/services/index.js +1 -0
  360. package/dist/services/roles-service.d.ts +35 -0
  361. package/dist/services/roles-service.d.ts.map +1 -0
  362. package/dist/services/roles-service.js +90 -0
  363. package/dist/services/version-service.d.ts.map +1 -1
  364. package/dist/types/auth.d.ts +43 -9
  365. package/dist/types/auth.d.ts.map +1 -1
  366. package/dist/types/auth.js +31 -26
  367. package/dist/types/capabilities.d.ts +104 -0
  368. package/dist/types/capabilities.d.ts.map +1 -0
  369. package/dist/types/capabilities.js +216 -0
  370. package/dist/types/index.d.ts +1 -0
  371. package/dist/types/index.d.ts.map +1 -1
  372. package/dist/types/index.js +1 -0
  373. package/dist/types/organization.d.ts +13 -4
  374. package/dist/types/organization.d.ts.map +1 -1
  375. package/dist/types/schemas.d.ts +71 -0
  376. package/dist/types/schemas.d.ts.map +1 -1
  377. package/dist/types/sidebar.d.ts +1 -1
  378. package/dist/types/sidebar.d.ts.map +1 -1
  379. package/dist/utils/mime-detect.d.ts.map +1 -1
  380. package/dist/utils/mime-detect.js +28 -6
  381. package/package.json +142 -138
@@ -17,6 +17,7 @@
17
17
  import elementEvents from '../../../utils/element-events';
18
18
  import { copyUrlToClipboard, downloadFile } from '../../../utils/asset-actions';
19
19
  import AssetBrowserModal from '../AssetBrowserModal.svelte';
20
+ import { usePermissions } from '../../../permissions-context.svelte';
20
21
 
21
22
  interface Props {
22
23
  field: FileFieldType;
@@ -44,6 +45,12 @@
44
45
  organizationId
45
46
  }: Props = $props();
46
47
 
48
+ // Read-only when forced by caller OR the user lacks asset.upload. Keeps
49
+ // the `readonly` prop as an explicit override for hosts that want to
50
+ // neutralise the field regardless of RBAC state.
51
+ const perms = usePermissions();
52
+ const isReadOnly = $derived(readonly || !perms.can('asset.upload'));
53
+
47
54
  let isDragging = $state(false);
48
55
  let isUploading = $state(false);
49
56
  let uploadError = $state<string | null>(null);
@@ -97,7 +104,7 @@
97
104
  }
98
105
 
99
106
  async function handleFileSelect(files: FileList | null) {
100
- if (readonly || !files || files.length === 0) return;
107
+ if (isReadOnly || !files || files.length === 0) return;
101
108
 
102
109
  const file = files[0]!;
103
110
 
@@ -115,37 +122,37 @@
115
122
  }
116
123
 
117
124
  function handleDragOver(event: DragEvent) {
118
- if (readonly) return;
125
+ if (isReadOnly) return;
119
126
  event.preventDefault();
120
127
  isDragging = true;
121
128
  }
122
129
 
123
130
  function handleDragLeave(event: DragEvent) {
124
- if (readonly) return;
131
+ if (isReadOnly) return;
125
132
  event.preventDefault();
126
133
  isDragging = false;
127
134
  }
128
135
 
129
136
  function handleDrop(event: DragEvent) {
130
- if (readonly) return;
137
+ if (isReadOnly) return;
131
138
  event.preventDefault();
132
139
  isDragging = false;
133
140
  handleFileSelect(event.dataTransfer?.files || null);
134
141
  }
135
142
 
136
143
  function handleFileInputChange(event: Event) {
137
- if (readonly) return;
144
+ if (isReadOnly) return;
138
145
  const target = event.target as HTMLInputElement;
139
146
  handleFileSelect(target.files);
140
147
  }
141
148
 
142
149
  function openFileDialog() {
143
- if (readonly) return;
150
+ if (isReadOnly) return;
144
151
  fileInputRef?.click();
145
152
  }
146
153
 
147
154
  function removeFile() {
148
- if (readonly) return;
155
+ if (isReadOnly) return;
149
156
  onUpdate(null);
150
157
  uploadError = null;
151
158
  }
@@ -271,7 +278,7 @@
271
278
  {/if}
272
279
  </div>
273
280
 
274
- {#if !readonly}
281
+ {#if !isReadOnly}
275
282
  <DropdownMenu>
276
283
  <DropdownMenuTrigger>
277
284
  <Button variant="ghost" size="sm" class="h-8 w-8 p-0">
@@ -312,7 +319,7 @@
312
319
  variant="outline"
313
320
  class="w-full justify-start"
314
321
  onclick={openFileDialog}
315
- disabled={isUploading || readonly}
322
+ disabled={isUploading || isReadOnly}
316
323
  type="button"
317
324
  >
318
325
  {#if isUploading}
@@ -330,9 +337,7 @@
330
337
  <div class="border-border overflow-hidden rounded-md border {validationClasses}">
331
338
  <!-- File info card -->
332
339
  <div class="flex items-center gap-4 p-4">
333
- <div
334
- class="bg-muted flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-lg"
335
- >
340
+ <div class="bg-muted flex h-14 w-14 flex-shrink-0 items-center justify-center rounded-lg">
336
341
  {#if loadingAsset}
337
342
  <div class="border-primary h-6 w-6 animate-spin rounded-full border-b-2"></div>
338
343
  {:else}
@@ -353,7 +358,7 @@
353
358
  </div>
354
359
 
355
360
  <!-- Controls -->
356
- {#if !readonly}
361
+ {#if !isReadOnly}
357
362
  <DropdownMenu>
358
363
  <DropdownMenuTrigger>
359
364
  <Button variant="secondary" size="icon" class="h-8 w-8">
@@ -404,7 +409,7 @@
404
409
  {:else}
405
410
  <!-- Upload bar -->
406
411
  <div
407
- class="border-border flex h-10 items-center overflow-hidden rounded-md border transition-colors {validationClasses} {readonly
412
+ class="border-border flex h-10 items-center overflow-hidden rounded-md border transition-colors {validationClasses} {isReadOnly
408
413
  ? ''
409
414
  : isDragging
410
415
  ? 'bg-primary/5'
@@ -426,7 +431,7 @@
426
431
  {:else}
427
432
  <FileIcon size={16} class="text-muted-foreground" />
428
433
  <span class="text-muted-foreground text-sm">
429
- {readonly ? 'No file' : isDragging ? 'Drop file here' : 'Drag or select a file'}
434
+ {isReadOnly ? 'No file' : isDragging ? 'Drop file here' : 'Drag or select a file'}
430
435
  </span>
431
436
  {/if}
432
437
  </div>
@@ -434,7 +439,7 @@
434
439
  <div class="flex items-center gap-1 pr-2">
435
440
  <button
436
441
  onclick={openFileDialog}
437
- disabled={isUploading || readonly}
442
+ disabled={isUploading || isReadOnly}
438
443
  type="button"
439
444
  class="text-muted-foreground hover:text-foreground flex items-center gap-1 px-2 py-1 text-sm transition-colors disabled:opacity-50"
440
445
  >
@@ -442,7 +447,7 @@
442
447
  Upload
443
448
  </button>
444
449
  <button
445
- disabled={isUploading || readonly}
450
+ disabled={isUploading || isReadOnly}
446
451
  type="button"
447
452
  onclick={() => {
448
453
  showAssetBrowser = true;
@@ -1 +1 @@
1
- {"version":3,"file":"FileField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/FileField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAiBxE,UAAU,KAAK;IACd,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAgaF,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"FileField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/FileField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAkBxE,UAAU,KAAK;IACd,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAuaF,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -18,6 +18,7 @@
18
18
  import { copyUrlToClipboard, downloadFile } from '../../../utils/asset-actions';
19
19
  import AssetBrowserModal from '../AssetBrowserModal.svelte';
20
20
  import { Input } from '@aphexcms/ui/shadcn/input';
21
+ import { usePermissions } from '../../../permissions-context.svelte';
21
22
 
22
23
  interface Props {
23
24
  field: ImageFieldType;
@@ -45,6 +46,11 @@
45
46
  organizationId
46
47
  }: Props = $props();
47
48
 
49
+ // Treat the field as read-only when the explicit prop is set OR the user
50
+ // lacks asset.upload — both paths land the user at the same UX.
51
+ const perms = usePermissions();
52
+ const isReadOnly = $derived(readonly || !perms.can('asset.upload'));
53
+
48
54
  // Component state
49
55
  let isDragging = $state(false);
50
56
  let isUploading = $state(false);
@@ -95,7 +101,7 @@
95
101
 
96
102
  // Handle file selection
97
103
  async function handleFileSelect(files: FileList | null) {
98
- if (readonly || !files || files.length === 0) return;
104
+ if (isReadOnly || !files || files.length === 0) return;
99
105
 
100
106
  const file = files[0]!;
101
107
 
@@ -107,19 +113,19 @@
107
113
 
108
114
  // Drag and drop handlers
109
115
  function handleDragOver(event: DragEvent) {
110
- if (readonly) return;
116
+ if (isReadOnly) return;
111
117
  event.preventDefault();
112
118
  isDragging = true;
113
119
  }
114
120
 
115
121
  function handleDragLeave(event: DragEvent) {
116
- if (readonly) return;
122
+ if (isReadOnly) return;
117
123
  event.preventDefault();
118
124
  isDragging = false;
119
125
  }
120
126
 
121
127
  function handleDrop(event: DragEvent) {
122
- if (readonly) return;
128
+ if (isReadOnly) return;
123
129
  event.preventDefault();
124
130
  isDragging = false;
125
131
  handleFileSelect(event.dataTransfer?.files || null);
@@ -127,19 +133,19 @@
127
133
 
128
134
  // File input handlers
129
135
  function handleFileInputChange(event: Event) {
130
- if (readonly) return;
136
+ if (isReadOnly) return;
131
137
  const target = event.target as HTMLInputElement;
132
138
  handleFileSelect(target.files);
133
139
  }
134
140
 
135
141
  function openFileDialog() {
136
- if (readonly) return;
142
+ if (isReadOnly) return;
137
143
  fileInputRef?.click();
138
144
  }
139
145
 
140
146
  // Remove image
141
147
  function removeImage() {
142
- if (readonly) return;
148
+ if (isReadOnly) return;
143
149
  onUpdate(null);
144
150
  uploadError = null;
145
151
  }
@@ -299,7 +305,7 @@
299
305
  </div>
300
306
 
301
307
  <!-- Options menu -->
302
- {#if !readonly}
308
+ {#if !isReadOnly}
303
309
  <DropdownMenu>
304
310
  <DropdownMenuTrigger>
305
311
  <Button variant="ghost" size="sm" class="h-8 w-8 p-0">
@@ -341,7 +347,7 @@
341
347
  variant="outline"
342
348
  class="w-full justify-start"
343
349
  onclick={openFileDialog}
344
- disabled={isUploading || readonly}
350
+ disabled={isUploading || isReadOnly}
345
351
  type="button"
346
352
  >
347
353
  {#if isUploading}
@@ -383,7 +389,7 @@
383
389
  </div>
384
390
 
385
391
  <!-- Overlay controls (hidden for read-only) -->
386
- {#if !readonly}
392
+ {#if !isReadOnly}
387
393
  <div class="absolute inset-2 flex items-start justify-end gap-2">
388
394
  <DropdownMenu>
389
395
  <DropdownMenuTrigger>
@@ -443,14 +449,14 @@
443
449
  placeholder="Describe this image..."
444
450
  value={altText}
445
451
  oninput={(e) => updateAltText(e.currentTarget.value)}
446
- disabled={readonly}
452
+ disabled={isReadOnly}
447
453
  />
448
454
  </div>
449
455
  </div>
450
456
  {:else}
451
457
  <!-- Sanity-style upload bar -->
452
458
  <div
453
- class="border-border flex h-10 items-center overflow-hidden rounded-md border transition-colors {validationClasses} {readonly
459
+ class="border-border flex h-10 items-center overflow-hidden rounded-md border transition-colors {validationClasses} {isReadOnly
454
460
  ? ''
455
461
  : isDragging
456
462
  ? 'bg-primary/5'
@@ -473,7 +479,7 @@
473
479
  {:else}
474
480
  <FileImage size={16} class="text-muted-foreground" />
475
481
  <span class="text-muted-foreground text-sm">
476
- {readonly ? 'No image' : isDragging ? 'Drop image here' : 'Drag or paste image here'}
482
+ {isReadOnly ? 'No image' : isDragging ? 'Drop image here' : 'Drag or paste image here'}
477
483
  </span>
478
484
  {/if}
479
485
  </div>
@@ -482,7 +488,7 @@
482
488
  <div class="flex items-center gap-1 pr-2">
483
489
  <button
484
490
  onclick={openFileDialog}
485
- disabled={isUploading || readonly}
491
+ disabled={isUploading || isReadOnly}
486
492
  type="button"
487
493
  class="text-muted-foreground hover:text-foreground flex items-center gap-1 px-2 py-1 text-sm transition-colors disabled:opacity-50"
488
494
  >
@@ -490,7 +496,7 @@
490
496
  Upload
491
497
  </button>
492
498
  <button
493
- disabled={isUploading || readonly}
499
+ disabled={isUploading || isReadOnly}
494
500
  type="button"
495
501
  onclick={() => {
496
502
  showAssetBrowser = true;
@@ -1 +1 @@
1
- {"version":3,"file":"ImageField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ImageField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAkB1E,UAAU,KAAK;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAubF,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
1
+ {"version":3,"file":"ImageField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ImageField.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAmB1E,UAAU,KAAK;IACd,KAAK,EAAE,cAAc,CAAC;IACtB,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AA6bF,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -1,15 +1,17 @@
1
1
  <script lang="ts">
2
2
  import CheckIcon from '@lucide/svelte/icons/check';
3
- import ChevronsUpDownIcon from '@lucide/svelte/icons/chevrons-up-down';
4
3
  import PlusIcon from '@lucide/svelte/icons/plus';
5
- import XIcon from '@lucide/svelte/icons/x';
6
4
  import { tick } from 'svelte';
7
5
  import * as Command from '@aphexcms/ui/shadcn/command';
8
6
  import * as Popover from '@aphexcms/ui/shadcn/popover';
7
+ import * as DropdownMenu from '@aphexcms/ui/shadcn/dropdown-menu';
9
8
  import { Button } from '@aphexcms/ui/shadcn/button';
10
9
  import { cn } from '@aphexcms/ui/utils';
10
+ import { ExternalLink, Ellipsis, Trash2, FileText } from '@lucide/svelte';
11
11
  import type { Field, ReferenceField as ReferenceFieldType } from '../../../types/schemas';
12
12
  import { documents } from '../../../api/documents';
13
+ import { getSchemaContext } from '../../../schema-context.svelte';
14
+ import { getSchemaByName } from '../../../schema-utils/utils';
13
15
  import { toast } from 'svelte-sonner';
14
16
  import { cmsLogger } from '../../../utils/logger';
15
17
  import { pluralize } from '../../../utils/pluralize';
@@ -28,6 +30,10 @@
28
30
  const referenceField = field as ReferenceFieldType;
29
31
  const targetType = referenceField.to?.[0]?.type;
30
32
 
33
+ const schemas = getSchemaContext();
34
+ const targetSchema = $derived(targetType ? getSchemaByName(schemas, targetType) : null);
35
+ const TargetIcon = $derived(targetSchema?.icon ?? null);
36
+
31
37
  // State
32
38
  let open = $state(false);
33
39
  let searchResults = $state<any[]>([]);
@@ -143,123 +149,147 @@
143
149
  </script>
144
150
 
145
151
  {#if selectedDocument}
146
- <!-- Selected document display -->
147
- <div class="border-border bg-muted/30 flex items-center gap-2 rounded-md border p-3">
148
- <div class="flex-1">
149
- <div class="text-sm font-medium">{getDocumentTitle(selectedDocument)}</div>
150
- <div class="text-muted-foreground text-xs">
151
- {targetType} {selectedDocument.status === 'published' ? '🟢' : '🟡'}
152
- {selectedDocument.status}
153
- </div>
152
+ <!-- Selected document row styled like an ArrayField item -->
153
+ <div
154
+ class="border-border/50 bg-background hover:bg-muted/50 flex h-10 items-center gap-1 rounded border px-1 transition-colors"
155
+ >
156
+ <!-- Type icon -->
157
+ <div class="text-muted-foreground flex h-8 w-8 shrink-0 items-center justify-center">
158
+ {#if TargetIcon}
159
+ <TargetIcon class="h-4 w-4" />
160
+ {:else}
161
+ <FileText class="h-4 w-4" />
162
+ {/if}
154
163
  </div>
155
- <Button
156
- variant="ghost"
157
- size="sm"
164
+
165
+ <!-- Title + status dot (clickable to open referenced document) -->
166
+ <button
167
+ class="flex min-w-0 flex-1 cursor-pointer items-center gap-2 text-left"
158
168
  onclick={openReference}
159
- class="text-muted-foreground hover:text-foreground h-8 w-8 p-0"
160
- title="Edit referenced document"
169
+ title="Open referenced document"
161
170
  >
162
- <svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
163
- <path
164
- stroke-linecap="round"
165
- stroke-linejoin="round"
166
- stroke-width="2"
167
- d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
168
- />
169
- </svg>
170
- </Button>
171
- {#if !readonly}
172
- <Button
173
- variant="ghost"
174
- size="sm"
175
- onclick={clearSelection}
176
- class="text-muted-foreground hover:text-destructive h-8 w-8 p-0"
177
- title="Clear selection"
178
- >
179
- <XIcon class="h-4 w-4" />
180
- </Button>
181
- {/if}
182
- </div>
183
- {:else}
184
- <!-- Search/select interface -->
185
- {#if readonly}
186
- <!-- Read-only state: show placeholder -->
187
- <div
188
- class="border-input bg-muted/50 flex h-10 w-full items-center justify-between rounded-md border px-3 py-2 text-sm"
189
- >
190
- <span class="text-muted-foreground">No reference selected</span>
191
- </div>
192
- {:else}
193
- <Popover.Root bind:open>
194
- <Popover.Trigger bind:ref={triggerRef}>
171
+ <span class="truncate text-sm">{getDocumentTitle(selectedDocument)}</span>
172
+ {#if selectedDocument.status === 'published'}
173
+ <span class="h-1.5 w-1.5 shrink-0 rounded-full bg-green-500" title="Published"></span>
174
+ {:else if selectedDocument.status === 'unpublished'}
175
+ <span class="bg-muted-foreground/60 h-1.5 w-1.5 shrink-0 rounded-full" title="Unpublished"
176
+ ></span>
177
+ {:else}
178
+ <span class="h-1.5 w-1.5 shrink-0 rounded-full bg-amber-500" title="Draft"></span>
179
+ {/if}
180
+ </button>
181
+
182
+ <!-- Context menu -->
183
+ <DropdownMenu.Root>
184
+ <DropdownMenu.Trigger>
195
185
  {#snippet child({ props })}
196
- <Button
186
+ <button
197
187
  {...props}
198
- variant="outline"
199
- class="w-full justify-between"
200
- role="combobox"
201
- aria-expanded={open}
188
+ class="text-muted-foreground hover:text-foreground flex h-8 w-8 shrink-0 cursor-pointer items-center justify-center rounded transition-colors"
202
189
  >
203
- {selectedLabel || `Select ${targetType}...`}
204
- <ChevronsUpDownIcon class="opacity-50" />
205
- </Button>
190
+ <Ellipsis class="h-4 w-4" />
191
+ </button>
206
192
  {/snippet}
207
- </Popover.Trigger>
208
- <Popover.Content class="!z-[9999] w-[400px] p-0">
209
- <Command.Root>
210
- <Command.List>
211
- {#if loading}
212
- <Command.Loading>Loading...</Command.Loading>
213
- {:else if searchResults.length === 0}
214
- <Command.Empty>
215
- <div class="flex flex-col items-center gap-2 py-4">
216
- <p class="text-muted-foreground text-sm">
217
- No {pluralize(targetType || '')} found
218
- </p>
219
- <Button size="sm" onclick={createNewDocument} disabled={creating} class="gap-1">
220
- <PlusIcon class="h-3 w-3" />
221
- {creating ? 'Creating...' : `Create new ${targetType}`}
222
- </Button>
223
- </div>
224
- </Command.Empty>
225
- {:else if searchResults.length > 0}
226
- <Command.Group>
227
- {#each searchResults as doc (doc.id)}
228
- <Command.Item
229
- value={doc.id}
230
- onSelect={() => selectDocument(doc)}
231
- class="flex items-center justify-between"
232
- >
233
- <div class="flex items-center gap-2">
234
- <CheckIcon class={cn('h-4 w-4', value !== doc.id && 'text-transparent')} />
235
- <div>
236
- <div class="text-sm font-medium">{getDocumentTitle(doc)}</div>
237
- <div class="text-muted-foreground text-xs">
238
- {doc.status === 'published' ? '🟢' : '🟡'}
239
- {doc.status}
240
- </div>
241
- </div>
242
- </div>
243
- </Command.Item>
244
- {/each}
245
- </Command.Group>
246
- <Command.Separator />
247
- <Command.Group>
248
- <Command.Item onSelect={createNewDocument} class="justify-center">
249
- <div class="flex items-center gap-1">
250
- <PlusIcon class="h-3 w-3" />
251
- {creating ? 'Creating...' : `Create new ${targetType}`}
193
+ </DropdownMenu.Trigger>
194
+ <DropdownMenu.Content align="end">
195
+ <DropdownMenu.Item onclick={openReference}>
196
+ <ExternalLink class="mr-2 h-4 w-4" />
197
+ Open
198
+ </DropdownMenu.Item>
199
+ {#if !readonly}
200
+ <DropdownMenu.Separator />
201
+ <DropdownMenu.Item
202
+ class="text-destructive focus:text-destructive"
203
+ onclick={clearSelection}
204
+ >
205
+ <Trash2 class="mr-2 h-4 w-4" />
206
+ Remove
207
+ </DropdownMenu.Item>
208
+ {/if}
209
+ </DropdownMenu.Content>
210
+ </DropdownMenu.Root>
211
+ </div>
212
+ {:else if readonly}
213
+ <!-- Read-only empty state -->
214
+ <div
215
+ class="border-border/50 bg-muted/30 flex items-center justify-center rounded border border-dashed p-6"
216
+ >
217
+ <p class="text-muted-foreground text-sm">No reference selected</p>
218
+ </div>
219
+ {:else}
220
+ <!-- Empty state: dashed "Add reference" button that opens a search popover -->
221
+ <Popover.Root bind:open>
222
+ <Popover.Trigger bind:ref={triggerRef}>
223
+ {#snippet child({ props })}
224
+ <button
225
+ {...props}
226
+ class="border-border/50 text-muted-foreground hover:text-foreground hover:bg-muted/50 flex h-10 w-full cursor-pointer items-center justify-center gap-2 rounded border border-dashed text-sm transition-colors"
227
+ role="combobox"
228
+ aria-expanded={open}
229
+ >
230
+ <PlusIcon class="h-4 w-4" />
231
+ Add {targetType || 'reference'}...
232
+ </button>
233
+ {/snippet}
234
+ </Popover.Trigger>
235
+ <Popover.Content class="!z-[9999] w-[400px] p-0">
236
+ <Command.Root>
237
+ <Command.List>
238
+ {#if loading}
239
+ <Command.Loading>Loading...</Command.Loading>
240
+ {:else if searchResults.length === 0}
241
+ <Command.Empty>
242
+ <div class="flex flex-col items-center gap-2 py-4">
243
+ <p class="text-muted-foreground text-sm">
244
+ No {pluralize(targetType || '')} found
245
+ </p>
246
+ <Button size="sm" onclick={createNewDocument} disabled={creating} class="gap-1">
247
+ <PlusIcon class="h-3 w-3" />
248
+ {creating ? 'Creating...' : `Create new ${targetType}`}
249
+ </Button>
250
+ </div>
251
+ </Command.Empty>
252
+ {:else}
253
+ <Command.Group>
254
+ {#each searchResults as doc (doc.id)}
255
+ <Command.Item
256
+ value={doc.id}
257
+ onSelect={() => selectDocument(doc)}
258
+ class="flex items-center justify-between"
259
+ >
260
+ <div class="flex min-w-0 flex-1 items-center gap-2">
261
+ <CheckIcon
262
+ class={cn('h-4 w-4 shrink-0', value !== doc.id && 'text-transparent')}
263
+ />
264
+ <span class="truncate text-sm">{getDocumentTitle(doc)}</span>
252
265
  </div>
266
+ {#if doc.status === 'published'}
267
+ <span class="h-1.5 w-1.5 shrink-0 rounded-full bg-green-500" title="Published"
268
+ ></span>
269
+ {:else if doc.status === 'unpublished'}
270
+ <span
271
+ class="bg-muted-foreground/60 h-1.5 w-1.5 shrink-0 rounded-full"
272
+ title="Unpublished"
273
+ ></span>
274
+ {:else}
275
+ <span class="h-1.5 w-1.5 shrink-0 rounded-full bg-amber-500" title="Draft"
276
+ ></span>
277
+ {/if}
253
278
  </Command.Item>
254
- </Command.Group>
255
- {:else}
256
- <Command.Empty>
257
- No {pluralize(targetType || '')} available
258
- </Command.Empty>
259
- {/if}
260
- </Command.List>
261
- </Command.Root>
262
- </Popover.Content>
263
- </Popover.Root>
264
- {/if}
279
+ {/each}
280
+ </Command.Group>
281
+ <Command.Separator />
282
+ <Command.Group>
283
+ <Command.Item onSelect={createNewDocument} class="justify-center">
284
+ <div class="flex items-center gap-1">
285
+ <PlusIcon class="h-3 w-3" />
286
+ {creating ? 'Creating...' : `Create new ${targetType}`}
287
+ </div>
288
+ </Command.Item>
289
+ </Command.Group>
290
+ {/if}
291
+ </Command.List>
292
+ </Command.Root>
293
+ </Popover.Content>
294
+ </Popover.Root>
265
295
  {/if}
@@ -1 +1 @@
1
- {"version":3,"file":"ReferenceField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ReferenceField.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,KAAK,EAAwC,MAAM,wBAAwB,CAAC;AAOzF,UAAU,KAAK;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAyOF,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"ReferenceField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/ReferenceField.svelte.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,KAAK,EAAwC,MAAM,wBAAwB,CAAC;AASzF,UAAU,KAAK;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IACzC,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACrE,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AAqQF,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { Textarea } from '@aphexcms/ui/shadcn/textarea';
3
- import type { Field } from '../../../types/schemas';
3
+ import type { TextField } from '../../../types/schemas';
4
4
 
5
5
  interface Props {
6
- field: Field;
6
+ field: TextField;
7
7
  value: any;
8
8
  onUpdate: (value: any) => void;
9
9
  validationClasses?: string;
@@ -32,9 +32,10 @@
32
32
  id={field.name}
33
33
  value={value || ''}
34
34
  placeholder={field.title}
35
+ rows={field.rows}
35
36
  oninput={handleInputChange}
36
37
  onblur={onBlur}
37
38
  onfocus={onFocus}
38
- class="min-h-[100px] {validationClasses}"
39
+ class="{field.rows ? 'field-sizing-fixed' : 'min-h-[100px]'} {validationClasses}"
39
40
  disabled={readonly}
40
41
  />
@@ -1,6 +1,6 @@
1
- import type { Field } from '../../../types/schemas.js';
1
+ import type { TextField } from '../../../types/schemas.js';
2
2
  interface Props {
3
- field: Field;
3
+ field: TextField;
4
4
  value: any;
5
5
  onUpdate: (value: any) => void;
6
6
  validationClasses?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"TextareaField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/TextareaField.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAGnD,UAAU,KAAK;IACd,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AA0BF,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"TextareaField.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/admin/fields/TextareaField.svelte.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAGvD,UAAU,KAAK;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC;IACX,QAAQ,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC9B,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACnB;AA0BF,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}