@rebasepro/cms 0.17.3 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,761 +0,0 @@
1
-
2
- import type { AdditionalFieldDelegateProps } from "@rebasepro/cms-types";
3
- import type { FormContext, PropertyFieldBindingProps } from "../types/fields";
4
- import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
5
- import { Entity, EntityStatus, EntityValues } from "@rebasepro/types";
6
- import type { EntityFormProps } from "../types/components/EntityFormProps";
7
- import { deepEqual as equal } from "fast-equals";
8
-
9
- import { ErrorBoundary } from "@rebasepro/ui";
10
- import { AlignLeftIcon, useDebouncedCallback } from "@rebasepro/ui";
11
- import { getDefaultValuesFor } from "@rebasepro/common";
12
- import { isDisabled, isReadOnly } from "@rebasepro/app";
13
-
14
- import { getFormFieldKeys, resolveFormLayout } from "@rebasepro/app";
15
- import type { ResolvedFormField } from "@rebasepro/app";
16
- import { Alert, Button, cls, defaultBorderMixin, Dialog, DialogActions, DialogContent, DialogTitle, paperMixin, Typography } from "@rebasepro/ui";
17
- import { Formex, FormexController, useCreateFormex } from "@rebasepro/forms";
18
-
19
- import { FieldBlock, isSelfLabellingProperty, LABEL_ICON_SIZE, spanClass } from "./components/FieldBlock";
20
- import { AdditionalFieldValue } from "../components/AdditionalFieldValue";
21
- import { FormRail, RecordMeta } from "./components/FormRail";
22
- import { FormSections } from "./components/FormSections";
23
- import { useRailVisible } from "./components/useRailVisible";
24
- import { PropertyFieldBinding } from "./PropertyFieldBinding";
25
- import { flattenKeys } from "@rebasepro/app";
26
- import { ErrorFocus } from "./components/ErrorFocus";
27
- import { CustomFieldValidator, getEntitySchema } from "./validation";
28
- import { EntityFormActions } from "./EntityFormActions";
29
- import type { EntityFormActionsProps } from "../types/components/EntityFormActionsProps";
30
- import { LocalChangesMenu } from "./components/LocalChangesMenu";
31
- import { useUndoableDiscard } from "./useUndoableDiscard";
32
-
33
- import { mergeDeep } from "@rebasepro/utils";
34
- import {
35
- getChanges,
36
- zodToFormErrors
37
- } from "./form_utils";
38
-
39
- /**
40
- * Headless entity form component.
41
- *
42
- * Renders a form for a entity collection without any admin or backend dependencies.
43
- * All backend concerns (save, caching, analytics, plugin slots) are provided via
44
- * callback props. For admin-connected usage, use {@link EntityFormBinding} instead.
45
- *
46
- * @group Components
47
- */
48
- export function EntityForm<M extends Record<string, unknown>>({
49
- path,
50
- entityId: entityIdProp,
51
- collection,
52
- onValuesModified,
53
- onIdChange,
54
- onSaved,
55
- entity,
56
- initialDirtyValues,
57
- onFormContextReady,
58
- initialStatus,
59
- className,
60
- onStatusChange,
61
- onEntityChange,
62
- openEntityMode = "full_screen",
63
- formex: formexProp,
64
- disabled: disabledProp,
65
- Builder,
66
- EntityFormActionsComponent = EntityFormActions,
67
- showDefaultActions = true,
68
- navigateBack: navigateBackProp,
69
- children,
70
- // Headless callback props
71
- onSubmit: onSubmitProp,
72
- onValuesChangeDeferred: onValuesChangeDeferredProp,
73
- onReset: onResetProp,
74
- uniqueFieldValidator: uniqueFieldValidatorProp,
75
- // Slots
76
- beforeFields,
77
- afterFields,
78
- pluginActions: pluginActionsProp,
79
- // Local changes (managed externally)
80
- computedInitialValues,
81
- hasLocalChanges: hasLocalChangesProp,
82
- localChangesData,
83
- manualApplyLocalChanges,
84
- localChangesCacheKey,
85
- onClearLocalChanges
86
- }: EntityFormProps<M>) {
87
-
88
- const navigateBack = useCallback(() => {
89
- if (navigateBackProp) {
90
- navigateBackProp();
91
- }
92
- }, [navigateBackProp]);
93
-
94
- const [status, setStatus] = useState<EntityStatus>(initialStatus);
95
-
96
- const updateStatus = (status: EntityStatus) => {
97
- setStatus(status);
98
- onStatusChange?.(status);
99
- };
100
-
101
- const [valuesToBeSaved, setValuesToBeSaved] = useState<EntityValues<M> | undefined>(undefined);
102
- useDebouncedCallback(valuesToBeSaved, () => {
103
- if (valuesToBeSaved && onSubmitProp) {
104
- setIsSavingAutoSave(true);
105
- Promise.resolve(onSubmitProp(valuesToBeSaved, formex))
106
- .finally(() => setIsSavingAutoSave(false));
107
- }
108
- }, false, 2000);
109
-
110
- const [underlyingChanges] = useState<Partial<EntityValues<M>>>({});
111
-
112
- const initialEntityId: string | number | undefined = useMemo(() => {
113
- if (status === "new" || status === "copy") {
114
- return undefined;
115
- } else {
116
- return entityIdProp;
117
- }
118
- }, [entityIdProp, status]);
119
-
120
- const [entityId, setEntityId] = useState<string | number | undefined>(initialEntityId);
121
- const [savingError, setSavingError] = useState<Error | undefined>();
122
- const [isSavingAutoSave, setIsSavingAutoSave] = useState<boolean>(false);
123
- const [discardDialogOpen, setDiscardDialogOpen] = useState<boolean>(false);
124
-
125
- const discard = useUndoableDiscard();
126
-
127
- const autoSave = collection.formAutoSave;
128
-
129
- // Use externally computed initial values if provided, otherwise compute from entity + collection
130
- const baseInitialValues = useMemo(() => {
131
- if (computedInitialValues !== undefined) {
132
- return computedInitialValues;
133
- }
134
- // Fallback: compute from entity/collection (requires authController from context)
135
- // In headless mode without computedInitialValues, use entity values or defaults
136
- if ((status === "existing" || status === "copy") && entity) {
137
- return entity.values ?? getDefaultValuesFor(collection.properties);
138
- }
139
- return getDefaultValuesFor(collection.properties);
140
- }, [computedInitialValues, collection.properties, status, entity]);
141
-
142
- const [localChangesCleared, setLocalChangesCleared] = useState<boolean>(false);
143
-
144
- const hasLocalChanges = hasLocalChangesProp !== undefined
145
- ? (hasLocalChangesProp && !localChangesCleared)
146
- : false;
147
-
148
- const onSubmit = (values: EntityValues<M>, formexController: FormexController<EntityValues<M>>) => {
149
-
150
- setSavingError(undefined);
151
-
152
- if (status === "existing") {
153
- if (!entity?.id) throw Error("Form misconfiguration when saving, no id for existing entity");
154
- } else if (status !== "new" && status !== "copy") {
155
- throw Error("New FormType added, check EntityForm");
156
- }
157
-
158
- if (!onSubmitProp) {
159
- console.warn("EntityForm: no onSubmit callback provided. Form submission has no effect.");
160
- formexController.setSubmitting(false);
161
- return;
162
- }
163
-
164
- return Promise.resolve(save(values))
165
- ?.then((savedEntity) => {
166
- if (savedEntity) {
167
- formexController.resetForm({
168
- values: savedEntity.values || values,
169
- submitCount: 0,
170
- touched: {}
171
- });
172
- }
173
- })
174
- .finally(() => {
175
- formexController.setSubmitting(false);
176
- });
177
- };
178
-
179
- /**
180
- * What the form opens showing, when that is not what is stored — an edit
181
- * carried over from the side panel's "open full screen", or a draft
182
- * restored from the local-changes backup.
183
- *
184
- * The merge is deliberately *not* folded into the baseline. `mergeDeep`
185
- * used to produce a single `initialValues` that served as both, with a
186
- * `initialDirty: true` bolted on beside it to say what the baseline could
187
- * no longer show — and that flag survived exactly one render, because the
188
- * record's data arriving replaced the baseline and the form recomputed
189
- * dirty as false against a baseline that already contained the edit.
190
- *
191
- * Read once, at mount: this is a handoff, and re-reading it every render
192
- * tied the form to a cache that is cleared as soon as it has been consumed.
193
- */
194
- const initialModifiedValues = useRef(
195
- initialDirtyValues && Object.keys(initialDirtyValues).length > 0
196
- ? mergeDeep(baseInitialValues, initialDirtyValues)
197
- : undefined
198
- ).current;
199
-
200
- const internalFormex = useCreateFormex<M>({
201
- initialValues: baseInitialValues as M,
202
- initialModifiedValues: initialModifiedValues as M | undefined,
203
- debugId: `EntityForm:${path}/${entityIdProp}`,
204
- initialTouched: initialDirtyValues ?
205
- flattenKeys(initialDirtyValues!)
206
- .reduce((previousValue, currentValue) => ({
207
- ...previousValue,
208
- [currentValue]: true
209
- }), {})
210
- : {},
211
- onSubmit,
212
- onReset: () => {
213
- onResetProp?.();
214
- // The stored values — a reset returns the form to them, and by now
215
- // that is the baseline whether or not it was at mount.
216
- onValuesModified?.(false, baseInitialValues as M);
217
- },
218
- onValuesChangeDeferred: onValuesChangeDeferredProp,
219
- validation: async (values): Promise<Record<string, string>> => {
220
- if (!validationSchema) return {};
221
- const result = await validationSchema.safeParseAsync(values);
222
- if (result.success) return {};
223
- return zodToFormErrors(result.error);
224
- }
225
- });
226
- const formex: FormexController<M> = formexProp ?? internalFormex;
227
-
228
- useEffect(() => {
229
-
230
- const handleKeyDown = (e: KeyboardEvent) => {
231
- const isUndo = (e.metaKey || e.ctrlKey) && !e.shiftKey && e.key.toLowerCase() === "z";
232
- const isRedo =
233
- ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "z") ||
234
- ((e.metaKey || e.ctrlKey) && !e.shiftKey && e.key.toLowerCase() === "y");
235
- const isSave = (e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "s";
236
-
237
- if (isSave && !disabled && formex.dirty) {
238
- e.preventDefault();
239
- formex.handleSubmit();
240
- } else if (isUndo && formex.canUndo) {
241
- e.preventDefault();
242
- formex.undo();
243
- } else if (isRedo && formex.canRedo) {
244
- e.preventDefault();
245
- formex.redo();
246
- }
247
- };
248
-
249
- window.addEventListener("keydown", handleKeyDown);
250
- return () => window.removeEventListener("keydown", handleKeyDown);
251
-
252
- }, [formex]);
253
-
254
- const afterSave = (updatedEntity: Entity<M>) => {
255
- onResetProp?.();
256
- onValuesModified?.(false, updatedEntity.values);
257
- onEntityChange?.(updatedEntity);
258
- updateStatus("existing");
259
- setEntityId(updatedEntity.id);
260
-
261
- if (onSaved) {
262
- onSaved({
263
- entity: updatedEntity,
264
- status,
265
- path,
266
- entityId: updatedEntity.id,
267
- collection
268
- });
269
- }
270
- };
271
-
272
- const lastSavedValues = useRef<EntityValues<M> | undefined>(entity?.values);
273
- const save = async (values: EntityValues<M>): Promise<Entity<M> | void> => {
274
- const valuesToSave = status === "existing"
275
- ? getChanges(values, entity?.values || {}) as EntityValues<M>
276
- : values;
277
-
278
- if (status === "existing" && Object.keys(valuesToSave).length === 0 && entity) {
279
- return Promise.resolve(entity);
280
- }
281
-
282
- lastSavedValues.current = values;
283
-
284
- if (!onSubmitProp) {
285
- return;
286
- }
287
-
288
- const autoSaveEnabled = autoSave ?? false;
289
-
290
- if (autoSaveEnabled) {
291
- setValuesToBeSaved(values);
292
- return Promise.resolve();
293
- }
294
-
295
- return Promise.resolve(onSubmitProp(valuesToSave as M, formex))
296
- .then((result) => {
297
- if (result) {
298
- afterSave(result as Entity<M>);
299
- }
300
- return result as Entity<M> | void;
301
- })
302
- .catch(e => {
303
- console.error(e);
304
- setSavingError(e);
305
- });
306
- };
307
-
308
- const disabled = formex.isSubmitting || Boolean(disabledProp);
309
-
310
- const formContext: FormContext<M> = {
311
- setFieldValue: useCallback((key: string, value: unknown) => formex.setFieldValue(key, value), []),
312
- values: formex.values,
313
- collection,
314
- entityId: entityId as string,
315
- path,
316
- save,
317
- submit: formex.handleSubmit,
318
- formex,
319
- entity,
320
- savingError,
321
- status,
322
- openEntityMode,
323
- disabled,
324
- isSaving: formex.isSubmitting || isSavingAutoSave
325
- };
326
-
327
- useEffect(() => {
328
- onFormContextReady?.(formContext);
329
- // `formex.version` only moves on `resetForm`, so these deps used to hand
330
- // the container one snapshot at mount and never another. That was
331
- // invisible while Save lived inside the form and read `formex` directly;
332
- // once the identity bar owned Save, its `dirty` was frozen false and the
333
- // button never enabled — for any field, not just the one that exposed
334
- // it. Custom entity views read `formContext.values` through the same
335
- // channel and were reading a stale copy too.
336
- //
337
- // Deps are the state *transitions* a container cares about, not
338
- // `formex.values`: re-publishing on every keystroke would re-render the
339
- // whole entity view per character.
340
- }, [
341
- formex.version, collection, entityId, path,
342
- formex.dirty, formex.isSubmitting, formex.submitCount, isSavingAutoSave
343
- ]);
344
-
345
- const actionsDisabled = disabled || formex.isSubmitting || (status === "existing" && !formex.dirty) || Boolean(disabledProp);
346
-
347
- // The record's title is resolved by the container that renders the identity
348
- // bar (see `useEntityDisplayTitle`), not here — the form no longer draws a
349
- // heading of its own.
350
-
351
- const modified = formex.dirty;
352
-
353
- useEffect(() => {
354
- if (!autoSave) {
355
- onValuesModified?.(modified, formex.values);
356
- }
357
- }, [formex.dirty]);
358
-
359
- // Default no-op unique field validator — always passes
360
- const defaultUniqueFieldValidator: CustomFieldValidator = useCallback(async () => true, []);
361
-
362
- const uniqueFieldValidator: CustomFieldValidator = useMemo(() => {
363
- if (uniqueFieldValidatorProp) {
364
- return uniqueFieldValidatorProp as CustomFieldValidator;
365
- }
366
- return defaultUniqueFieldValidator;
367
- }, [uniqueFieldValidatorProp, defaultUniqueFieldValidator]);
368
-
369
- const validationSchema = useMemo(() => getEntitySchema(
370
- entityId,
371
- collection.properties,
372
- uniqueFieldValidator),
373
- [entityId, collection.properties, uniqueFieldValidator]);
374
-
375
- useOnAutoSave(autoSave, formex, lastSavedValues, save);
376
-
377
- useEffect(() => {
378
- if (!autoSave && !formex.isSubmitting && underlyingChanges && entity) {
379
- // we update the form fields from the driver data
380
- // if they were not touched
381
- Object.entries(underlyingChanges).forEach(([key, value]) => {
382
- const formValue = formex.values[key];
383
- if (!equal(value, formValue) && !formex.touched[key]) {
384
- console.debug("Updated value from the driver:", key, value);
385
- formex.setFieldValue(key, value !== undefined ? value : null);
386
- }
387
- });
388
- }
389
- }, [formex.isSubmitting, autoSave, underlyingChanges, entity, formex.values, formex.touched, formex.setFieldValue]);
390
-
391
- const formFieldKeys = getFormFieldKeys(collection);
392
-
393
- const layout = useMemo(() => resolveFormLayout({
394
- collection,
395
- fieldKeys: formFieldKeys,
396
- status
397
- }), [collection, formFieldKeys.join(","), status]);
398
-
399
- const formElementRef = useRef<HTMLFormElement>(null);
400
- // Measured, not a breakpoint: the rail holds fields the resolver moved
401
- // out of the column, so when it cannot be shown they have to come back.
402
- const railVisible = useRailVisible(formElementRef);
403
- const showRail = !Builder && layout.hasRail && railVisible;
404
-
405
- // Collapsed sections are per-section-key so a renamed title keeps its state,
406
- // and initial state comes from the config rather than being forced open.
407
- const [collapsedSections, setCollapsedSections] = useState<Set<string>>(
408
- () => new Set(layout.sections.filter(s => s.collapsed).map(s => s.key))
409
- );
410
- const toggleSection = useCallback((key: string) => {
411
- setCollapsedSections(prev => {
412
- const next = new Set(prev);
413
- if (next.has(key)) next.delete(key); else next.add(key);
414
- return next;
415
- });
416
- }, []);
417
-
418
- const errorKeys = useMemo(
419
- () => new Set(formex.submitCount > 0 ? Object.keys(formex.errors) : []),
420
- [formex.errors, formex.submitCount]
421
- );
422
-
423
- // Autofocus lands on the first field the user can actually type into. Tracked
424
- // across the whole layout rather than per section, so a collapsed leading
425
- // group does not steal it.
426
- const autoFocusKey = useMemo(() => {
427
- if (status !== "new" && status !== "copy") return undefined;
428
- const ordered = [...layout.sections.flatMap(s => s.fields), ...layout.sidebar];
429
- return ordered.find(field => {
430
- const property = collection.properties?.[field.key];
431
- return property ? !isFieldDisabled(property) : false;
432
- })?.key;
433
- }, [layout, collection, status, disabledProp]);
434
-
435
- function isFieldDisabled(property: NonNullable<typeof collection.properties[string]>): boolean {
436
- const isNew = status === "new" || status === "copy";
437
- const isStringOrNumber = property.type === "string" || property.type === "number";
438
- const isIdAndAuto = isStringOrNumber && "isId" in property && typeof property.isId === "string" && property.isId !== "manual";
439
- return Boolean(
440
- disabledProp
441
- || (!autoSave && formex.isSubmitting)
442
- || isReadOnly(property)
443
- || isDisabled(property)
444
- || (!isNew && "isId" in property && Boolean(property.isId))
445
- || (isNew && isIdAndAuto)
446
- );
447
- }
448
-
449
- const renderField = (field: ResolvedFormField): React.ReactNode => {
450
-
451
- if (field.additional) {
452
- const additionalField = collection.additionalFields?.find(f => f.key === field.key);
453
- if (!additionalField || !entity) return null;
454
-
455
- const AdditionalFieldBuilder = additionalField.Builder;
456
- if (!AdditionalFieldBuilder && !additionalField.value) {
457
- throw new Error("When using additional fields you need to provide a Builder or a value");
458
- }
459
- const additionalFieldContext = formContext as unknown as AdditionalFieldDelegateProps["context"];
460
- const child = AdditionalFieldBuilder
461
- ? <AdditionalFieldBuilder entity={entity} context={additionalFieldContext}/>
462
- : <div className={"w-full"}>
463
- <AdditionalFieldValue
464
- field={additionalField}
465
- entity={entity}
466
- context={additionalFieldContext}/>
467
- </div>;
468
-
469
- return (
470
- // Through FieldBlock like every other cell, so a computed
471
- // column is labelled at the same size, with the same gap to its
472
- // box, as the property next to it on the grid.
473
- <div key={`additional_${field.key}`}
474
- className={spanClass(field.span)}>
475
- <FieldBlock propertyKey={field.key}
476
- showLabel={true}
477
- label={additionalField.name}
478
- icon={<AlignLeftIcon size={LABEL_ICON_SIZE}/>}>
479
- <div className={cls(paperMixin, "w-full min-h-12 p-4 md:p-6 overflow-x-auto no-scrollbar")}>
480
- {child}
481
- </div>
482
- </FieldBlock>
483
- </div>
484
- );
485
- }
486
-
487
- const property = collection.properties?.[field.key];
488
- if (!property) {
489
- console.warn(`Property ${field.key} not found in collection ${collection.name} in properties or additional fields. Skipping.`);
490
- return null;
491
- }
492
-
493
- const underlyingValueHasChanged: boolean =
494
- !!underlyingChanges &&
495
- Object.keys(underlyingChanges).includes(field.key) &&
496
- formex.touched[field.key];
497
-
498
- const disabled = isFieldDisabled(property);
499
- // The panel-style editors carry their own header; everything else is
500
- // labelled by FieldBlock, which is what puts every label in one place.
501
- const selfLabelling = isSelfLabellingProperty(property);
502
-
503
- const cmsFormFieldProps: PropertyFieldBindingProps<M> = {
504
- propertyKey: field.key,
505
- disabled,
506
- property,
507
- // FieldBlock owns the description now, so the binding must not
508
- // repeat it — it still renders validation errors, which belong
509
- // against the control rather than under the label.
510
- includeDescription: false,
511
- hideLabel: !selfLabelling,
512
- underlyingValueHasChanged: underlyingValueHasChanged && !autoSave,
513
- context: formContext,
514
- partOfArray: false,
515
- minimalistView: false,
516
- // One height for every control in the form. Left to their own
517
- // defaults, a text field came out 48px, a select 44 and a switch 64.
518
- size: "large",
519
- autoFocus: autoFocusKey === field.key
520
- };
521
-
522
- return (
523
- <div key={`field_${field.key}`} className={spanClass(field.span)}>
524
- <FieldBlock propertyKey={field.key}
525
- property={property}
526
- showLabel={!selfLabelling}>
527
- <PropertyFieldBinding {...cmsFormFieldProps}/>
528
- </FieldBlock>
529
- </div>
530
- );
531
- };
532
-
533
- const formFields = () => {
534
-
535
- if (Builder) {
536
- return <Builder
537
- collection={collection}
538
- entity={entity}
539
- modifiedValues={formex.values}
540
- formContext={formContext}
541
- />;
542
- }
543
-
544
- const sections = showRail || !layout.sidebar.length
545
- ? layout.sections
546
- : [
547
- ...layout.sections,
548
- // Trailing, not leading. Beside the column these read as
549
- // peripheral; stacked above it they pushed the record's own name
550
- // below its status, which is the wrong thing to meet first.
551
- // Settings come after the content they apply to.
552
- {
553
- key: "__rail",
554
- title: "Settings",
555
- collapsible: false,
556
- collapsed: false,
557
- fields: layout.sidebar
558
- }
559
- ];
560
-
561
- return <>
562
- <FormSections
563
- sections={sections}
564
- collapsed={collapsedSections}
565
- onToggle={toggleSection}
566
- errorKeys={errorKeys}
567
- renderField={renderField}/>
568
-
569
- {/* Folded back with the rail's fields, and for the same reason. The
570
- rail renders only where it has been measured to fit, so on the
571
- split pane, the side panel and the dialog this block was dropped
572
- outright and the record's id was nowhere on screen but the
573
- truncated chip in the bar. */}
574
- {!showRail && layout.showRecordMeta && status === "existing" && entity && (
575
- <div className={cls("mt-8 pt-5 border-t max-w-sm", defaultBorderMixin)}>
576
- <RecordMeta entity={entity as Entity<Record<string, unknown>>}/>
577
- </div>
578
- )}
579
- </>;
580
- };
581
-
582
- const formRef = useRef<HTMLDivElement>(null);
583
-
584
- const hasFormErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
585
-
586
- const formView = <ErrorBoundary>
587
- <>
588
- {beforeFields}
589
-
590
- {/* The title, the `path/id` chip and the 72px gap under them used to
591
- live here — 219px above the first field, carrying nothing, and
592
- scrolling the record's identity away on the first wheel click.
593
- It is now in the persistent bar, where it stays put. */}
594
-
595
- {!entity?.values && initialStatus === "existing" &&
596
- <Alert color={"warning"} size={"small"} outerClassName={"w-full mb-4 text-xs"}>
597
- This entity does not exist yet
598
- </Alert>}
599
-
600
- {children}
601
-
602
- {initialEntityId && !entity && initialStatus !== "new" && <Alert color={"info"} size={"small"}>
603
- This entity does not exist yet
604
- </Alert>}
605
-
606
- {hasFormErrors && <Alert color={"error"} size={"small"} outerClassName={"w-full mt-2"}>
607
- Please fix the highlighted errors before saving.
608
- </Alert>}
609
-
610
- {formContext && <>
611
- <div ref={formRef}>
612
- {formFields()}
613
- <ErrorFocus containerRef={formRef}/>
614
- </div>
615
- </>}
616
-
617
- {afterFields}
618
-
619
- <Dialog open={discardDialogOpen} onOpenChange={setDiscardDialogOpen} maxWidth={"sm"}>
620
- <DialogTitle>{status === "existing" ? "Discard changes?" : "Clear form?"}</DialogTitle>
621
- <DialogContent>
622
- <Typography>
623
- {status === "existing"
624
- ? "All unsaved changes will be lost. "
625
- : "All entered values will be cleared. "}
626
- You can bring them back with Undo (⌘Z / Ctrl+Z), or from
627
- the notification, for as long as this form stays open.
628
- </Typography>
629
- </DialogContent>
630
- <DialogActions>
631
- <Button variant={"text"} onClick={() => setDiscardDialogOpen(false)}>
632
- Cancel
633
- </Button>
634
- <Button variant={"filled"} color={"error"} onClick={() => {
635
- setDiscardDialogOpen(false);
636
- discard(formex, status, baseInitialValues);
637
- }}>
638
- {status === "existing" ? "Discard" : "Clear"}
639
- </Button>
640
- </DialogActions>
641
- </Dialog>
642
- </>
643
- </ErrorBoundary>;
644
-
645
- useEffect(() => {
646
- if (entityId && onIdChange)
647
- onIdChange(entityId);
648
- }, [entityId, onIdChange]);
649
-
650
- if (!collection || !path) {
651
- throw Error("INTERNAL: Collection and path must be defined in form context");
652
- }
653
-
654
- const EntityFormActionsRender = EntityFormActionsComponent as React.FC<EntityFormActionsProps>;
655
-
656
- const dialogActions = <EntityFormActionsRender
657
- collection={collection}
658
- path={path}
659
- entity={entity}
660
- savingError={savingError}
661
- formex={formex as FormexController<Record<string, unknown>>}
662
- disabled={actionsDisabled}
663
- status={status}
664
- pluginActions={pluginActionsProp ?? []}
665
- openEntityMode={openEntityMode}
666
- showDefaultActions={showDefaultActions}
667
- navigateBack={navigateBack}
668
- formContext={formContext as FormContext<Record<string, unknown>>}
669
- />;
670
-
671
- return (
672
- <Formex value={formex}>
673
- <form
674
- ref={formElementRef}
675
- onSubmit={formex.handleSubmit}
676
- onReset={(e) => {
677
- e.preventDefault();
678
- if (formex.dirty) {
679
- setDiscardDialogOpen(true);
680
- } else {
681
- formex.resetForm({ values: baseInitialValues as M });
682
- }
683
- }}
684
- noValidate
685
- className={cls("@container/form flex-1 flex flex-col w-full min-h-0", className)}>
686
-
687
- {/* The actions bar is a sibling of this row rather than absolutely
688
- positioned over it, so the scroll area ends where the bar
689
- begins. As an overlay it hid the last field, and the bottom
690
- padding that compensated was a guess at its height. */}
691
- <div className={"flex-1 min-h-0 flex flex-row w-full"}>
692
-
693
- {/* Main column. Its own container scope, so a field's span
694
- answers to the column it sits in rather than to the window —
695
- the same form renders at four very different widths. */}
696
- {/* `items-start`: the column is a flex item, so without it the cross-axis
697
- default stretches it to the scroller's height. Its content then
698
- overflows its own box and the bottom padding sits at the bottom of
699
- the *viewport* instead of after the last field — which is why the
700
- form appeared to have no padding however large `pb-*` grew. */}
701
- <div className={"flex-1 min-w-0 overflow-y-auto flex justify-center items-start"}>
702
- <div
703
- id={`form_${path}`}
704
- className={cls(
705
- // Two rules widen the column, and they answer to
706
- // different things on purpose. `@7xl/form` measures
707
- // the form itself: full screen on a laptop is ~1400px
708
- // of form, which after the 304px rail leaves room for
709
- // the wider column with real gutters either side — and
710
- // it stays 768 in the split pane and the side panel,
711
- // which never get that wide. `2xl` is the older
712
- // viewport rule, kept so a panel on a large monitor
713
- // does not get *narrower* than it is today.
714
- "@container/col w-full max-w-3xl @7xl/form:max-w-4xl 2xl:max-w-4xl flex flex-col",
715
- openEntityMode === "dialog"
716
- ? "pt-5 pb-8 px-6 sm:px-8"
717
- : "pt-6 pb-12 px-5 sm:px-8"
718
- )}>
719
-
720
- {manualApplyLocalChanges && hasLocalChanges && localChangesCacheKey &&
721
- <div className={"flex justify-end mb-3"}>
722
- <LocalChangesMenu<M>
723
- cacheKey={localChangesCacheKey}
724
- properties={collection.properties}
725
- cachedData={localChangesData as Partial<M>}
726
- formex={formex}
727
- onClearLocalChanges={() => {
728
- setLocalChangesCleared(true);
729
- onClearLocalChanges?.();
730
- }}
731
- />
732
- </div>}
733
-
734
- {formView}
735
-
736
- </div>
737
- </div>
738
-
739
- {showRail && <FormRail
740
- fields={layout.sidebar}
741
- showRecordMeta={layout.showRecordMeta && status === "existing"}
742
- entity={entity as Entity<Record<string, unknown>> | undefined}
743
- renderField={renderField}/>}
744
- </div>
745
-
746
- {dialogActions}
747
-
748
- </form>
749
-
750
- </Formex>
751
- );
752
- }
753
-
754
- function useOnAutoSave<M extends Record<string, unknown>>(autoSave: undefined | boolean, formex: FormexController<M>, lastSavedValues: React.MutableRefObject<EntityValues<M> | undefined>, save: (values: EntityValues<M>) => Promise<Entity<M> | void>) {
755
- useEffect(() => {
756
- if (!autoSave) return;
757
- if (formex.values && !equal(formex.values, lastSavedValues.current)) {
758
- save(formex.values);
759
- }
760
- }, [autoSave, formex.values]);
761
- }