@rebasepro/cms 0.17.3 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (449) hide show
  1. package/README.md +4 -0
  2. package/dist/{CollectionEditorDialog-B-akreOU.js → CollectionEditorDialog-BeX4b92r.js} +13 -7
  3. package/dist/{CollectionEditorDialog-B-akreOU.js.map → CollectionEditorDialog-BeX4b92r.js.map} +1 -1
  4. package/dist/{PropertyEditView-CiY84wkR.js → PropertyEditView-C7thfj4L.js} +3 -3
  5. package/dist/{PropertyEditView-CiY84wkR.js.map → PropertyEditView-C7thfj4L.js.map} +1 -1
  6. package/dist/{RouterCollectionsStudioView-DkAWda4N.js → RouterCollectionsStudioView-BtjzvB6E.js} +4 -4
  7. package/dist/{RouterCollectionsStudioView-DkAWda4N.js.map → RouterCollectionsStudioView-BtjzvB6E.js.map} +1 -1
  8. package/dist/{SchemaChangeDialog-DceT8QFX.js → SchemaChangeDialog-CkqK6KOC.js} +4 -2
  9. package/dist/{SchemaChangeDialog-DceT8QFX.js.map → SchemaChangeDialog-CkqK6KOC.js.map} +1 -1
  10. package/dist/collection_editor/api/generateCollectionApi.d.ts +1 -2
  11. package/dist/collection_editor_ui.d.ts +2 -0
  12. package/dist/collection_editor_ui.js +6 -5
  13. package/dist/collection_editor_ui.js.map +1 -1
  14. package/dist/components/DeleteEntityDialog.d.ts +2 -3
  15. package/dist/components/RebaseLayout.d.ts +11 -4
  16. package/dist/components/field_configs.d.ts +1 -1
  17. package/dist/editor/sanitize-html.d.ts +15 -0
  18. package/dist/editor.js +195 -10
  19. package/dist/editor.js.map +1 -1
  20. package/dist/{export-Ben8E355.js → export--arni_VY.js} +2 -2
  21. package/dist/{export-Ben8E355.js.map → export--arni_VY.js.map} +1 -1
  22. package/dist/form/components/LabelWithIcon.d.ts +10 -0
  23. package/dist/{history-DIEVd26f.js → history-C2TpoQwi.js} +2 -2
  24. package/dist/{history-DIEVd26f.js.map → history-C2TpoQwi.js.map} +1 -1
  25. package/dist/hooks/navigation/useBuildNavigationStateController.d.ts +1 -1
  26. package/dist/hooks/navigation/useResolvedViews.d.ts +1 -1
  27. package/dist/hooks/navigation/useTopLevelNavigation.d.ts +1 -1
  28. package/dist/{import-D25x7ko-.js → import-DTkXNoBg.js} +2 -2
  29. package/dist/{import-D25x7ko-.js.map → import-DTkXNoBg.js.map} +1 -1
  30. package/dist/index.js +78 -33
  31. package/dist/index.js.map +1 -1
  32. package/dist/util/propertyConfigMapper.d.ts +1 -1
  33. package/dist/util-CfLFggP7.js +57 -0
  34. package/dist/util-CfLFggP7.js.map +1 -0
  35. package/dist/{util-DVqnqlLn.js → util-DE1WQW6h.js} +134 -112
  36. package/dist/util-DE1WQW6h.js.map +1 -0
  37. package/package.json +42 -34
  38. package/dist/util-DVqnqlLn.js.map +0 -1
  39. package/src/collection_editor/CollectionEditorDialogsContext.tsx +0 -25
  40. package/src/collection_editor/ConfigControllerProvider.tsx +0 -395
  41. package/src/collection_editor/_cms_internals.ts +0 -41
  42. package/src/collection_editor/api/generateCollectionApi.ts +0 -126
  43. package/src/collection_editor/api/index.ts +0 -1
  44. package/src/collection_editor/extensibility_types.ts +0 -168
  45. package/src/collection_editor/index.ts +0 -108
  46. package/src/collection_editor/liveSchemaClient.ts +0 -285
  47. package/src/collection_editor/relation_kinds.ts +0 -44
  48. package/src/collection_editor/serializable_types.ts +0 -535
  49. package/src/collection_editor/serializable_utils.ts +0 -729
  50. package/src/collection_editor/types/collection_editor_controller.tsx +0 -62
  51. package/src/collection_editor/types/collection_inference.ts +0 -18
  52. package/src/collection_editor/types/config_controller.tsx +0 -121
  53. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +0 -199
  54. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +0 -51
  55. package/src/collection_editor/ui/EditorCollectionAction.tsx +0 -54
  56. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +0 -90
  57. package/src/collection_editor/ui/EditorEntityAction.tsx +0 -50
  58. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +0 -114
  59. package/src/collection_editor/ui/KanbanSetupAction.tsx +0 -43
  60. package/src/collection_editor/ui/MissingReferenceWidget.tsx +0 -35
  61. package/src/collection_editor/ui/NewCollectionButton.tsx +0 -27
  62. package/src/collection_editor/ui/NewCollectionCard.tsx +0 -48
  63. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +0 -49
  64. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +0 -260
  65. package/src/collection_editor/ui/collection_editor/AIModifiedPathsContext.tsx +0 -90
  66. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +0 -388
  67. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +0 -1098
  68. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +0 -301
  69. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +0 -172
  70. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +0 -620
  71. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +0 -530
  72. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +0 -462
  73. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +0 -104
  74. package/src/collection_editor/ui/collection_editor/CollectionYupValidation.tsx +0 -9
  75. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +0 -199
  76. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +0 -315
  77. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +0 -164
  78. package/src/collection_editor/ui/collection_editor/EntityActionsSelectDialog.tsx +0 -40
  79. package/src/collection_editor/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +0 -39
  80. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +0 -373
  81. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +0 -288
  82. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +0 -141
  83. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +0 -194
  84. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +0 -53
  85. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +0 -980
  86. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +0 -164
  87. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +0 -364
  88. package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +0 -44
  89. package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +0 -41
  90. package/src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx +0 -470
  91. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +0 -256
  92. package/src/collection_editor/ui/collection_editor/SwitchControl.tsx +0 -39
  93. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +0 -68
  94. package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +0 -67
  95. package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.tsx +0 -296
  96. package/src/collection_editor/ui/collection_editor/import/clean_import_data.ts +0 -57
  97. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +0 -147
  98. package/src/collection_editor/ui/collection_editor/properties/BooleanPropertyField.tsx +0 -41
  99. package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +0 -113
  100. package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +0 -250
  101. package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +0 -126
  102. package/src/collection_editor/ui/collection_editor/properties/KeyValuePropertyField.tsx +0 -20
  103. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +0 -153
  104. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +0 -217
  105. package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +0 -117
  106. package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +0 -129
  107. package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +0 -335
  108. package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -107
  109. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +0 -403
  110. package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +0 -148
  111. package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +0 -91
  112. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +0 -34
  113. package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +0 -49
  114. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +0 -925
  115. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +0 -28
  116. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +0 -626
  117. package/src/collection_editor/ui/collection_editor/properties/conditions/index.ts +0 -6
  118. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +0 -93
  119. package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +0 -52
  120. package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +0 -63
  121. package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +0 -114
  122. package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +0 -154
  123. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +0 -28
  124. package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +0 -112
  125. package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +0 -183
  126. package/src/collection_editor/ui/collection_editor/templates/products_template.ts +0 -88
  127. package/src/collection_editor/ui/collection_editor/templates/users_template.ts +0 -42
  128. package/src/collection_editor/ui/collection_editor/util.ts +0 -28
  129. package/src/collection_editor/ui/collection_editor/utils/strings.ts +0 -1
  130. package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -39
  131. package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +0 -276
  132. package/src/collection_editor/useCollectionEditorController.tsx +0 -9
  133. package/src/collection_editor/useCollectionsConfigController.tsx +0 -9
  134. package/src/collection_editor/useJsonCollectionsConfigController.tsx +0 -297
  135. package/src/collection_editor/useLiveSchemaEditing.tsx +0 -315
  136. package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -341
  137. package/src/collection_editor/useSafeSnackbarController.ts +0 -9
  138. package/src/collection_editor/validateCollectionJson.ts +0 -440
  139. package/src/collection_editor_ui.ts +0 -21
  140. package/src/components/AdditionalFieldValue.tsx +0 -68
  141. package/src/components/AdminModeSyncer.tsx +0 -56
  142. package/src/components/ArrayContainer.tsx +0 -542
  143. package/src/components/ClearFilterSortButton.tsx +0 -56
  144. package/src/components/CollectionEditorDialogs.tsx +0 -69
  145. package/src/components/CollectionPanel.tsx +0 -179
  146. package/src/components/CollectionTableBinding/CollectionRowActions.tsx +0 -244
  147. package/src/components/CollectionTableBinding/CollectionTableBinding.tsx +0 -394
  148. package/src/components/CollectionTableBinding/CollectionTableBindingProps.tsx +0 -172
  149. package/src/components/CollectionTableBinding/PropertyTableCell.tsx +0 -350
  150. package/src/components/CollectionTableBinding/column_utils.tsx +0 -155
  151. package/src/components/CollectionTableBinding/fields/TableMultipleRelationField.tsx +0 -131
  152. package/src/components/CollectionTableBinding/fields/TableReferenceField.tsx +0 -193
  153. package/src/components/CollectionTableBinding/fields/TableRelationField.tsx +0 -192
  154. package/src/components/CollectionTableBinding/fields/TableRelationSelectorField.tsx +0 -42
  155. package/src/components/CollectionTableBinding/fields/TableStorageUpload.tsx +0 -324
  156. package/src/components/CollectionTableBinding/fields/VirtualTableSelect.tsx +0 -132
  157. package/src/components/CollectionTableBinding/fields/VirtualTableUserSelect.tsx +0 -41
  158. package/src/components/CollectionTableBinding/index.tsx +0 -14
  159. package/src/components/CollectionTableBinding/internal/CollectionTableToolbar.tsx +0 -96
  160. package/src/components/CollectionTableBinding/internal/EntityTableCell.tsx +0 -309
  161. package/src/components/CollectionTableBinding/internal/EntityTableCellActions.tsx +0 -80
  162. package/src/components/CollectionTableBinding/internal/common.tsx +0 -74
  163. package/src/components/CollectionTableBinding/internal/popup_field/PopupFormField.tsx +0 -422
  164. package/src/components/CollectionTableBinding/internal/popup_field/useDraggable.tsx +0 -99
  165. package/src/components/CollectionTableBinding/internal/popup_field/useWindowSize.tsx +0 -22
  166. package/src/components/CollectionTableBinding/table_bindings.tsx +0 -350
  167. package/src/components/CollectionViewBinding/BoardCardBinding.tsx +0 -263
  168. package/src/components/CollectionViewBinding/CollectionBoardViewBinding.tsx +0 -662
  169. package/src/components/CollectionViewBinding/CollectionCardViewBinding.tsx +0 -159
  170. package/src/components/CollectionViewBinding/CollectionListViewBinding.tsx +0 -1430
  171. package/src/components/CollectionViewBinding/CollectionViewActions.tsx +0 -227
  172. package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +0 -1603
  173. package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +0 -240
  174. package/src/components/CollectionViewBinding/EntityCardBinding.tsx +0 -239
  175. package/src/components/CollectionViewBinding/FilterPresetsButton.tsx +0 -298
  176. package/src/components/CollectionViewBinding/FiltersDialog.tsx +0 -218
  177. package/src/components/CollectionViewBinding/SearchExplanation.tsx +0 -106
  178. package/src/components/CollectionViewBinding/SearchHighlight.tsx +0 -311
  179. package/src/components/CollectionViewBinding/SlotValue.tsx +0 -156
  180. package/src/components/CollectionViewBinding/SortButton.tsx +0 -354
  181. package/src/components/CollectionViewBinding/SplitListCloseButton.tsx +0 -49
  182. package/src/components/CollectionViewBinding/SplitListShowButton.tsx +0 -28
  183. package/src/components/CollectionViewBinding/SplitListView.tsx +0 -488
  184. package/src/components/CollectionViewBinding/SplitViewContext.tsx +0 -34
  185. package/src/components/CollectionViewBinding/ViewModeToggle.tsx +0 -250
  186. package/src/components/CollectionViewBinding/hooks/useCollectionInlineEditor.ts +0 -81
  187. package/src/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.ts +0 -181
  188. package/src/components/CollectionViewBinding/useBoardDataController.tsx +0 -802
  189. package/src/components/CollectionViewBinding/usePreviewSlots.ts +0 -703
  190. package/src/components/CollectionViewBinding/useSelectionController.tsx +0 -40
  191. package/src/components/CollectionViewBinding/utils.ts +0 -22
  192. package/src/components/DefaultAppBar.tsx +0 -264
  193. package/src/components/DefaultDrawer.tsx +0 -593
  194. package/src/components/DeleteEntityDialog.tsx +0 -205
  195. package/src/components/DetailViewBinding.tsx +0 -731
  196. package/src/components/DrawerNavigationGroup.tsx +0 -141
  197. package/src/components/DrawerNavigationItem.tsx +0 -115
  198. package/src/components/EditFormActions.tsx +0 -303
  199. package/src/components/EditViewBinding.tsx +0 -1069
  200. package/src/components/EntityDisplayHeader.tsx +0 -170
  201. package/src/components/EntityIdentityBar.tsx +0 -428
  202. package/src/components/EntityInspector.tsx +0 -156
  203. package/src/components/EntityPreviewBinding.tsx +0 -432
  204. package/src/components/EntityPreviewNesting.tsx +0 -50
  205. package/src/components/EntityViewBinding.tsx +0 -374
  206. package/src/components/FieldCaption.tsx +0 -14
  207. package/src/components/HomePage/ContentHomePage.tsx +0 -586
  208. package/src/components/HomePage/FavouritesView.tsx +0 -60
  209. package/src/components/HomePage/HomePageDnD.tsx +0 -704
  210. package/src/components/HomePage/NavigationCard.tsx +0 -81
  211. package/src/components/HomePage/NavigationCardBinding.tsx +0 -107
  212. package/src/components/HomePage/NavigationGroup.tsx +0 -156
  213. package/src/components/HomePage/RenameGroupDialog.tsx +0 -123
  214. package/src/components/HomePage/SmallNavigationCard.tsx +0 -41
  215. package/src/components/HomePage/index.tsx +0 -5
  216. package/src/components/InlineEntityPreview.tsx +0 -149
  217. package/src/components/JsonPreviewBinding.tsx +0 -66
  218. package/src/components/PropertyCollectionView.tsx +0 -336
  219. package/src/components/PropertyConfigBadge.tsx +0 -28
  220. package/src/components/PropertyIdCopyTooltip.tsx +0 -47
  221. package/src/components/RebaseAuthGate.tsx +0 -44
  222. package/src/components/RebaseCMS.tsx +0 -30
  223. package/src/components/RebaseLayout.tsx +0 -80
  224. package/src/components/RebaseNavigation.tsx +0 -369
  225. package/src/components/RebaseRouteDefs.tsx +0 -127
  226. package/src/components/RebaseShell.tsx +0 -83
  227. package/src/components/ReferenceTable/SelectionTableBinding.tsx +0 -389
  228. package/src/components/ReferenceWidget.tsx +0 -156
  229. package/src/components/RelationSelector.tsx +0 -926
  230. package/src/components/SearchIconsView.tsx +0 -78
  231. package/src/components/SelectableTable/SelectableTable.tsx +0 -309
  232. package/src/components/SelectableTable/SelectableTableContext.tsx +0 -7
  233. package/src/components/SelectableTable/SelectionStore.ts +0 -43
  234. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +0 -59
  235. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +0 -146
  236. package/src/components/SelectableTable/filters/FilterFieldBinding.tsx +0 -190
  237. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +0 -250
  238. package/src/components/SelectableTable/filters/RelationFilterField.tsx +0 -238
  239. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +0 -282
  240. package/src/components/SelectableTable/filters/null_filter.ts +0 -63
  241. package/src/components/SideDialogs.tsx +0 -238
  242. package/src/components/SidePanelBinding.tsx +0 -361
  243. package/src/components/SidePanelProvider.tsx +0 -80
  244. package/src/components/UserSelector.tsx +0 -513
  245. package/src/components/admin/CreationResultDialog.tsx +0 -138
  246. package/src/components/admin/index.ts +0 -1
  247. package/src/components/app/AppBar.tsx +0 -17
  248. package/src/components/app/Drawer.tsx +0 -38
  249. package/src/components/app/Scaffold.tsx +0 -366
  250. package/src/components/app/index.ts +0 -4
  251. package/src/components/app/useApp.tsx +0 -36
  252. package/src/components/common/default_entity_actions.tsx +0 -440
  253. package/src/components/common/index.ts +0 -1
  254. package/src/components/field_configs.tsx +0 -506
  255. package/src/components/history/EntityHistoryEntry.tsx +0 -203
  256. package/src/components/history/EntityHistoryView.tsx +0 -206
  257. package/src/components/history/LastEditedByFormAction.tsx +0 -24
  258. package/src/components/history/LastEditedByIndicator.tsx +0 -95
  259. package/src/components/history/UserChip.tsx +0 -15
  260. package/src/components/history/index.tsx +0 -5
  261. package/src/components/index.ts +0 -63
  262. package/src/contexts/BreacrumbsContext.tsx +0 -45
  263. package/src/contexts/SideDialogsControllerContext.tsx +0 -5
  264. package/src/contexts/SidePanelControllerContext.tsx +0 -5
  265. package/src/data_export/export/BasicExportAction.tsx +0 -142
  266. package/src/data_export/export/ExportCollectionAction.tsx +0 -321
  267. package/src/data_export/export/export.ts +0 -295
  268. package/src/data_export/export/fetch_export_data.ts +0 -90
  269. package/src/data_export/export/index.ts +0 -4
  270. package/src/data_export/index.ts +0 -1
  271. package/src/data_import/components/DataNewPropertiesMapping.tsx +0 -261
  272. package/src/data_import/components/ImportFileUpload.tsx +0 -42
  273. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +0 -58
  274. package/src/data_import/components/ImportSaveInProgress.tsx +0 -121
  275. package/src/data_import/components/index.ts +0 -4
  276. package/src/data_import/hooks/index.ts +0 -1
  277. package/src/data_import/hooks/useImportConfig.tsx +0 -34
  278. package/src/data_import/import/ImportCollectionAction.tsx +0 -461
  279. package/src/data_import/import/index.ts +0 -1
  280. package/src/data_import/index.ts +0 -5
  281. package/src/data_import/types/column_mapping.ts +0 -32
  282. package/src/data_import/types/index.ts +0 -1
  283. package/src/data_import/utils/csv.ts +0 -153
  284. package/src/data_import/utils/data.ts +0 -181
  285. package/src/data_import/utils/file_headers.ts +0 -14
  286. package/src/data_import/utils/file_to_json.ts +0 -149
  287. package/src/data_import/utils/get_import_inference_type.ts +0 -33
  288. package/src/data_import/utils/get_properties_mapping.ts +0 -67
  289. package/src/data_import/utils/index.ts +0 -5
  290. package/src/data_import/utils/save_entities.ts +0 -138
  291. package/src/data_import/utils/transforms.ts +0 -70
  292. package/src/editor/components/SlashCommandMenu.tsx +0 -532
  293. package/src/editor/components/editor-bubble-item.tsx +0 -32
  294. package/src/editor/components/editor-bubble.tsx +0 -143
  295. package/src/editor/components/image-bubble.tsx +0 -183
  296. package/src/editor/components/index.ts +0 -14
  297. package/src/editor/components/table-bubble.tsx +0 -233
  298. package/src/editor/editor.tsx +0 -529
  299. package/src/editor/extensions/HighlightDecorationExtension.ts +0 -115
  300. package/src/editor/extensions/Image.ts +0 -159
  301. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +0 -107
  302. package/src/editor/extensions/clipboard.ts +0 -72
  303. package/src/editor/extensions/custom-keymap.ts +0 -25
  304. package/src/editor/extensions/drag-and-drop.tsx +0 -508
  305. package/src/editor/hooks/useProseMirror.ts +0 -126
  306. package/src/editor/hooks/useProseMirrorContext.ts +0 -15
  307. package/src/editor/index.ts +0 -2
  308. package/src/editor/markdown-it-plugins.d.ts +0 -24
  309. package/src/editor/markdown.ts +0 -204
  310. package/src/editor/nodeViews/ImageComponent.tsx +0 -20
  311. package/src/editor/nodeViews/ReactNodeView.tsx +0 -89
  312. package/src/editor/nodeViews/TaskItemComponent.tsx +0 -30
  313. package/src/editor/nodeViews/index.ts +0 -35
  314. package/src/editor/plugins/index.ts +0 -58
  315. package/src/editor/plugins/inputrules.ts +0 -82
  316. package/src/editor/plugins/placeholderPlugin.ts +0 -55
  317. package/src/editor/plugins/slashCommandPlugin.ts +0 -65
  318. package/src/editor/schema.ts +0 -339
  319. package/src/editor/selectors/ai-selector.tsx +0 -110
  320. package/src/editor/selectors/color-selector.tsx +0 -199
  321. package/src/editor/selectors/link-selector.tsx +0 -122
  322. package/src/editor/selectors/node-selector.tsx +0 -159
  323. package/src/editor/selectors/text-buttons.tsx +0 -79
  324. package/src/editor/types.ts +0 -6
  325. package/src/editor/useProseMirror.ts +0 -125
  326. package/src/editor/utils/prosemirror-utils.ts +0 -113
  327. package/src/editor/utils/remove_classes.ts +0 -18
  328. package/src/editor/utils/useDebouncedCallback.ts +0 -25
  329. package/src/form/EntityForm.tsx +0 -761
  330. package/src/form/EntityFormActions.tsx +0 -160
  331. package/src/form/EntityFormBinding.tsx +0 -342
  332. package/src/form/PropertyFieldBinding.tsx +0 -348
  333. package/src/form/components/ErrorFocus.tsx +0 -44
  334. package/src/form/components/FieldBlock.tsx +0 -189
  335. package/src/form/components/FieldHelperText.tsx +0 -84
  336. package/src/form/components/FormRail.tsx +0 -153
  337. package/src/form/components/FormSections.tsx +0 -145
  338. package/src/form/components/LabelWithIcon.tsx +0 -43
  339. package/src/form/components/LabelWithIconAndTooltip.tsx +0 -28
  340. package/src/form/components/LocalChangesMenu.tsx +0 -147
  341. package/src/form/components/StorageItemPreview.tsx +0 -81
  342. package/src/form/components/StorageUploadProgress.tsx +0 -118
  343. package/src/form/components/index.tsx +0 -6
  344. package/src/form/components/useRailVisible.tsx +0 -47
  345. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +0 -109
  346. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -172
  347. package/src/form/field_bindings/BinaryFieldBinding.tsx +0 -177
  348. package/src/form/field_bindings/BlockFieldBinding.tsx +0 -282
  349. package/src/form/field_bindings/DateTimeFieldBinding.tsx +0 -78
  350. package/src/form/field_bindings/GeopointFieldBinding.tsx +0 -200
  351. package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -574
  352. package/src/form/field_bindings/MapFieldBinding.tsx +0 -120
  353. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +0 -259
  354. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +0 -130
  355. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +0 -168
  356. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -94
  357. package/src/form/field_bindings/ReferenceFieldBinding.tsx +0 -146
  358. package/src/form/field_bindings/RelationFieldBinding.tsx +0 -202
  359. package/src/form/field_bindings/RepeatFieldBinding.tsx +0 -143
  360. package/src/form/field_bindings/SelectFieldBinding.tsx +0 -111
  361. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +0 -521
  362. package/src/form/field_bindings/SwitchFieldBinding.tsx +0 -70
  363. package/src/form/field_bindings/TextFieldBinding.tsx +0 -189
  364. package/src/form/field_bindings/UserSelectFieldBinding.tsx +0 -71
  365. package/src/form/field_bindings/VectorFieldBinding.tsx +0 -209
  366. package/src/form/form_utils.ts +0 -243
  367. package/src/form/index.tsx +0 -36
  368. package/src/form/useClearRestoreValue.tsx +0 -36
  369. package/src/form/useUndoableDiscard.ts +0 -39
  370. package/src/form/validation.ts +0 -583
  371. package/src/hooks/index.ts +0 -16
  372. package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +0 -22
  373. package/src/hooks/navigation/contexts/NavigationStateContext.tsx +0 -16
  374. package/src/hooks/navigation/contexts/UrlContext.tsx +0 -24
  375. package/src/hooks/navigation/contexts/index.ts +0 -14
  376. package/src/hooks/navigation/useAsyncResolver.ts +0 -100
  377. package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +0 -218
  378. package/src/hooks/navigation/useBuildNavigationStateController.tsx +0 -134
  379. package/src/hooks/navigation/useBuildUrlController.tsx +0 -66
  380. package/src/hooks/navigation/useNavigationResolution.ts +0 -271
  381. package/src/hooks/navigation/useResolvedCollections.ts +0 -102
  382. package/src/hooks/navigation/useResolvedViews.tsx +0 -139
  383. package/src/hooks/navigation/useTopLevelNavigation.ts +0 -273
  384. package/src/hooks/navigation/utils.ts +0 -200
  385. package/src/hooks/useAdminContext.tsx +0 -83
  386. package/src/hooks/useBreadcrumbsController.tsx +0 -17
  387. package/src/hooks/useBuildSideDialogsController.tsx +0 -145
  388. package/src/hooks/useBuildSidePanel.tsx +0 -315
  389. package/src/hooks/useChildViewSource.ts +0 -46
  390. package/src/hooks/useEntityDisplay.tsx +0 -262
  391. package/src/hooks/useEntityDisplayTitle.tsx +0 -49
  392. package/src/hooks/useHistory.ts +0 -178
  393. package/src/hooks/useRecordActions.tsx +0 -69
  394. package/src/hooks/useResolvedNavigationFrom.tsx +0 -167
  395. package/src/hooks/useResolvedUsers.ts +0 -148
  396. package/src/hooks/useSelectionDialog.tsx +0 -58
  397. package/src/hooks/useSideDialogsController.tsx +0 -25
  398. package/src/hooks/useSidePanel.tsx +0 -13
  399. package/src/index.ts +0 -124
  400. package/src/preview/PropertyPreview.tsx +0 -331
  401. package/src/preview/compact_text.ts +0 -68
  402. package/src/preview/components/ArrayEnumPreview.tsx +0 -39
  403. package/src/preview/components/BooleanPreview.tsx +0 -28
  404. package/src/preview/components/DatePreview.tsx +0 -106
  405. package/src/preview/components/EmptyValue.tsx +0 -10
  406. package/src/preview/components/EnumValuesChip.tsx +0 -39
  407. package/src/preview/components/ImagePreview.tsx +0 -144
  408. package/src/preview/components/InlineEntityListPreview.tsx +0 -42
  409. package/src/preview/components/ReferencePreview.tsx +0 -235
  410. package/src/preview/components/RelationPreview.tsx +0 -271
  411. package/src/preview/components/StorageThumbnail.tsx +0 -147
  412. package/src/preview/components/UrlComponentPreview.tsx +0 -116
  413. package/src/preview/components/UserPreview.tsx +0 -30
  414. package/src/preview/components/date_fns_locales.ts +0 -125
  415. package/src/preview/index.ts +0 -26
  416. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -73
  417. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -67
  418. package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +0 -77
  419. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -49
  420. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -70
  421. package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -79
  422. package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +0 -35
  423. package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -79
  424. package/src/preview/property_previews/MapPropertyPreview.tsx +0 -198
  425. package/src/preview/property_previews/NumberPropertyPreview.tsx +0 -39
  426. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +0 -276
  427. package/src/preview/property_previews/StringPropertyPreview.tsx +0 -70
  428. package/src/preview/util.ts +0 -39
  429. package/src/routes/CustomViewRoute.tsx +0 -33
  430. package/src/routes/RebaseRoute.tsx +0 -467
  431. package/src/routes/index.ts +0 -2
  432. package/src/types/components/EntityFormActionsProps.tsx +0 -20
  433. package/src/types/components/EntityFormProps.tsx +0 -119
  434. package/src/types/components/PropertyPreviewProps.tsx +0 -85
  435. package/src/types/components/formex.tsx +0 -2
  436. package/src/types/components/index.ts +0 -3
  437. package/src/types/fields.tsx +0 -340
  438. package/src/types/index.ts +0 -4
  439. package/src/util/dataControllerAdapter.ts +0 -88
  440. package/src/util/entity_actions.ts +0 -28
  441. package/src/util/index.ts +0 -5
  442. package/src/util/navigation_utils.ts +0 -89
  443. package/src/util/number_format.ts +0 -46
  444. package/src/util/previews.ts +0 -131
  445. package/src/util/propertyConfigMapper.ts +0 -134
  446. package/src/util/property_utils.tsx +0 -236
  447. package/src/util/resolutions.ts +0 -96
  448. package/src/util/view_constants.ts +0 -33
  449. package/src/util/view_mode.ts +0 -176
@@ -1,703 +0,0 @@
1
- import { useMemo } from "react";
2
- import type { Property, RelationProperty } from "@rebasepro/types";
3
- import type { Entity, EntityRelation } from "@rebasepro/types";
4
- import type { PropertyConfig, AdminCollection, EntityDisplayRole } from "@rebasepro/cms-types";
5
- import { getEntityImagePreviewPropertyKey } from "@rebasepro/app";
6
- import { getDisplayPropertyKey } from "@rebasepro/app";
7
- import { getLeadingRelationTitleKey, getTitlePropertyCandidates, looksLikeIdentifierValue } from "@rebasepro/app";
8
- import { getEntityFromCache } from "@rebasepro/app";
9
- import { getEntityPreviewKeys } from "../../util/previews";
10
- import { formatRelativeTime, getValueInPath } from "@rebasepro/utils";
11
- import type { AuthController } from "@rebasepro/cms-types";
12
- import { ChipColorScheme, CHIP_COLORS, CHIP_SEED_KEYS } from "@rebasepro/ui";
13
- import { useEntityDisplay } from "../../hooks/useEntityDisplay";
14
-
15
- /** Whether an authored relation yields many rows. Derived from its kind. */
16
- function relationCardinality(relation: { kind?: string; cardinality?: string } | undefined): "one" | "many" | undefined {
17
- if (!relation) return undefined;
18
- if (relation.kind === "via") return relation.cardinality as "one" | "many" | undefined;
19
- if (relation.kind === "hasMany" || relation.kind === "manyToMany") return "many";
20
- if (relation.kind === "belongsTo" || relation.kind === "hasOne") return "one";
21
- return relation.cardinality as "one" | "many" | undefined;
22
- }
23
-
24
-
25
- // ── Slot types ────────────────────────────────────────────────────────
26
-
27
- /**
28
- * A resolved "slot": what fills one display role for one record.
29
- *
30
- * `property` and `propertyKey` are set when the value was read off the record,
31
- * and absent when a `display` resolver computed it — a computed title has no
32
- * column behind it, so there is nothing to render it *as*. Renderers must go
33
- * through {@link SlotValue}, which makes that choice once: a property renders
34
- * with its own preview (an enum keeps its coloured chip, a date its format), a
35
- * computed value renders as text.
36
- */
37
- export interface PreviewSlot {
38
- property?: Property;
39
- propertyKey?: string;
40
- value: unknown;
41
- /**
42
- * Which display role this slot fills.
43
- *
44
- * Load-bearing for the computed case. Without a property there is nothing to
45
- * infer from, and "render it as text" is right for a title and wrong for an
46
- * image: a resolver that returned a URL had that URL printed inside the card's
47
- * image frame. The role is the one thing that distinguishes them, so it
48
- * travels with the slot rather than being re-derived at each call site.
49
- */
50
- role?: EntityDisplayRole;
51
- }
52
-
53
- /**
54
- * Date slot extends the base with a pre-formatted string.
55
- */
56
- export interface DatePreviewSlot extends PreviewSlot {
57
- formatted: string;
58
- }
59
-
60
- /**
61
- * A single resolved relation chip — one item to render as a compact chip.
62
- * For cardinality:"one" relations there will be one chip.
63
- * For cardinality:"many" there can be several (capped for layout stability).
64
- */
65
- export interface RelationChipItem {
66
- /** Human-readable display text for the chip */
67
- displayName: string;
68
- /** Relation ID */
69
- id: string | number;
70
- }
71
-
72
- /**
73
- * A resolved relation slot — groups all chips for one relation property.
74
- */
75
- export interface RelationChipSlot {
76
- /** The relation property definition */
77
- property: RelationProperty;
78
- /** The property key on this entity (e.g. "author", "tags") */
79
- propertyKey: string;
80
- /** The relation property's user-facing name (e.g. "Author", "Tags") */
81
- label: string;
82
- /** Resolved chip items (display names extracted from eagerly-loaded data) */
83
- items: RelationChipItem[];
84
- /** Total count (for "many" relations that exceed the chip cap) */
85
- totalCount: number;
86
- /** Deterministic color for this relation property */
87
- colorScheme: ChipColorScheme;
88
- }
89
-
90
- /**
91
- * Fixed set of preview slots resolved from any entity + collection.
92
- *
93
- * Every view (list, card, board) consumes these same slots and decides
94
- * which ones to render and how. This eliminates duplicated inference
95
- * logic across view components.
96
- */
97
- export interface EntityPreviewSlots {
98
- /** MEDIA — image thumbnail or `undefined` (view falls back to icon) */
99
- image: PreviewSlot | undefined;
100
- /** PRIMARY — title / name field */
101
- title: PreviewSlot | undefined;
102
- /** SECONDARY — subtitle or short description (first non-title text field) */
103
- subtitle: PreviewSlot | undefined;
104
- /** RELATIONS — compact chips for all relation properties (one + many) */
105
- relations: RelationChipSlot[];
106
- /** STATUS — enum chip (first enum field that isn't the title) */
107
- status: PreviewSlot | undefined;
108
- /** META — date / timestamp */
109
- date: DatePreviewSlot | undefined;
110
- /**
111
- * TAGS — free chips beside the status.
112
- *
113
- * Declared only. Every other role has an inference ladder behind it, and
114
- * this one deliberately does not: there is no "first enum" or "looks like a
115
- * timestamp" that means *labels*, so guessing would scatter arbitrary chips
116
- * across every row of every panel that never asked for them.
117
- *
118
- * The role existed on `EntityDisplay` and in `useEntityDisplay` before this
119
- * field did, which is why a declared `display.tags` resolved correctly and
120
- * then had nowhere to go.
121
- */
122
- tags: PreviewSlot | undefined;
123
- /** Entity ID (always available) */
124
- entityId: string | number;
125
- }
126
-
127
- // ── Collection-level slot resolution (entity-independent) ─────────────
128
-
129
- /**
130
- * Resolved property keys per slot. This is the expensive part (walks
131
- * all properties) so we memoize it at the collection level, not per entity.
132
- */
133
- export interface CollectionSlotKeys {
134
- titleKey: string | undefined;
135
- /** Every property that could act as the title, best first (see `getTitlePropertyCandidates`) */
136
- titleKeyCandidates: string[];
137
- imageKey: string | undefined;
138
- subtitleKey: string | undefined;
139
- relationKeys: string[];
140
- statusKey: string | undefined;
141
- dateKey: string | undefined;
142
- /** Declared only — see {@link EntityPreviewSlots.tags}. */
143
- tagsKey: string | undefined;
144
- }
145
-
146
- /**
147
- * Resolve which property key fills each slot for a given collection.
148
- * Pure function — call inside `useMemo`.
149
- */
150
- export function resolveCollectionSlotKeys(
151
- collection: AdminCollection<Record<string, unknown>>,
152
- authController: AuthController,
153
- propertyConfigs: Record<string, PropertyConfig>
154
- ): CollectionSlotKeys {
155
- // One row per entity: when the collection leads with a relation and holds no
156
- // name of its own, that relation *is* what the row is called. See
157
- // `getLeadingRelationTitleKey` — the general ranking keeps relations last,
158
- // which is right for a detail header but leaves a junction row titleless.
159
- const rankedCandidates = getTitlePropertyCandidates(collection);
160
- const leadingRelationKey = getLeadingRelationTitleKey(collection);
161
- const titleKeyCandidates = leadingRelationKey
162
- ? [leadingRelationKey, ...rankedCandidates.filter(key => key !== leadingRelationKey)]
163
- : rankedCandidates;
164
- const titleKey = titleKeyCandidates[0];
165
- // `getEntityImagePreviewPropertyKey` prefers `display.image` itself, so
166
- // every caller of it — this, the reference card, the board — agrees.
167
- const imageKey = getEntityImagePreviewPropertyKey(collection);
168
-
169
- // Status: declared, else the first string-enum that isn't the title.
170
- //
171
- // Everything below this line is inference — "the first enum", "a key that
172
- // looks like a timestamp", "the longest remaining string". It is a good
173
- // guess and it is only a guess, so a collection that states the role wins
174
- // outright and the ladder is skipped. That is the whole point of
175
- // `admin.display`: the heuristics stay for the collections that never say
176
- // anything, and stop overruling the ones that do.
177
- let statusKey: string | undefined = getDisplayPropertyKey(collection, "status");
178
-
179
- // 1. Explicitly defined in previewProperties
180
- if (!statusKey && collection.previewProperties) {
181
- for (const key of collection.previewProperties) {
182
- const p = collection.properties[key] as Property | undefined;
183
- if (p?.type === "string" && "enum" in p && p.enum && key !== titleKey) {
184
- statusKey = key;
185
- break;
186
- }
187
- }
188
- }
189
-
190
- // 2. Explicitly defined in propertiesOrder
191
- if (!statusKey && collection.propertiesOrder) {
192
- for (const key of collection.propertiesOrder) {
193
- if (typeof key === "string" && !key.startsWith("subcollection:")) {
194
- const p = collection.properties[key] as Property | undefined;
195
- if (p?.type === "string" && "enum" in p && p.enum && key !== titleKey) {
196
- statusKey = key;
197
- break;
198
- }
199
- }
200
- }
201
- }
202
-
203
- // 3. Default automatic inference
204
- if (!statusKey) {
205
- for (const [key, prop] of Object.entries(collection.properties)) {
206
- const p = prop as Property;
207
- if (p.type === "string" && "enum" in p && p.enum && key !== titleKey) {
208
- statusKey = key;
209
- break;
210
- }
211
- }
212
- }
213
-
214
- // Date: declared, else a well-known timestamp field, else any date
215
- let dateKey: string | undefined = getDisplayPropertyKey(collection, "date");
216
- const dateCandidates = ["updated_at", "updatedAt", "modified_at", "modifiedAt", "created_at", "createdAt"];
217
- if (!dateKey) {
218
- for (const candidate of dateCandidates) {
219
- if (collection.properties[candidate]) {
220
- dateKey = candidate;
221
- break;
222
- }
223
- }
224
- }
225
- if (!dateKey) {
226
- for (const [key, prop] of Object.entries(collection.properties)) {
227
- const p = prop as Property;
228
- if (p.type === "date") {
229
- dateKey = key;
230
- break;
231
- }
232
- }
233
- }
234
-
235
- // Relations: collect relation property keys for chip rendering.
236
- // When propertiesOrder is explicitly set, skip this — relations will
237
- // be shown in the developer-defined order, not as separate chips.
238
- const hasExplicitOrder = !!(collection.propertiesOrder as string[] | undefined);
239
- const relationKeys: string[] = [];
240
- if (!hasExplicitOrder) {
241
- for (const [key, prop] of Object.entries(collection.properties)) {
242
- const p = prop as Property;
243
- // The relation filling the title slot is already the row's headline;
244
- // repeating it as a chip below says the same thing twice.
245
- if (p.type === "relation" && key !== titleKey) {
246
- relationKeys.push(key);
247
- }
248
- }
249
- }
250
-
251
- // Subtitle: first preview key that isn't title/image/status/date/id.
252
- // When propertiesOrder is not set, also exclude relation keys (they render as chips).
253
- // Prefer string fields (especially multiline/description-like) over numbers.
254
- const excludeKeys = new Set([titleKey, imageKey, statusKey, dateKey, ...relationKeys]);
255
- const previewKeys = getEntityPreviewKeys(authController, collection, propertyConfigs, undefined, 10)
256
- .filter(k => !excludeKeys.has(k) && k !== "id");
257
-
258
- // When propertiesOrder is set, respect the developer-defined order (no re-sorting).
259
- // When not set, sort: strings first (prefer multiline → good description candidate).
260
- const sortedPreviewKeys = hasExplicitOrder
261
- ? previewKeys
262
- : [...previewKeys].sort((a, b) => {
263
- const propA = collection.properties[a] as Property | undefined;
264
- const propB = collection.properties[b] as Property | undefined;
265
- const scoreA = propA?.type === "string" ? (propA.admin?.multiline ? 2 : 1) : 0;
266
- const scoreB = propB?.type === "string" ? (propB.admin?.multiline ? 2 : 1) : 0;
267
- return scoreB - scoreA;
268
- });
269
- const subtitleKey = getDisplayPropertyKey(collection, "subtitle")
270
- ?? (sortedPreviewKeys.length > 0 ? sortedPreviewKeys[0] : undefined);
271
-
272
- return { titleKey,
273
- titleKeyCandidates,
274
- imageKey,
275
- subtitleKey,
276
- relationKeys,
277
- statusKey,
278
- dateKey,
279
- tagsKey: getDisplayPropertyKey(collection, "tags") };
280
- }
281
-
282
- // ── Image unwrapping helper ───────────────────────────────────────────
283
-
284
- /**
285
- * Unwrap image property + value from potential array-of-images.
286
- * Returns `{ property, value }` where property is the *inner* property
287
- * and value is the first element (for arrays) or the raw value.
288
- */
289
- function resolveImageSlot(
290
- collection: AdminCollection<Record<string, unknown>>,
291
- imageKey: string,
292
- entity: Entity<Record<string, unknown>>
293
- ): PreviewSlot | undefined {
294
- const imageProperty = collection.properties[imageKey];
295
- if (!imageProperty) return undefined;
296
-
297
- const ofProp = "of" in imageProperty ? imageProperty.of : undefined;
298
- const resolvedProperty = ofProp
299
- ? (Array.isArray(ofProp) ? ofProp[0] : ofProp)
300
- : imageProperty;
301
-
302
- const rawValue = getValueInPath(entity.values, imageKey);
303
- const resolvedValue = ofProp
304
- ? (((rawValue as unknown[]) ?? []).length > 0 ? (rawValue as unknown[])[0] : undefined)
305
- : rawValue;
306
-
307
- if (resolvedValue === undefined || resolvedValue === null) return undefined;
308
-
309
- return {
310
- role: "image",
311
- property: resolvedProperty as Property,
312
- propertyKey: imageKey,
313
- value: resolvedValue
314
- };
315
- }
316
-
317
- // ── Title resolution (entity-level) ───────────────────────────────────
318
-
319
- /**
320
- * Walk the collection's ranked title candidates and return the first one that
321
- * holds something a person can read for this entity. Candidates are already
322
- * ordered and free of identifier properties; this only rejects values —
323
- * empties, and strings that turn out to be an id at runtime.
324
- */
325
- function resolveEntityTitleKey(
326
- entity: Entity<Record<string, unknown>>,
327
- candidates: string[]
328
- ): string | undefined {
329
- for (const key of candidates) {
330
- const value = getValueInPath(entity.values, key);
331
- if (value === undefined || value === null || value === "") continue;
332
- if (typeof value === "string") {
333
- if (looksLikeIdentifierValue(value)) continue;
334
- if (value === String(entity.id)) continue;
335
- }
336
- return key;
337
- }
338
- return candidates[0];
339
- }
340
-
341
- // ── Date formatting ───────────────────────────────────────────────────
342
-
343
- function formatDateValue(value: unknown): string {
344
- if (!value) return "";
345
- const date = value instanceof Date ? value : new Date(value as string | number);
346
- if (isNaN(date.getTime())) return String(value);
347
-
348
- const now = new Date();
349
- // A date slot holds whatever property the collection points it at, which is
350
- // as often a due or publish date as a `updated_at`. `formatRelativeTime`
351
- // reads the sign, so a scheduled date says "in 3d" instead of "Just now".
352
- const relative = formatRelativeTime(date, { now });
353
- if (relative) return relative;
354
-
355
- return date.toLocaleDateString(undefined, {
356
- month: "short",
357
- day: "numeric",
358
- year: date.getFullYear() !== now.getFullYear() ? "numeric" : undefined
359
- });
360
- }
361
-
362
- // ── Hook: collection-level slot keys ──────────────────────────────────
363
-
364
- /**
365
- * Resolves which property key fills each preview slot for a collection.
366
- * Memoized — only recomputes when the collection definition changes.
367
- *
368
- * Use this in the parent list/grid component, then pass the result to
369
- * `resolveEntitySlots` for each entity row.
370
- */
371
- export function useCollectionSlotKeys(
372
- collection: AdminCollection<Record<string, unknown>>,
373
- authController: AuthController,
374
- propertyConfigs: Record<string, PropertyConfig>
375
- ): CollectionSlotKeys {
376
- return useMemo(
377
- () => resolveCollectionSlotKeys(collection, authController, propertyConfigs),
378
- [collection, authController, propertyConfigs]
379
- );
380
- }
381
-
382
- // ── Pure function: entity-level slot resolution ───────────────────────
383
-
384
- /**
385
- * Resolve concrete slot values for a single entity.
386
- * This is a pure function (no hooks) so it can be called inside
387
- * `React.memo` render functions or loops without violating hook rules.
388
- */
389
- export function resolveEntitySlots(
390
- entity: Entity<Record<string, unknown>>,
391
- collection: AdminCollection<Record<string, unknown>>,
392
- slotKeys: CollectionSlotKeys
393
- ): EntityPreviewSlots {
394
- const { titleKey, titleKeyCandidates, imageKey, subtitleKey, relationKeys, statusKey, dateKey, tagsKey } = slotKeys;
395
-
396
- // Image
397
- const image = imageKey ? resolveImageSlot(collection, imageKey, entity) : undefined;
398
-
399
- // Title — the best-ranked candidate that carries a readable value for THIS
400
- // entity, so a row whose name is empty (or whose column happens to hold a
401
- // UUID) falls through to the next candidate instead of showing an id.
402
- const resolvedTitleKey = resolveEntityTitleKey(entity, titleKeyCandidates ?? (titleKey ? [titleKey] : []));
403
- let title: PreviewSlot | undefined;
404
- if (resolvedTitleKey) {
405
- const prop = collection.properties[resolvedTitleKey] as Property | undefined;
406
- const val = getValueInPath(entity.values, resolvedTitleKey);
407
- if (prop) title = { role: "title",
408
- property: prop,
409
- propertyKey: resolvedTitleKey,
410
- value: val };
411
- }
412
-
413
- // Subtitle
414
- let subtitle: PreviewSlot | undefined;
415
- if (subtitleKey && subtitleKey !== resolvedTitleKey) {
416
- const prop = collection.properties[subtitleKey] as Property | undefined;
417
- const val = getValueInPath(entity.values, subtitleKey);
418
- if (prop && val !== undefined && val !== null && val !== "") {
419
- subtitle = { role: "subtitle",
420
- property: prop,
421
- propertyKey: subtitleKey,
422
- value: val };
423
- }
424
- }
425
-
426
- // Relations — resolve chip items for every relation property
427
- const relations: RelationChipSlot[] = [];
428
- const MAX_CHIPS_PER_RELATION = 3;
429
-
430
- for (const relKey of relationKeys) {
431
- const prop = collection.properties[relKey] as RelationProperty | undefined;
432
- if (!prop || prop.type !== "relation") continue;
433
-
434
- const val = getValueInPath(entity.values, relKey);
435
- if (val === undefined || val === null) continue;
436
-
437
- const items: RelationChipItem[] = [];
438
- let totalCount = 0;
439
-
440
- const isMany = relationCardinality(prop.relation) === "many";
441
-
442
- if (isMany && Array.isArray(val)) {
443
- // cardinality:"many" → array of EntityRelation
444
- totalCount = val.length;
445
- for (let i = 0; i < Math.min(val.length, MAX_CHIPS_PER_RELATION); i++) {
446
- const rel = val[i];
447
- if (rel && typeof rel === "object") {
448
- const displayName = resolveRelationDisplayName(rel as EntityRelation, prop);
449
- const id = (rel as EntityRelation).id ?? i;
450
- if (displayName) {
451
- items.push({ displayName,
452
- id });
453
- }
454
- }
455
- }
456
- } else if (!isMany && val && typeof val === "object") {
457
- // cardinality:"one" → single EntityRelation
458
- const obj = val as Record<string, unknown>;
459
- const isRelation = ("__type" in obj && obj.__type === "relation")
460
- || (typeof obj.isEntityRelation === "function"
461
- && (obj.isEntityRelation as () => boolean)());
462
- if (isRelation) {
463
- const relation = obj as unknown as EntityRelation;
464
- const displayName = resolveRelationDisplayName(relation, prop);
465
- totalCount = 1;
466
- if (displayName) {
467
- items.push({ displayName,
468
- id: relation.id });
469
- }
470
- }
471
- }
472
-
473
- if (items.length > 0) {
474
- const relIndex = relationKeys.indexOf(relKey);
475
- // Walking the seed keys rather than `Object.values`: the table also
476
- // holds a bare-hue alias per hue, so raw values would hand the first
477
- // two relations the same scheme.
478
- const colorScheme = CHIP_COLORS[CHIP_SEED_KEYS[relIndex % CHIP_SEED_KEYS.length]];
479
- relations.push({
480
- property: prop,
481
- propertyKey: relKey,
482
- label: prop.name || relKey,
483
- items,
484
- totalCount,
485
- colorScheme
486
- });
487
- }
488
- }
489
-
490
- // Status
491
- let status: PreviewSlot | undefined;
492
- if (statusKey) {
493
- const prop = collection.properties[statusKey] as Property | undefined;
494
- const val = getValueInPath(entity.values, statusKey);
495
- if (prop && val !== undefined && val !== null) {
496
- status = { role: "status",
497
- property: prop,
498
- propertyKey: statusKey,
499
- value: val };
500
- }
501
- }
502
-
503
- // Date
504
- let date: DatePreviewSlot | undefined;
505
- if (dateKey) {
506
- const prop = collection.properties[dateKey] as Property | undefined;
507
- const val = getValueInPath(entity.values, dateKey);
508
- if (prop && val !== undefined && val !== null) {
509
- date = {
510
- role: "date",
511
- property: prop,
512
- propertyKey: dateKey,
513
- value: val,
514
- formatted: formatDateValue(val)
515
- };
516
- }
517
- }
518
-
519
- // Tags — declared only, and empty means absent: an empty array is "this
520
- // record has no labels", which must render as nothing rather than as an
521
- // empty chip row that shifts every other slot down.
522
- let tags: PreviewSlot | undefined;
523
- if (tagsKey) {
524
- const prop = collection.properties[tagsKey] as Property | undefined;
525
- const val = getValueInPath(entity.values, tagsKey);
526
- const empty = val === undefined || val === null || val === ""
527
- || (Array.isArray(val) && val.length === 0);
528
- if (prop && !empty) {
529
- tags = { role: "tags",
530
- property: prop,
531
- propertyKey: tagsKey,
532
- value: val };
533
- }
534
- }
535
-
536
- return {
537
- image,
538
- title,
539
- subtitle,
540
- relations,
541
- status,
542
- date,
543
- tags,
544
- entityId: entity.id
545
- };
546
- }
547
-
548
- // ── Relation display name resolution ─────────────────────────────────
549
-
550
- /**
551
- * Extract a human-readable display name from an eagerly-loaded EntityRelation.
552
- * Uses the target collection's title property when available, otherwise
553
- * walks the entity values for the first short string.
554
- */
555
- function resolveRelationDisplayName(
556
- relation: EntityRelation | Record<string, unknown>,
557
- prop: RelationProperty
558
- ): string | undefined {
559
- // Support both EntityRelation instances and plain objects
560
- const data = "data" in relation ? (relation as EntityRelation).data : undefined;
561
-
562
- // Resolve target collection from either `prop.relation.target()` or `prop.relation?.target()` (inline API)
563
- let targetCollection: AdminCollection | undefined;
564
- try {
565
- const resolved = prop.relation?.target?.() ?? (typeof prop.relation?.target === "function" ? prop.relation?.target() : undefined);
566
- if (resolved && typeof resolved === "object") {
567
- targetCollection = resolved as AdminCollection;
568
- }
569
- } catch {
570
- // Target collection may not be resolvable
571
- }
572
-
573
- // Helper: extract display name from entity values using the target collection
574
- //
575
- // This used to carry a ranking of its own — priority keys `name/title/label/
576
- // displayName`, then the first visible non-id string — which is a *seventh*
577
- // answer to "what is this record called", and one that disagreed with the
578
- // shared one: it read `titleProperty` with a flat lookup (so a dotted path
579
- // was ignored), never saw `display.title`, and ranked by key name where the
580
- // shared ranking excludes identifiers structurally. A chip and the record it
581
- // points at could therefore be labelled differently on the same screen.
582
- //
583
- // What is left here is the part that is genuinely local: a relation carries
584
- // *eagerly loaded* values, not an entity, so a resolver cannot run against
585
- // it — a computed title falls back to the ranked property, which is the same
586
- // thing the list row shows while its own resolver is in flight.
587
- const extractDisplayName = (values: Record<string, unknown>): string | undefined => {
588
- if (targetCollection) {
589
- for (const key of getTitlePropertyCandidates(targetCollection)) {
590
- const value = getValueInPath(values, key);
591
- if (value === undefined || value === null || value === "") continue;
592
- if (typeof value === "string" && looksLikeIdentifierValue(value)) continue;
593
- return String(value);
594
- }
595
- }
596
- // Generic fallback: walk entity values for any short string.
597
- for (const [, v] of Object.entries(values)) {
598
- if (typeof v === "string" && v.length > 0 && v.length < 200) {
599
- return v;
600
- }
601
- }
602
- return undefined;
603
- };
604
-
605
- // 1. Try eagerly-loaded data on the relation object
606
- if (data && data.values) {
607
- const result = extractDisplayName(data.values as Record<string, unknown>);
608
- if (result) return result;
609
- }
610
-
611
- const id = "id" in relation ? relation.id : undefined;
612
-
613
- // 2. Try the entity cache (sessionStorage) as a fallback
614
- if (id !== undefined && targetCollection) {
615
- try {
616
- const slug = targetCollection.slug ?? ("table" in targetCollection ? targetCollection.table : undefined);
617
- if (slug) {
618
- const cacheKey = `${slug}/${id}`;
619
- const cached = getEntityFromCache(cacheKey) as { values?: Record<string, unknown> } | undefined;
620
- if (cached?.values) {
621
- const result = extractDisplayName(cached.values);
622
- if (result) return result;
623
- }
624
- }
625
- } catch {
626
- // Cache lookup failed — fall through
627
- }
628
- }
629
-
630
- // 3. Final fallback: show the ID
631
- return id !== undefined ? String(id) : undefined;
632
- }
633
-
634
- /**
635
- * The slots for one record, with `admin.display` resolvers applied.
636
- *
637
- * {@link resolveEntitySlots} answers the question from values already in hand —
638
- * which is everything a slot filled by a property needs, and nothing a slot
639
- * filled by a *resolver* can use. A computed title may have to be fetched, so it
640
- * arrives after the first render; this hook is where the two meet.
641
- *
642
- * Until a resolver lands, the derived slot shows. That is deliberate: a list of
643
- * fifty rows must not blank its titles for a beat while fifty promises settle,
644
- * and the derived answer — the best-ranked property carrying a readable value —
645
- * is a reasonable thing to be looking at meanwhile. When the resolved value
646
- * arrives it replaces the slot outright, property and all, because there is no
647
- * property behind a computed value (see {@link PreviewSlot}).
648
- *
649
- * Every role is hooked unconditionally, so the hook order is fixed regardless of
650
- * what a given collection declares.
651
- */
652
- export function useEntitySlots(
653
- entity: Entity<Record<string, unknown>>,
654
- collection: AdminCollection<Record<string, unknown>>,
655
- slotKeys: CollectionSlotKeys
656
- ): EntityPreviewSlots {
657
-
658
- const derived = useMemo(
659
- () => resolveEntitySlots(entity, collection, slotKeys),
660
- [entity, collection, slotKeys]
661
- );
662
-
663
- const params = { collection,
664
- entity };
665
- const title = useEntityDisplay<string>("title", params);
666
- const subtitle = useEntityDisplay<string>("subtitle", params);
667
- const image = useEntityDisplay<string>("image", params);
668
- const status = useEntityDisplay<string>("status", params);
669
- const date = useEntityDisplay<Date | string | number>("date", params);
670
- const tags = useEntityDisplay<string[] | string>("tags", params);
671
-
672
- return useMemo(() => {
673
- // `source` is set only when the value came from a property, so its
674
- // absence is exactly the "this was computed" signal — no second flag to
675
- // keep in step with the first.
676
- // The role travels with the computed slot too. It is the only thing left
677
- // to say about a value with no property behind it, and `SlotValue` needs
678
- // it to tell a computed image from a computed title.
679
- const computed = (
680
- role: EntityDisplayRole,
681
- resolved: { value: unknown, source?: unknown }
682
- ): PreviewSlot | undefined =>
683
- resolved.value !== undefined && resolved.source === undefined
684
- ? { role,
685
- value: resolved.value }
686
- : undefined;
687
-
688
- const computedDate = computed("date", date);
689
-
690
- return {
691
- ...derived,
692
- title: computed("title", title) ?? derived.title,
693
- subtitle: computed("subtitle", subtitle) ?? derived.subtitle,
694
- image: computed("image", image) ?? derived.image,
695
- status: computed("status", status) ?? derived.status,
696
- date: computedDate
697
- ? { ...computedDate,
698
- formatted: formatDateValue(computedDate.value) }
699
- : derived.date,
700
- tags: computed("tags", tags) ?? derived.tags
701
- };
702
- }, [derived, title, subtitle, image, status, date, tags]);
703
- }