@rebasepro/admin 0.0.1-canary.eae7889 → 0.0.1-canary.eb08332

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 (716) hide show
  1. package/LICENSE +21 -6
  2. package/README.md +139 -0
  3. package/dist/CollectionEditorDialog-DKGlYDPc.js +3630 -0
  4. package/dist/CollectionEditorDialog-DKGlYDPc.js.map +1 -0
  5. package/dist/PropertyEditView-h0N-AMCY.js +3808 -0
  6. package/dist/PropertyEditView-h0N-AMCY.js.map +1 -0
  7. package/dist/RouterCollectionsStudioView-DdEStpFk.js +192 -0
  8. package/dist/RouterCollectionsStudioView-DdEStpFk.js.map +1 -0
  9. package/dist/collection_editor/ConfigControllerProvider.d.ts +2 -11
  10. package/dist/collection_editor/_cms_internals.d.ts +4 -4
  11. package/dist/collection_editor/api/generateCollectionApi.d.ts +10 -9
  12. package/dist/collection_editor/extensibility_types.d.ts +135 -0
  13. package/dist/collection_editor/index.d.ts +6 -1
  14. package/dist/collection_editor/pgColumnToProperty.d.ts +3 -3
  15. package/dist/collection_editor/serializable_types.d.ts +370 -0
  16. package/dist/collection_editor/serializable_utils.d.ts +50 -0
  17. package/dist/collection_editor/types/collection_editor_controller.d.ts +11 -10
  18. package/dist/collection_editor/types/collection_inference.d.ts +2 -2
  19. package/dist/collection_editor/types/config_controller.d.ts +21 -14
  20. package/dist/collection_editor/ui/AddKanbanColumnAction.d.ts +7 -5
  21. package/dist/collection_editor/ui/CollectionViewHeaderAction.d.ts +7 -5
  22. package/dist/collection_editor/ui/EditorCollectionAction.d.ts +1 -1
  23. package/dist/collection_editor/ui/EditorCollectionActionStart.d.ts +1 -1
  24. package/dist/collection_editor/ui/EditorEntityAction.d.ts +1 -1
  25. package/dist/collection_editor/ui/HomePageEditorCollectionAction.d.ts +1 -1
  26. package/dist/collection_editor/ui/KanbanSetupAction.d.ts +7 -5
  27. package/dist/collection_editor/ui/MissingReferenceWidget.d.ts +1 -1
  28. package/dist/collection_editor/ui/NewCollectionButton.d.ts +1 -1
  29. package/dist/collection_editor/ui/NewCollectionCard.d.ts +1 -1
  30. package/dist/collection_editor/ui/PropertyAddColumnComponent.d.ts +6 -5
  31. package/dist/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.d.ts +4 -4
  32. package/dist/collection_editor/ui/collection_editor/AIModifiedPathsContext.d.ts +1 -1
  33. package/dist/collection_editor/ui/collection_editor/CollectionDetailsForm.d.ts +7 -7
  34. package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +10 -11
  35. package/dist/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.d.ts +4 -4
  36. package/dist/collection_editor/ui/collection_editor/CollectionJsonImportDialog.d.ts +4 -3
  37. package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +17 -7
  38. package/dist/collection_editor/ui/collection_editor/CollectionRLSTab.d.ts +2 -1
  39. package/dist/collection_editor/ui/collection_editor/CollectionRelationsTab.d.ts +2 -1
  40. package/dist/collection_editor/ui/collection_editor/CollectionStudioView.d.ts +14 -1
  41. package/dist/collection_editor/ui/collection_editor/CollectionYupValidation.d.ts +1 -9
  42. package/dist/collection_editor/ui/collection_editor/CollectionsStudioView.d.ts +25 -2
  43. package/dist/collection_editor/ui/collection_editor/DisplaySettingsForm.d.ts +4 -2
  44. package/dist/collection_editor/ui/collection_editor/EntityActionsEditTab.d.ts +4 -3
  45. package/dist/collection_editor/ui/collection_editor/EntityActionsSelectDialog.d.ts +2 -1
  46. package/dist/collection_editor/ui/collection_editor/EntityCustomViewsSelectDialog.d.ts +2 -1
  47. package/dist/collection_editor/ui/collection_editor/EnumForm.d.ts +2 -1
  48. package/dist/collection_editor/ui/collection_editor/GeneralSettingsForm.d.ts +8 -4
  49. package/dist/collection_editor/ui/collection_editor/GetCodeDialog.d.ts +4 -3
  50. package/dist/collection_editor/ui/collection_editor/KanbanConfigSection.d.ts +2 -1
  51. package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +3 -3
  52. package/dist/collection_editor/ui/collection_editor/PropertyEditView.d.ts +17 -5
  53. package/dist/collection_editor/ui/collection_editor/PropertyFieldPreview.d.ts +2 -2
  54. package/dist/collection_editor/ui/collection_editor/PropertyTree.d.ts +2 -2
  55. package/dist/collection_editor/ui/collection_editor/RouterCollectionStudioView.d.ts +15 -0
  56. package/dist/collection_editor/ui/collection_editor/RouterCollectionsStudioView.d.ts +14 -0
  57. package/dist/collection_editor/ui/collection_editor/SubcollectionsEditTab.d.ts +8 -6
  58. package/dist/collection_editor/ui/collection_editor/SwitchControl.d.ts +3 -2
  59. package/dist/collection_editor/ui/collection_editor/ViewModeSwitch.d.ts +1 -1
  60. package/dist/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.d.ts +1 -1
  61. package/dist/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.d.ts +3 -2
  62. package/dist/collection_editor/ui/collection_editor/properties/BlockPropertyField.d.ts +2 -1
  63. package/dist/collection_editor/ui/collection_editor/properties/BooleanPropertyField.d.ts +2 -1
  64. package/dist/collection_editor/ui/collection_editor/properties/DateTimePropertyField.d.ts +2 -1
  65. package/dist/collection_editor/ui/collection_editor/properties/EnumPropertyField.d.ts +2 -1
  66. package/dist/collection_editor/ui/collection_editor/properties/KeyValuePropertyField.d.ts +2 -1
  67. package/dist/collection_editor/ui/collection_editor/properties/MapPropertyField.d.ts +2 -1
  68. package/dist/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.d.ts +2 -1
  69. package/dist/collection_editor/ui/collection_editor/properties/NumberPropertyField.d.ts +2 -1
  70. package/dist/collection_editor/ui/collection_editor/properties/ReferencePropertyField.d.ts +3 -2
  71. package/dist/collection_editor/ui/collection_editor/properties/RelationPropertyField.d.ts +3 -8
  72. package/dist/collection_editor/ui/collection_editor/properties/RepeatPropertyField.d.ts +2 -1
  73. package/dist/collection_editor/ui/collection_editor/properties/StoragePropertyField.d.ts +2 -1
  74. package/dist/collection_editor/ui/collection_editor/properties/StringPropertyField.d.ts +2 -1
  75. package/dist/collection_editor/ui/collection_editor/properties/UrlPropertyField.d.ts +2 -1
  76. package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +4 -0
  77. package/dist/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.d.ts +2 -1
  78. package/dist/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.d.ts +2 -1
  79. package/dist/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.d.ts +1 -1
  80. package/dist/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.d.ts +2 -1
  81. package/dist/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.d.ts +2 -1
  82. package/dist/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.d.ts +2 -1
  83. package/dist/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.d.ts +2 -1
  84. package/dist/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.d.ts +2 -1
  85. package/dist/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.d.ts +1 -1
  86. package/dist/collection_editor/ui/collection_editor/templates/blog_template.d.ts +2 -2
  87. package/dist/collection_editor/ui/collection_editor/templates/pages_template.d.ts +2 -2
  88. package/dist/collection_editor/ui/collection_editor/templates/products_template.d.ts +2 -2
  89. package/dist/collection_editor/ui/collection_editor/templates/users_template.d.ts +2 -2
  90. package/dist/collection_editor/useJsonCollectionsConfigController.d.ts +37 -0
  91. package/dist/collection_editor/useLocalCollectionsConfigController.d.ts +2 -2
  92. package/dist/collection_editor/useSafeSnackbarController.d.ts +2 -0
  93. package/dist/collection_editor/validateCollectionJson.d.ts +2 -2
  94. package/dist/collection_editor_ui.d.ts +4 -0
  95. package/dist/collection_editor_ui.js +33 -11
  96. package/dist/collection_editor_ui.js.map +1 -1
  97. package/dist/components/ArrayContainer.d.ts +5 -5
  98. package/dist/components/ClearFilterSortButton.d.ts +1 -1
  99. package/dist/components/CollectionEditorDialogs.d.ts +2 -1
  100. package/dist/components/CollectionPanel.d.ts +58 -0
  101. package/dist/components/{EntityCollectionTable/EntityCollectionRowActions.d.ts → CollectionTableBinding/CollectionRowActions.d.ts} +5 -5
  102. package/dist/components/CollectionTableBinding/CollectionTableBinding.d.ts +28 -0
  103. package/dist/components/{EntityCollectionTable/EntityCollectionTableProps.d.ts → CollectionTableBinding/CollectionTableBindingProps.d.ts} +4 -4
  104. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/column_utils.d.ts +2 -2
  105. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableMultipleRelationField.d.ts +6 -6
  106. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableReferenceField.d.ts +6 -6
  107. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationField.d.ts +6 -6
  108. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationSelectorField.d.ts +3 -2
  109. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableStorageUpload.d.ts +4 -4
  110. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableSelect.d.ts +1 -1
  111. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableUserSelect.d.ts +1 -1
  112. package/dist/components/CollectionTableBinding/index.d.ts +6 -0
  113. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/CollectionTableToolbar.d.ts +5 -1
  114. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCell.d.ts +3 -3
  115. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCellActions.d.ts +1 -1
  116. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/common.d.ts +2 -2
  117. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/PopupFormField.d.ts +7 -6
  118. package/dist/components/{EntityCollectionTable → CollectionTableBinding}/table_bindings.d.ts +4 -3
  119. package/dist/components/CollectionViewBinding/BoardCardBinding.d.ts +31 -0
  120. package/dist/components/CollectionViewBinding/CollectionBoardViewBinding.d.ts +22 -0
  121. package/dist/components/{EntityCollectionView/EntityCollectionCardView.d.ts → CollectionViewBinding/CollectionCardViewBinding.d.ts} +5 -5
  122. package/dist/components/CollectionViewBinding/CollectionListViewBinding.d.ts +50 -0
  123. package/dist/components/CollectionViewBinding/CollectionViewActions.d.ts +20 -0
  124. package/dist/components/CollectionViewBinding/CollectionViewBinding.d.ts +41 -0
  125. package/dist/components/CollectionViewBinding/CollectionViewStartActions.d.ts +21 -0
  126. package/dist/components/CollectionViewBinding/EntityCardBinding.d.ts +21 -0
  127. package/dist/components/CollectionViewBinding/FilterPresetsButton.d.ts +22 -0
  128. package/dist/components/{EntityCollectionView → CollectionViewBinding}/FiltersDialog.d.ts +3 -2
  129. package/dist/components/{EntityCollectionView → CollectionViewBinding}/SplitListView.d.ts +6 -5
  130. package/dist/components/{EntityCollectionView → CollectionViewBinding}/ViewModeToggle.d.ts +2 -1
  131. package/dist/components/{EntityCollectionView → CollectionViewBinding}/hooks/useCollectionInlineEditor.d.ts +3 -3
  132. package/dist/components/{EntityCollectionView → CollectionViewBinding}/hooks/useKanbanDragAndDrop.d.ts +7 -6
  133. package/dist/components/{EntityCollectionView → CollectionViewBinding}/useBoardDataController.d.ts +2 -2
  134. package/dist/components/{EntityCollectionView/useEntityPreviewSlots.d.ts → CollectionViewBinding/usePreviewSlots.d.ts} +5 -5
  135. package/dist/components/DefaultAppBar.d.ts +18 -1
  136. package/dist/components/DefaultDrawer.d.ts +53 -5
  137. package/dist/components/DeleteEntityDialog.d.ts +6 -5
  138. package/dist/components/DetailViewBinding.d.ts +28 -0
  139. package/dist/components/DrawerNavigationGroup.d.ts +1 -1
  140. package/dist/components/DrawerNavigationItem.d.ts +1 -1
  141. package/dist/components/EditFormActions.d.ts +3 -0
  142. package/dist/components/EditViewBinding.d.ts +58 -0
  143. package/dist/components/{EntityPreview.d.ts → EntityPreviewBinding.d.ts} +14 -14
  144. package/dist/components/EntityViewBinding.d.ts +13 -0
  145. package/dist/components/FieldCaption.d.ts +1 -1
  146. package/dist/components/HomePage/ContentHomePage.d.ts +1 -1
  147. package/dist/components/HomePage/FavouritesView.d.ts +1 -1
  148. package/dist/components/HomePage/HomePageDnD.d.ts +7 -7
  149. package/dist/components/HomePage/NavigationCard.d.ts +1 -1
  150. package/dist/components/HomePage/NavigationCardBinding.d.ts +2 -1
  151. package/dist/components/HomePage/NavigationGroup.d.ts +2 -2
  152. package/dist/components/HomePage/RenameGroupDialog.d.ts +2 -1
  153. package/dist/components/HomePage/SmallNavigationCard.d.ts +1 -1
  154. package/dist/components/JsonPreviewBinding.d.ts +4 -0
  155. package/dist/components/PropertyCollectionView.d.ts +3 -2
  156. package/dist/components/PropertyIdCopyTooltip.d.ts +3 -3
  157. package/dist/components/{RebaseCMS.d.ts → RebaseAdmin.d.ts} +2 -2
  158. package/dist/components/RebaseAuthGate.d.ts +1 -1
  159. package/dist/components/RebaseLayout.d.ts +6 -5
  160. package/dist/components/RebaseNavigation.d.ts +2 -2
  161. package/dist/components/RebaseRouteDefs.d.ts +2 -2
  162. package/dist/components/RebaseShell.d.ts +2 -1
  163. package/dist/components/ReferenceTable/{EntitySelectionTable.d.ts → SelectionTableBinding.d.ts} +6 -6
  164. package/dist/components/ReferenceWidget.d.ts +3 -2
  165. package/dist/components/RelationSelector.d.ts +1 -1
  166. package/dist/components/SearchIconsView.d.ts +2 -1
  167. package/dist/components/SelectableTable/SelectableTable.d.ts +11 -11
  168. package/dist/components/SelectableTable/SelectableTableContext.d.ts +3 -3
  169. package/dist/components/SelectableTable/SelectionStore.d.ts +16 -22
  170. package/dist/components/SelectableTable/filters/BooleanFilterField.d.ts +9 -3
  171. package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +10 -3
  172. package/dist/components/SelectableTable/filters/FilterFieldBinding.d.ts +40 -0
  173. package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +10 -3
  174. package/dist/components/SelectableTable/filters/RelationFilterField.d.ts +8 -1
  175. package/dist/components/SelectableTable/filters/StringNumberFilterField.d.ts +10 -3
  176. package/dist/components/SideDialogs.d.ts +2 -2
  177. package/dist/components/SidePanelBinding.d.ts +11 -0
  178. package/dist/components/{SideEntityProvider.d.ts → SidePanelProvider.d.ts} +8 -8
  179. package/dist/components/admin/CreationResultDialog.d.ts +6 -0
  180. package/dist/components/admin/index.d.ts +1 -3
  181. package/dist/components/app/AppBar.d.ts +1 -1
  182. package/dist/components/app/Drawer.d.ts +9 -2
  183. package/dist/components/common/default_entity_actions.d.ts +8 -1
  184. package/dist/components/field_configs.d.ts +1 -1
  185. package/dist/components/history/EntityHistoryEntry.d.ts +3 -3
  186. package/dist/components/history/EntityHistoryView.d.ts +1 -1
  187. package/dist/components/history/LastEditedByFormAction.d.ts +2 -1
  188. package/dist/components/history/LastEditedByIndicator.d.ts +4 -3
  189. package/dist/components/history/UserChip.d.ts +1 -1
  190. package/dist/components/index.d.ts +16 -13
  191. package/dist/contexts/SidePanelControllerContext.d.ts +3 -0
  192. package/dist/data_export/export/BasicExportAction.d.ts +2 -1
  193. package/dist/data_export/export/ExportCollectionAction.d.ts +4 -4
  194. package/dist/data_export/export/export.d.ts +3 -3
  195. package/dist/data_import/components/DataNewPropertiesMapping.d.ts +1 -1
  196. package/dist/data_import/components/ImportFileUpload.d.ts +1 -1
  197. package/dist/data_import/components/ImportNewPropertyFieldPreview.d.ts +2 -1
  198. package/dist/data_import/components/ImportSaveInProgress.d.ts +3 -3
  199. package/dist/data_import/import/ImportCollectionAction.d.ts +4 -3
  200. package/dist/data_import/utils/data.d.ts +1 -1
  201. package/dist/data_import/utils/file_headers.d.ts +6 -1
  202. package/dist/data_import/utils/file_to_json.d.ts +1 -11
  203. package/dist/data_import/utils/transforms.d.ts +11 -0
  204. package/dist/editor/components/SlashCommandMenu.d.ts +2 -1
  205. package/dist/editor/components/editor-bubble.d.ts +5 -1
  206. package/dist/editor/components/image-bubble.d.ts +5 -1
  207. package/dist/editor/components/index.d.ts +3 -3
  208. package/dist/editor/components/table-bubble.d.ts +5 -1
  209. package/dist/editor/editor.d.ts +4 -4
  210. package/dist/editor/nodeViews/ReactNodeView.d.ts +4 -1
  211. package/dist/editor/selectors/color-selector.d.ts +1 -1
  212. package/dist/editor/selectors/link-selector.d.ts +1 -1
  213. package/dist/editor/selectors/node-selector.d.ts +1 -1
  214. package/dist/editor/selectors/text-buttons.d.ts +1 -1
  215. package/dist/editor/useProseMirror.d.ts +2 -2
  216. package/dist/editor/utils/remove_classes.d.ts +1 -1
  217. package/dist/editor.js +2625 -3569
  218. package/dist/editor.js.map +1 -1
  219. package/dist/form/EntityForm.d.ts +11 -9
  220. package/dist/form/EntityFormActions.d.ts +2 -1
  221. package/dist/form/EntityFormBinding.d.ts +27 -0
  222. package/dist/form/PropertyFieldBinding.d.ts +1 -1
  223. package/dist/form/components/FieldHelperText.d.ts +1 -1
  224. package/dist/form/components/FormEntry.d.ts +1 -1
  225. package/dist/form/components/FormLayout.d.ts +1 -1
  226. package/dist/form/components/LabelWithIconAndTooltip.d.ts +1 -1
  227. package/dist/form/components/LocalChangesMenu.d.ts +3 -2
  228. package/dist/form/components/StorageItemPreview.d.ts +2 -1
  229. package/dist/form/components/StorageUploadProgress.d.ts +10 -4
  230. package/dist/form/field_bindings/ArrayCustomShapedFieldBinding.d.ts +2 -1
  231. package/dist/form/field_bindings/ArrayOfReferencesFieldBinding.d.ts +2 -1
  232. package/dist/form/field_bindings/BlockFieldBinding.d.ts +2 -1
  233. package/dist/form/field_bindings/DateTimeFieldBinding.d.ts +2 -1
  234. package/dist/form/field_bindings/KeyValueFieldBinding.d.ts +2 -1
  235. package/dist/form/field_bindings/MapFieldBinding.d.ts +2 -1
  236. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +4 -3
  237. package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +2 -1
  238. package/dist/form/field_bindings/MultipleRelationFieldBinding.d.ts +2 -1
  239. package/dist/form/field_bindings/ReadOnlyFieldBinding.d.ts +2 -1
  240. package/dist/form/field_bindings/ReferenceFieldBinding.d.ts +2 -1
  241. package/dist/form/field_bindings/RelationFieldBinding.d.ts +2 -1
  242. package/dist/form/field_bindings/RepeatFieldBinding.d.ts +2 -1
  243. package/dist/form/field_bindings/SelectFieldBinding.d.ts +2 -1
  244. package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +5 -4
  245. package/dist/form/field_bindings/SwitchFieldBinding.d.ts +2 -1
  246. package/dist/form/field_bindings/TextFieldBinding.d.ts +2 -1
  247. package/dist/form/field_bindings/UserSelectFieldBinding.d.ts +2 -1
  248. package/dist/form/field_bindings/VectorFieldBinding.d.ts +12 -0
  249. package/dist/form/form_utils.d.ts +8 -0
  250. package/dist/form/index.d.ts +6 -2
  251. package/dist/form/validation.d.ts +3 -3
  252. package/dist/history-C0FdqGNz.js +311 -0
  253. package/dist/history-C0FdqGNz.js.map +1 -0
  254. package/dist/hooks/index.d.ts +4 -4
  255. package/dist/hooks/navigation/contexts/CollectionRegistryContext.d.ts +2 -2
  256. package/dist/hooks/navigation/useAsyncResolver.d.ts +26 -0
  257. package/dist/hooks/navigation/useBuildCollectionRegistryController.d.ts +2 -0
  258. package/dist/hooks/navigation/useBuildNavigationStateController.d.ts +6 -8
  259. package/dist/hooks/navigation/useNavigationResolution.d.ts +6 -7
  260. package/dist/hooks/navigation/useResolvedCollections.d.ts +11 -7
  261. package/dist/hooks/navigation/useResolvedViews.d.ts +2 -5
  262. package/dist/hooks/navigation/useTopLevelNavigation.d.ts +3 -3
  263. package/dist/hooks/navigation/utils.d.ts +5 -5
  264. package/dist/hooks/useBreadcrumbsController.d.ts +2 -32
  265. package/dist/hooks/useBuildSidePanel.d.ts +6 -0
  266. package/dist/hooks/useCMSContext.d.ts +2 -2
  267. package/dist/hooks/{useEntityHistory.d.ts → useHistory.d.ts} +2 -2
  268. package/dist/hooks/useResolvedNavigationFrom.d.ts +3 -3
  269. package/dist/hooks/{useEntitySelectionDialog.d.ts → useSelectionDialog.d.ts} +2 -2
  270. package/dist/hooks/useSideDialogsController.d.ts +1 -1
  271. package/dist/hooks/useSidePanel.d.ts +11 -0
  272. package/dist/index.d.ts +6 -3
  273. package/dist/index.js +2 -799
  274. package/dist/markdown-CklalUUk.js +526 -0
  275. package/dist/markdown-CklalUUk.js.map +1 -0
  276. package/dist/preview/components/ArrayEnumPreview.d.ts +2 -1
  277. package/dist/preview/components/EmptyValue.d.ts +2 -1
  278. package/dist/preview/components/EnumValuesChip.d.ts +1 -1
  279. package/dist/preview/components/ImagePreview.d.ts +2 -1
  280. package/dist/preview/components/ReferencePreview.d.ts +2 -1
  281. package/dist/preview/components/RelationPreview.d.ts +2 -1
  282. package/dist/preview/components/StorageThumbnail.d.ts +3 -1
  283. package/dist/preview/components/UrlComponentPreview.d.ts +1 -0
  284. package/dist/preview/components/UserPreview.d.ts +6 -3
  285. package/dist/preview/property_previews/ArrayOfMapsPreview.d.ts +2 -1
  286. package/dist/preview/property_previews/ArrayOfReferencesPreview.d.ts +1 -1
  287. package/dist/preview/property_previews/ArrayOfRelationsPreview.d.ts +1 -1
  288. package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +2 -1
  289. package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +2 -1
  290. package/dist/preview/property_previews/ArrayOneOfPreview.d.ts +2 -1
  291. package/dist/preview/property_previews/ArrayPropertyEnumPreview.d.ts +1 -1
  292. package/dist/preview/property_previews/ArrayPropertyPreview.d.ts +2 -1
  293. package/dist/preview/property_previews/MapPropertyPreview.d.ts +3 -2
  294. package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +5 -4
  295. package/dist/rolldown-runtime-D7D4PA-g.js +13 -0
  296. package/dist/routes/CustomViewRoute.d.ts +2 -1
  297. package/dist/routes/RebaseRoute.d.ts +1 -1
  298. package/dist/src-DLAFyeZI.js +24222 -0
  299. package/dist/src-DLAFyeZI.js.map +1 -0
  300. package/dist/types/components/EntityFormActionsProps.d.ts +4 -4
  301. package/dist/types/components/EntityFormProps.d.ts +65 -5
  302. package/dist/types/components/PropertyPreviewProps.d.ts +6 -1
  303. package/dist/types/components/formex.d.ts +1 -40
  304. package/dist/types/fields.d.ts +23 -12
  305. package/dist/util/dataControllerAdapter.d.ts +27 -0
  306. package/dist/util/navigation_utils.d.ts +16 -6
  307. package/dist/util/previews.d.ts +8 -3
  308. package/dist/util/propertyConfigMapper.d.ts +17 -0
  309. package/dist/util/property_utils.d.ts +3 -3
  310. package/dist/util/resolutions.d.ts +1 -2
  311. package/dist/util/view_constants.d.ts +6 -0
  312. package/package.json +56 -55
  313. package/src/collection_editor/ConfigControllerProvider.tsx +37 -53
  314. package/src/collection_editor/_cms_internals.ts +4 -4
  315. package/src/collection_editor/api/generateCollectionApi.ts +10 -9
  316. package/src/collection_editor/extensibility_types.ts +168 -0
  317. package/src/collection_editor/index.ts +47 -3
  318. package/src/collection_editor/pgColumnToProperty.ts +23 -6
  319. package/src/collection_editor/serializable_types.ts +474 -0
  320. package/src/collection_editor/serializable_utils.ts +576 -0
  321. package/src/collection_editor/types/collection_editor_controller.tsx +8 -11
  322. package/src/collection_editor/types/collection_inference.ts +2 -2
  323. package/src/collection_editor/types/config_controller.tsx +14 -14
  324. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +21 -9
  325. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +8 -8
  326. package/src/collection_editor/ui/EditorCollectionAction.tsx +9 -14
  327. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +13 -18
  328. package/src/collection_editor/ui/EditorEntityAction.tsx +9 -14
  329. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +13 -19
  330. package/src/collection_editor/ui/KanbanSetupAction.tsx +8 -6
  331. package/src/collection_editor/ui/MissingReferenceWidget.tsx +5 -3
  332. package/src/collection_editor/ui/NewCollectionButton.tsx +4 -4
  333. package/src/collection_editor/ui/NewCollectionCard.tsx +8 -13
  334. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +11 -16
  335. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +20 -12
  336. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +29 -59
  337. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +213 -135
  338. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +21 -7
  339. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +29 -23
  340. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +142 -112
  341. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +49 -12
  342. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +29 -10
  343. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +26 -23
  344. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +104 -37
  345. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +26 -14
  346. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +21 -8
  347. package/src/collection_editor/ui/collection_editor/EntityActionsSelectDialog.tsx +1 -1
  348. package/src/collection_editor/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +1 -1
  349. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +20 -5
  350. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +45 -12
  351. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +10 -12
  352. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +5 -6
  353. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
  354. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +190 -27
  355. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +58 -49
  356. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +17 -4
  357. package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +44 -0
  358. package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +41 -0
  359. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +27 -13
  360. package/src/collection_editor/ui/collection_editor/SwitchControl.tsx +1 -1
  361. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
  362. package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +4 -4
  363. package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.tsx +4 -4
  364. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +5 -6
  365. package/src/collection_editor/ui/collection_editor/properties/BooleanPropertyField.tsx +1 -1
  366. package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +5 -5
  367. package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +10 -10
  368. package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +10 -9
  369. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +7 -8
  370. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +17 -10
  371. package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +7 -7
  372. package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +19 -53
  373. package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +43 -60
  374. package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +3 -3
  375. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +56 -13
  376. package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +7 -7
  377. package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +4 -3
  378. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
  379. package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +5 -6
  380. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +18 -9
  381. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
  382. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +17 -5
  383. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
  384. package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +4 -4
  385. package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +3 -3
  386. package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +6 -9
  387. package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +6 -6
  388. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
  389. package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +3 -3
  390. package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +3 -3
  391. package/src/collection_editor/ui/collection_editor/templates/products_template.ts +4 -4
  392. package/src/collection_editor/ui/collection_editor/templates/users_template.ts +2 -2
  393. package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -1
  394. package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +7 -29
  395. package/src/collection_editor/useJsonCollectionsConfigController.tsx +286 -0
  396. package/src/collection_editor/useLocalCollectionsConfigController.tsx +11 -8
  397. package/src/collection_editor/useSafeSnackbarController.ts +9 -0
  398. package/src/collection_editor/validateCollectionJson.ts +111 -24
  399. package/src/collection_editor_ui.ts +6 -0
  400. package/src/components/AdminModeSyncer.tsx +2 -2
  401. package/src/components/ArrayContainer.tsx +28 -24
  402. package/src/components/ClearFilterSortButton.tsx +2 -3
  403. package/src/components/CollectionEditorDialogs.tsx +1 -1
  404. package/src/components/CollectionPanel.tsx +178 -0
  405. package/src/components/{EntityCollectionTable/EntityCollectionRowActions.tsx → CollectionTableBinding/CollectionRowActions.tsx} +26 -16
  406. package/src/components/{EntityCollectionTable/EntityCollectionTable.tsx → CollectionTableBinding/CollectionTableBinding.tsx} +34 -31
  407. package/src/components/{EntityCollectionTable/EntityCollectionTableProps.tsx → CollectionTableBinding/CollectionTableBindingProps.tsx} +4 -4
  408. package/src/components/{EntityCollectionTable → CollectionTableBinding}/PropertyTableCell.tsx +14 -12
  409. package/src/components/{EntityCollectionTable → CollectionTableBinding}/column_utils.tsx +4 -4
  410. package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableMultipleRelationField.tsx +13 -13
  411. package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableReferenceField.tsx +39 -19
  412. package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationField.tsx +14 -14
  413. package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableRelationSelectorField.tsx +3 -3
  414. package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/TableStorageUpload.tsx +29 -27
  415. package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableSelect.tsx +0 -1
  416. package/src/components/CollectionTableBinding/index.tsx +14 -0
  417. package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/CollectionTableToolbar.tsx +22 -28
  418. package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCell.tsx +8 -9
  419. package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/EntityTableCellActions.tsx +2 -3
  420. package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/common.tsx +7 -7
  421. package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/PopupFormField.tsx +12 -13
  422. package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useDraggable.tsx +5 -2
  423. package/src/components/{EntityCollectionTable → CollectionTableBinding}/table_bindings.tsx +101 -104
  424. package/src/components/{EntityCollectionView/EntityBoardCard.tsx → CollectionViewBinding/BoardCardBinding.tsx} +39 -40
  425. package/src/components/{EntityCollectionView/EntityCollectionBoardView.tsx → CollectionViewBinding/CollectionBoardViewBinding.tsx} +88 -52
  426. package/src/components/CollectionViewBinding/CollectionCardViewBinding.tsx +157 -0
  427. package/src/components/{EntityCollectionView/EntityCollectionListView.tsx → CollectionViewBinding/CollectionListViewBinding.tsx} +234 -151
  428. package/src/components/{EntityCollectionView/EntityCollectionViewActions.tsx → CollectionViewBinding/CollectionViewActions.tsx} +36 -26
  429. package/src/components/{EntityCollectionView/EntityCollectionView.tsx → CollectionViewBinding/CollectionViewBinding.tsx} +392 -213
  430. package/src/components/{EntityCollectionView/EntityCollectionViewStartActions.tsx → CollectionViewBinding/CollectionViewStartActions.tsx} +42 -23
  431. package/src/components/{EntityCollectionView/EntityCard.tsx → CollectionViewBinding/EntityCardBinding.tsx} +14 -14
  432. package/src/components/CollectionViewBinding/FilterPresetsButton.tsx +294 -0
  433. package/src/components/{EntityCollectionView → CollectionViewBinding}/FiltersDialog.tsx +37 -79
  434. package/src/components/{EntityCollectionView → CollectionViewBinding}/SplitListView.tsx +97 -30
  435. package/src/components/{EntityCollectionView → CollectionViewBinding}/ViewModeToggle.tsx +20 -8
  436. package/src/components/{EntityCollectionView → CollectionViewBinding}/hooks/useCollectionInlineEditor.ts +9 -8
  437. package/src/components/{EntityCollectionView → CollectionViewBinding}/hooks/useKanbanDragAndDrop.ts +17 -16
  438. package/src/components/{EntityCollectionView → CollectionViewBinding}/useBoardDataController.tsx +118 -70
  439. package/src/components/{EntityCollectionView/useEntityPreviewSlots.ts → CollectionViewBinding/usePreviewSlots.ts} +136 -48
  440. package/src/components/DefaultAppBar.tsx +73 -41
  441. package/src/components/DefaultDrawer.tsx +317 -85
  442. package/src/components/DeleteEntityDialog.tsx +7 -7
  443. package/src/components/DetailViewBinding.tsx +670 -0
  444. package/src/components/DrawerNavigationGroup.tsx +11 -11
  445. package/src/components/DrawerNavigationItem.tsx +6 -6
  446. package/src/components/{EntityEditViewFormActions.tsx → EditFormActions.tsx} +78 -59
  447. package/src/components/EditViewBinding.tsx +761 -0
  448. package/src/components/{EntityPreview.tsx → EntityPreviewBinding.tsx} +53 -39
  449. package/src/components/{EntityView.tsx → EntityViewBinding.tsx} +8 -9
  450. package/src/components/HomePage/ContentHomePage.tsx +35 -17
  451. package/src/components/HomePage/FavouritesView.tsx +2 -3
  452. package/src/components/HomePage/HomePageDnD.tsx +3 -2
  453. package/src/components/HomePage/NavigationCard.tsx +9 -16
  454. package/src/components/HomePage/NavigationCardBinding.tsx +6 -7
  455. package/src/components/HomePage/NavigationGroup.tsx +4 -5
  456. package/src/components/HomePage/RenameGroupDialog.tsx +1 -1
  457. package/src/components/HomePage/SmallNavigationCard.tsx +0 -5
  458. package/src/components/{EntityJsonPreview.tsx → JsonPreviewBinding.tsx} +2 -2
  459. package/src/components/PropertyCollectionView.tsx +2 -1
  460. package/src/components/PropertyIdCopyTooltip.tsx +2 -3
  461. package/src/components/{RebaseCMS.tsx → RebaseAdmin.tsx} +8 -6
  462. package/src/components/RebaseAuthGate.tsx +5 -3
  463. package/src/components/RebaseLayout.tsx +10 -9
  464. package/src/components/RebaseNavigation.tsx +107 -31
  465. package/src/components/RebaseRouteDefs.tsx +10 -13
  466. package/src/components/RebaseShell.tsx +18 -14
  467. package/src/components/ReferenceTable/{EntitySelectionTable.tsx → SelectionTableBinding.tsx} +40 -33
  468. package/src/components/ReferenceWidget.tsx +7 -7
  469. package/src/components/RelationSelector.tsx +82 -24
  470. package/src/components/SearchIconsView.tsx +13 -12
  471. package/src/components/SelectableTable/SelectableTable.tsx +68 -115
  472. package/src/components/SelectableTable/SelectableTableContext.tsx +4 -3
  473. package/src/components/SelectableTable/SelectionStore.ts +20 -44
  474. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +13 -5
  475. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +37 -16
  476. package/src/components/SelectableTable/filters/FilterFieldBinding.tsx +187 -0
  477. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +27 -13
  478. package/src/components/SelectableTable/filters/RelationFilterField.tsx +17 -3
  479. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +95 -35
  480. package/src/components/SideDialogs.tsx +58 -40
  481. package/src/components/SidePanelBinding.tsx +261 -0
  482. package/src/components/{SideEntityProvider.tsx → SidePanelProvider.tsx} +17 -16
  483. package/src/components/UserSelector.tsx +123 -9
  484. package/src/components/admin/CreationResultDialog.tsx +138 -0
  485. package/src/components/admin/index.ts +1 -3
  486. package/src/components/app/Drawer.tsx +9 -1
  487. package/src/components/app/Scaffold.tsx +16 -9
  488. package/src/components/common/default_entity_actions.tsx +270 -29
  489. package/src/components/field_configs.tsx +68 -46
  490. package/src/components/history/EntityHistoryEntry.tsx +4 -5
  491. package/src/components/history/EntityHistoryView.tsx +18 -8
  492. package/src/components/history/LastEditedByIndicator.tsx +4 -4
  493. package/src/components/index.ts +20 -17
  494. package/src/contexts/BreacrumbsContext.tsx +15 -6
  495. package/src/contexts/SidePanelControllerContext.tsx +5 -0
  496. package/src/data_export/export/BasicExportAction.tsx +42 -43
  497. package/src/data_export/export/ExportCollectionAction.tsx +55 -54
  498. package/src/data_export/export/export.ts +17 -17
  499. package/src/data_import/components/DataNewPropertiesMapping.tsx +17 -4
  500. package/src/data_import/components/ImportFileUpload.tsx +2 -3
  501. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +2 -3
  502. package/src/data_import/components/ImportSaveInProgress.tsx +4 -4
  503. package/src/data_import/import/ImportCollectionAction.tsx +26 -13
  504. package/src/data_import/utils/data.ts +26 -8
  505. package/src/data_import/utils/file_headers.ts +13 -89
  506. package/src/data_import/utils/file_to_json.ts +43 -68
  507. package/src/data_import/utils/get_properties_mapping.ts +1 -1
  508. package/src/data_import/utils/transforms.ts +47 -0
  509. package/src/editor/components/SlashCommandMenu.tsx +17 -2
  510. package/src/editor/components/editor-bubble-item.tsx +1 -1
  511. package/src/editor/components/editor-bubble.tsx +32 -9
  512. package/src/editor/components/image-bubble.tsx +28 -12
  513. package/src/editor/components/index.ts +3 -3
  514. package/src/editor/components/table-bubble.tsx +80 -18
  515. package/src/editor/editor.tsx +34 -15
  516. package/src/editor/extensions/HighlightDecorationExtension.ts +3 -2
  517. package/src/editor/extensions/Image/index.ts +3 -3
  518. package/src/editor/extensions/Image.ts +3 -3
  519. package/src/editor/extensions/clipboard.ts +2 -2
  520. package/src/editor/markdown-it-plugins.d.ts +24 -0
  521. package/src/editor/markdown.ts +2 -3
  522. package/src/editor/nodeViews/ReactNodeView.tsx +1 -1
  523. package/src/editor/nodeViews/TaskItemComponent.tsx +9 -8
  524. package/src/editor/schema.ts +135 -59
  525. package/src/editor/selectors/ai-selector.tsx +0 -1
  526. package/src/editor/selectors/color-selector.tsx +1 -2
  527. package/src/editor/selectors/link-selector.tsx +9 -7
  528. package/src/editor/selectors/node-selector.tsx +17 -3
  529. package/src/editor/selectors/text-buttons.tsx +1 -2
  530. package/src/editor/useProseMirror.ts +2 -2
  531. package/src/editor/utils/prosemirror-utils.ts +1 -1
  532. package/src/editor/utils/remove_classes.ts +6 -5
  533. package/src/form/EntityForm.tsx +222 -442
  534. package/src/form/EntityFormActions.tsx +49 -55
  535. package/src/form/EntityFormBinding.tsx +323 -0
  536. package/src/form/PropertyFieldBinding.tsx +81 -84
  537. package/src/form/components/ErrorFocus.tsx +1 -1
  538. package/src/form/components/FieldHelperText.tsx +6 -7
  539. package/src/form/components/FormLayout.tsx +1 -1
  540. package/src/form/components/LocalChangesMenu.tsx +20 -5
  541. package/src/form/components/StorageItemPreview.tsx +2 -3
  542. package/src/form/components/StorageUploadProgress.tsx +14 -7
  543. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +5 -5
  544. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +12 -13
  545. package/src/form/field_bindings/BlockFieldBinding.tsx +59 -58
  546. package/src/form/field_bindings/DateTimeFieldBinding.tsx +2 -2
  547. package/src/form/field_bindings/KeyValueFieldBinding.tsx +319 -303
  548. package/src/form/field_bindings/MapFieldBinding.tsx +14 -56
  549. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +28 -10
  550. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +3 -4
  551. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +11 -12
  552. package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +9 -2
  553. package/src/form/field_bindings/ReferenceFieldBinding.tsx +17 -15
  554. package/src/form/field_bindings/RelationFieldBinding.tsx +157 -156
  555. package/src/form/field_bindings/RepeatFieldBinding.tsx +8 -8
  556. package/src/form/field_bindings/SelectFieldBinding.tsx +3 -4
  557. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +107 -103
  558. package/src/form/field_bindings/SwitchFieldBinding.tsx +17 -17
  559. package/src/form/field_bindings/TextFieldBinding.tsx +90 -78
  560. package/src/form/field_bindings/UserSelectFieldBinding.tsx +18 -18
  561. package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
  562. package/src/form/form_utils.ts +163 -0
  563. package/src/form/index.tsx +15 -6
  564. package/src/form/useClearRestoreValue.tsx +1 -1
  565. package/src/form/validation.ts +104 -50
  566. package/src/hooks/index.ts +4 -4
  567. package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +5 -4
  568. package/src/hooks/navigation/contexts/NavigationStateContext.tsx +2 -2
  569. package/src/hooks/navigation/contexts/UrlContext.tsx +1 -2
  570. package/src/hooks/navigation/useAsyncResolver.ts +100 -0
  571. package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +40 -21
  572. package/src/hooks/navigation/useBuildNavigationStateController.tsx +21 -22
  573. package/src/hooks/navigation/useNavigationResolution.ts +193 -21
  574. package/src/hooks/navigation/useResolvedCollections.ts +45 -77
  575. package/src/hooks/navigation/useResolvedViews.tsx +44 -123
  576. package/src/hooks/navigation/useTopLevelNavigation.ts +22 -18
  577. package/src/hooks/navigation/utils.ts +12 -9
  578. package/src/hooks/useBreadcrumbsController.tsx +2 -34
  579. package/src/hooks/{useBuildSideEntityController.tsx → useBuildSidePanel.tsx} +63 -24
  580. package/src/hooks/useCMSContext.tsx +7 -7
  581. package/src/hooks/{useEntityHistory.ts → useHistory.ts} +9 -4
  582. package/src/hooks/useResolvedNavigationFrom.tsx +8 -5
  583. package/src/hooks/{useEntitySelectionDialog.tsx → useSelectionDialog.tsx} +7 -7
  584. package/src/hooks/useSideDialogsController.tsx +1 -1
  585. package/src/hooks/useSidePanel.tsx +13 -0
  586. package/src/index.ts +34 -20
  587. package/src/preview/PropertyPreview.tsx +34 -41
  588. package/src/preview/components/DatePreview.tsx +1 -1
  589. package/src/preview/components/EnumValuesChip.tsx +1 -1
  590. package/src/preview/components/ImagePreview.tsx +4 -3
  591. package/src/preview/components/ReferencePreview.tsx +69 -18
  592. package/src/preview/components/RelationPreview.tsx +107 -18
  593. package/src/preview/components/StorageThumbnail.tsx +28 -8
  594. package/src/preview/components/UrlComponentPreview.tsx +12 -4
  595. package/src/preview/components/UserPreview.tsx +6 -15
  596. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +5 -5
  597. package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +5 -5
  598. package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +4 -4
  599. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +4 -4
  600. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +3 -2
  601. package/src/preview/property_previews/ArrayOneOfPreview.tsx +7 -9
  602. package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +1 -1
  603. package/src/preview/property_previews/ArrayPropertyPreview.tsx +4 -4
  604. package/src/preview/property_previews/MapPropertyPreview.tsx +4 -3
  605. package/src/preview/property_previews/NumberPropertyPreview.tsx +5 -3
  606. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +24 -25
  607. package/src/preview/property_previews/StringPropertyPreview.tsx +13 -11
  608. package/src/routes/CustomViewRoute.tsx +14 -6
  609. package/src/routes/RebaseRoute.tsx +112 -36
  610. package/src/types/components/EntityFormActionsProps.tsx +4 -4
  611. package/src/types/components/EntityFormProps.tsx +75 -5
  612. package/src/types/components/PropertyPreviewProps.tsx +6 -1
  613. package/src/types/components/formex.tsx +1 -45
  614. package/src/types/fields.tsx +26 -15
  615. package/src/util/dataControllerAdapter.ts +87 -0
  616. package/src/util/navigation_utils.ts +43 -13
  617. package/src/util/previews.ts +149 -13
  618. package/src/util/propertyConfigMapper.ts +134 -0
  619. package/src/util/property_utils.tsx +24 -9
  620. package/src/util/resolutions.ts +4 -8
  621. package/src/util/view_constants.ts +6 -0
  622. package/dist/CollectionEditorDialog-B2M9lCyL.js +0 -4720
  623. package/dist/CollectionEditorDialog-B2M9lCyL.js.map +0 -1
  624. package/dist/CollectionsStudioView-WG6soyfs.js +0 -218
  625. package/dist/CollectionsStudioView-WG6soyfs.js.map +0 -1
  626. package/dist/ContentHomePage-CDF_a6Lp.js +0 -1786
  627. package/dist/ContentHomePage-CDF_a6Lp.js.map +0 -1
  628. package/dist/ExportCollectionAction-Dc0VOWMN.js +0 -439
  629. package/dist/ExportCollectionAction-Dc0VOWMN.js.map +0 -1
  630. package/dist/ImportCollectionAction-DpCagAOy.js +0 -686
  631. package/dist/ImportCollectionAction-DpCagAOy.js.map +0 -1
  632. package/dist/PropertyEditView-DS67DxoT.js +0 -8138
  633. package/dist/PropertyEditView-DS67DxoT.js.map +0 -1
  634. package/dist/RoleChip-QtUFXeTp.js +0 -67
  635. package/dist/RoleChip-QtUFXeTp.js.map +0 -1
  636. package/dist/RolesView-CIuYBimF.js +0 -424
  637. package/dist/RolesView-CIuYBimF.js.map +0 -1
  638. package/dist/UsersView-B5zelXnH.js +0 -493
  639. package/dist/UsersView-B5zelXnH.js.map +0 -1
  640. package/dist/collection_editor/types/config_permissions.d.ts +0 -19
  641. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +0 -27
  642. package/dist/components/EntityCollectionTable/fields/VirtualTableDateField.d.ts +0 -12
  643. package/dist/components/EntityCollectionTable/fields/VirtualTableInput.d.ts +0 -9
  644. package/dist/components/EntityCollectionTable/fields/VirtualTableNumberInput.d.ts +0 -8
  645. package/dist/components/EntityCollectionTable/fields/VirtualTableSwitch.d.ts +0 -7
  646. package/dist/components/EntityCollectionTable/index.d.ts +0 -6
  647. package/dist/components/EntityCollectionView/Board.d.ts +0 -2
  648. package/dist/components/EntityCollectionView/BoardColumn.d.ts +0 -42
  649. package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +0 -9
  650. package/dist/components/EntityCollectionView/BoardSortableList.d.ts +0 -14
  651. package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +0 -31
  652. package/dist/components/EntityCollectionView/EntityCard.d.ts +0 -20
  653. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +0 -21
  654. package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +0 -34
  655. package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +0 -64
  656. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +0 -18
  657. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +0 -18
  658. package/dist/components/EntityCollectionView/board_types.d.ts +0 -105
  659. package/dist/components/EntityEditView.d.ts +0 -49
  660. package/dist/components/EntityEditViewFormActions.d.ts +0 -2
  661. package/dist/components/EntityJsonPreview.d.ts +0 -3
  662. package/dist/components/EntitySidePanel.d.ts +0 -10
  663. package/dist/components/EntityView.d.ts +0 -12
  664. package/dist/components/admin/RoleChip.d.ts +0 -4
  665. package/dist/components/admin/RolesView.d.ts +0 -4
  666. package/dist/components/admin/UsersView.d.ts +0 -4
  667. package/dist/contexts/SideEntityControllerContext.d.ts +0 -3
  668. package/dist/form/field_bindings/ReferenceAsStringFieldBinding.d.ts +0 -10
  669. package/dist/hooks/navigation/useNavigationRegistry.d.ts +0 -11
  670. package/dist/hooks/navigation/useNavigationURLs.d.ts +0 -11
  671. package/dist/hooks/useBuildSideEntityController.d.ts +0 -6
  672. package/dist/hooks/useSideEntityController.d.ts +0 -11
  673. package/dist/index-CBhrgpR7.js +0 -12
  674. package/dist/index-CBhrgpR7.js.map +0 -1
  675. package/dist/index-CHxgwt6E.js +0 -456
  676. package/dist/index-CHxgwt6E.js.map +0 -1
  677. package/dist/index-Dey5WJpO.js +0 -8
  678. package/dist/index-Dey5WJpO.js.map +0 -1
  679. package/dist/index.js.map +0 -1
  680. package/dist/markdown-z2Ir7Cgo.js +0 -618
  681. package/dist/markdown-z2Ir7Cgo.js.map +0 -1
  682. package/dist/useEntityHistory-Dcj4zhGj.js +0 -121
  683. package/dist/useEntityHistory-Dcj4zhGj.js.map +0 -1
  684. package/dist/util-BQ82ySL3.js +0 -27720
  685. package/dist/util-BQ82ySL3.js.map +0 -1
  686. package/src/collection_editor/types/config_permissions.ts +0 -20
  687. package/src/components/EntityCollectionTable/fields/VirtualTableDateField.tsx +0 -39
  688. package/src/components/EntityCollectionTable/fields/VirtualTableInput.tsx +0 -90
  689. package/src/components/EntityCollectionTable/fields/VirtualTableNumberInput.tsx +0 -80
  690. package/src/components/EntityCollectionTable/fields/VirtualTableSwitch.tsx +0 -32
  691. package/src/components/EntityCollectionTable/index.tsx +0 -14
  692. package/src/components/EntityCollectionView/Board.tsx +0 -474
  693. package/src/components/EntityCollectionView/BoardColumn.tsx +0 -158
  694. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +0 -45
  695. package/src/components/EntityCollectionView/BoardSortableList.tsx +0 -177
  696. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +0 -267
  697. package/src/components/EntityCollectionView/board_types.ts +0 -113
  698. package/src/components/EntityEditView.tsx +0 -632
  699. package/src/components/EntitySidePanel.tsx +0 -160
  700. package/src/components/admin/RoleChip.tsx +0 -23
  701. package/src/components/admin/RolesView.tsx +0 -419
  702. package/src/components/admin/UsersView.tsx +0 -782
  703. package/src/contexts/SideEntityControllerContext.tsx +0 -5
  704. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +0 -141
  705. package/src/hooks/navigation/useNavigationRegistry.ts +0 -153
  706. package/src/hooks/navigation/useNavigationURLs.ts +0 -56
  707. package/src/hooks/useSideEntityController.tsx +0 -13
  708. /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/PropertyTableCell.d.ts +0 -0
  709. /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useDraggable.d.ts +0 -0
  710. /package/dist/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useWindowSize.d.ts +0 -0
  711. /package/dist/components/{EntityCollectionView → CollectionViewBinding}/useSelectionController.d.ts +0 -0
  712. /package/dist/components/{EntityCollectionView → CollectionViewBinding}/utils.d.ts +0 -0
  713. /package/src/components/{EntityCollectionTable → CollectionTableBinding}/fields/VirtualTableUserSelect.tsx +0 -0
  714. /package/src/components/{EntityCollectionTable → CollectionTableBinding}/internal/popup_field/useWindowSize.tsx +0 -0
  715. /package/src/components/{EntityCollectionView → CollectionViewBinding}/useSelectionController.tsx +0 -0
  716. /package/src/components/{EntityCollectionView → CollectionViewBinding}/utils.ts +0 -0
@@ -0,0 +1,3630 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
+ import { At as useImportConfig, Bn as useUrlController, Bt as getFieldId, Ct as useCollectionEditorController, Et as convertDataToEntity, Ft as PropertyConfigBadge, Hn as useNavigationStateController, Mt as ImportFileUpload, Qn as CollectionTableBinding, Tt as DataNewPropertiesMapping, Wn as useCollectionRegistryController, Xn as useSelectionController, dn as SearchIconsView, fn as FieldCaption, h as toSerializableCollectionConfig, i as namespaceToPropertiesOrderPath, jt as ImportSaveInProgress, kt as getInferenceType, n as getFullIdPath, r as idToPropertiesPath, s as CollectionGenerationApiError, t as getFullId, u as validateCollectionJson, v as useCollectionsConfigController, wt as ImportNewPropertyFieldPreview, zt as getFieldConfig } from "./src-DLAFyeZI.js";
3
+ import { a as updatePropertyFromWidget, c as useAIModifiedPaths, i as supportedFields, l as useSafeSnackbarController, n as PropertyForm, o as PropertyTree, r as PropertyFormDialog, s as AIModifiedPathsProvider } from "./PropertyEditView-h0N-AMCY.js";
4
+ import * as React$1 from "react";
5
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
6
+ import { Alert, AppWindow, ArrowLeftIcon, BooleanSwitchWithLabel, Button, Card, CheckIcon, Chip, CircularProgress, CircularProgressCenter, CodeIcon, ColumnsIcon, Container, CopyIcon, DebouncedTextField, Dialog, DialogActions, DialogContent, DialogTitle, ErrorBoundary, FileIcon, FileSearchIcon, FileTextIcon, IconButton, KanbanIcon, KeyIcon, LayoutGridIcon, ListIcon, LoadingButton, Menu, MultiSelect, MultiSelectItem, PanelLeftIcon, Paper, PlusIcon, Select, SelectItem, ShoppingCartIcon, SquareIcon, Tab, TableIcon, Tabs, TextField, ToggleButtonGroup, Tooltip, Trash2Icon, Typography, UserIcon, XIcon, cls, coolIconKeys, defaultBorderMixin, iconSize } from "@rebasepro/ui";
7
+ import { getSubcollections, getTableName, isPropertyBuilder, removeInitialAndTrailingSlashes } from "@rebasepro/common";
8
+ import { AIIcon, ConfirmationDialog, ErrorView, IconForView, UnsavedChangesDialog, useAuthController, useCustomizationController, useLargeLayout, useRebaseContext, useUnsavedChangesDialog } from "@rebasepro/app";
9
+ import { Field, Formex, clone, getIn, useCreateFormex, useFormex } from "@rebasepro/forms";
10
+ import { z } from "zod";
11
+ import { camelCase, isEmptyObject, mergeDeep, prettifyIdentifier, randomString, removeUndefined, singular, slugify, toSnakeCase, unslugify } from "@rebasepro/utils";
12
+ import { getDataSourceCapabilities } from "@rebasepro/types";
13
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
14
+ import { Highlight, themes } from "prism-react-renderer";
15
+ import { buildEntityPropertiesFromData, buildPropertyFromData } from "@rebasepro/inference";
16
+ import JSON5 from "json5";
17
+ //#region src/collection_editor/ui/collection_editor/CollectionYupValidation.tsx
18
+ var CollectionEditorSchema = z.object({
19
+ slug: z.string().min(1, "Required"),
20
+ name: z.string().min(1, "Required"),
21
+ table: z.string().min(1, "Required")
22
+ });
23
+ //#endregion
24
+ //#region src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx
25
+ function GeneralSettingsForm({ isNewCollection, existingPaths, existingIds, parentCollection, renderExtraCollectionFields, standalone }) {
26
+ const { values, setFieldValue, handleChange, touched, errors, setFieldTouched, submitCount } = useFormex();
27
+ const [iconDialogOpen, setIconDialogOpen] = useState(false);
28
+ const configControllerFromContext = useCollectionsConfigController();
29
+ const configController = standalone ? { readOnly: false } : configControllerFromContext;
30
+ const updateDatabaseId = (databaseId) => {
31
+ setFieldValue("databaseId", databaseId ?? void 0);
32
+ };
33
+ const updateName = (name) => {
34
+ setFieldValue("name", name);
35
+ if (!getIn(touched, "table") && isNewCollection && name) setFieldValue("table", toSnakeCase(name));
36
+ if (!getIn(touched, "slug") && isNewCollection && name) setFieldValue("slug", toSnakeCase(name));
37
+ if (!getIn(touched, "singularName") && isNewCollection && name) setFieldValue("singularName", singular(name));
38
+ };
39
+ const collectionIcon = /* @__PURE__ */ jsx(IconForView, { collectionOrView: values });
40
+ const isSubcollection = !!parentCollection;
41
+ const showErrors = submitCount > 0;
42
+ return /* @__PURE__ */ jsx("div", {
43
+ className: "overflow-auto my-auto",
44
+ children: /* @__PURE__ */ jsxs(Container, {
45
+ maxWidth: "4xl",
46
+ className: "flex flex-col gap-4 p-8 m-auto",
47
+ children: [
48
+ /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsxs("div", {
49
+ className: "flex flex-row gap-2 items-center",
50
+ children: [
51
+ /* @__PURE__ */ jsx(Typography, {
52
+ variant: !isNewCollection ? "h5" : "h4",
53
+ className: "flex-grow",
54
+ children: isNewCollection ? "New collection" : `${values?.name} collection`
55
+ }),
56
+ /* @__PURE__ */ jsx(DefaultDatabaseField, {
57
+ databaseId: values.databaseId,
58
+ disabled: configController?.readOnly,
59
+ onDatabaseIdUpdate: updateDatabaseId
60
+ }),
61
+ /* @__PURE__ */ jsx(Tooltip, {
62
+ title: "Change icon",
63
+ asChild: true,
64
+ children: /* @__PURE__ */ jsx(IconButton, {
65
+ shape: "square",
66
+ disabled: configController?.readOnly,
67
+ onClick: () => setIconDialogOpen(true),
68
+ children: collectionIcon
69
+ })
70
+ })
71
+ ]
72
+ }), parentCollection && /* @__PURE__ */ jsx(Chip, {
73
+ colorScheme: "teal",
74
+ children: /* @__PURE__ */ jsxs(Typography, {
75
+ variant: "caption",
76
+ children: ["This is a subcollection of ", /* @__PURE__ */ jsx("b", { children: parentCollection.name })]
77
+ })
78
+ })] }),
79
+ /* @__PURE__ */ jsxs("fieldset", {
80
+ disabled: configController?.readOnly,
81
+ className: "contents",
82
+ children: [/* @__PURE__ */ jsxs("div", {
83
+ className: "grid grid-cols-12 gap-4",
84
+ children: [
85
+ /* @__PURE__ */ jsxs("div", {
86
+ className: "col-span-12",
87
+ children: [/* @__PURE__ */ jsx(TextField, {
88
+ value: values.name ?? "",
89
+ onChange: (e) => updateName(e.target.value),
90
+ label: "Name",
91
+ autoFocus: true,
92
+ required: true,
93
+ error: showErrors && Boolean(errors.name)
94
+ }), /* @__PURE__ */ jsx(FieldCaption, {
95
+ error: touched.name && Boolean(errors.name),
96
+ children: touched.name && Boolean(errors.name) ? errors.name : "Name of this collection, usually a plural name (e.g. Products)"
97
+ })]
98
+ }),
99
+ /* @__PURE__ */ jsxs("div", {
100
+ className: cls("col-span-12"),
101
+ children: [/* @__PURE__ */ jsx(Field, {
102
+ name: "table",
103
+ as: DebouncedTextField,
104
+ label: "Table name",
105
+ required: true,
106
+ error: showErrors && Boolean(errors.table)
107
+ }), /* @__PURE__ */ jsx(FieldCaption, {
108
+ error: touched.table && Boolean(errors.table),
109
+ children: touched.table && Boolean(errors.table) ? errors.table : isSubcollection ? "Relative path to the parent (no need to include the parent path)" : "PostgreSQL table name for this collection"
110
+ })]
111
+ }),
112
+ /* @__PURE__ */ jsxs("div", {
113
+ className: "col-span-12",
114
+ children: [/* @__PURE__ */ jsx(TextField, {
115
+ error: showErrors && Boolean(errors.singularName),
116
+ name: "singularName",
117
+ "aria-describedby": "singularName-helper",
118
+ onChange: (e) => {
119
+ setFieldTouched("singularName", true);
120
+ return handleChange(e);
121
+ },
122
+ value: values.singularName ?? "",
123
+ label: "Singular name"
124
+ }), /* @__PURE__ */ jsx(FieldCaption, {
125
+ error: showErrors && Boolean(errors.singularName),
126
+ children: showErrors && Boolean(errors.singularName) ? errors.singularName : "Optionally define a singular name for your entities"
127
+ })]
128
+ }),
129
+ /* @__PURE__ */ jsxs("div", {
130
+ className: "col-span-12",
131
+ children: [/* @__PURE__ */ jsx(TextField, {
132
+ error: showErrors && Boolean(errors.description),
133
+ name: "description",
134
+ value: values.description ?? "",
135
+ onChange: handleChange,
136
+ multiline: true,
137
+ minRows: 2,
138
+ "aria-describedby": "description-helper-text",
139
+ label: "Description"
140
+ }), /* @__PURE__ */ jsx(FieldCaption, {
141
+ error: showErrors && Boolean(errors.description),
142
+ children: showErrors && Boolean(errors.description) ? errors.description : "Description of the collection, you can use markdown"
143
+ })]
144
+ }),
145
+ /* @__PURE__ */ jsxs("div", {
146
+ className: "col-span-12",
147
+ children: [/* @__PURE__ */ jsx(DebouncedTextField, {
148
+ name: "slug",
149
+ value: values.slug ?? "",
150
+ onChange: (e) => setFieldValue("slug", e.target.value),
151
+ disabled: !isNewCollection,
152
+ label: "Collection ID",
153
+ error: showErrors && Boolean(errors.slug)
154
+ }), /* @__PURE__ */ jsx(FieldCaption, {
155
+ error: touched.slug && Boolean(errors.slug),
156
+ children: touched.slug && Boolean(errors.slug) ? errors.slug : "This ID identifies this collection. Typically the same as the path."
157
+ })]
158
+ })
159
+ ]
160
+ }), null]
161
+ }),
162
+ /* @__PURE__ */ jsx("div", { style: { height: "52px" } }),
163
+ /* @__PURE__ */ jsx(Dialog, {
164
+ open: iconDialogOpen,
165
+ onOpenChange: setIconDialogOpen,
166
+ maxWidth: "xl",
167
+ fullWidth: true,
168
+ children: /* @__PURE__ */ jsx("div", {
169
+ className: "p-4 overflow-auto min-h-[200px]",
170
+ children: /* @__PURE__ */ jsx(SearchIconsView, {
171
+ selectedIcon: typeof values.icon === "string" ? values.icon : void 0,
172
+ onIconSelected: (icon) => {
173
+ setIconDialogOpen(false);
174
+ setFieldValue("icon", icon);
175
+ }
176
+ })
177
+ })
178
+ }),
179
+ renderExtraCollectionFields && /* @__PURE__ */ jsx("div", {
180
+ className: "mt-4",
181
+ children: renderExtraCollectionFields({
182
+ metadata: values.metadata ?? {},
183
+ onMetadataChange: (key, value) => {
184
+ setFieldValue(`metadata.${key}`, value);
185
+ },
186
+ collection: toSerializableCollectionConfig(values)
187
+ })
188
+ })
189
+ ]
190
+ })
191
+ });
192
+ }
193
+ function DefaultDatabaseField({ databaseId, disabled = false, onDatabaseIdUpdate }) {
194
+ return /* @__PURE__ */ jsx(Tooltip, {
195
+ title: "Database ID",
196
+ side: "top",
197
+ align: "start",
198
+ children: /* @__PURE__ */ jsx(TextField, {
199
+ size: "small",
200
+ invisible: true,
201
+ inputClassName: "text-end",
202
+ disabled,
203
+ value: databaseId ?? "",
204
+ onChange: (e) => onDatabaseIdUpdate(e.target.value),
205
+ placeholder: "(default)"
206
+ })
207
+ });
208
+ }
209
+ //#endregion
210
+ //#region src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx
211
+ function LayoutModeSwitch({ value, onChange, className }) {
212
+ return /* @__PURE__ */ jsxs("div", {
213
+ className: cls(className),
214
+ children: [
215
+ /* @__PURE__ */ jsx(Typography, {
216
+ variant: "label",
217
+ color: "secondary",
218
+ className: "ml-3.5",
219
+ children: "Document view"
220
+ }),
221
+ /* @__PURE__ */ jsx("div", {
222
+ className: "my-2",
223
+ children: /* @__PURE__ */ jsx(ToggleButtonGroup, {
224
+ value,
225
+ onValueChange: onChange,
226
+ options: [
227
+ {
228
+ value: "side_panel",
229
+ label: "Side panel",
230
+ icon: /* @__PURE__ */ jsx(ColumnsIcon, {})
231
+ },
232
+ {
233
+ value: "full_screen",
234
+ label: "Full screen",
235
+ icon: /* @__PURE__ */ jsx(SquareIcon, {})
236
+ },
237
+ {
238
+ value: "split",
239
+ label: "Split view",
240
+ icon: /* @__PURE__ */ jsx(PanelLeftIcon, {})
241
+ },
242
+ {
243
+ value: "dialog",
244
+ label: "Centered dialog",
245
+ icon: /* @__PURE__ */ jsx(AppWindow, {})
246
+ }
247
+ ]
248
+ })
249
+ }),
250
+ /* @__PURE__ */ jsx(Typography, {
251
+ variant: "caption",
252
+ color: "secondary",
253
+ className: "ml-3.5",
254
+ children: "Should documents be opened full screen, inline side dialog, or centered dialog"
255
+ })
256
+ ]
257
+ });
258
+ }
259
+ //#endregion
260
+ //#region src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx
261
+ function ViewModeSwitch({ value, onChange, className }) {
262
+ return /* @__PURE__ */ jsxs("div", {
263
+ className: cls(className),
264
+ children: [
265
+ /* @__PURE__ */ jsx(Typography, {
266
+ variant: "label",
267
+ color: "secondary",
268
+ className: "ml-3.5",
269
+ children: "Default collection view"
270
+ }),
271
+ /* @__PURE__ */ jsx("div", {
272
+ className: "my-2",
273
+ children: /* @__PURE__ */ jsx(ToggleButtonGroup, {
274
+ value,
275
+ onValueChange: onChange,
276
+ options: [
277
+ {
278
+ value: "list",
279
+ label: "List",
280
+ icon: /* @__PURE__ */ jsx(ListIcon, {})
281
+ },
282
+ {
283
+ value: "table",
284
+ label: "Table",
285
+ icon: /* @__PURE__ */ jsx(TableIcon, {})
286
+ },
287
+ {
288
+ value: "cards",
289
+ label: "Cards",
290
+ icon: /* @__PURE__ */ jsx(LayoutGridIcon, {})
291
+ },
292
+ {
293
+ value: "kanban",
294
+ label: "Kanban",
295
+ icon: /* @__PURE__ */ jsx(KanbanIcon, {})
296
+ }
297
+ ]
298
+ })
299
+ }),
300
+ /* @__PURE__ */ jsx(Typography, {
301
+ variant: "caption",
302
+ color: "secondary",
303
+ className: "ml-3.5",
304
+ children: "Choose how entities should be displayed by default"
305
+ })
306
+ ]
307
+ });
308
+ }
309
+ //#endregion
310
+ //#region src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx
311
+ function KanbanConfigSection({ className, forceExpanded }) {
312
+ useAuthController();
313
+ const customizationController = useCustomizationController();
314
+ const { values, setFieldValue } = useFormex();
315
+ const panelRef = useRef(null);
316
+ const [columnPropertyDialogOpen, setColumnPropertyDialogOpen] = useState(false);
317
+ const enumStringProperties = useMemo(() => {
318
+ const result = [];
319
+ if (!values.properties) return result;
320
+ Object.entries(values.properties).forEach(([key, prop]) => {
321
+ if (prop && "type" in prop && prop.type === "string" && prop.enum) result.push({
322
+ key,
323
+ label: prop.name || key,
324
+ property: prop
325
+ });
326
+ });
327
+ return result;
328
+ }, [values.properties]);
329
+ const kanbanConfig = values.kanban;
330
+ const columnPropertyMissing = Boolean(kanbanConfig?.columnProperty) && !enumStringProperties.some((p) => p.key === kanbanConfig?.columnProperty);
331
+ React.useEffect(() => {
332
+ if (forceExpanded && panelRef.current) setTimeout(() => {
333
+ panelRef.current?.scrollIntoView({
334
+ behavior: "smooth",
335
+ block: "center"
336
+ });
337
+ }, 100);
338
+ }, [forceExpanded]);
339
+ const showCreateButton = !kanbanConfig?.columnProperty || columnPropertyMissing;
340
+ const dialogPropertyKey = columnPropertyMissing && kanbanConfig?.columnProperty ? kanbanConfig.columnProperty : "status";
341
+ const dialogPropertyName = columnPropertyMissing && kanbanConfig?.columnProperty ? unslugify(kanbanConfig.columnProperty) : "Status";
342
+ return /* @__PURE__ */ jsxs("div", {
343
+ className,
344
+ ref: panelRef,
345
+ children: [
346
+ /* @__PURE__ */ jsx(Select, {
347
+ name: "kanban.columnProperty",
348
+ label: "Kanban Column Property",
349
+ fullWidth: true,
350
+ position: "item-aligned",
351
+ disabled: enumStringProperties.length === 0,
352
+ error: columnPropertyMissing,
353
+ value: kanbanConfig?.columnProperty ?? "",
354
+ onValueChange: (v) => {
355
+ if (v) setFieldValue("kanban", {
356
+ ...kanbanConfig,
357
+ columnProperty: v
358
+ });
359
+ else setFieldValue("kanban", void 0);
360
+ },
361
+ renderValue: (value) => {
362
+ if (columnPropertyMissing) return /* @__PURE__ */ jsxs("span", {
363
+ className: "text-red-500",
364
+ children: [value, " (not found)"]
365
+ });
366
+ const prop = enumStringProperties.find((p) => p.key === value);
367
+ if (!prop) return "Select a property";
368
+ return /* @__PURE__ */ jsxs("div", {
369
+ className: "flex items-center gap-2",
370
+ children: [/* @__PURE__ */ jsx(PropertyConfigBadge, { propertyConfig: getFieldConfig(prop.property, customizationController.propertyConfigs) }), /* @__PURE__ */ jsx("span", { children: prop.label })]
371
+ });
372
+ },
373
+ endAdornment: kanbanConfig?.columnProperty ? /* @__PURE__ */ jsx(IconButton, {
374
+ size: "small",
375
+ onClick: (e) => {
376
+ e.stopPropagation();
377
+ setFieldValue("kanban", void 0);
378
+ },
379
+ children: /* @__PURE__ */ jsx(XIcon, { size: iconSize.smallest })
380
+ }) : void 0,
381
+ children: enumStringProperties.map((prop) => {
382
+ const fieldConfig = getFieldConfig(prop.property, customizationController.propertyConfigs);
383
+ return /* @__PURE__ */ jsx(SelectItem, {
384
+ value: prop.key,
385
+ children: /* @__PURE__ */ jsxs("div", {
386
+ className: "flex items-center gap-3",
387
+ children: [/* @__PURE__ */ jsx(PropertyConfigBadge, { propertyConfig: fieldConfig }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: prop.label }), /* @__PURE__ */ jsx(Typography, {
388
+ variant: "caption",
389
+ color: "secondary",
390
+ children: fieldConfig?.name || "Enum"
391
+ })] })]
392
+ })
393
+ }, prop.key);
394
+ })
395
+ }, `column-select-${enumStringProperties.length}`),
396
+ /* @__PURE__ */ jsx(FieldCaption, {
397
+ error: columnPropertyMissing,
398
+ children: columnPropertyMissing ? `Property "${kanbanConfig?.columnProperty}" does not exist or is not an enum string property. Please select a valid property or clear the selection.` : enumStringProperties.length === 0 ? "No enum string properties found. Add a string property with enum to use Kanban view." : "Select a string property with enum values to group entities into columns"
399
+ }),
400
+ showCreateButton && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Button, {
401
+ variant: "text",
402
+ size: "small",
403
+ className: "ml-3.5 mt-2",
404
+ onClick: () => setColumnPropertyDialogOpen(true),
405
+ children: [
406
+ "+ Create \"",
407
+ dialogPropertyKey,
408
+ "\" property"
409
+ ]
410
+ }), /* @__PURE__ */ jsx(PropertyFormDialog, {
411
+ open: columnPropertyDialogOpen,
412
+ onCancel: () => setColumnPropertyDialogOpen(false),
413
+ property: {
414
+ type: "string",
415
+ name: dialogPropertyName,
416
+ enum: [
417
+ {
418
+ id: "todo",
419
+ label: "To Do"
420
+ },
421
+ {
422
+ id: "in_progress",
423
+ label: "In Progress"
424
+ },
425
+ {
426
+ id: "done",
427
+ label: "Done"
428
+ }
429
+ ]
430
+ },
431
+ propertyKey: dialogPropertyKey,
432
+ existingProperty: false,
433
+ autoOpenTypeSelect: false,
434
+ autoUpdateId: false,
435
+ inArray: false,
436
+ allowDataInference: false,
437
+ propertyConfigs: customizationController.propertyConfigs,
438
+ existingPropertyKeys: Object.keys(values.properties ?? {}),
439
+ onPropertyChanged: ({ id, property }) => {
440
+ const newProperties = {
441
+ ...values.properties,
442
+ [id]: property
443
+ };
444
+ const newPropertiesOrder = [...values.propertiesOrder ?? Object.keys(values.properties ?? {}), id];
445
+ setFieldValue("properties", newProperties);
446
+ setFieldValue("propertiesOrder", newPropertiesOrder);
447
+ setFieldValue("kanban", {
448
+ ...kanbanConfig,
449
+ columnProperty: id
450
+ });
451
+ setColumnPropertyDialogOpen(false);
452
+ }
453
+ })] })
454
+ ]
455
+ });
456
+ }
457
+ //#endregion
458
+ //#region src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx
459
+ function DisplaySettingsForm({ expandKanban, standalone }) {
460
+ const { values, setFieldValue, handleChange, submitCount } = useFormex();
461
+ const [orderPropertyDialogOpen, setOrderPropertyDialogOpen] = useState(false);
462
+ const customizationController = useCustomizationController();
463
+ const configControllerFromContext = useCollectionsConfigController();
464
+ const configController = standalone ? { readOnly: false } : configControllerFromContext;
465
+ const textProperties = useMemo(() => {
466
+ const result = [];
467
+ if (!values.properties) return result;
468
+ Object.entries(values.properties).forEach(([key, prop]) => {
469
+ if (prop && "type" in prop && prop.type === "string") result.push({
470
+ key,
471
+ label: prop.name || key,
472
+ property: prop
473
+ });
474
+ });
475
+ return result;
476
+ }, [values.properties]);
477
+ return /* @__PURE__ */ jsx("div", {
478
+ className: "overflow-auto my-auto",
479
+ children: /* @__PURE__ */ jsxs(Container, {
480
+ maxWidth: "4xl",
481
+ className: "flex flex-col gap-4 p-8 m-auto",
482
+ children: [
483
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Typography, {
484
+ variant: "h5",
485
+ className: "flex-grow",
486
+ children: "Display settings"
487
+ }) }),
488
+ /* @__PURE__ */ jsx("fieldset", {
489
+ disabled: configController?.readOnly,
490
+ className: "contents",
491
+ children: /* @__PURE__ */ jsxs("div", {
492
+ className: "grid grid-cols-12 gap-4",
493
+ children: [
494
+ /* @__PURE__ */ jsx(LayoutModeSwitch, {
495
+ className: "col-span-12",
496
+ value: values.openEntityMode ?? "side_panel",
497
+ onChange: (value) => setFieldValue("openEntityMode", value)
498
+ }),
499
+ /* @__PURE__ */ jsx(ViewModeSwitch, {
500
+ className: "col-span-12",
501
+ value: values.defaultViewMode ?? "table",
502
+ onChange: (value) => setFieldValue("defaultViewMode", value)
503
+ }),
504
+ /* @__PURE__ */ jsx(KanbanConfigSection, {
505
+ className: "col-span-12",
506
+ forceExpanded: expandKanban
507
+ }),
508
+ /* @__PURE__ */ jsxs("div", {
509
+ className: "col-span-12 mt-4",
510
+ children: [(() => {
511
+ const orderPropertyMissing = Boolean(values.orderProperty) && !textProperties.some((p) => p.key === values.orderProperty);
512
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Select, {
513
+ name: "orderProperty",
514
+ label: "Order Property",
515
+ fullWidth: true,
516
+ position: "item-aligned",
517
+ disabled: textProperties.length === 0,
518
+ error: orderPropertyMissing,
519
+ value: values.orderProperty ?? "",
520
+ onValueChange: (v) => {
521
+ setFieldValue("orderProperty", v || void 0);
522
+ },
523
+ renderValue: (value) => {
524
+ if (orderPropertyMissing) return /* @__PURE__ */ jsxs("span", {
525
+ className: "text-red-500",
526
+ children: [value, " (not found)"]
527
+ });
528
+ const prop = textProperties.find((p) => p.key === value);
529
+ if (!prop) return "Select a property";
530
+ return /* @__PURE__ */ jsxs("div", {
531
+ className: "flex items-center gap-2",
532
+ children: [/* @__PURE__ */ jsx(PropertyConfigBadge, { propertyConfig: getFieldConfig(prop.property, customizationController?.propertyConfigs ?? {}) }), /* @__PURE__ */ jsx("span", { children: prop.label })]
533
+ });
534
+ },
535
+ endAdornment: values.orderProperty ? /* @__PURE__ */ jsx(IconButton, {
536
+ size: "small",
537
+ onClick: (e) => {
538
+ e.stopPropagation();
539
+ setFieldValue("orderProperty", void 0);
540
+ },
541
+ children: /* @__PURE__ */ jsx(XIcon, { size: iconSize.smallest })
542
+ }) : void 0,
543
+ children: textProperties.map((prop) => {
544
+ const fieldConfig = getFieldConfig(prop.property, customizationController?.propertyConfigs ?? {});
545
+ return /* @__PURE__ */ jsx(SelectItem, {
546
+ value: prop.key,
547
+ children: /* @__PURE__ */ jsxs("div", {
548
+ className: "flex items-center gap-3",
549
+ children: [/* @__PURE__ */ jsx(PropertyConfigBadge, { propertyConfig: fieldConfig }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: prop.label }), /* @__PURE__ */ jsx(Typography, {
550
+ variant: "caption",
551
+ color: "secondary",
552
+ children: fieldConfig?.name || "Text"
553
+ })] })]
554
+ })
555
+ }, prop.key);
556
+ })
557
+ }, `order-select-${textProperties.length}`), /* @__PURE__ */ jsx(FieldCaption, {
558
+ error: orderPropertyMissing,
559
+ children: orderPropertyMissing ? `Property "${values.orderProperty}" does not exist or is not a text property. Please select a valid property or clear the selection.` : textProperties.length === 0 ? "No text properties found. Add a text property to enable ordering." : "Select a text property to persist the order of items"
560
+ })] });
561
+ })(), (() => {
562
+ const orderPropertyMissing = Boolean(values.orderProperty) && !textProperties.some((p) => p.key === values.orderProperty);
563
+ const showCreateButton = !values.orderProperty || orderPropertyMissing;
564
+ const dialogPropertyKey = orderPropertyMissing && values.orderProperty ? values.orderProperty : "__order";
565
+ const dialogPropertyName = orderPropertyMissing && values.orderProperty ? unslugify(values.orderProperty) : "Order";
566
+ if (!showCreateButton) return null;
567
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs(Button, {
568
+ variant: "text",
569
+ size: "small",
570
+ className: "ml-3.5 mt-2",
571
+ onClick: () => setOrderPropertyDialogOpen(true),
572
+ children: [
573
+ "+ Create \"",
574
+ dialogPropertyKey,
575
+ "\" property"
576
+ ]
577
+ }), /* @__PURE__ */ jsx(PropertyFormDialog, {
578
+ open: orderPropertyDialogOpen,
579
+ onCancel: () => setOrderPropertyDialogOpen(false),
580
+ property: {
581
+ type: "string",
582
+ name: dialogPropertyName,
583
+ ui: {
584
+ disabled: true,
585
+ hideFromCollection: true
586
+ }
587
+ },
588
+ propertyKey: dialogPropertyKey,
589
+ existingProperty: false,
590
+ autoOpenTypeSelect: false,
591
+ autoUpdateId: false,
592
+ inArray: false,
593
+ allowDataInference: false,
594
+ propertyConfigs: customizationController?.propertyConfigs ?? {},
595
+ existingPropertyKeys: Object.keys(values.properties ?? {}),
596
+ onPropertyChanged: ({ id, property }) => {
597
+ const newProperties = {
598
+ ...values.properties,
599
+ [id]: property
600
+ };
601
+ const newPropertiesOrder = [...values.propertiesOrder ?? Object.keys(values.properties ?? {}), id];
602
+ setFieldValue("properties", newProperties);
603
+ setFieldValue("propertiesOrder", newPropertiesOrder);
604
+ setFieldValue("orderProperty", id);
605
+ setOrderPropertyDialogOpen(false);
606
+ }
607
+ })] });
608
+ })()]
609
+ }),
610
+ /* @__PURE__ */ jsx("div", {
611
+ className: "col-span-12",
612
+ children: /* @__PURE__ */ jsx(Select, {
613
+ name: "defaultSize",
614
+ fullWidth: true,
615
+ label: "Default row size",
616
+ position: "item-aligned",
617
+ onChange: handleChange,
618
+ value: values.defaultSize ?? "",
619
+ renderValue: (value) => value.toUpperCase(),
620
+ children: [
621
+ "xs",
622
+ "s",
623
+ "m",
624
+ "l",
625
+ "xl"
626
+ ].map((value) => /* @__PURE__ */ jsx(SelectItem, {
627
+ value,
628
+ children: value.toUpperCase()
629
+ }, `size-select-${value}`))
630
+ })
631
+ }),
632
+ /* @__PURE__ */ jsxs("div", {
633
+ className: "col-span-12",
634
+ children: [/* @__PURE__ */ jsx(TextField, {
635
+ name: "sideDialogWidth",
636
+ type: "number",
637
+ "aria-describedby": "sideDialogWidth-helper",
638
+ onChange: (e) => {
639
+ const value = e.target.value;
640
+ if (!value) setFieldValue("sideDialogWidth", null);
641
+ else if (!isNaN(Number(value))) setFieldValue("sideDialogWidth", Number(value));
642
+ },
643
+ endAdornment: /* @__PURE__ */ jsx(IconButton, {
644
+ size: "small",
645
+ onClick: () => {
646
+ setFieldValue("sideDialogWidth", null);
647
+ },
648
+ disabled: !values.sideDialogWidth,
649
+ children: /* @__PURE__ */ jsx(XIcon, { size: iconSize.small })
650
+ }),
651
+ value: values.sideDialogWidth ?? "",
652
+ label: "Side dialog width"
653
+ }), /* @__PURE__ */ jsx(FieldCaption, { children: "Optionally define the width (in pixels) of entities side dialog. Default is 768px" })]
654
+ }),
655
+ /* @__PURE__ */ jsxs("div", {
656
+ className: "col-span-12",
657
+ children: [/* @__PURE__ */ jsx(BooleanSwitchWithLabel, {
658
+ position: "start",
659
+ label: values.inlineEditing === void 0 || values.inlineEditing ? "Data can be edited directly in the table view" : "Data can be edited only in the form view",
660
+ onValueChange: (v) => setFieldValue("inlineEditing", v),
661
+ value: values.inlineEditing === void 0 ? true : values.inlineEditing
662
+ }), /* @__PURE__ */ jsx(FieldCaption, { children: "Allow editing data directly in the table view, without opening the form view." })]
663
+ }),
664
+ /* @__PURE__ */ jsxs("div", {
665
+ className: "col-span-12",
666
+ children: [/* @__PURE__ */ jsx(BooleanSwitchWithLabel, {
667
+ position: "start",
668
+ label: values.includeJsonView === void 0 || values.includeJsonView ? "Include JSON view" : "Do not include JSON view",
669
+ onValueChange: (v) => setFieldValue("includeJsonView", v),
670
+ value: values.includeJsonView === void 0 ? true : values.includeJsonView
671
+ }), /* @__PURE__ */ jsx(FieldCaption, { children: "Allows removing the form view JSON tab if you think it is confusing for your users." })]
672
+ })
673
+ ]
674
+ })
675
+ }),
676
+ /* @__PURE__ */ jsx("div", { style: { height: "52px" } })
677
+ ]
678
+ })
679
+ });
680
+ }
681
+ //#endregion
682
+ //#region src/collection_editor/ui/collection_editor/GetCodeDialog.tsx
683
+ function GetCodeDialog({ collection, onOpenChange, open }) {
684
+ const snackbarController = useSafeSnackbarController();
685
+ const code = collection ? "import { CollectionConfig } from \"@rebasepro/app\";\n\nconst " + (collection?.name ? camelCase(collection.name) : "my") + "Collection:CollectionConfig = " + JSON5.stringify(collectionToCode({ ...collection }), null, " ") : "No collection selected";
686
+ return /* @__PURE__ */ jsxs(Dialog, {
687
+ open,
688
+ onOpenChange,
689
+ maxWidth: "4xl",
690
+ children: [
691
+ /* @__PURE__ */ jsxs(DialogTitle, {
692
+ variant: "h6",
693
+ children: ["Code for ", collection.name]
694
+ }),
695
+ /* @__PURE__ */ jsxs(DialogContent, { children: [/* @__PURE__ */ jsxs(Typography, {
696
+ variant: "body2",
697
+ className: "my-4 mb-8",
698
+ children: [
699
+ "If you want to customise the collection in code, you can add this collection code to your CMS app configuration. More info in the ",
700
+ /* @__PURE__ */ jsx("a", {
701
+ rel: "noopener noreferrer",
702
+ href: "https://rebase.pro/docs/cloud/quickstart",
703
+ children: "docs"
704
+ }),
705
+ "."
706
+ ]
707
+ }), /* @__PURE__ */ jsx(Highlight, {
708
+ theme: themes.vsDark,
709
+ code,
710
+ language: "typescript",
711
+ children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsx("pre", {
712
+ style,
713
+ className: "p-4 rounded-xs text-sm",
714
+ children: tokens.map((line, i) => /* @__PURE__ */ jsx("div", {
715
+ ...getLineProps({ line }),
716
+ children: line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
717
+ }, i))
718
+ })
719
+ })] }),
720
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsxs(Button, {
721
+ variant: "text",
722
+ size: "small",
723
+ onClick: (e) => {
724
+ e.stopPropagation();
725
+ e.preventDefault();
726
+ snackbarController?.open({
727
+ type: "success",
728
+ message: "Copied"
729
+ });
730
+ return navigator.clipboard.writeText(code);
731
+ },
732
+ children: [/* @__PURE__ */ jsx(CopyIcon, {}), "CopyIcon to clipboard"]
733
+ }), /* @__PURE__ */ jsx(Button, {
734
+ onClick: () => onOpenChange(false),
735
+ children: "Close"
736
+ })] })
737
+ ]
738
+ });
739
+ }
740
+ function collectionToCode(collection) {
741
+ const propertyCleanup = (value) => {
742
+ if (value === void 0 || value === null) return value;
743
+ const valueCopy = clone(value);
744
+ if (typeof valueCopy === "function") return valueCopy;
745
+ if (Array.isArray(valueCopy)) return valueCopy.map((v) => propertyCleanup(v));
746
+ if (typeof valueCopy === "object") {
747
+ if (valueCopy === null) return valueCopy;
748
+ const obj = valueCopy;
749
+ Object.keys(obj).forEach((key) => {
750
+ if (!isEmptyObject(obj)) {
751
+ const childRes = propertyCleanup(obj[key]);
752
+ if (childRes !== null && childRes !== void 0 && childRes !== false && !isEmptyObject(childRes)) obj[key] = childRes;
753
+ else delete obj[key];
754
+ }
755
+ });
756
+ delete obj.resolved;
757
+ delete obj.propertiesOrder;
758
+ delete obj.propertyConfig;
759
+ }
760
+ return valueCopy;
761
+ };
762
+ return {
763
+ id: collection.slug,
764
+ name: collection.name,
765
+ singularName: collection.singularName,
766
+ path: collection.slug,
767
+ description: collection.description,
768
+ icon: collection.icon,
769
+ defaultFilter: collection.defaultFilter,
770
+ sort: collection.sort,
771
+ properties: Object.entries({ ...collection.properties ?? {} }).map(([key, value]) => ({ [key]: propertyCleanup(value) })).reduce((a, b) => ({
772
+ ...a,
773
+ ...b
774
+ }), {})
775
+ };
776
+ }
777
+ //#endregion
778
+ //#region src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx
779
+ function CollectionPropertiesEditorForm({ showErrors, isNewCollection, propertyErrorsRef, onPropertyError, setDirty, extraIcon, getUser, getData, doCollectionInference, propertyConfigs, propertyTypePresets, hiddenPropertyTypes, renderExtraPropertyFields, standalone }) {
780
+ const { values, setFieldValue, setFieldError, setFieldTouched, errors, dirty } = useFormex();
781
+ const snackbarController = useSafeSnackbarController();
782
+ const configControllerFromContext = useCollectionsConfigController();
783
+ const configController = standalone ? { readOnly: false } : configControllerFromContext;
784
+ const largeLayout = useLargeLayout();
785
+ const asDialog = standalone ? false : !largeLayout;
786
+ const [selectedPropertyIndex, setSelectedPropertyIndex] = useState();
787
+ const [selectedPropertyKey, setSelectedPropertyKey] = useState();
788
+ const [selectedPropertyNamespace, setSelectedPropertyNamespace] = useState();
789
+ const selectedPropertyFullId = selectedPropertyKey ? getFullId(selectedPropertyKey, selectedPropertyNamespace) : void 0;
790
+ const selectedProperty = selectedPropertyFullId ? getIn(values.properties, selectedPropertyFullId.replaceAll(".", ".properties.")) : void 0;
791
+ const [codeDialogOpen, setCodeDialogOpen] = useState(false);
792
+ const [inferringProperties, setInferringProperties] = useState(false);
793
+ const [newPropertyDialogOpen, setNewPropertyDialogOpen] = useState(false);
794
+ const [inferredPropertyKeys, setInferredPropertyKeys] = useState([]);
795
+ const currentPropertiesOrderRef = React.useRef(values.propertiesOrder ? { "": values.propertiesOrder } : {});
796
+ useEffect(() => {
797
+ if (setDirty) setDirty(dirty);
798
+ }, [dirty]);
799
+ const inferPropertiesFromData = doCollectionInference ? () => {
800
+ const inferenceFn = doCollectionInference;
801
+ if (!inferenceFn || configController?.readOnly) return;
802
+ setInferringProperties(true);
803
+ console.debug("CollectionEditor: inferring properties from data", values);
804
+ const promise = inferenceFn(values);
805
+ if (!promise) {
806
+ setInferringProperties(false);
807
+ return;
808
+ }
809
+ promise.then((newCollection) => {
810
+ if (!newCollection) {
811
+ snackbarController?.open?.({
812
+ type: "error",
813
+ message: "Could not infer properties from data"
814
+ });
815
+ return;
816
+ }
817
+ const findNewPropertyKeys = (existingProps, newProps, namespace) => {
818
+ if (!newProps) return [];
819
+ const keys = [];
820
+ for (const key of Object.keys(newProps)) {
821
+ const fullKey = namespace ? `${namespace}.${key}` : key;
822
+ const existingProp = existingProps?.[key];
823
+ const newProp = newProps[key];
824
+ if (!existingProp) keys.push(fullKey);
825
+ else if (typeof newProp === "object" && "type" in newProp && newProp.type === "map" && newProp.properties) {
826
+ const existingMapProps = typeof existingProp === "object" && "type" in existingProp && existingProp.type === "map" ? existingProp.properties : void 0;
827
+ keys.push(...findNewPropertyKeys(existingMapProps, newProp.properties, fullKey));
828
+ }
829
+ }
830
+ return keys;
831
+ };
832
+ const addNewPropertiesOnly = (existingProps, newProps) => {
833
+ if (!newProps) return existingProps ?? {};
834
+ if (!existingProps) return newProps;
835
+ const result = { ...existingProps };
836
+ for (const key of Object.keys(newProps)) {
837
+ const existingProp = existingProps[key];
838
+ const newProp = newProps[key];
839
+ if (!existingProp) result[key] = newProp;
840
+ else if (typeof existingProp === "object" && "type" in existingProp && existingProp.type === "map" && typeof newProp === "object" && "type" in newProp && newProp.type === "map" && newProp.properties) {
841
+ const existingMapProps = existingProp.properties;
842
+ if (existingMapProps) result[key] = {
843
+ ...existingProp,
844
+ properties: addNewPropertiesOnly(existingMapProps, newProp.properties)
845
+ };
846
+ }
847
+ }
848
+ return result;
849
+ };
850
+ const updatedProperties = addNewPropertiesOnly(values.properties ?? {}, newCollection.properties);
851
+ const allNewPropertyKeys = findNewPropertyKeys(values.properties, newCollection.properties);
852
+ const newTopLevelPropertyKeys = (newCollection.properties ? Object.keys(newCollection.properties) : []).filter((propertyKey) => !values.properties[propertyKey]);
853
+ if (allNewPropertyKeys.length === 0) {
854
+ snackbarController?.open?.({
855
+ type: "info",
856
+ message: "No new properties found in existing data"
857
+ });
858
+ return;
859
+ }
860
+ const allExistingKeys = values.propertiesOrder ?? Object.keys(values.properties ?? {});
861
+ const updatedPropertiesOrder = [...newTopLevelPropertyKeys, ...allExistingKeys.filter((key) => !newTopLevelPropertyKeys.includes(key))];
862
+ setFieldValue("properties", updatedProperties, false);
863
+ updatePropertiesOrder(updatedPropertiesOrder);
864
+ setInferredPropertyKeys(allNewPropertyKeys);
865
+ snackbarController?.open?.({
866
+ type: "success",
867
+ message: `Added ${allNewPropertyKeys.length} new ${allNewPropertyKeys.length === 1 ? "property" : "properties"}`
868
+ });
869
+ }).finally(() => {
870
+ setInferringProperties(false);
871
+ });
872
+ } : void 0;
873
+ const getCurrentPropertiesOrder = (namespace) => {
874
+ if (!namespace) return currentPropertiesOrderRef.current[""] ?? getIn(values, namespaceToPropertiesOrderPath());
875
+ return currentPropertiesOrderRef.current[namespace] ?? getIn(values, namespaceToPropertiesOrderPath(namespace));
876
+ };
877
+ const updatePropertiesOrder = (newPropertiesOrder, namespace) => {
878
+ setFieldValue(namespaceToPropertiesOrderPath(namespace), newPropertiesOrder, false);
879
+ currentPropertiesOrderRef.current[namespace ?? ""] = newPropertiesOrder;
880
+ };
881
+ const deleteProperty = (propertyKey, namespace) => {
882
+ if (configController?.readOnly) return;
883
+ const fullId = propertyKey ? getFullId(propertyKey, namespace) : void 0;
884
+ if (!fullId) throw Error("collection editor miss config");
885
+ setFieldValue(idToPropertiesPath(fullId), void 0, false);
886
+ const currentPropertiesOrder = getCurrentPropertiesOrder(namespace);
887
+ if (currentPropertiesOrder) updatePropertiesOrder(currentPropertiesOrder.filter((p) => p !== propertyKey), namespace);
888
+ setNewPropertyDialogOpen(false);
889
+ setSelectedPropertyIndex(void 0);
890
+ setSelectedPropertyKey(void 0);
891
+ setSelectedPropertyNamespace(void 0);
892
+ };
893
+ const onPropertyMove = (propertiesOrder, namespace) => {
894
+ if (configController?.readOnly) return;
895
+ setFieldValue(namespaceToPropertiesOrderPath(namespace), propertiesOrder, false);
896
+ };
897
+ const onPropertyCreated = ({ id, property }) => {
898
+ if (configController?.readOnly) return;
899
+ if (!id) throw Error("Need to include an ID when creating a new property");
900
+ setFieldValue("properties", {
901
+ ...values.properties ?? {},
902
+ [id]: property
903
+ }, false);
904
+ const newPropertiesOrder = [...values.propertiesOrder ?? Object.keys(values.properties), id];
905
+ updatePropertiesOrder(newPropertiesOrder);
906
+ setNewPropertyDialogOpen(false);
907
+ if (largeLayout) {
908
+ setSelectedPropertyIndex(newPropertiesOrder.indexOf(id));
909
+ setSelectedPropertyKey(id);
910
+ }
911
+ setSelectedPropertyNamespace(void 0);
912
+ };
913
+ const onPropertyChanged = ({ id, property, previousId, namespace }) => {
914
+ const fullId = id ? getFullId(id, namespace) : void 0;
915
+ const propertyPath = fullId ? idToPropertiesPath(fullId) : void 0;
916
+ if (previousId && previousId !== id) {
917
+ const previousPropertyPath = idToPropertiesPath(getFullId(previousId, namespace));
918
+ const newPropertiesOrder = getCurrentPropertiesOrder(namespace).map((p) => p === previousId ? id : p).filter((p) => p !== void 0);
919
+ updatePropertiesOrder(newPropertiesOrder, namespace);
920
+ if (id) {
921
+ setSelectedPropertyIndex(newPropertiesOrder.indexOf(id));
922
+ setSelectedPropertyKey(id);
923
+ }
924
+ setFieldValue(previousPropertyPath, void 0, false);
925
+ setFieldTouched(previousPropertyPath, false, false);
926
+ }
927
+ if (propertyPath) {
928
+ setFieldValue(propertyPath, property, false);
929
+ setFieldTouched(propertyPath, true, false);
930
+ }
931
+ };
932
+ const onPropertyErrorInternal = (id, namespace, error) => {
933
+ const propertyPath = id ? getFullId(id, namespace) : void 0;
934
+ console.debug("onPropertyErrorInternal", {
935
+ id,
936
+ namespace,
937
+ error,
938
+ propertyPath
939
+ });
940
+ if (propertyPath) {
941
+ const hasError = error && Object.keys(error).length > 0;
942
+ onPropertyError(id, namespace, hasError ? error : void 0);
943
+ setFieldError(idToPropertiesPath(propertyPath), hasError ? "Property error" : void 0);
944
+ }
945
+ };
946
+ const closePropertyDialog = () => {
947
+ setSelectedPropertyIndex(void 0);
948
+ setSelectedPropertyKey(void 0);
949
+ };
950
+ const initialErrors = selectedPropertyKey && propertyErrorsRef?.current?.properties ? propertyErrorsRef.current.properties[selectedPropertyKey] : void 0;
951
+ const emptyCollection = (values?.propertiesOrder === void 0 || values.propertiesOrder.length === 0) && (!values?.properties || Object.keys(values.properties).length === 0);
952
+ const usedPropertiesOrder = values.propertiesOrder ? values.propertiesOrder : Object.keys(values.properties);
953
+ const owner = useMemo(() => values.ownerId && getUser ? getUser(values.ownerId) : null, [getUser, values.ownerId]);
954
+ const generationCounter = useAIModifiedPaths()?.generationCounter ?? 0;
955
+ const onPropertyClick = (propertyKey, namespace) => {
956
+ console.debug("CollectionEditor: onPropertyClick", {
957
+ propertyKey,
958
+ namespace
959
+ });
960
+ setSelectedPropertyIndex(usedPropertiesOrder.indexOf(propertyKey));
961
+ setSelectedPropertyKey(propertyKey);
962
+ setSelectedPropertyNamespace(namespace);
963
+ };
964
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
965
+ /* @__PURE__ */ jsxs("div", {
966
+ className: "grid grid-cols-12 h-full min-h-0 bg-surface-50 dark:bg-surface-800",
967
+ children: [
968
+ /* @__PURE__ */ jsxs("div", {
969
+ className: cls("col-span-12 lg:col-span-5 h-full min-h-0 flex flex-col bg-surface-50 dark:bg-surface-800", !asDialog && "border-r " + defaultBorderMixin),
970
+ children: [/* @__PURE__ */ jsxs("div", {
971
+ className: cls("flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px] shrink-0", defaultBorderMixin),
972
+ children: [
973
+ /* @__PURE__ */ jsx("div", {
974
+ className: "flex-grow min-w-0 pr-2",
975
+ children: /* @__PURE__ */ jsx(Field, {
976
+ name: "name",
977
+ as: DebouncedTextField,
978
+ invisible: true,
979
+ className: "-ml-1",
980
+ inputClassName: "text-sm font-semibold truncate bg-transparent border-0 outline-none focus:ring-0",
981
+ placeholder: "Collection name",
982
+ size: "small",
983
+ required: true,
984
+ error: Boolean(errors?.name)
985
+ })
986
+ }),
987
+ extraIcon && /* @__PURE__ */ jsx("div", {
988
+ className: "flex-shrink-0",
989
+ children: extraIcon
990
+ }),
991
+ /* @__PURE__ */ jsxs("div", {
992
+ className: "flex items-center gap-1.5 flex-shrink-0 ml-2",
993
+ children: [inferPropertiesFromData && /* @__PURE__ */ jsx(Tooltip, {
994
+ title: "Add new properties based on data",
995
+ asChild: true,
996
+ children: /* @__PURE__ */ jsx(IconButton, {
997
+ size: "small",
998
+ disabled: inferringProperties,
999
+ onClick: inferPropertiesFromData,
1000
+ children: inferringProperties ? /* @__PURE__ */ jsx(CircularProgress, { size: "smallest" }) : /* @__PURE__ */ jsx(FileSearchIcon, { size: iconSize.smallest })
1001
+ })
1002
+ }), /* @__PURE__ */ jsx(Tooltip, {
1003
+ title: "Add new property",
1004
+ asChild: true,
1005
+ children: /* @__PURE__ */ jsx(IconButton, {
1006
+ size: "small",
1007
+ disabled: configController?.readOnly,
1008
+ onClick: () => setNewPropertyDialogOpen(true),
1009
+ children: /* @__PURE__ */ jsx(PlusIcon, { size: iconSize.smallest })
1010
+ })
1011
+ })]
1012
+ })
1013
+ ]
1014
+ }), /* @__PURE__ */ jsxs("div", {
1015
+ className: "flex-grow overflow-y-auto p-3 space-y-3 bg-surface-50 dark:bg-surface-800",
1016
+ children: [
1017
+ owner && /* @__PURE__ */ jsx("div", {
1018
+ className: "px-1 py-0.5",
1019
+ children: /* @__PURE__ */ jsxs(Typography, {
1020
+ variant: "body2",
1021
+ color: "secondary",
1022
+ children: ["Created by ", owner.displayName]
1023
+ })
1024
+ }),
1025
+ /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(PropertyTree, {
1026
+ inferredPropertyKeys,
1027
+ selectedPropertyKey: selectedPropertyKey ? getFullId(selectedPropertyKey, selectedPropertyNamespace) : void 0,
1028
+ properties: values.properties,
1029
+ additionalFields: values.additionalFields,
1030
+ propertiesOrder: usedPropertiesOrder,
1031
+ onPropertyClick,
1032
+ onPropertyMove,
1033
+ onPropertyRemove: (isNewCollection || inferredPropertyKeys && inferredPropertyKeys.length > 0) && !configController?.readOnly ? deleteProperty : void 0,
1034
+ errors
1035
+ }) }),
1036
+ /* @__PURE__ */ jsx(Button, {
1037
+ className: "w-full",
1038
+ variant: "outlined",
1039
+ color: "neutral",
1040
+ disabled: configController?.readOnly,
1041
+ onClick: () => setNewPropertyDialogOpen(true),
1042
+ startIcon: /* @__PURE__ */ jsx(PlusIcon, {}),
1043
+ children: "Add new property"
1044
+ })
1045
+ ]
1046
+ })]
1047
+ }),
1048
+ !asDialog && /* @__PURE__ */ jsx("div", {
1049
+ className: "col-span-12 lg:col-span-7 p-4 md:py-8 md:px-4 h-full overflow-auto bg-surface-50 dark:bg-surface-800",
1050
+ children: /* @__PURE__ */ jsxs("div", {
1051
+ className: "sticky top-8 min-h-full w-full flex flex-col justify-center",
1052
+ children: [
1053
+ selectedPropertyFullId && !!selectedProperty && !isPropertyBuilder(selectedProperty) && /* @__PURE__ */ jsx(PropertyForm, {
1054
+ inArray: false,
1055
+ existingProperty: !isNewCollection,
1056
+ autoUpdateId: false,
1057
+ allowDataInference: !isNewCollection,
1058
+ autoOpenTypeSelect: false,
1059
+ propertyKey: selectedPropertyKey,
1060
+ propertyNamespace: selectedPropertyNamespace,
1061
+ property: selectedProperty,
1062
+ onPropertyChanged,
1063
+ onDelete: deleteProperty,
1064
+ onError: onPropertyErrorInternal,
1065
+ forceShowErrors: showErrors,
1066
+ initialErrors,
1067
+ getData,
1068
+ propertyConfigs,
1069
+ propertyTypePresets,
1070
+ hiddenPropertyTypes,
1071
+ renderExtraPropertyFields,
1072
+ collectionValues: values
1073
+ }, `edit_view_${selectedPropertyIndex}_${generationCounter}`),
1074
+ !selectedProperty && /* @__PURE__ */ jsxs("div", {
1075
+ className: "w-full flex flex-col items-center justify-center h-full gap-4",
1076
+ children: [/* @__PURE__ */ jsx(Typography, {
1077
+ variant: "label",
1078
+ className: "",
1079
+ children: emptyCollection ? "Now you can add your first property" : "Select a property to edit it"
1080
+ }), /* @__PURE__ */ jsxs(Button, {
1081
+ disabled: configController?.readOnly,
1082
+ onClick: () => setNewPropertyDialogOpen(true),
1083
+ children: [/* @__PURE__ */ jsx(PlusIcon, {}), "Add new property"]
1084
+ })]
1085
+ }),
1086
+ !!selectedProperty && isPropertyBuilder(selectedProperty) && /* @__PURE__ */ jsx(Typography, {
1087
+ variant: "label",
1088
+ className: "flex items-center justify-center",
1089
+ children: "This property is defined as a property builder in code"
1090
+ })
1091
+ ]
1092
+ })
1093
+ }),
1094
+ asDialog && /* @__PURE__ */ jsx(PropertyFormDialog, {
1095
+ inArray: false,
1096
+ open: selectedPropertyIndex !== void 0,
1097
+ autoUpdateId: !selectedProperty,
1098
+ allowDataInference: !isNewCollection,
1099
+ existingProperty: true,
1100
+ autoOpenTypeSelect: false,
1101
+ propertyKey: selectedPropertyKey,
1102
+ propertyNamespace: selectedPropertyNamespace,
1103
+ property: selectedProperty,
1104
+ onPropertyChanged,
1105
+ onDelete: deleteProperty,
1106
+ onError: onPropertyErrorInternal,
1107
+ forceShowErrors: showErrors,
1108
+ initialErrors,
1109
+ getData,
1110
+ propertyConfigs,
1111
+ propertyTypePresets,
1112
+ hiddenPropertyTypes,
1113
+ renderExtraPropertyFields,
1114
+ collectionValues: values,
1115
+ onCancel: closePropertyDialog,
1116
+ onOkClicked: asDialog ? closePropertyDialog : void 0
1117
+ }, `edit_view_${selectedPropertyIndex}_${generationCounter}`)
1118
+ ]
1119
+ }),
1120
+ /* @__PURE__ */ jsx(PropertyFormDialog, {
1121
+ inArray: false,
1122
+ existingProperty: false,
1123
+ autoOpenTypeSelect: true,
1124
+ autoUpdateId: true,
1125
+ forceShowErrors: showErrors,
1126
+ open: newPropertyDialogOpen,
1127
+ onCancel: () => setNewPropertyDialogOpen(false),
1128
+ onPropertyChanged: onPropertyCreated,
1129
+ getData,
1130
+ allowDataInference: !isNewCollection,
1131
+ propertyConfigs,
1132
+ propertyTypePresets,
1133
+ hiddenPropertyTypes,
1134
+ renderExtraPropertyFields,
1135
+ collectionValues: values,
1136
+ existingPropertyKeys: values.propertiesOrder
1137
+ }),
1138
+ /* @__PURE__ */ jsx(ErrorBoundary, { children: /* @__PURE__ */ jsx(GetCodeDialog, {
1139
+ collection: values,
1140
+ open: codeDialogOpen,
1141
+ onOpenChange: setCodeDialogOpen
1142
+ }) })
1143
+ ] });
1144
+ }
1145
+ //#endregion
1146
+ //#region src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx
1147
+ var EXAMPLE_JSON = `{
1148
+ "id": "products",
1149
+ "name": "Products",
1150
+ "path": "products",
1151
+ "icon": "shopping_cart",
1152
+ "properties": {
1153
+ "name": {
1154
+ "type": "string",
1155
+ "name": "Name",
1156
+ "validation": { "required": true }
1157
+ },
1158
+ "price": {
1159
+ "type": "number",
1160
+ "name": "Price"
1161
+ },
1162
+ "available": {
1163
+ "type": "boolean",
1164
+ "name": "Available"
1165
+ }
1166
+ }
1167
+ }`;
1168
+ function CollectionJsonImportDialog({ open, onClose, onImport }) {
1169
+ const [jsonValue, setJsonValue] = useState("");
1170
+ const [errors, setErrors] = useState([]);
1171
+ const [touched, setTouched] = useState(false);
1172
+ const handleJsonChange = useCallback((e) => {
1173
+ const value = e.target.value;
1174
+ setJsonValue(value);
1175
+ setTouched(true);
1176
+ if (!value.trim()) {
1177
+ setErrors([]);
1178
+ return;
1179
+ }
1180
+ setErrors(validateCollectionJson(value).errors);
1181
+ }, []);
1182
+ const handleImport = useCallback(() => {
1183
+ const result = validateCollectionJson(jsonValue);
1184
+ if (result.valid && result.collection) {
1185
+ onImport(result.collection);
1186
+ setJsonValue("");
1187
+ setErrors([]);
1188
+ setTouched(false);
1189
+ onClose();
1190
+ }
1191
+ }, [
1192
+ jsonValue,
1193
+ onImport,
1194
+ onClose
1195
+ ]);
1196
+ const handleClose = useCallback(() => {
1197
+ setJsonValue("");
1198
+ setErrors([]);
1199
+ setTouched(false);
1200
+ onClose();
1201
+ }, [onClose]);
1202
+ const isValid = touched && jsonValue.trim() && errors.length === 0;
1203
+ return /* @__PURE__ */ jsxs(Dialog, {
1204
+ open,
1205
+ onOpenChange: (open) => !open && handleClose(),
1206
+ maxWidth: "2xl",
1207
+ children: [
1208
+ /* @__PURE__ */ jsxs(DialogTitle, {
1209
+ className: "flex items-center gap-2",
1210
+ children: [/* @__PURE__ */ jsx(CodeIcon, { size: iconSize.smallest }), "Import Collection from JSON"]
1211
+ }),
1212
+ /* @__PURE__ */ jsxs(DialogContent, {
1213
+ className: "flex flex-col gap-4",
1214
+ children: [
1215
+ /* @__PURE__ */ jsxs(Typography, {
1216
+ variant: "body2",
1217
+ color: "secondary",
1218
+ children: [
1219
+ "Paste a JSON object representing your collection configuration. The JSON must include ",
1220
+ /* @__PURE__ */ jsx("code", {
1221
+ className: "bg-surface-200 dark:bg-surface-700 px-1 rounded",
1222
+ children: "id"
1223
+ }),
1224
+ ",",
1225
+ /* @__PURE__ */ jsx("code", {
1226
+ className: "bg-surface-200 dark:bg-surface-700 px-1 rounded",
1227
+ children: "name"
1228
+ }),
1229
+ ",",
1230
+ /* @__PURE__ */ jsx("code", {
1231
+ className: "bg-surface-200 dark:bg-surface-700 px-1 rounded",
1232
+ children: "path"
1233
+ }),
1234
+ ", and",
1235
+ /* @__PURE__ */ jsx("code", {
1236
+ className: "bg-surface-200 dark:bg-surface-700 px-1 rounded",
1237
+ children: "properties"
1238
+ }),
1239
+ "."
1240
+ ]
1241
+ }),
1242
+ /* @__PURE__ */ jsx(TextField, {
1243
+ multiline: true,
1244
+ minRows: 12,
1245
+ value: jsonValue,
1246
+ onChange: handleJsonChange,
1247
+ placeholder: EXAMPLE_JSON,
1248
+ error: errors.length > 0 && touched,
1249
+ className: "w-full",
1250
+ inputClassName: "font-mono text-sm resize-none overflow-y-auto h-[300px]"
1251
+ }),
1252
+ errors.length > 0 && touched && /* @__PURE__ */ jsxs(Alert, {
1253
+ color: "error",
1254
+ children: [/* @__PURE__ */ jsx(Typography, {
1255
+ variant: "body2",
1256
+ className: "font-medium mb-2",
1257
+ children: "Validation errors:"
1258
+ }), /* @__PURE__ */ jsx("ul", {
1259
+ className: "list-disc list-inside space-y-1",
1260
+ children: errors.map((error, index) => /* @__PURE__ */ jsx("li", {
1261
+ className: "text-sm",
1262
+ children: error.path ? /* @__PURE__ */ jsxs(Fragment, { children: [
1263
+ /* @__PURE__ */ jsx("code", {
1264
+ className: "bg-red-100 dark:bg-red-900/40 px-1 rounded",
1265
+ children: error.path
1266
+ }),
1267
+ ": ",
1268
+ error.message
1269
+ ] }) : error.message
1270
+ }, index))
1271
+ })]
1272
+ }),
1273
+ isValid && /* @__PURE__ */ jsx(Alert, {
1274
+ color: "success",
1275
+ children: /* @__PURE__ */ jsx(Typography, {
1276
+ variant: "body2",
1277
+ children: "✓ JSON is valid and ready to import"
1278
+ })
1279
+ })
1280
+ ]
1281
+ }),
1282
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
1283
+ variant: "text",
1284
+ onClick: handleClose,
1285
+ children: "Cancel"
1286
+ }), /* @__PURE__ */ jsx(Button, {
1287
+ variant: "filled",
1288
+ color: "primary",
1289
+ onClick: handleImport,
1290
+ disabled: !isValid,
1291
+ children: "Import Collection"
1292
+ })] })
1293
+ ]
1294
+ });
1295
+ }
1296
+ //#endregion
1297
+ //#region src/collection_editor/ui/collection_editor/templates/products_template.ts
1298
+ var productsCollectionTemplate = {
1299
+ slug: "products",
1300
+ table: "products",
1301
+ name: "Products",
1302
+ singularName: "Product",
1303
+ icon: "ShoppingCart",
1304
+ description: "List of the products currently sold in your shop",
1305
+ properties: {
1306
+ name: {
1307
+ type: "string",
1308
+ name: "Name",
1309
+ description: "Name of this product",
1310
+ validation: { required: true }
1311
+ },
1312
+ brand: {
1313
+ type: "string",
1314
+ name: "Brand",
1315
+ validation: { required: true }
1316
+ },
1317
+ description: {
1318
+ type: "string",
1319
+ name: "Description",
1320
+ description: "Description of this product, supports markdown",
1321
+ markdown: true
1322
+ },
1323
+ main_image: {
1324
+ type: "string",
1325
+ name: "Image",
1326
+ storage: {
1327
+ storagePath: "images",
1328
+ acceptedFiles: ["image/*"]
1329
+ },
1330
+ description: "Upload field for images"
1331
+ },
1332
+ available: {
1333
+ type: "boolean",
1334
+ name: "Available",
1335
+ ui: { columnWidth: 100 },
1336
+ description: "Is this product available in the website"
1337
+ },
1338
+ price: {
1339
+ type: "number",
1340
+ name: "Price",
1341
+ validation: {
1342
+ requiredMessage: "You must set a positive price",
1343
+ min: 0
1344
+ }
1345
+ },
1346
+ images: {
1347
+ type: "array",
1348
+ name: "Images",
1349
+ ui: { hideFromCollection: true },
1350
+ of: {
1351
+ type: "string",
1352
+ storage: {
1353
+ storagePath: "images",
1354
+ acceptedFiles: ["image/*"]
1355
+ }
1356
+ }
1357
+ },
1358
+ related_products: {
1359
+ type: "array",
1360
+ name: "Related products",
1361
+ description: "Products related to this one",
1362
+ of: {
1363
+ type: "reference",
1364
+ path: "products"
1365
+ }
1366
+ },
1367
+ metadata: {
1368
+ name: "Metadata",
1369
+ description: "This is an example of a map property",
1370
+ type: "map",
1371
+ keyValue: true
1372
+ },
1373
+ added_on: {
1374
+ type: "date",
1375
+ name: "Added on",
1376
+ autoValue: "on_create"
1377
+ }
1378
+ }
1379
+ };
1380
+ //#endregion
1381
+ //#region src/collection_editor/ui/collection_editor/templates/blog_template.ts
1382
+ var blogCollectionTemplate = {
1383
+ slug: "blog",
1384
+ table: "blog",
1385
+ name: "Blog",
1386
+ singularName: "Blog entry",
1387
+ icon: "FileText",
1388
+ description: "A collection of blog entries",
1389
+ defaultSize: "l",
1390
+ properties: {
1391
+ name: {
1392
+ name: "Name",
1393
+ validation: { required: true },
1394
+ type: "string"
1395
+ },
1396
+ header_image: {
1397
+ name: "Header image",
1398
+ type: "string",
1399
+ storage: {
1400
+ storagePath: "images",
1401
+ acceptedFiles: ["image/*"],
1402
+ metadata: { cacheControl: "max-age=1000000" }
1403
+ }
1404
+ },
1405
+ content: {
1406
+ name: "Content",
1407
+ description: "Content blocks for the blog entry",
1408
+ validation: { required: true },
1409
+ type: "array",
1410
+ oneOf: {
1411
+ typeField: "type",
1412
+ valueField: "value",
1413
+ properties: {
1414
+ text: {
1415
+ type: "string",
1416
+ name: "Text",
1417
+ markdown: true
1418
+ },
1419
+ quote: {
1420
+ type: "string",
1421
+ name: "Quote",
1422
+ multiline: true
1423
+ },
1424
+ images: {
1425
+ name: "Images",
1426
+ type: "array",
1427
+ of: {
1428
+ type: "string",
1429
+ storage: {
1430
+ storagePath: "images",
1431
+ acceptedFiles: ["image/*"],
1432
+ metadata: { cacheControl: "max-age=1000000" }
1433
+ }
1434
+ },
1435
+ description: "This fields allows uploading multiple images at once and reordering"
1436
+ },
1437
+ products: {
1438
+ name: "Products",
1439
+ type: "array",
1440
+ of: {
1441
+ type: "reference",
1442
+ path: "products",
1443
+ previewProperties: ["name", "main_image"]
1444
+ }
1445
+ }
1446
+ },
1447
+ propertiesOrder: [
1448
+ "text",
1449
+ "quote",
1450
+ "images",
1451
+ "products"
1452
+ ]
1453
+ }
1454
+ },
1455
+ created_on: {
1456
+ name: "Created on",
1457
+ type: "date",
1458
+ autoValue: "on_create"
1459
+ },
1460
+ status: {
1461
+ name: "Status",
1462
+ validation: { required: true },
1463
+ type: "string",
1464
+ enum: {
1465
+ published: {
1466
+ id: "published",
1467
+ label: "Published"
1468
+ },
1469
+ draft: "Draft"
1470
+ },
1471
+ defaultValue: "draft"
1472
+ },
1473
+ publish_date: {
1474
+ name: "Publish date",
1475
+ type: "date",
1476
+ ui: { clearable: true }
1477
+ },
1478
+ reviewed: {
1479
+ name: "Reviewed",
1480
+ type: "boolean"
1481
+ },
1482
+ tags: {
1483
+ name: "Tags",
1484
+ description: "Example of generic array",
1485
+ type: "array",
1486
+ of: {
1487
+ type: "string",
1488
+ previewAsTag: true
1489
+ }
1490
+ }
1491
+ }
1492
+ };
1493
+ //#endregion
1494
+ //#region src/collection_editor/ui/collection_editor/templates/users_template.ts
1495
+ var usersCollectionTemplate = {
1496
+ slug: "users",
1497
+ table: "users",
1498
+ name: "Users",
1499
+ singularName: "User",
1500
+ description: "Registered users in the app/web",
1501
+ icon: "User",
1502
+ properties: {
1503
+ displayName: {
1504
+ name: "Display name",
1505
+ type: "string"
1506
+ },
1507
+ email: {
1508
+ name: "Email",
1509
+ type: "string",
1510
+ email: true
1511
+ },
1512
+ emailVerified: {
1513
+ name: "Email verified",
1514
+ type: "boolean"
1515
+ },
1516
+ phone: {
1517
+ name: "Phone",
1518
+ type: "string"
1519
+ },
1520
+ favourite_products: {
1521
+ name: "Favourite products",
1522
+ type: "array",
1523
+ of: {
1524
+ type: "reference",
1525
+ path: "products"
1526
+ }
1527
+ },
1528
+ photoURL: {
1529
+ name: "Photo URL",
1530
+ type: "string",
1531
+ url: "image"
1532
+ }
1533
+ }
1534
+ };
1535
+ //#endregion
1536
+ //#region src/collection_editor/ui/collection_editor/templates/pages_template.ts
1537
+ var pagesCollectionTemplate = {
1538
+ slug: "pages",
1539
+ table: "pages",
1540
+ name: "Pages",
1541
+ singularName: "Page",
1542
+ icon: "File",
1543
+ description: "List of website pages that can be edited here",
1544
+ properties: {
1545
+ title: {
1546
+ type: "string",
1547
+ name: "Page Title",
1548
+ validation: { required: true }
1549
+ },
1550
+ slug: {
1551
+ type: "string",
1552
+ name: "URL Slug",
1553
+ validation: {
1554
+ required: true,
1555
+ unique: true,
1556
+ matches: "^[a-z0-9]+(?:-[a-z0-9]+)*$",
1557
+ matchesMessage: "Must be lowercase, alphanumeric, and hyphenated"
1558
+ }
1559
+ },
1560
+ hero_section: {
1561
+ type: "map",
1562
+ name: "Hero Section",
1563
+ properties: {
1564
+ headline: {
1565
+ type: "string",
1566
+ name: "Headline",
1567
+ validation: { required: true }
1568
+ },
1569
+ subhead: {
1570
+ type: "string",
1571
+ name: "Subheadline"
1572
+ },
1573
+ background_image: {
1574
+ type: "string",
1575
+ name: "Background Image",
1576
+ storage: {
1577
+ storagePath: "page_hero/images",
1578
+ acceptedFiles: ["image/*"]
1579
+ }
1580
+ },
1581
+ call_to_action: {
1582
+ type: "string",
1583
+ name: "Call to Action"
1584
+ },
1585
+ call_to_action_link: {
1586
+ type: "string",
1587
+ name: "CTA Link",
1588
+ url: true
1589
+ }
1590
+ }
1591
+ },
1592
+ content: {
1593
+ type: "array",
1594
+ name: "Content",
1595
+ oneOf: { properties: {
1596
+ section: {
1597
+ type: "map",
1598
+ name: "Section",
1599
+ properties: {
1600
+ title: {
1601
+ type: "string",
1602
+ name: "Section Title",
1603
+ validation: { required: true }
1604
+ },
1605
+ content: {
1606
+ type: "string",
1607
+ name: "Section Content",
1608
+ markdown: true
1609
+ },
1610
+ image: {
1611
+ type: "string",
1612
+ name: "Section Image",
1613
+ storage: {
1614
+ storagePath: "page_sections/images",
1615
+ acceptedFiles: ["image/*"]
1616
+ }
1617
+ },
1618
+ link: {
1619
+ type: "string",
1620
+ name: "Section Link",
1621
+ url: true
1622
+ }
1623
+ }
1624
+ },
1625
+ image: {
1626
+ type: "string",
1627
+ name: "Image",
1628
+ storage: {
1629
+ storagePath: "page_sections/images",
1630
+ acceptedFiles: ["image/*"]
1631
+ }
1632
+ },
1633
+ slider: {
1634
+ type: "array",
1635
+ name: "Slider",
1636
+ of: {
1637
+ type: "map",
1638
+ properties: {
1639
+ title: {
1640
+ type: "string",
1641
+ name: "Title",
1642
+ validation: { required: true }
1643
+ },
1644
+ image: {
1645
+ type: "string",
1646
+ storage: {
1647
+ storagePath: "page_sections/images",
1648
+ acceptedFiles: ["image/*"]
1649
+ }
1650
+ }
1651
+ }
1652
+ }
1653
+ }
1654
+ } }
1655
+ },
1656
+ sidebar: {
1657
+ type: "map",
1658
+ name: "Sidebar",
1659
+ properties: {
1660
+ title: {
1661
+ type: "string",
1662
+ name: "Sidebar Title",
1663
+ validation: { required: false }
1664
+ },
1665
+ content: {
1666
+ type: "string",
1667
+ name: "Sidebar Content",
1668
+ markdown: true
1669
+ }
1670
+ }
1671
+ },
1672
+ seo_metadata: {
1673
+ type: "map",
1674
+ name: "SEO Metadata",
1675
+ properties: {
1676
+ meta_title: {
1677
+ type: "string",
1678
+ name: "Meta Title"
1679
+ },
1680
+ meta_description: {
1681
+ type: "string",
1682
+ name: "Meta Description"
1683
+ },
1684
+ focus_keywords: {
1685
+ type: "array",
1686
+ name: "Focus Keywords",
1687
+ of: { type: "string" }
1688
+ }
1689
+ }
1690
+ },
1691
+ footer_override: {
1692
+ type: "string",
1693
+ name: "Footer Override",
1694
+ markdown: true
1695
+ },
1696
+ publish_date: {
1697
+ type: "date",
1698
+ name: "Publish Date",
1699
+ validation: { required: true }
1700
+ },
1701
+ last_updated: {
1702
+ type: "date",
1703
+ name: "Last Updated",
1704
+ autoValue: "on_update"
1705
+ },
1706
+ is_published: {
1707
+ type: "boolean",
1708
+ name: "Is Published",
1709
+ ui: { columnWidth: 100 },
1710
+ description: "Should this page be live on the site?"
1711
+ }
1712
+ }
1713
+ };
1714
+ //#endregion
1715
+ //#region src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx
1716
+ function AICollectionGeneratorPopover({ existingCollection, onGenerated, generateCollection, trigger, size = "small", showLabel = true, onAnalyticsEvent }) {
1717
+ const [menuOpen, setMenuOpen] = useState(false);
1718
+ const [prompt, setPrompt] = useState("");
1719
+ const [loading, setLoading] = useState(false);
1720
+ const [error, setError] = useState(null);
1721
+ const collectionRegistry = useCollectionRegistryController();
1722
+ const configController = useCollectionsConfigController();
1723
+ const snackbarController = useSafeSnackbarController();
1724
+ const existingCollections = collectionRegistry.collections ?? [];
1725
+ const handleGenerate = async () => {
1726
+ if (!prompt.trim()) return;
1727
+ setLoading(true);
1728
+ setError(null);
1729
+ const mode = existingCollection ? "modify" : "create";
1730
+ onAnalyticsEvent?.("ai_collection_generate_start", { mode });
1731
+ try {
1732
+ const collectionsContext = existingCollections.map((c) => ({
1733
+ slug: c.slug,
1734
+ name: c.name,
1735
+ properties: c.properties,
1736
+ propertiesOrder: c.propertiesOrder
1737
+ }));
1738
+ const result = await generateCollection({
1739
+ prompt: prompt.trim(),
1740
+ existingCollections: collectionsContext.slice(0, 30),
1741
+ ...existingCollection && { existingCollection: {
1742
+ slug: existingCollection.slug,
1743
+ name: existingCollection.name,
1744
+ properties: existingCollection.properties,
1745
+ propertiesOrder: existingCollection.propertiesOrder
1746
+ } }
1747
+ });
1748
+ onGenerated(result.collection, result.operations);
1749
+ setMenuOpen(false);
1750
+ setPrompt("");
1751
+ onAnalyticsEvent?.("ai_collection_generate_success", {
1752
+ mode,
1753
+ operationsCount: result.operations?.length
1754
+ });
1755
+ snackbarController?.open({
1756
+ type: "success",
1757
+ message: existingCollection ? "Collection updated with AI suggestions" : "Collection generated successfully"
1758
+ });
1759
+ } catch (e) {
1760
+ console.error("Error generating collection:", e);
1761
+ const errorMessage = e instanceof CollectionGenerationApiError ? e.message : "Failed to generate collection. Please try again.";
1762
+ setError(errorMessage);
1763
+ onAnalyticsEvent?.("ai_collection_generate_error", {
1764
+ mode,
1765
+ error: errorMessage
1766
+ });
1767
+ snackbarController?.open({
1768
+ type: "error",
1769
+ message: errorMessage
1770
+ });
1771
+ } finally {
1772
+ setLoading(false);
1773
+ }
1774
+ };
1775
+ const handleKeyDown = (e) => {
1776
+ if (e.key === "Enter" && !e.shiftKey) {
1777
+ e.preventDefault();
1778
+ handleGenerate();
1779
+ }
1780
+ };
1781
+ const tooltipTitle = configController?.readOnly ? configController.readOnlyReason || "Collection generation is disabled" : void 0;
1782
+ const defaultTrigger = showLabel ? /* @__PURE__ */ jsx(Tooltip, {
1783
+ title: tooltipTitle,
1784
+ asChild: true,
1785
+ children: /* @__PURE__ */ jsx(Button, {
1786
+ variant: "text",
1787
+ size,
1788
+ disabled: loading || configController?.readOnly,
1789
+ startIcon: loading ? /* @__PURE__ */ jsx(CircularProgress, { size: "smallest" }) : /* @__PURE__ */ jsx(AIIcon, { size: "small" }),
1790
+ children: "AI Assist"
1791
+ })
1792
+ }) : /* @__PURE__ */ jsx(Tooltip, {
1793
+ title: tooltipTitle,
1794
+ asChild: true,
1795
+ children: /* @__PURE__ */ jsx(IconButton, {
1796
+ size,
1797
+ disabled: loading || configController?.readOnly,
1798
+ "aria-label": "AI Assist",
1799
+ children: loading ? /* @__PURE__ */ jsx(CircularProgress, { size: "smallest" }) : /* @__PURE__ */ jsx(AIIcon, { size: "small" })
1800
+ })
1801
+ });
1802
+ return /* @__PURE__ */ jsx(Menu, {
1803
+ open: menuOpen,
1804
+ onOpenChange: (open) => {
1805
+ setMenuOpen(open);
1806
+ if (!open) setError(null);
1807
+ },
1808
+ trigger: trigger ?? defaultTrigger,
1809
+ children: /* @__PURE__ */ jsxs("div", {
1810
+ className: "p-4 flex flex-col gap-3 min-w-[360px] max-w-[480px]",
1811
+ children: [
1812
+ /* @__PURE__ */ jsxs("div", {
1813
+ className: "flex items-center gap-2",
1814
+ children: [/* @__PURE__ */ jsx(AIIcon, { size: "small" }), /* @__PURE__ */ jsx(Typography, {
1815
+ variant: "subtitle2",
1816
+ children: existingCollection ? "Modify Collection with AI" : "Generate Collection with AI"
1817
+ })]
1818
+ }),
1819
+ /* @__PURE__ */ jsx(Typography, {
1820
+ variant: "caption",
1821
+ color: "secondary",
1822
+ children: existingCollection ? "Describe the changes you want to make to this collection." : "Describe the collection you want to create."
1823
+ }),
1824
+ /* @__PURE__ */ jsx(TextField, {
1825
+ size: "small",
1826
+ multiline: true,
1827
+ autoFocus: true,
1828
+ className: "w-full text-text-primary dark:text-text-primary-dark",
1829
+ value: prompt,
1830
+ onChange: (e) => setPrompt(e.target.value),
1831
+ onKeyDown: handleKeyDown,
1832
+ placeholder: existingCollection ? "e.g., Add a thumbnail image field with storage, make price required..." : "e.g., Create a products collection with name, price, description, and category...",
1833
+ disabled: loading
1834
+ }),
1835
+ error && /* @__PURE__ */ jsx(Typography, {
1836
+ variant: "caption",
1837
+ className: "text-red-500",
1838
+ children: error
1839
+ }),
1840
+ /* @__PURE__ */ jsxs("div", {
1841
+ className: "flex justify-end gap-2",
1842
+ children: [/* @__PURE__ */ jsx(Button, {
1843
+ variant: "text",
1844
+ size: "small",
1845
+ onClick: () => setMenuOpen(false),
1846
+ disabled: loading,
1847
+ children: "Cancel"
1848
+ }), /* @__PURE__ */ jsx(Button, {
1849
+ variant: "filled",
1850
+ size: "small",
1851
+ onClick: handleGenerate,
1852
+ disabled: !prompt.trim() || loading,
1853
+ startIcon: loading ? /* @__PURE__ */ jsx(CircularProgress, { size: "smallest" }) : void 0,
1854
+ children: loading ? "Generating..." : "Generate"
1855
+ })]
1856
+ })
1857
+ ]
1858
+ })
1859
+ });
1860
+ }
1861
+ //#endregion
1862
+ //#region src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx
1863
+ function CollectionEditorWelcomeView({ path, parentCollection, onContinue, existingCollectionPaths, generateCollection, onAnalyticsEvent, unmappedTables, onImportFromTable }) {
1864
+ const { pathSuggestions } = useCollectionEditorController();
1865
+ const filteredSuggestions = (pathSuggestions ?? []).filter((s) => !(existingCollectionPaths ?? []).find((c) => c.trim().toLowerCase() === s.trim().toLowerCase()));
1866
+ const { values, setFieldValue, setValues, submitCount } = useFormex();
1867
+ const [jsonImportOpen, setJsonImportOpen] = useState(false);
1868
+ const [importingTable, setImportingTable] = useState(null);
1869
+ const filteredUnmappedTables = (unmappedTables ?? []).filter((t) => !(existingCollectionPaths ?? []).find((c) => c.trim().toLowerCase() === t.trim().toLowerCase()));
1870
+ return /* @__PURE__ */ jsx("div", {
1871
+ className: "overflow-auto my-auto",
1872
+ children: /* @__PURE__ */ jsxs(Container, {
1873
+ maxWidth: "4xl",
1874
+ className: "flex flex-col gap-4 p-8 m-auto",
1875
+ children: [
1876
+ /* @__PURE__ */ jsx("div", {
1877
+ className: "flex flex-row py-2 pt-3 items-center",
1878
+ children: /* @__PURE__ */ jsx(Typography, {
1879
+ variant: "h4",
1880
+ className: "grow",
1881
+ children: "New collection"
1882
+ })
1883
+ }),
1884
+ parentCollection && /* @__PURE__ */ jsx(Chip, {
1885
+ colorScheme: "teal",
1886
+ children: /* @__PURE__ */ jsxs(Typography, {
1887
+ variant: "caption",
1888
+ children: ["This is a subcollection of ", /* @__PURE__ */ jsx("b", { children: parentCollection.name })]
1889
+ })
1890
+ }),
1891
+ filteredUnmappedTables.length > 0 && /* @__PURE__ */ jsxs("div", {
1892
+ className: "my-2",
1893
+ children: [/* @__PURE__ */ jsx(Typography, {
1894
+ variant: "caption",
1895
+ color: "secondary",
1896
+ children: "● Import from an existing database table:"
1897
+ }), /* @__PURE__ */ jsx("div", {
1898
+ className: "flex flex-wrap gap-x-2 gap-y-1 items-center my-2 min-h-7",
1899
+ children: filteredUnmappedTables.map((tableName) => /* @__PURE__ */ jsxs(Chip, {
1900
+ colorScheme: "purple",
1901
+ onClick: () => {
1902
+ if (onImportFromTable) {
1903
+ setImportingTable(tableName);
1904
+ onImportFromTable(tableName);
1905
+ } else {
1906
+ setFieldValue("name", prettifyIdentifier(tableName));
1907
+ setFieldValue("id", tableName);
1908
+ setFieldValue("path", tableName);
1909
+ onContinue();
1910
+ }
1911
+ },
1912
+ size: "small",
1913
+ children: [/* @__PURE__ */ jsx(TableIcon, { size: iconSize.smallest }), importingTable === tableName ? "Loading..." : tableName]
1914
+ }, tableName))
1915
+ })]
1916
+ }),
1917
+ (filteredSuggestions ?? []).length > 0 && /* @__PURE__ */ jsxs("div", {
1918
+ className: "my-2",
1919
+ children: [/* @__PURE__ */ jsx(Typography, {
1920
+ variant: "caption",
1921
+ color: "secondary",
1922
+ children: "● Use one of the existing paths in your database:"
1923
+ }), /* @__PURE__ */ jsx("div", {
1924
+ className: "flex flex-wrap gap-x-2 gap-y-1 items-center my-2 min-h-7",
1925
+ children: filteredSuggestions?.map((suggestion, index) => /* @__PURE__ */ jsx(Chip, {
1926
+ colorScheme: "cyan",
1927
+ onClick: () => {
1928
+ setFieldValue("name", prettifyIdentifier(suggestion));
1929
+ setFieldValue("id", suggestion);
1930
+ setFieldValue("path", suggestion);
1931
+ setFieldValue("properties", void 0);
1932
+ onContinue();
1933
+ },
1934
+ size: "small",
1935
+ children: suggestion
1936
+ }, suggestion))
1937
+ })]
1938
+ }),
1939
+ /* @__PURE__ */ jsxs("div", {
1940
+ className: "flex flex-row gap-8",
1941
+ children: [generateCollection && /* @__PURE__ */ jsxs("div", {
1942
+ className: "my-2",
1943
+ children: [/* @__PURE__ */ jsx(Typography, {
1944
+ variant: "caption",
1945
+ color: "secondary",
1946
+ className: "mb-2",
1947
+ children: "● Describe your collection to AI:"
1948
+ }), /* @__PURE__ */ jsx(AICollectionGeneratorPopover, {
1949
+ onGenerated: (generatedCollection) => {
1950
+ setValues(generatedCollection);
1951
+ onContinue();
1952
+ },
1953
+ generateCollection,
1954
+ onAnalyticsEvent,
1955
+ trigger: /* @__PURE__ */ jsx(Button, {
1956
+ variant: "filled",
1957
+ color: "neutral",
1958
+ startIcon: /* @__PURE__ */ jsx(AIIcon, { size: "small" }),
1959
+ children: "Generate with AI"
1960
+ })
1961
+ })]
1962
+ }), /* @__PURE__ */ jsxs("div", {
1963
+ className: "my-2",
1964
+ children: [
1965
+ /* @__PURE__ */ jsx(Typography, {
1966
+ variant: "caption",
1967
+ color: "secondary",
1968
+ className: "mb-2",
1969
+ children: "● Create from JSON configuration:"
1970
+ }),
1971
+ /* @__PURE__ */ jsx(Button, {
1972
+ variant: "filled",
1973
+ color: "neutral",
1974
+ onClick: () => setJsonImportOpen(true),
1975
+ startIcon: /* @__PURE__ */ jsx(CodeIcon, { size: iconSize.small }),
1976
+ children: "Paste JSON Configuration"
1977
+ }),
1978
+ /* @__PURE__ */ jsx(CollectionJsonImportDialog, {
1979
+ open: jsonImportOpen,
1980
+ onClose: () => setJsonImportOpen(false),
1981
+ onImport: (collection) => {
1982
+ setValues(collection);
1983
+ onContinue();
1984
+ }
1985
+ })
1986
+ ]
1987
+ })]
1988
+ }),
1989
+ !parentCollection && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
1990
+ variant: "caption",
1991
+ color: "secondary",
1992
+ className: "mb-2",
1993
+ children: "● Create a collection from a file (csv, json, xls, xslx...)"
1994
+ }), /* @__PURE__ */ jsx(ImportFileUpload, { onDataAdded: (data, propertiesOrder) => onContinue(data, propertiesOrder) })] }),
1995
+ /* @__PURE__ */ jsxs("div", {
1996
+ className: "my-2",
1997
+ children: [/* @__PURE__ */ jsx(Typography, {
1998
+ variant: "caption",
1999
+ color: "secondary",
2000
+ children: "● Select a template:"
2001
+ }), /* @__PURE__ */ jsxs("div", {
2002
+ className: "flex gap-2",
2003
+ children: [
2004
+ /* @__PURE__ */ jsx(TemplateButton, {
2005
+ title: "Products",
2006
+ subtitle: "A collection of products with images, prices and stock",
2007
+ icon: /* @__PURE__ */ jsx(ShoppingCartIcon, { size: iconSize.small }),
2008
+ onClick: () => {
2009
+ setValues(productsCollectionTemplate);
2010
+ onContinue();
2011
+ }
2012
+ }),
2013
+ /* @__PURE__ */ jsx(TemplateButton, {
2014
+ title: "Users",
2015
+ subtitle: "A collection of users with emails, names and roles",
2016
+ icon: /* @__PURE__ */ jsx(UserIcon, { size: iconSize.small }),
2017
+ onClick: () => {
2018
+ setValues(usersCollectionTemplate);
2019
+ onContinue();
2020
+ }
2021
+ }),
2022
+ /* @__PURE__ */ jsx(TemplateButton, {
2023
+ title: "Blog posts",
2024
+ subtitle: "A collection of blog posts with images, authors and complex content",
2025
+ icon: /* @__PURE__ */ jsx(FileTextIcon, { size: iconSize.small }),
2026
+ onClick: () => {
2027
+ setValues(blogCollectionTemplate);
2028
+ onContinue();
2029
+ }
2030
+ }),
2031
+ /* @__PURE__ */ jsx(TemplateButton, {
2032
+ title: "Pages",
2033
+ subtitle: "A collection of pages with images, authors and complex content",
2034
+ icon: /* @__PURE__ */ jsx(FileIcon, { size: iconSize.small }),
2035
+ onClick: () => {
2036
+ setValues(pagesCollectionTemplate);
2037
+ onContinue();
2038
+ }
2039
+ })
2040
+ ]
2041
+ })]
2042
+ })
2043
+ ]
2044
+ })
2045
+ });
2046
+ }
2047
+ function TemplateButton({ title, subtitle, icon, onClick }) {
2048
+ return /* @__PURE__ */ jsx(Tooltip, {
2049
+ title: subtitle,
2050
+ asChild: true,
2051
+ children: /* @__PURE__ */ jsxs(Card, {
2052
+ onClick,
2053
+ className: cls("my-2 rounded-md border px-4 py-3 focus:outline-none transition ease-in-out duration-150 flex flex-row gap-4 items-center", "text-text-secondary dark:text-text-secondary-dark", "hover:border-primary-dark hover:text-primary-dark dark:hover:text-primary focus:ring-primary hover:ring-1 hover:ring-primary", "border-surface-400 dark:border-surface-600 "),
2054
+ children: [icon, /* @__PURE__ */ jsx("div", {
2055
+ className: "flex flex-col items-start",
2056
+ children: /* @__PURE__ */ jsx(Typography, {
2057
+ variant: "subtitle2",
2058
+ children: title
2059
+ })
2060
+ })]
2061
+ })
2062
+ });
2063
+ }
2064
+ //#endregion
2065
+ //#region src/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.tsx
2066
+ function CollectionEditorImportMapping({ importConfig, propertyConfigs }) {
2067
+ const { setFieldValue, setFieldTouched, values } = useFormex();
2068
+ const [selectedProperty, setSelectedProperty] = useState(void 0);
2069
+ const currentPropertiesOrderRef = React.useRef(values.propertiesOrder ? { "": values.propertiesOrder } : {});
2070
+ const propertyKey = selectedProperty ? selectedProperty.id : void 0;
2071
+ const property = selectedProperty || void 0;
2072
+ const onPropertyChanged = ({ id, property, previousId, namespace }) => {
2073
+ const fullId = id ? getFullId(id, namespace) : void 0;
2074
+ const propertyPath = fullId ? idToPropertiesPath(fullId) : void 0;
2075
+ const getCurrentPropertiesOrder = (namespace) => {
2076
+ if (!namespace) return currentPropertiesOrderRef.current[""];
2077
+ return currentPropertiesOrderRef.current[namespace] ?? getIn(values, namespaceToPropertiesOrderPath(namespace));
2078
+ };
2079
+ const updatePropertiesOrder = (newPropertiesOrder, namespace) => {
2080
+ setFieldValue(namespaceToPropertiesOrderPath(namespace), newPropertiesOrder, false);
2081
+ currentPropertiesOrderRef.current[namespace ?? ""] = newPropertiesOrder;
2082
+ };
2083
+ if (previousId && previousId !== id) {
2084
+ const previousPropertyPath = idToPropertiesPath(getFullId(previousId, namespace));
2085
+ updatePropertiesOrder(getCurrentPropertiesOrder(namespace).map((p) => p === previousId ? id : p).filter((p) => p !== void 0), namespace);
2086
+ const newHeadersMapping = { ...importConfig.headersMapping };
2087
+ Object.keys(newHeadersMapping).forEach((key) => {
2088
+ if (newHeadersMapping[key] === previousId) newHeadersMapping[key] = id ?? "";
2089
+ });
2090
+ importConfig.setHeadersMapping(newHeadersMapping);
2091
+ setFieldValue(previousPropertyPath, void 0, false);
2092
+ setFieldTouched(previousPropertyPath, false, false);
2093
+ }
2094
+ if (propertyPath) {
2095
+ setFieldValue(propertyPath, property, false);
2096
+ setFieldTouched(propertyPath, true, false);
2097
+ }
2098
+ };
2099
+ const onPropertyTypeChanged = async ({ id, importKey, property, namespace }) => {
2100
+ const fullId = id ? getFullId(id, namespace) : void 0;
2101
+ const propertyPath = fullId ? idToPropertiesPath(fullId) : void 0;
2102
+ const inferredNewProperty = { ...buildPropertyFromData(importConfig.importData.map((d) => getIn(d, importKey)), property, getInferenceType) };
2103
+ if (propertyPath) {
2104
+ if (inferredNewProperty) setFieldValue(propertyPath, inferredNewProperty, false);
2105
+ else setFieldValue(propertyPath, property, false);
2106
+ setFieldTouched(propertyPath, true, false);
2107
+ }
2108
+ };
2109
+ return /* @__PURE__ */ jsxs("div", {
2110
+ className: "overflow-auto my-auto",
2111
+ children: [
2112
+ /* @__PURE__ */ jsxs(Container, {
2113
+ maxWidth: "6xl",
2114
+ className: "flex flex-col gap-4 p-8 m-auto",
2115
+ children: [/* @__PURE__ */ jsx(Typography, {
2116
+ variant: "h6",
2117
+ className: "my-4 ml-3.5",
2118
+ children: "Data property mapping"
2119
+ }), /* @__PURE__ */ jsx(DataNewPropertiesMapping, {
2120
+ importConfig,
2121
+ destinationProperties: values.properties,
2122
+ buildPropertyView: ({ property, propertyKey, importKey, isIdColumn }) => {
2123
+ if (isIdColumn) return /* @__PURE__ */ jsx(Typography, { children: " This column will be used as ID" });
2124
+ return /* @__PURE__ */ jsx(ImportNewPropertyFieldPreview, {
2125
+ property,
2126
+ propertyKey,
2127
+ onPropertyNameChanged: (propertyKey, value) => setFieldValue(`properties.${propertyKey}.name`, value, false),
2128
+ onEditClick: () => {
2129
+ if (!propertyKey || !property) return;
2130
+ setSelectedProperty({
2131
+ ...property,
2132
+ id: propertyKey
2133
+ });
2134
+ },
2135
+ propertyTypeView: /* @__PURE__ */ jsx(PropertySelect, {
2136
+ property,
2137
+ disabled: false,
2138
+ onPropertyChanged: (props) => onPropertyTypeChanged({
2139
+ ...props,
2140
+ importKey
2141
+ }),
2142
+ propertyKey,
2143
+ propertyConfigs
2144
+ })
2145
+ });
2146
+ }
2147
+ })]
2148
+ }),
2149
+ /* @__PURE__ */ jsx(PropertyFormDialog, {
2150
+ open: selectedProperty !== void 0,
2151
+ propertyKey,
2152
+ property,
2153
+ inArray: false,
2154
+ autoUpdateId: false,
2155
+ onPropertyChanged,
2156
+ allowDataInference: false,
2157
+ onOkClicked: () => {
2158
+ setSelectedProperty(void 0);
2159
+ },
2160
+ onCancel: () => {
2161
+ setSelectedProperty(void 0);
2162
+ },
2163
+ autoOpenTypeSelect: false,
2164
+ existingProperty: false,
2165
+ propertyConfigs
2166
+ }),
2167
+ /* @__PURE__ */ jsx("div", { style: { height: "52px" } })
2168
+ ]
2169
+ });
2170
+ }
2171
+ function PropertySelect({ property, onPropertyChanged, propertyKey, propertyConfigs, disabled }) {
2172
+ const fieldId = property ? getFieldId(property) : null;
2173
+ const widget = property ? getFieldConfig(property, propertyConfigs) : null;
2174
+ const [selectOpen, setSelectOpen] = useState(false);
2175
+ return /* @__PURE__ */ jsx(Tooltip, {
2176
+ title: property && widget ? `${widget?.name} - ${property.type}` : void 0,
2177
+ open: selectOpen ? false : void 0,
2178
+ children: /* @__PURE__ */ jsx(Select, {
2179
+ open: selectOpen,
2180
+ onOpenChange: setSelectOpen,
2181
+ invisible: true,
2182
+ className: "w-full",
2183
+ disabled,
2184
+ error: !widget,
2185
+ fullWidth: true,
2186
+ value: fieldId ?? "",
2187
+ placeholder: "Select a property widget",
2188
+ position: "item-aligned",
2189
+ renderValue: (value) => {
2190
+ if (!widget) return null;
2191
+ return /* @__PURE__ */ jsx(PropertyConfigBadge, { propertyConfig: widget });
2192
+ },
2193
+ onValueChange: (newSelectedWidgetId) => {
2194
+ const newProperty = updatePropertyFromWidget(property, newSelectedWidgetId, propertyConfigs);
2195
+ if (!propertyKey) return;
2196
+ onPropertyChanged({
2197
+ id: propertyKey,
2198
+ property: newProperty,
2199
+ previousId: propertyKey,
2200
+ namespace: void 0
2201
+ });
2202
+ },
2203
+ children: Object.entries(supportedFields).map(([key, widget]) => {
2204
+ return /* @__PURE__ */ jsx(ImportPropertySelectItem, {
2205
+ value: key,
2206
+ optionDisabled: false,
2207
+ propertyConfig: widget,
2208
+ existing: false
2209
+ }, key);
2210
+ })
2211
+ })
2212
+ });
2213
+ }
2214
+ function ImportPropertySelectItem({ value, optionDisabled, propertyConfig, existing }) {
2215
+ return /* @__PURE__ */ jsx(SelectItem, {
2216
+ value,
2217
+ disabled: optionDisabled,
2218
+ className: "flex flex-row items-center",
2219
+ children: /* @__PURE__ */ jsxs("div", {
2220
+ className: cls("flex flex-row items-center text-base min-h-[48px]", optionDisabled ? "w-full" : ""),
2221
+ children: [/* @__PURE__ */ jsx("div", {
2222
+ className: "mr-8",
2223
+ children: /* @__PURE__ */ jsx(PropertyConfigBadge, { propertyConfig })
2224
+ }), /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", { children: propertyConfig.name }), /* @__PURE__ */ jsx(Typography, {
2225
+ variant: "caption",
2226
+ color: "disabled",
2227
+ className: "max-w-sm",
2228
+ children: existing && optionDisabled ? "You can only switch to widgets that use the same data type" : propertyConfig.description
2229
+ })] })]
2230
+ })
2231
+ });
2232
+ }
2233
+ //#endregion
2234
+ //#region src/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx
2235
+ function CollectionEditorImportDataPreview({ importConfig, properties, propertiesOrder }) {
2236
+ const authController = useAuthController();
2237
+ const registry = useCollectionRegistryController();
2238
+ const [loading, setLoading] = useState(false);
2239
+ async function loadEntities() {
2240
+ const mappedData = importConfig.importData.map((d) => convertDataToEntity(authController, registry, d, importConfig.idColumn, importConfig.headersMapping, properties, "TEMP_PATH", importConfig.defaultValues));
2241
+ importConfig.setEntities(mappedData);
2242
+ }
2243
+ useEffect(() => {
2244
+ loadEntities().finally(() => setLoading(false));
2245
+ }, []);
2246
+ const selectionController = useSelectionController();
2247
+ if (loading) return /* @__PURE__ */ jsx(CircularProgressCenter, {});
2248
+ return /* @__PURE__ */ jsx(CollectionTableBinding, {
2249
+ title: /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx(Typography, {
2250
+ variant: "subtitle2",
2251
+ children: "Imported data preview"
2252
+ }), /* @__PURE__ */ jsx(Typography, {
2253
+ variant: "caption",
2254
+ children: "Entities with the same id will be overwritten"
2255
+ })] }),
2256
+ tableController: {
2257
+ data: importConfig.entities,
2258
+ dataLoading: false,
2259
+ noMoreToLoad: false
2260
+ },
2261
+ endAdornment: /* @__PURE__ */ jsx("div", { className: "h-12" }),
2262
+ filterable: false,
2263
+ sortable: false,
2264
+ selectionController,
2265
+ displayedColumnIds: propertiesOrder.map((p) => ({
2266
+ key: p,
2267
+ disabled: false
2268
+ })),
2269
+ openEntityMode: "side_panel",
2270
+ properties,
2271
+ enablePopupIcon: false
2272
+ });
2273
+ }
2274
+ //#endregion
2275
+ //#region src/collection_editor/ui/collection_editor/import/clean_import_data.ts
2276
+ function cleanPropertiesFromImport(properties, parentSlug = "") {
2277
+ const result = Object.keys(properties).reduce((acc, key) => {
2278
+ const property = properties[key];
2279
+ const slug = slugify(key);
2280
+ const fullSlug = parentSlug ? `${parentSlug}.${slug}` : slug;
2281
+ if (property.type === "map" && property.properties) {
2282
+ const slugifiedResult = cleanPropertiesFromImport(property.properties, fullSlug);
2283
+ return {
2284
+ headersMapping: {
2285
+ ...acc.headersMapping,
2286
+ [key]: fullSlug
2287
+ },
2288
+ properties: {
2289
+ ...acc.properties,
2290
+ [slug]: {
2291
+ ...property,
2292
+ properties: slugifiedResult.properties,
2293
+ propertiesOrder: Object.keys(slugifiedResult.properties)
2294
+ }
2295
+ }
2296
+ };
2297
+ }
2298
+ const updatedProperties = {
2299
+ ...acc.properties,
2300
+ [slug]: property
2301
+ };
2302
+ return {
2303
+ headersMapping: {
2304
+ ...acc.headersMapping,
2305
+ [key]: fullSlug
2306
+ },
2307
+ properties: updatedProperties
2308
+ };
2309
+ }, {
2310
+ headersMapping: {},
2311
+ properties: {}
2312
+ });
2313
+ const firstKey = Object.keys(result.headersMapping)?.[0];
2314
+ let idColumn;
2315
+ if (firstKey?.includes("id") || firstKey?.includes("key")) idColumn = firstKey;
2316
+ return {
2317
+ ...result,
2318
+ idColumn
2319
+ };
2320
+ }
2321
+ //#endregion
2322
+ //#region src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx
2323
+ /**
2324
+ * Validates and double-quotes a SQL identifier to prevent injection.
2325
+ * Only allows safe Postgres identifiers (letters, digits, underscores).
2326
+ * Throws if the identifier contains unsafe characters.
2327
+ */
2328
+ function sanitizeSqlIdentifier(name) {
2329
+ if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) throw new Error(`Invalid SQL identifier: "${name}". Only letters, digits, and underscores are allowed.`);
2330
+ return `"${name}"`;
2331
+ }
2332
+ function CollectionRLSTab() {
2333
+ const { values, setFieldValue } = useFormex();
2334
+ const [editingPolicy, setEditingPolicy] = useState(null);
2335
+ const rules = values.securityRules || [];
2336
+ const { databaseAdmin } = useRebaseContext();
2337
+ const [dbPolicies, setDbPolicies] = useState([]);
2338
+ const [isLoadingDb, setIsLoadingDb] = useState(false);
2339
+ useEffect(() => {
2340
+ const fetchLivePolicies = async () => {
2341
+ const tableName = values.id || values.table || values.alias;
2342
+ if (!tableName || !databaseAdmin?.executeSql) return;
2343
+ setIsLoadingDb(true);
2344
+ try {
2345
+ const sql = `
2346
+ SELECT policyname, permissive, roles, cmd, qual, with_check
2347
+ FROM pg_policies
2348
+ WHERE tablename = '${sanitizeSqlIdentifier(tableName).slice(1, -1)}' AND schemaname NOT IN ('information_schema', 'pg_catalog');
2349
+ `;
2350
+ const result = await databaseAdmin.executeSql(sql);
2351
+ const extractRows = (res) => {
2352
+ if (res && typeof res === "object" && "rows" in res && Array.isArray(res.rows)) return res.rows;
2353
+ if (Array.isArray(res)) return res;
2354
+ return [];
2355
+ };
2356
+ setDbPolicies(extractRows(result).map((p) => {
2357
+ let parsedRoles = [];
2358
+ const r = p.roles || p.ROLES;
2359
+ if (Array.isArray(r)) parsedRoles = r;
2360
+ else if (typeof r === "string") parsedRoles = r.replace(/^{|}$/g, "").split(",").map((s) => s.trim());
2361
+ return {
2362
+ policyname: p.policyname || p.POLICYNAME || "",
2363
+ tablename: tableName,
2364
+ permissive: p.permissive || p.PERMISSIVE || "PERMISSIVE",
2365
+ roles: parsedRoles,
2366
+ cmd: p.cmd || p.CMD || "ALL",
2367
+ qual: p.qual || p.QUAL || null,
2368
+ with_check: p.with_check || p.WITH_CHECK || null
2369
+ };
2370
+ }));
2371
+ } catch (e) {
2372
+ console.error("Failed to fetch DB policies", e);
2373
+ } finally {
2374
+ setIsLoadingDb(false);
2375
+ }
2376
+ };
2377
+ fetchLivePolicies();
2378
+ }, [
2379
+ databaseAdmin,
2380
+ values.id,
2381
+ values.table,
2382
+ values.alias
2383
+ ]);
2384
+ const unmappedPolicies = dbPolicies.filter((dp) => !rules.some((r) => r.name === dp.policyname));
2385
+ const handleSave = async (newPolicy) => {
2386
+ const rule = {
2387
+ name: newPolicy.policyname ?? "",
2388
+ operation: newPolicy.cmd?.toLowerCase(),
2389
+ mode: newPolicy.permissive?.toLowerCase(),
2390
+ using: newPolicy.qual || void 0,
2391
+ withCheck: newPolicy.with_check || void 0,
2392
+ roles: newPolicy.roles
2393
+ };
2394
+ let newRules;
2395
+ if (editingPolicy === "new") newRules = [...rules, rule];
2396
+ else newRules = rules.map((r) => r.name === editingPolicy.policyname ? rule : r);
2397
+ setFieldValue("securityRules", newRules);
2398
+ setEditingPolicy(null);
2399
+ };
2400
+ return /* @__PURE__ */ jsx("div", {
2401
+ className: "overflow-auto my-auto",
2402
+ children: /* @__PURE__ */ jsxs(Container, {
2403
+ maxWidth: "4xl",
2404
+ className: "flex flex-col gap-4 p-8 m-auto",
2405
+ children: [/* @__PURE__ */ jsxs("div", {
2406
+ className: "w-full flex flex-col",
2407
+ children: [
2408
+ /* @__PURE__ */ jsxs("div", {
2409
+ className: "flex items-center justify-between mb-8",
2410
+ children: [/* @__PURE__ */ jsx(Typography, {
2411
+ variant: "h5",
2412
+ children: "Row Level Security"
2413
+ }), /* @__PURE__ */ jsx(Button, {
2414
+ variant: "filled",
2415
+ color: "neutral",
2416
+ onClick: () => setEditingPolicy("new"),
2417
+ children: "CREATE POLICY"
2418
+ })]
2419
+ }),
2420
+ rules.length === 0 ? /* @__PURE__ */ jsx("div", {
2421
+ className: "flex-grow flex items-center justify-center text-text-disabled py-12",
2422
+ children: /* @__PURE__ */ jsx(Typography, {
2423
+ variant: "body2",
2424
+ children: "No RLS policies defined for this collection."
2425
+ })
2426
+ }) : /* @__PURE__ */ jsx("div", {
2427
+ className: "flex flex-col gap-3",
2428
+ children: rules.map((rule) => /* @__PURE__ */ jsxs(Paper, {
2429
+ className: "p-4 border border-transparent hover:border-surface-200 dark:hover:border-surface-700 rounded-lg flex flex-col sm:flex-row sm:items-center justify-between gap-4 transition-colors bg-white dark:bg-surface-800 shadow-sm",
2430
+ children: [/* @__PURE__ */ jsxs("div", {
2431
+ className: "flex flex-col gap-1.5 min-w-0",
2432
+ children: [/* @__PURE__ */ jsxs("div", {
2433
+ className: "flex items-center gap-2",
2434
+ children: [/* @__PURE__ */ jsx(KeyIcon, {
2435
+ size: iconSize.smallest,
2436
+ className: "text-text-disabled dark:text-text-disabled-dark shrink-0"
2437
+ }), /* @__PURE__ */ jsx(Typography, {
2438
+ variant: "subtitle2",
2439
+ className: "truncate",
2440
+ children: rule.name
2441
+ })]
2442
+ }), /* @__PURE__ */ jsxs("div", {
2443
+ className: "flex gap-2 text-xs pl-6 overflow-x-auto hide-scrollbar",
2444
+ children: [/* @__PURE__ */ jsxs(Chip, {
2445
+ size: "small",
2446
+ className: "bg-surface-100 dark:bg-surface-900 text-text-secondary border-none",
2447
+ children: ["Action: ", rule.operation || "ALL"]
2448
+ }), /* @__PURE__ */ jsxs(Chip, {
2449
+ size: "small",
2450
+ className: "bg-surface-100 dark:bg-surface-900 text-text-secondary border-none",
2451
+ children: ["Roles: ", Array.isArray(rule.roles) ? rule.roles.join(", ") : rule.roles]
2452
+ })]
2453
+ })]
2454
+ }), /* @__PURE__ */ jsxs("div", {
2455
+ className: "flex items-center gap-1 sm:gap-2 shrink-0",
2456
+ children: [/* @__PURE__ */ jsx(Button, {
2457
+ size: "small",
2458
+ variant: "text",
2459
+ onClick: () => setEditingPolicy({
2460
+ policyname: rule.name,
2461
+ tablename: values.id || values.table || values.alias || "your_table",
2462
+ permissive: (rule.mode || "permissive").toUpperCase(),
2463
+ cmd: (rule.operation || "ALL").toUpperCase(),
2464
+ roles: rule.roles || ["public"],
2465
+ qual: rule.using || null,
2466
+ with_check: rule.withCheck || null
2467
+ }),
2468
+ children: "EDIT"
2469
+ }), /* @__PURE__ */ jsx(IconButton, {
2470
+ size: "small",
2471
+ onClick: () => {
2472
+ setFieldValue("securityRules", rules.filter((r) => r.name !== rule.name));
2473
+ },
2474
+ children: /* @__PURE__ */ jsx(Trash2Icon, {
2475
+ size: iconSize.smallest,
2476
+ className: "text-text-secondary dark:text-text-secondary-dark hover:text-red-500 dark:hover:text-red-500 transition-colors"
2477
+ })
2478
+ })]
2479
+ })]
2480
+ }, rule.name))
2481
+ }),
2482
+ isLoadingDb && unmappedPolicies.length === 0 && /* @__PURE__ */ jsx("div", {
2483
+ className: "flex justify-center mt-8",
2484
+ children: /* @__PURE__ */ jsx(CircularProgress, { size: "small" })
2485
+ }),
2486
+ !isLoadingDb && unmappedPolicies.length > 0 && /* @__PURE__ */ jsxs("div", {
2487
+ className: "mt-12 flex flex-col gap-4",
2488
+ children: [
2489
+ /* @__PURE__ */ jsx(Typography, {
2490
+ variant: "h6",
2491
+ className: "text-text-secondary",
2492
+ children: "Unmapped Database Policies"
2493
+ }),
2494
+ /* @__PURE__ */ jsx(Typography, {
2495
+ variant: "body2",
2496
+ className: "text-text-secondary opacity-80 -mt-2",
2497
+ children: "These policies exist in your Postgres database but are not mapped to this collection's codebase configuration."
2498
+ }),
2499
+ /* @__PURE__ */ jsx("div", {
2500
+ className: "flex flex-col gap-3",
2501
+ children: unmappedPolicies.map((dp) => /* @__PURE__ */ jsxs(Paper, {
2502
+ className: "p-4 border border-orange-200 dark:border-orange-900/50 bg-orange-50/50 dark:bg-orange-900/10 rounded-lg flex flex-col sm:flex-row sm:items-center justify-between gap-4 transition-colors",
2503
+ children: [/* @__PURE__ */ jsxs("div", {
2504
+ className: "flex flex-col gap-1.5 min-w-0",
2505
+ children: [/* @__PURE__ */ jsxs("div", {
2506
+ className: "flex items-center gap-2",
2507
+ children: [
2508
+ /* @__PURE__ */ jsx(KeyIcon, {
2509
+ size: iconSize.smallest,
2510
+ className: "text-orange-500 shrink-0"
2511
+ }),
2512
+ /* @__PURE__ */ jsx(Typography, {
2513
+ variant: "subtitle2",
2514
+ className: "truncate",
2515
+ children: dp.policyname
2516
+ }),
2517
+ /* @__PURE__ */ jsx(Tooltip, {
2518
+ title: "This policy is live in the database but missing from your codebase schema.",
2519
+ children: /* @__PURE__ */ jsx("div", {
2520
+ className: "px-1.5 py-0.5 rounded text-[10px] uppercase bg-orange-500/10 text-orange-600 border border-orange-500/20 shrink-0",
2521
+ children: "DB Only"
2522
+ })
2523
+ })
2524
+ ]
2525
+ }), /* @__PURE__ */ jsxs("div", {
2526
+ className: "flex gap-2 text-xs pl-6 overflow-x-auto hide-scrollbar",
2527
+ children: [/* @__PURE__ */ jsxs(Chip, {
2528
+ size: "small",
2529
+ className: "bg-white dark:bg-surface-900 text-text-secondary border-none",
2530
+ children: ["Action: ", dp.cmd || "ALL"]
2531
+ }), /* @__PURE__ */ jsxs(Chip, {
2532
+ size: "small",
2533
+ className: "bg-white dark:bg-surface-900 text-text-secondary border-none",
2534
+ children: ["Roles: ", Array.isArray(dp.roles) ? dp.roles.join(", ") : dp.roles]
2535
+ })]
2536
+ })]
2537
+ }), /* @__PURE__ */ jsx("div", {
2538
+ className: "flex items-center gap-1 sm:gap-2 shrink-0",
2539
+ children: /* @__PURE__ */ jsx(Button, {
2540
+ size: "small",
2541
+ variant: "outlined",
2542
+ color: "primary",
2543
+ onClick: () => {
2544
+ const rule = {
2545
+ name: dp.policyname,
2546
+ operation: dp.cmd?.toLowerCase(),
2547
+ mode: dp.permissive?.toLowerCase(),
2548
+ using: dp.qual || void 0,
2549
+ withCheck: dp.with_check || void 0,
2550
+ roles: dp.roles
2551
+ };
2552
+ setFieldValue("securityRules", [...rules, rule]);
2553
+ },
2554
+ children: "Import to codebase"
2555
+ })
2556
+ })]
2557
+ }, dp.policyname))
2558
+ })
2559
+ ]
2560
+ })
2561
+ ]
2562
+ }), /* @__PURE__ */ jsx(Dialog, {
2563
+ open: !!editingPolicy,
2564
+ onOpenChange: (open) => !open && setEditingPolicy(null),
2565
+ maxWidth: "4xl",
2566
+ children: editingPolicy && /* @__PURE__ */ jsx(InlinePolicyEditor, {
2567
+ policy: editingPolicy === "new" ? void 0 : editingPolicy,
2568
+ table: values.id || values.table || values.alias || "your_table",
2569
+ onSave: handleSave,
2570
+ onCancel: () => setEditingPolicy(null)
2571
+ })
2572
+ })]
2573
+ })
2574
+ });
2575
+ }
2576
+ var COMMAND_OPTIONS = [
2577
+ "ALL",
2578
+ "SELECT",
2579
+ "INSERT",
2580
+ "UPDATE",
2581
+ "DELETE"
2582
+ ];
2583
+ var ROLE_OPTIONS = [
2584
+ "public",
2585
+ "authenticated",
2586
+ "anon",
2587
+ "admin"
2588
+ ];
2589
+ function InlinePolicyEditor({ policy, table, onSave, onCancel }) {
2590
+ const [name, setName] = useState(policy?.policyname || "");
2591
+ const [behavior, setBehavior] = useState(policy?.permissive || "PERMISSIVE");
2592
+ const [command, setCommand] = useState(policy?.cmd || "ALL");
2593
+ const [roles, setRoles] = useState(policy?.roles ? Array.isArray(policy.roles) ? policy.roles : [policy.roles] : ["public"]);
2594
+ const [usingExpr, setUsingExpr] = useState(policy?.qual || "");
2595
+ const [checkExpr, setCheckExpr] = useState(policy?.with_check || "");
2596
+ const showCheck = command === "ALL" || command === "INSERT" || command === "UPDATE";
2597
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
2598
+ /* @__PURE__ */ jsxs(DialogTitle, {
2599
+ variant: "h6",
2600
+ children: [policy ? "Edit Policy" : "Create Policy", /* @__PURE__ */ jsxs("div", {
2601
+ className: "text-sm font-normal text-text-secondary dark:text-text-secondary-dark tracking-wide mt-1",
2602
+ children: ["Define RLS rules for ", /* @__PURE__ */ jsxs("span", {
2603
+ className: "font-mono text-primary bg-primary-bg dark:bg-primary-bg-dark px-1 py-0.5 rounded",
2604
+ children: ["public.", table]
2605
+ })]
2606
+ })]
2607
+ }),
2608
+ /* @__PURE__ */ jsx(DialogContent, {
2609
+ className: "p-4 md:p-6 border-t dark:border-surface-700 bg-surface-50 dark:bg-surface-800",
2610
+ includeMargin: false,
2611
+ children: /* @__PURE__ */ jsxs(Paper, {
2612
+ className: cls("p-4 md:p-6 flex flex-col gap-6 bg-white dark:bg-surface-800 border-none sm:border-solid rounded-none sm:rounded-xl", defaultBorderMixin),
2613
+ children: [
2614
+ /* @__PURE__ */ jsxs("div", {
2615
+ className: "grid grid-cols-1 md:grid-cols-2 gap-4",
2616
+ children: [/* @__PURE__ */ jsxs("div", {
2617
+ className: "flex flex-col gap-1.5",
2618
+ children: [/* @__PURE__ */ jsx(Typography, {
2619
+ variant: "caption",
2620
+ className: "uppercase tracking-wider text-text-secondary",
2621
+ children: "Policy Name"
2622
+ }), /* @__PURE__ */ jsx(TextField, {
2623
+ value: name,
2624
+ onChange: (e) => setName(e.target.value),
2625
+ placeholder: "e.g. allow_read_all"
2626
+ })]
2627
+ }), /* @__PURE__ */ jsxs("div", {
2628
+ className: "flex flex-col gap-1.5",
2629
+ children: [/* @__PURE__ */ jsx(Typography, {
2630
+ variant: "caption",
2631
+ className: "uppercase tracking-wider text-text-secondary",
2632
+ children: "Behavior"
2633
+ }), /* @__PURE__ */ jsxs(Select, {
2634
+ value: behavior,
2635
+ onValueChange: (val) => setBehavior(val),
2636
+ position: "item-aligned",
2637
+ children: [/* @__PURE__ */ jsx(SelectItem, {
2638
+ value: "PERMISSIVE",
2639
+ children: "Permissive"
2640
+ }), /* @__PURE__ */ jsx(SelectItem, {
2641
+ value: "RESTRICTIVE",
2642
+ children: "Restrictive"
2643
+ })]
2644
+ })]
2645
+ })]
2646
+ }),
2647
+ /* @__PURE__ */ jsxs("div", {
2648
+ className: "flex flex-col gap-1.5",
2649
+ children: [/* @__PURE__ */ jsx(Typography, {
2650
+ variant: "caption",
2651
+ className: "uppercase tracking-wider text-text-secondary",
2652
+ children: "Command"
2653
+ }), /* @__PURE__ */ jsx("div", {
2654
+ className: "flex flex-wrap gap-1.5",
2655
+ children: COMMAND_OPTIONS.map((cmd) => /* @__PURE__ */ jsx(Button, {
2656
+ size: "small",
2657
+ variant: command === cmd ? "filled" : "text",
2658
+ color: "neutral",
2659
+ onClick: () => setCommand(cmd),
2660
+ children: cmd
2661
+ }, cmd))
2662
+ })]
2663
+ }),
2664
+ /* @__PURE__ */ jsxs("div", {
2665
+ className: "flex flex-col gap-1.5",
2666
+ children: [/* @__PURE__ */ jsx(Typography, {
2667
+ variant: "caption",
2668
+ className: "uppercase tracking-wider text-text-secondary",
2669
+ children: "Target Roles"
2670
+ }), /* @__PURE__ */ jsx(MultiSelect, {
2671
+ size: "small",
2672
+ value: roles,
2673
+ onValueChange: setRoles,
2674
+ placeholder: "Select roles",
2675
+ children: ROLE_OPTIONS.map((r) => /* @__PURE__ */ jsx(MultiSelectItem, {
2676
+ value: r,
2677
+ children: r
2678
+ }, r))
2679
+ })]
2680
+ }),
2681
+ command !== "INSERT" && /* @__PURE__ */ jsxs("div", {
2682
+ className: "flex flex-col gap-1.5",
2683
+ children: [/* @__PURE__ */ jsx(Typography, {
2684
+ variant: "caption",
2685
+ className: "uppercase tracking-wider text-text-secondary",
2686
+ children: "USING expression"
2687
+ }), /* @__PURE__ */ jsx(TextField, {
2688
+ value: usingExpr,
2689
+ onChange: (e) => setUsingExpr(e.target.value),
2690
+ placeholder: "e.g. auth.uid() = user_id"
2691
+ })]
2692
+ }),
2693
+ showCheck && /* @__PURE__ */ jsxs("div", {
2694
+ className: "flex flex-col gap-1.5",
2695
+ children: [/* @__PURE__ */ jsx(Typography, {
2696
+ variant: "caption",
2697
+ className: "uppercase tracking-wider text-text-secondary",
2698
+ children: "WITH CHECK expression"
2699
+ }), /* @__PURE__ */ jsx(TextField, {
2700
+ value: checkExpr,
2701
+ onChange: (e) => setCheckExpr(e.target.value),
2702
+ placeholder: "e.g. auth.uid() = user_id"
2703
+ })]
2704
+ })
2705
+ ]
2706
+ })
2707
+ }),
2708
+ /* @__PURE__ */ jsxs(DialogActions, { children: [/* @__PURE__ */ jsx(Button, {
2709
+ size: "small",
2710
+ variant: "text",
2711
+ color: "neutral",
2712
+ onClick: onCancel,
2713
+ children: "Cancel"
2714
+ }), /* @__PURE__ */ jsx(Button, {
2715
+ size: "small",
2716
+ variant: "filled",
2717
+ color: "primary",
2718
+ disabled: !name,
2719
+ onClick: () => onSave({
2720
+ policyname: name,
2721
+ permissive: behavior,
2722
+ cmd: command,
2723
+ roles,
2724
+ qual: usingExpr,
2725
+ with_check: showCheck ? checkExpr : null
2726
+ }),
2727
+ children: "Save"
2728
+ })] })
2729
+ ] });
2730
+ }
2731
+ //#endregion
2732
+ //#region src/collection_editor/pgColumnToProperty.ts
2733
+ /**
2734
+ * Maps a PostgreSQL column data type to a Rebase property type.
2735
+ */
2736
+ function pgTypeToRebaseProperty(column) {
2737
+ const { column_name, data_type, udt_name, is_nullable, column_default, enum_values } = column;
2738
+ const required = is_nullable === "NO";
2739
+ const prettifiedName = prettifyIdentifier(column_name);
2740
+ const isAutoId = column_default != null && (column_default.includes("nextval") || column_default.includes("gen_random_uuid") || column_default.includes("uuid_generate") || column_default.includes("identity"));
2741
+ if (data_type === "USER-DEFINED" && enum_values && enum_values.length > 0) return {
2742
+ type: "string",
2743
+ name: prettifiedName,
2744
+ enum: enum_values.map((v) => ({
2745
+ id: v,
2746
+ label: prettifyIdentifier(v)
2747
+ })),
2748
+ validation: required ? { required: true } : void 0
2749
+ };
2750
+ const dt = data_type.toLowerCase();
2751
+ switch (dt) {
2752
+ case "character varying":
2753
+ case "varchar":
2754
+ case "text":
2755
+ case "char":
2756
+ case "character":
2757
+ case "citext": {
2758
+ let colType = "varchar";
2759
+ if (dt === "text" || dt === "citext") colType = "text";
2760
+ if (dt === "char" || dt === "character") colType = "char";
2761
+ const prop = {
2762
+ type: "string",
2763
+ name: prettifiedName,
2764
+ columnType: colType,
2765
+ validation: required ? { required: true } : void 0
2766
+ };
2767
+ if (isAutoId) prop.isId = "manual";
2768
+ return prop;
2769
+ }
2770
+ case "uuid": {
2771
+ const prop = {
2772
+ type: "string",
2773
+ name: prettifiedName,
2774
+ validation: required ? { required: true } : void 0
2775
+ };
2776
+ if (isAutoId) prop.isId = "uuid";
2777
+ return prop;
2778
+ }
2779
+ case "integer":
2780
+ case "bigint":
2781
+ case "smallint": {
2782
+ const prop = {
2783
+ type: "number",
2784
+ name: prettifiedName,
2785
+ columnType: dt === "bigint" ? "bigint" : "integer",
2786
+ validation: {
2787
+ ...required ? { required: true } : {},
2788
+ integer: true
2789
+ }
2790
+ };
2791
+ if (isAutoId) prop.isId = "increment";
2792
+ return prop;
2793
+ }
2794
+ case "serial":
2795
+ case "bigserial":
2796
+ case "smallserial": return {
2797
+ type: "number",
2798
+ name: prettifiedName,
2799
+ columnType: dt === "bigserial" ? "bigserial" : "serial",
2800
+ isId: "increment",
2801
+ validation: {
2802
+ ...required ? { required: true } : {},
2803
+ integer: true
2804
+ }
2805
+ };
2806
+ case "numeric":
2807
+ case "decimal":
2808
+ case "real":
2809
+ case "double precision": {
2810
+ let colType = "numeric";
2811
+ if (dt === "real") colType = "real";
2812
+ if (dt === "double precision") colType = "double precision";
2813
+ return {
2814
+ type: "number",
2815
+ name: prettifiedName,
2816
+ columnType: colType,
2817
+ validation: required ? { required: true } : void 0
2818
+ };
2819
+ }
2820
+ case "boolean": return {
2821
+ type: "boolean",
2822
+ name: prettifiedName,
2823
+ validation: required ? { required: true } : void 0
2824
+ };
2825
+ case "timestamp with time zone":
2826
+ case "timestamp without time zone":
2827
+ case "timestamp":
2828
+ case "timestamptz":
2829
+ case "date":
2830
+ case "time with time zone":
2831
+ case "time without time zone":
2832
+ case "time": {
2833
+ let colType = "timestamp";
2834
+ if (dt.startsWith("date")) colType = "date";
2835
+ if (dt.startsWith("time ") || dt === "time") colType = "time";
2836
+ return {
2837
+ type: "date",
2838
+ name: prettifiedName,
2839
+ columnType: colType,
2840
+ validation: required ? { required: true } : void 0
2841
+ };
2842
+ }
2843
+ case "jsonb":
2844
+ case "json": return {
2845
+ type: "map",
2846
+ name: prettifiedName,
2847
+ columnType: dt === "jsonb" ? "jsonb" : "json",
2848
+ keyValue: true,
2849
+ properties: {}
2850
+ };
2851
+ case "array":
2852
+ case "ARRAY": {
2853
+ let innerType = "string";
2854
+ let colType = void 0;
2855
+ if (udt_name === "_text" || udt_name === "_varchar") {
2856
+ innerType = "string";
2857
+ colType = "text[]";
2858
+ } else if (udt_name === "_int4" || udt_name === "_int2" || udt_name === "_int8") {
2859
+ innerType = "number";
2860
+ colType = "integer[]";
2861
+ } else if (udt_name === "_bool") {
2862
+ innerType = "boolean";
2863
+ colType = "boolean[]";
2864
+ } else if (udt_name === "_numeric") {
2865
+ innerType = "number";
2866
+ colType = "numeric[]";
2867
+ }
2868
+ return {
2869
+ type: "array",
2870
+ name: prettifiedName,
2871
+ columnType: colType,
2872
+ of: { type: innerType }
2873
+ };
2874
+ }
2875
+ default: return {
2876
+ type: "string",
2877
+ name: prettifiedName,
2878
+ validation: required ? { required: true } : void 0
2879
+ };
2880
+ }
2881
+ }
2882
+ /**
2883
+ * Builds a partial CollectionConfig from PostgreSQL table metadata.
2884
+ * This is used when creating a new collection from an existing database table.
2885
+ */
2886
+ function buildCollectionFromTableMetadata(tableName, metadata) {
2887
+ const properties = {};
2888
+ const propertiesOrder = [];
2889
+ const relations = [];
2890
+ const securityRules = [];
2891
+ for (const column of metadata.columns) {
2892
+ const property = pgTypeToRebaseProperty(column);
2893
+ if (property) {
2894
+ const propRecord = property;
2895
+ Object.keys(propRecord).forEach((key) => propRecord[key] === void 0 && delete propRecord[key]);
2896
+ properties[column.column_name] = property;
2897
+ propertiesOrder.push(column.column_name);
2898
+ }
2899
+ }
2900
+ if (metadata.foreignKeys) for (const fk of metadata.foreignKeys) {
2901
+ const relName = fk.column_name.endsWith("_id") ? fk.column_name.substring(0, fk.column_name.length - 3) : fk.column_name;
2902
+ relations.push({
2903
+ id: fk.column_name,
2904
+ relationName: relName,
2905
+ target: fk.foreign_table_name,
2906
+ cardinality: "one",
2907
+ direction: "owning",
2908
+ localKey: fk.column_name
2909
+ });
2910
+ }
2911
+ if (metadata.junctions) for (const junction of metadata.junctions) {
2912
+ const relName = junction.target_table_name;
2913
+ relations.push({
2914
+ id: junction.target_table_name + "_relation",
2915
+ relationName: relName,
2916
+ target: junction.target_table_name,
2917
+ cardinality: "many",
2918
+ direction: "owning",
2919
+ through: {
2920
+ table: junction.junction_table_name,
2921
+ sourceColumn: junction.source_column_name,
2922
+ targetColumn: junction.target_column_name
2923
+ }
2924
+ });
2925
+ }
2926
+ if (metadata.policies) for (const policy of metadata.policies) {
2927
+ let operations = [];
2928
+ switch (policy.cmd) {
2929
+ case "ALL":
2930
+ operations = [
2931
+ "read",
2932
+ "create",
2933
+ "update",
2934
+ "delete"
2935
+ ];
2936
+ break;
2937
+ case "SELECT":
2938
+ operations = ["read"];
2939
+ break;
2940
+ case "INSERT":
2941
+ operations = ["create"];
2942
+ break;
2943
+ case "UPDATE":
2944
+ operations = ["update"];
2945
+ break;
2946
+ case "DELETE":
2947
+ operations = ["delete"];
2948
+ break;
2949
+ }
2950
+ securityRules.push({
2951
+ name: policy.policy_name,
2952
+ operations,
2953
+ roles: policy.roles ?? [],
2954
+ qual: policy.qual,
2955
+ with_check: policy.with_check
2956
+ });
2957
+ }
2958
+ return {
2959
+ name: prettifyIdentifier(tableName),
2960
+ slug: tableName,
2961
+ table: tableName,
2962
+ properties,
2963
+ propertiesOrder,
2964
+ ...relations.length > 0 ? { relations } : {},
2965
+ ...securityRules.length > 0 ? { securityRules } : {}
2966
+ };
2967
+ }
2968
+ //#endregion
2969
+ //#region src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx
2970
+ var CollectionEditorDialog_exports = /* @__PURE__ */ __exportAll({
2971
+ CollectionEditor: () => CollectionEditor,
2972
+ CollectionEditorDialog: () => CollectionEditorDialog
2973
+ });
2974
+ function CollectionEditorDialog(props) {
2975
+ const open = props.open;
2976
+ const [formDirty, setFormDirty] = React$1.useState(false);
2977
+ const { dialogProps, triggerDialog } = useUnsavedChangesDialog(open && formDirty, () => props.handleClose(void 0));
2978
+ const handleCancel = () => {
2979
+ if (!formDirty) props.handleClose(void 0);
2980
+ else triggerDialog();
2981
+ };
2982
+ useEffect(() => {
2983
+ if (!open) setFormDirty(false);
2984
+ }, [open]);
2985
+ return /* @__PURE__ */ jsxs(Dialog, {
2986
+ open,
2987
+ fullWidth: true,
2988
+ fullHeight: true,
2989
+ scrollable: false,
2990
+ maxWidth: "7xl",
2991
+ className: "bg-surface-50 dark:bg-surface-800",
2992
+ onOpenChange: (open) => !open ? handleCancel() : void 0,
2993
+ children: [/* @__PURE__ */ jsx(DialogTitle, {
2994
+ hidden: true,
2995
+ children: "Collection editor"
2996
+ }), /* @__PURE__ */ jsxs(AIModifiedPathsProvider, { children: [open && /* @__PURE__ */ jsx(CollectionEditor, {
2997
+ ...props,
2998
+ handleCancel,
2999
+ setFormDirty
3000
+ }), /* @__PURE__ */ jsx(UnsavedChangesDialog, { ...dialogProps })] })]
3001
+ });
3002
+ }
3003
+ function CollectionEditor(props) {
3004
+ const { standalone } = props;
3005
+ const customizationController = useCustomizationController();
3006
+ const navigationState = useNavigationStateController();
3007
+ const collectionRegistry = useCollectionRegistryController();
3008
+ const authController = useAuthController();
3009
+ const propertyConfigs = standalone ? customizationController?.propertyConfigs ?? {} : customizationController.propertyConfigs;
3010
+ standalone ? navigationState?.topLevelNavigation : navigationState.topLevelNavigation;
3011
+ const collections = standalone ? collectionRegistry?.collections ?? [] : collectionRegistry.collections;
3012
+ const initialValuesProp = props.initialValues;
3013
+ const copyFromProp = props.copyFrom;
3014
+ const includeTemplates = !copyFromProp && !initialValuesProp?.slug && (props.parentCollectionSlugs ?? []).length === 0;
3015
+ const collectionsInThisLevel = (props.parentCollection ? getSubcollections(props.parentCollection) : collections) ?? [];
3016
+ const existingPaths = collectionsInThisLevel.map((col) => getTableName(col)?.trim().toLowerCase()).filter(Boolean);
3017
+ const existingIds = collectionsInThisLevel.map((col) => col.slug?.trim().toLowerCase()).filter(Boolean);
3018
+ const [collection, setCollection] = React$1.useState();
3019
+ const [initialLoadingCompleted, setInitialLoadingCompleted] = React$1.useState(false);
3020
+ useEffect(() => {
3021
+ try {
3022
+ const initialised = (standalone ? true : collectionRegistry?.initialised ?? true) && !props.configController?.loading;
3023
+ const getRawCollection = standalone ? (() => void 0) : collectionRegistry.getRawCollection;
3024
+ if (initialised) {
3025
+ if (props.editedCollectionId) {
3026
+ const collectionPath = [...props.parentCollectionSlugs ?? [], props.editedCollectionId].reduce((acc, segment, i) => i === 0 ? segment : `${acc}/fake_id/${segment}`, "");
3027
+ const registryCol = getRawCollection ? getRawCollection(collectionPath) : void 0;
3028
+ const configCol = props.configController?.collections?.find((c) => c.slug === props.editedCollectionId);
3029
+ setCollection(registryCol ?? configCol);
3030
+ } else setCollection(void 0);
3031
+ setInitialLoadingCompleted(true);
3032
+ }
3033
+ } catch (e) {
3034
+ console.error(e);
3035
+ }
3036
+ }, [
3037
+ props.editedCollectionId,
3038
+ props.parentCollectionSlugs,
3039
+ props.parentEntityIds,
3040
+ standalone,
3041
+ collectionRegistry.initialised,
3042
+ collectionRegistry.getRawCollection,
3043
+ props.configController.collections,
3044
+ props.configController.loading,
3045
+ collections
3046
+ ]);
3047
+ const initialIcon = React$1.useMemo(() => coolIconKeys[Math.floor(Math.random() * coolIconKeys.length)], []);
3048
+ const fallbackSlug = React$1.useMemo(() => randomString(16), []);
3049
+ const initialCollection = React$1.useMemo(() => {
3050
+ return collection ? {
3051
+ ...collection,
3052
+ slug: collection.slug ?? fallbackSlug
3053
+ } : void 0;
3054
+ }, [collection, fallbackSlug]);
3055
+ const initialValues = React$1.useMemo(() => {
3056
+ return initialCollection ? applyPropertyConfigs(initialCollection, propertyConfigs) : copyFromProp ? (() => {
3057
+ const { subcollections: _sub, ...rest } = copyFromProp;
3058
+ return {
3059
+ ...rest,
3060
+ name: "",
3061
+ ownerId: authController.user?.uid ?? ""
3062
+ };
3063
+ })() : {
3064
+ slug: initialValuesProp?.slug ?? fallbackSlug,
3065
+ table: initialValuesProp?.slug ?? "",
3066
+ name: initialValuesProp?.name ?? "",
3067
+ properties: {},
3068
+ propertiesOrder: [],
3069
+ icon: initialIcon,
3070
+ ownerId: authController.user?.uid ?? ""
3071
+ };
3072
+ }, [
3073
+ initialCollection,
3074
+ propertyConfigs,
3075
+ copyFromProp,
3076
+ initialValuesProp,
3077
+ fallbackSlug,
3078
+ initialIcon,
3079
+ authController.user?.uid
3080
+ ]);
3081
+ if (!initialLoadingCompleted) return /* @__PURE__ */ jsx(CircularProgressCenter, {});
3082
+ if (!props.isNewCollection && (!(standalone ? true : collectionRegistry?.initialised ?? true) || !initialLoadingCompleted)) return /* @__PURE__ */ jsx(CircularProgressCenter, {});
3083
+ return /* @__PURE__ */ jsx(CollectionEditorInternal, {
3084
+ ...props,
3085
+ initialValues,
3086
+ existingPaths,
3087
+ existingIds,
3088
+ includeTemplates,
3089
+ collection,
3090
+ setCollection,
3091
+ propertyConfigs
3092
+ });
3093
+ }
3094
+ function CollectionEditorInternal({ isNewCollection, configController, editedCollectionId, parentCollectionSlugs, parentEntityIds, path, collectionInference, handleClose, extraView, handleCancel, setFormDirty, getUser, parentCollection, getData, existingPaths, existingIds, includeTemplates, collection, setCollection, initialValues, propertyConfigs, existingEntities, initialView: initialViewProp, expandKanban, generateCollection, onAnalyticsEvent, fullScreen, unmappedTables, onFetchTableMetadata, propertyTypePresets, hiddenPropertyTypes, renderExtraPropertyFields, renderExtraCollectionFields, visibleTabs, standalone }) {
3095
+ const importConfigRaw = useImportConfig();
3096
+ const urlControllerRaw = useUrlController();
3097
+ const collectionRegistryRaw = useCollectionRegistryController();
3098
+ const snackbarControllerRaw = useSafeSnackbarController();
3099
+ const importConfig = standalone ? void 0 : importConfigRaw;
3100
+ const urlController = standalone ? {
3101
+ basePath: "/",
3102
+ baseCollectionPath: "/c",
3103
+ urlPathToDataPath: () => "",
3104
+ homeUrl: "/",
3105
+ isUrlCollectionPath: () => false,
3106
+ buildUrlCollectionPath: () => "",
3107
+ buildAppUrlPath: () => "",
3108
+ resolveDatabasePathsFrom: (p) => p,
3109
+ navigate: () => {}
3110
+ } : urlControllerRaw;
3111
+ const collectionRegistryInternal = standalone ? { convertIdsToPaths: (ids) => ids } : collectionRegistryRaw;
3112
+ const snackbarController = snackbarControllerRaw ?? {
3113
+ open: () => {},
3114
+ close: () => {}
3115
+ };
3116
+ const propertyErrorsRef = useRef({});
3117
+ const [currentView, setCurrentView] = useState(isNewCollection ? includeTemplates ? "welcome" : "general" : initialViewProp ?? "properties");
3118
+ useEffect(() => {
3119
+ if (visibleTabs && !visibleTabs.includes(currentView)) setCurrentView(visibleTabs[0] || "general");
3120
+ }, [visibleTabs, currentView]);
3121
+ const [error, setError] = React$1.useState();
3122
+ const saveCollection = (updatedCollection) => {
3123
+ const id = updatedCollection.slug;
3124
+ return configController.saveCollection({
3125
+ id,
3126
+ collectionData: updatedCollection,
3127
+ previousId: editedCollectionId,
3128
+ parentCollectionSlugs
3129
+ }).then(() => {
3130
+ setError(void 0);
3131
+ return true;
3132
+ }).catch((e) => {
3133
+ setError(e);
3134
+ console.error(e);
3135
+ snackbarController.open({
3136
+ type: "error",
3137
+ message: "Error persisting collection: " + (e.message ?? "Details in the console")
3138
+ });
3139
+ return false;
3140
+ });
3141
+ };
3142
+ const setNextMode = () => {
3143
+ if (currentView === "general") if (importConfig?.inUse) setCurrentView("import_data_saving");
3144
+ else if (extraView) setCurrentView("extra_view");
3145
+ else setCurrentView("properties");
3146
+ else if (currentView === "welcome") setCurrentView("general");
3147
+ else if (currentView === "import_data_mapping") setCurrentView("import_data_preview");
3148
+ else if (currentView === "import_data_preview") setCurrentView("general");
3149
+ else if (currentView === "extra_view") setCurrentView("properties");
3150
+ else setCurrentView("general");
3151
+ };
3152
+ const doCollectionInference = collectionInference ? (collection) => {
3153
+ if (!collectionInference) return void 0;
3154
+ return collectionInference?.(collection.slug, parentPaths ?? [], collection.databaseId);
3155
+ } : void 0;
3156
+ const inferCollectionFromData = async (newCollection) => {
3157
+ try {
3158
+ if (!doCollectionInference) {
3159
+ setCollection(newCollection);
3160
+ return Promise.resolve(newCollection);
3161
+ }
3162
+ setCurrentView("loading");
3163
+ const inferredCollection = await doCollectionInference?.(newCollection);
3164
+ if (!inferredCollection) {
3165
+ setCollection(newCollection);
3166
+ return Promise.resolve(newCollection);
3167
+ }
3168
+ const values = { ...newCollection ?? {} };
3169
+ if (Object.keys(inferredCollection.properties ?? {}).length > 0) {
3170
+ values.properties = inferredCollection.properties;
3171
+ values.propertiesOrder = inferredCollection.propertiesOrder;
3172
+ }
3173
+ if (!values.propertiesOrder) {
3174
+ values.propertiesOrder = Object.keys(values.properties);
3175
+ return values;
3176
+ }
3177
+ setCollection(values);
3178
+ console.debug("Inferred collection", {
3179
+ newCollection: newCollection ?? {},
3180
+ values
3181
+ });
3182
+ return values;
3183
+ } catch (e) {
3184
+ console.error(e);
3185
+ snackbarController.open({
3186
+ type: "error",
3187
+ message: "Error inferring collection: " + (e instanceof Error ? e.message : "Details in the console")
3188
+ });
3189
+ return newCollection;
3190
+ }
3191
+ };
3192
+ const onSubmit = async (newCollectionState, formexController) => {
3193
+ console.debug("Submitting collection", newCollectionState);
3194
+ try {
3195
+ if (!isNewCollection) {
3196
+ if (await saveCollection(newCollectionState)) {
3197
+ aiModifiedPaths?.clearAllPaths();
3198
+ formexController.resetForm({ values: newCollectionState });
3199
+ handleClose(newCollectionState);
3200
+ }
3201
+ return;
3202
+ }
3203
+ if (currentView === "welcome") {
3204
+ setNextMode();
3205
+ formexController.resetForm({ values: newCollectionState });
3206
+ } else if (currentView === "general") if (extraView || importConfig?.inUse) {
3207
+ formexController.resetForm({ values: newCollectionState });
3208
+ setNextMode();
3209
+ } else if (isNewCollection) {
3210
+ const values = await inferCollectionFromData(newCollectionState);
3211
+ formexController.resetForm({
3212
+ values: values ?? newCollectionState,
3213
+ touched: {
3214
+ path: true,
3215
+ name: true
3216
+ }
3217
+ });
3218
+ setNextMode();
3219
+ } else {
3220
+ formexController.resetForm({ values: newCollectionState });
3221
+ setNextMode();
3222
+ }
3223
+ else if (currentView === "extra_view") {
3224
+ setNextMode();
3225
+ formexController.resetForm({ values: newCollectionState });
3226
+ } else if (currentView === "import_data_mapping") setNextMode();
3227
+ else if (currentView === "import_data_preview") setNextMode();
3228
+ else if (currentView === "properties") {
3229
+ if (await saveCollection(newCollectionState)) {
3230
+ formexController.resetForm({ values: initialValues });
3231
+ setNextMode();
3232
+ handleClose(newCollectionState);
3233
+ }
3234
+ } else {
3235
+ setNextMode();
3236
+ formexController.resetForm({ values: newCollectionState });
3237
+ }
3238
+ } catch (e) {
3239
+ snackbarController.open({
3240
+ type: "error",
3241
+ message: "Error persisting collection: " + (e instanceof Error ? e.message : "Details in the console")
3242
+ });
3243
+ console.error(e);
3244
+ formexController.resetForm({ values: newCollectionState });
3245
+ }
3246
+ };
3247
+ const validation = (col) => {
3248
+ let errors = {};
3249
+ const schema = (currentView === "properties" || currentView === "general") && CollectionEditorSchema;
3250
+ if (schema) {
3251
+ const result = schema.safeParse(col);
3252
+ if (!result.success) result.error.issues.forEach((issue) => {
3253
+ const path = issue.path.join(".");
3254
+ if (path) errors[path] = issue.message;
3255
+ });
3256
+ }
3257
+ if (currentView === "properties") errors = {
3258
+ ...errors,
3259
+ ...propertyErrorsRef.current
3260
+ };
3261
+ if (currentView === "general") {
3262
+ const pathError = validatePath(getTableName(col), isNewCollection, existingPaths, col.slug);
3263
+ if (pathError) errors.slug = pathError;
3264
+ const idError = validateId(col.slug, isNewCollection, existingPaths, existingIds);
3265
+ if (idError) errors.id = idError;
3266
+ }
3267
+ if (Object.keys(errors).length > 0) console.error("Formex validation blocked save:", errors, "Current view:", currentView);
3268
+ return errors;
3269
+ };
3270
+ const formController = useCreateFormex({
3271
+ initialValues,
3272
+ onSubmit,
3273
+ validation,
3274
+ debugId: "COLLECTION_EDITOR"
3275
+ });
3276
+ const { values, setFieldValue, isSubmitting, dirty, submitCount } = formController;
3277
+ const usedPath = getTableName(values);
3278
+ const pathError = validatePath(usedPath, isNewCollection, existingPaths, values.slug);
3279
+ const parentPaths = !pathError && parentCollectionSlugs ? collectionRegistryInternal.convertIdsToPaths(parentCollectionSlugs) : void 0;
3280
+ const updatedFullPath = parentPaths && parentPaths.length > 0 ? [...parentPaths, usedPath].join("/fake_id/") : path?.includes("/") ? path.split("/").slice(0, -1).join("/") + "/" + usedPath : usedPath;
3281
+ const resolvedPath = !pathError ? urlController.resolveDatabasePathsFrom(updatedFullPath) : void 0;
3282
+ const getDataWithPath = resolvedPath && getData ? async () => {
3283
+ const data = await getData(resolvedPath, parentPaths ?? []);
3284
+ if (existingEntities) {
3285
+ const existingData = existingEntities.map((e) => e.values);
3286
+ data.push(...existingData);
3287
+ }
3288
+ return data;
3289
+ } : void 0;
3290
+ useEffect(() => {
3291
+ setFormDirty(dirty);
3292
+ }, [dirty]);
3293
+ function onImportDataSet(data, propertiesOrder) {
3294
+ importConfig?.setInUse(true);
3295
+ buildEntityPropertiesFromData(data, getInferenceType).then((properties) => {
3296
+ const res = cleanPropertiesFromImport(properties);
3297
+ importConfig?.setIdColumn(res.idColumn);
3298
+ importConfig?.setImportData(data);
3299
+ importConfig?.setHeadersMapping(res.headersMapping);
3300
+ const filteredHeadingsOrder = (propertiesOrder ?? []).filter((key) => res.headersMapping[key]) ?? Object.keys(res.properties);
3301
+ importConfig?.setHeadingsOrder(filteredHeadingsOrder);
3302
+ importConfig?.setOriginProperties(res.properties);
3303
+ const mappedHeadings = (propertiesOrder ?? []).map((key) => res.headersMapping[key]).filter(Boolean) ?? Object.keys(res.properties);
3304
+ setFieldValue("properties", res.properties);
3305
+ setFieldValue("propertiesOrder", mappedHeadings);
3306
+ });
3307
+ }
3308
+ const validValues = Boolean(values.name) && Boolean(values.slug);
3309
+ const onImportMappingComplete = () => {
3310
+ const updatedProperties = { ...values.properties };
3311
+ if (importConfig?.idColumn) delete updatedProperties[importConfig.idColumn];
3312
+ setFieldValue("properties", updatedProperties);
3313
+ setNextMode();
3314
+ };
3315
+ const [deleteRequested, setDeleteRequested] = useState(false);
3316
+ const deleteCollection = () => {
3317
+ if (!collection) return;
3318
+ configController?.deleteCollection({ id: collection.slug }).then(() => {
3319
+ setDeleteRequested(false);
3320
+ handleCancel();
3321
+ snackbarController.open({
3322
+ message: "Collection deleted",
3323
+ type: "success"
3324
+ });
3325
+ });
3326
+ };
3327
+ const onWelcomeScreenContinue = (importData, propertiesOrder) => {
3328
+ if (importData) {
3329
+ onImportDataSet(importData, propertiesOrder);
3330
+ setCurrentView("import_data_mapping");
3331
+ } else setCurrentView("general");
3332
+ };
3333
+ const aiModifiedPaths = useAIModifiedPaths();
3334
+ const handleAIGenerated = (generatedCollection, operations) => {
3335
+ formController.setValues(generatedCollection);
3336
+ if (operations && aiModifiedPaths) aiModifiedPaths.addModifiedPaths(operations);
3337
+ };
3338
+ return /* @__PURE__ */ jsxs("div", {
3339
+ className: "h-full w-full flex flex-col bg-surface-50 dark:bg-surface-800",
3340
+ children: [/* @__PURE__ */ jsx(Formex, {
3341
+ value: formController,
3342
+ children: /* @__PURE__ */ jsxs(Fragment, { children: [!isNewCollection && /* @__PURE__ */ jsxs("div", {
3343
+ className: cls("px-4 py-2 w-full flex shrink-0 items-center justify-between gap-4 bg-surface-50 dark:bg-surface-900 border-b", defaultBorderMixin),
3344
+ children: [/* @__PURE__ */ jsx("div", {
3345
+ className: "flex flex-1 items-center justify-end gap-4 min-w-0",
3346
+ children: /* @__PURE__ */ jsxs(Tabs, {
3347
+ value: currentView,
3348
+ className: "bg-transparent !w-fit max-w-full",
3349
+ onValueChange: (v) => setCurrentView(v),
3350
+ children: [
3351
+ (!visibleTabs || visibleTabs.includes("general")) && /* @__PURE__ */ jsx(Tab, {
3352
+ value: "general",
3353
+ children: "General"
3354
+ }),
3355
+ (!visibleTabs || visibleTabs.includes("display")) && /* @__PURE__ */ jsx(Tab, {
3356
+ value: "display",
3357
+ children: "Display"
3358
+ }),
3359
+ (!visibleTabs || visibleTabs.includes("properties")) && /* @__PURE__ */ jsx(Tab, {
3360
+ value: "properties",
3361
+ children: "Properties"
3362
+ }),
3363
+ (!visibleTabs || visibleTabs.includes("rls")) && getDataSourceCapabilities(values.engine).supportsRLS && /* @__PURE__ */ jsx(Tab, {
3364
+ value: "rls",
3365
+ children: "RLS"
3366
+ })
3367
+ ]
3368
+ })
3369
+ }), /* @__PURE__ */ jsxs("div", {
3370
+ className: "flex items-center gap-4",
3371
+ children: [generateCollection && /* @__PURE__ */ jsx(AICollectionGeneratorPopover, {
3372
+ existingCollection: values,
3373
+ onGenerated: handleAIGenerated,
3374
+ generateCollection,
3375
+ onAnalyticsEvent
3376
+ }), fullScreen && !isNewCollection && /* @__PURE__ */ jsx("div", {
3377
+ className: "flex items-center gap-2",
3378
+ children: /* @__PURE__ */ jsx(LoadingButton, {
3379
+ variant: "filled",
3380
+ color: "primary",
3381
+ type: "submit",
3382
+ onClick: () => formController.handleSubmit(),
3383
+ disabled: !dirty || isSubmitting || configController?.readOnly,
3384
+ loading: isSubmitting,
3385
+ children: configController?.readOnly ? "Update (Read-only)" : "Update"
3386
+ })
3387
+ })]
3388
+ })]
3389
+ }), /* @__PURE__ */ jsxs("form", {
3390
+ noValidate: true,
3391
+ onSubmit: formController.handleSubmit,
3392
+ className: "flex-grow flex flex-col min-h-0 relative",
3393
+ children: [/* @__PURE__ */ jsxs("div", {
3394
+ className: "flex-grow flex flex-col min-h-0 relative w-full h-full bg-surface-50 dark:bg-surface-800",
3395
+ children: [
3396
+ currentView === "loading" && /* @__PURE__ */ jsx(CircularProgressCenter, {}),
3397
+ currentView === "extra_view" && usedPath && extraView?.View && /* @__PURE__ */ jsx(extraView.View, { path: usedPath }),
3398
+ currentView === "welcome" && /* @__PURE__ */ jsx(CollectionEditorWelcomeView, {
3399
+ path: usedPath,
3400
+ onContinue: onWelcomeScreenContinue,
3401
+ existingCollectionPaths: existingPaths,
3402
+ parentCollection,
3403
+ generateCollection,
3404
+ onAnalyticsEvent,
3405
+ unmappedTables,
3406
+ onImportFromTable: onFetchTableMetadata ? async (tableName) => {
3407
+ try {
3408
+ const columns = await onFetchTableMetadata(tableName);
3409
+ if (!columns) return;
3410
+ const collectionData = buildCollectionFromTableMetadata(tableName, columns);
3411
+ formController.setValues({
3412
+ ...formController.values,
3413
+ ...collectionData
3414
+ });
3415
+ onWelcomeScreenContinue();
3416
+ } catch (e) {
3417
+ console.error("Error importing table:", e);
3418
+ snackbarController.open({
3419
+ type: "error",
3420
+ message: "Error importing table: " + (e instanceof Error ? e.message : "Unknown error")
3421
+ });
3422
+ }
3423
+ } : void 0
3424
+ }),
3425
+ currentView === "import_data_mapping" && importConfig && /* @__PURE__ */ jsx(CollectionEditorImportMapping, {
3426
+ importConfig,
3427
+ propertyConfigs
3428
+ }),
3429
+ currentView === "import_data_preview" && importConfig && /* @__PURE__ */ jsx(CollectionEditorImportDataPreview, {
3430
+ importConfig,
3431
+ properties: values.properties,
3432
+ propertiesOrder: values.propertiesOrder
3433
+ }),
3434
+ currentView === "import_data_saving" && importConfig && /* @__PURE__ */ jsx(ImportSaveInProgress, {
3435
+ importConfig,
3436
+ collection: values,
3437
+ path: usedPath,
3438
+ onImportSuccess: async (importedCollection) => {
3439
+ snackbarController.open({
3440
+ type: "info",
3441
+ message: "Data imported successfully"
3442
+ });
3443
+ await saveCollection(values);
3444
+ handleClose(importedCollection);
3445
+ }
3446
+ }),
3447
+ currentView === "general" && /* @__PURE__ */ jsx(GeneralSettingsForm, {
3448
+ isNewCollection,
3449
+ existingPaths,
3450
+ existingIds,
3451
+ parentCollection,
3452
+ renderExtraCollectionFields,
3453
+ standalone
3454
+ }),
3455
+ currentView === "display" && /* @__PURE__ */ jsx(DisplaySettingsForm, {
3456
+ expandKanban,
3457
+ standalone
3458
+ }),
3459
+ currentView === "rls" && getDataSourceCapabilities(values.engine).supportsRLS && /* @__PURE__ */ jsx(CollectionRLSTab, {}),
3460
+ currentView === "properties" && /* @__PURE__ */ jsx(CollectionPropertiesEditorForm, {
3461
+ showErrors: submitCount > 0,
3462
+ isNewCollection,
3463
+ onPropertyError: (propertyKey, namespace, error) => {
3464
+ propertyErrorsRef.current = removeUndefined({
3465
+ ...propertyErrorsRef.current,
3466
+ [getFullIdPath(propertyKey, namespace)]: removeUndefined(error, true)
3467
+ }, true);
3468
+ formController.validate();
3469
+ },
3470
+ getUser,
3471
+ getData: getDataWithPath,
3472
+ doCollectionInference,
3473
+ propertyConfigs,
3474
+ propertyTypePresets,
3475
+ hiddenPropertyTypes,
3476
+ renderExtraPropertyFields,
3477
+ extraIcon: extraView?.icon && /* @__PURE__ */ jsx(IconButton, {
3478
+ color: "primary",
3479
+ onClick: () => setCurrentView("extra_view"),
3480
+ children: extraView.icon
3481
+ }),
3482
+ standalone
3483
+ })
3484
+ ]
3485
+ }), (!fullScreen || isNewCollection || !!error) && /* @__PURE__ */ jsxs("div", {
3486
+ className: "shrink-0 w-full p-4 sm:px-6 sm:py-4 border-t border-surface-200 dark:border-surface-900 flex items-center justify-between gap-4 bg-surface-50 dark:bg-surface-900",
3487
+ children: [
3488
+ error && /* @__PURE__ */ jsx(ErrorView, { error }),
3489
+ isNewCollection && includeTemplates && currentView === "import_data_mapping" && /* @__PURE__ */ jsx(Button, {
3490
+ variant: "text",
3491
+ type: "button",
3492
+ onClick: () => {
3493
+ importConfig?.setInUse(false);
3494
+ return setCurrentView("welcome");
3495
+ },
3496
+ children: "Back"
3497
+ }),
3498
+ isNewCollection && includeTemplates && currentView === "import_data_preview" && /* @__PURE__ */ jsx(Button, {
3499
+ variant: "text",
3500
+ type: "button",
3501
+ onClick: () => {
3502
+ setCurrentView("import_data_mapping");
3503
+ },
3504
+ children: "Back"
3505
+ }),
3506
+ isNewCollection && includeTemplates && currentView === "general" && /* @__PURE__ */ jsx(Button, {
3507
+ variant: "text",
3508
+ type: "button",
3509
+ onClick: () => setCurrentView("welcome"),
3510
+ children: "Back"
3511
+ }),
3512
+ isNewCollection && currentView === "properties" && /* @__PURE__ */ jsxs(Button, {
3513
+ variant: "text",
3514
+ type: "button",
3515
+ color: "neutral",
3516
+ onClick: () => setCurrentView("general"),
3517
+ children: [/* @__PURE__ */ jsx(ArrowLeftIcon, {}), "Back"]
3518
+ }),
3519
+ (!fullScreen || isNewCollection) && /* @__PURE__ */ jsx(Button, {
3520
+ variant: "text",
3521
+ color: "neutral",
3522
+ onClick: () => {
3523
+ handleCancel();
3524
+ },
3525
+ children: "Cancel"
3526
+ }),
3527
+ currentView === "welcome" && /* @__PURE__ */ jsx(Button, {
3528
+ variant: "text",
3529
+ onClick: () => onWelcomeScreenContinue(),
3530
+ children: "Continue from scratch"
3531
+ }),
3532
+ isNewCollection && currentView === "import_data_mapping" && /* @__PURE__ */ jsx(Button, {
3533
+ variant: "filled",
3534
+ color: "primary",
3535
+ onClick: onImportMappingComplete,
3536
+ children: "Next"
3537
+ }),
3538
+ isNewCollection && currentView === "import_data_preview" && /* @__PURE__ */ jsx(Button, {
3539
+ variant: "filled",
3540
+ color: "primary",
3541
+ onClick: () => {
3542
+ setNextMode();
3543
+ },
3544
+ children: "Next"
3545
+ }),
3546
+ isNewCollection && (currentView === "general" || currentView === "properties") && /* @__PURE__ */ jsxs(LoadingButton, {
3547
+ variant: "filled",
3548
+ color: "primary",
3549
+ type: "submit",
3550
+ loading: isSubmitting,
3551
+ disabled: isSubmitting || currentView === "general" && !validValues || configController?.readOnly,
3552
+ startIcon: currentView === "properties" ? /* @__PURE__ */ jsx(CheckIcon, {}) : void 0,
3553
+ children: [currentView === "general" && "Next", currentView === "properties" && "Create collection"]
3554
+ }),
3555
+ !isNewCollection && !fullScreen && /* @__PURE__ */ jsx(LoadingButton, {
3556
+ variant: "filled",
3557
+ color: "primary",
3558
+ type: "submit",
3559
+ disabled: isSubmitting || configController?.readOnly,
3560
+ loading: isSubmitting,
3561
+ children: configController?.readOnly ? "Update collection (Read-only)" : "Update collection"
3562
+ })
3563
+ ]
3564
+ })]
3565
+ })] })
3566
+ }), /* @__PURE__ */ jsx(ConfirmationDialog, {
3567
+ open: deleteRequested,
3568
+ onAccept: deleteCollection,
3569
+ onCancel: () => setDeleteRequested(false),
3570
+ title: /* @__PURE__ */ jsx(Fragment, { children: "Delete the stored config?" }),
3571
+ body: /* @__PURE__ */ jsxs(Fragment, { children: [
3572
+ " This will ",
3573
+ /* @__PURE__ */ jsx("b", { children: "not delete any data" }),
3574
+ ", only the stored config, and reset to the code state."
3575
+ ] })
3576
+ })]
3577
+ });
3578
+ }
3579
+ function applyPropertyConfigs(collection, propertyConfigs) {
3580
+ const { properties, ...rest } = collection;
3581
+ const propertiesResult = {};
3582
+ if (properties) Object.keys(properties).forEach((key) => {
3583
+ const prop = properties[key];
3584
+ if (prop == null) return;
3585
+ propertiesResult[key] = applyPropertiesConfig(prop, propertyConfigs);
3586
+ });
3587
+ return {
3588
+ ...rest,
3589
+ properties: propertiesResult
3590
+ };
3591
+ }
3592
+ function applyPropertiesConfig(property, propertyConfigs) {
3593
+ let internalProperty = property;
3594
+ if (propertyConfigs && internalProperty && typeof internalProperty === "object" && internalProperty.propertyConfig) {
3595
+ const propertyConfig = propertyConfigs[internalProperty.propertyConfig];
3596
+ if (propertyConfig && isPropertyBuilder(propertyConfig.property)) internalProperty = propertyConfig.property;
3597
+ else {
3598
+ if (propertyConfig) internalProperty = mergeDeep(propertyConfig.property, internalProperty);
3599
+ if (!isPropertyBuilder(internalProperty) && internalProperty.type === "map" && internalProperty.properties) {
3600
+ const properties = {};
3601
+ Object.keys(internalProperty.properties).forEach((key) => {
3602
+ properties[key] = applyPropertiesConfig(internalProperty.properties[key], propertyConfigs);
3603
+ });
3604
+ internalProperty = {
3605
+ ...internalProperty,
3606
+ properties
3607
+ };
3608
+ }
3609
+ }
3610
+ }
3611
+ return internalProperty;
3612
+ }
3613
+ var validatePath = (value, isNewCollection, existingPaths, idValue) => {
3614
+ let error;
3615
+ if (!value) error = "You must specify a path in the database for this collection";
3616
+ if (isNewCollection && existingPaths?.includes(value.trim().toLowerCase()) && !idValue) error = "There is already a collection with the specified path. If you want to have multiple collections referring to the same database path, make sure the have different ids";
3617
+ if (removeInitialAndTrailingSlashes(value).split("/").length % 2 === 0) error = `Collection paths must have an odd number of segments: ${value}`;
3618
+ return error;
3619
+ };
3620
+ var validateId = (value, isNewCollection, existingPaths, existingIds) => {
3621
+ if (!value) return void 0;
3622
+ let error;
3623
+ if (isNewCollection && existingPaths?.includes(value.trim().toLowerCase())) error = "There is already a collection that uses this value as a path";
3624
+ if (isNewCollection && existingIds?.includes(value.trim().toLowerCase())) error = "There is already a collection which uses this id";
3625
+ return error;
3626
+ };
3627
+ //#endregion
3628
+ export { CollectionEditorDialog as n, CollectionEditorDialog_exports as r, CollectionEditor as t };
3629
+
3630
+ //# sourceMappingURL=CollectionEditorDialog-DKGlYDPc.js.map