@firecms/core 3.0.0 → 3.1.0-canary.02232f4

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 (340) hide show
  1. package/README.md +1 -1
  2. package/dist/components/AIIcon.d.ts +16 -0
  3. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +7 -1
  4. package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
  5. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +14 -0
  6. package/dist/components/EntityCollectionTable/PropertyTableCell.d.ts +6 -0
  7. package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -4
  8. package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +6 -0
  9. package/dist/components/EntityCollectionTable/internal/popup_field/useDraggable.d.ts +2 -2
  10. package/dist/components/EntityCollectionView/Board.d.ts +2 -0
  11. package/dist/components/EntityCollectionView/BoardColumn.d.ts +42 -0
  12. package/dist/components/EntityCollectionView/BoardColumnTitle.d.ts +9 -0
  13. package/dist/components/EntityCollectionView/BoardSortableList.d.ts +14 -0
  14. package/dist/components/EntityCollectionView/CollectionDataErrorBanner.d.ts +4 -0
  15. package/dist/components/EntityCollectionView/EntityBoardCard.d.ts +26 -0
  16. package/dist/components/EntityCollectionView/EntityCard.d.ts +19 -0
  17. package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +20 -0
  18. package/dist/components/EntityCollectionView/EntityCollectionCardView.d.ts +31 -0
  19. package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +2 -2
  20. package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +7 -3
  21. package/dist/components/EntityCollectionView/FiltersDialog.d.ts +14 -0
  22. package/dist/components/EntityCollectionView/ViewModeToggle.d.ts +44 -0
  23. package/dist/components/EntityCollectionView/board_types.d.ts +105 -0
  24. package/dist/components/EntityCollectionView/useBoardDataController.d.ts +60 -0
  25. package/dist/components/ErrorBoundary.d.ts +4 -2
  26. package/dist/components/HomePage/DefaultHomePage.d.ts +0 -1
  27. package/dist/components/LanguageToggle.d.ts +1 -0
  28. package/dist/components/SelectableTable/SelectableTable.d.ts +5 -1
  29. package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -1
  30. package/dist/components/UnsavedChangesDialog.d.ts +1 -0
  31. package/dist/components/VirtualTable/VirtualTable.performance.test.d.ts +1 -0
  32. package/dist/components/VirtualTable/VirtualTableCell.d.ts +6 -0
  33. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +4 -1
  34. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  35. package/dist/components/VirtualTable/VirtualTableProps.d.ts +17 -1
  36. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
  37. package/dist/components/VirtualTable/types.d.ts +3 -0
  38. package/dist/components/index.d.ts +4 -0
  39. package/dist/contexts/index.d.ts +10 -0
  40. package/dist/core/DrawerNavigationGroup.d.ts +45 -0
  41. package/dist/core/index.d.ts +1 -0
  42. package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
  43. package/dist/editor/components/editor-bubble-item.d.ts +8 -0
  44. package/dist/editor/components/editor-bubble.d.ts +8 -0
  45. package/dist/editor/components/image-bubble.d.ts +5 -0
  46. package/dist/editor/components/index.d.ts +16 -0
  47. package/dist/editor/components/table-bubble.d.ts +5 -0
  48. package/dist/editor/editor.d.ts +30 -0
  49. package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
  50. package/dist/editor/extensions/Image/index.d.ts +6 -0
  51. package/dist/editor/extensions/Image.d.ts +6 -0
  52. package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
  53. package/dist/editor/extensions/clipboard.d.ts +7 -0
  54. package/dist/editor/extensions/custom-keymap.d.ts +1 -0
  55. package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
  56. package/dist/editor/hooks/useProseMirror.d.ts +13 -0
  57. package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
  58. package/dist/editor/index.d.ts +2 -0
  59. package/dist/editor/markdown.d.ts +5 -0
  60. package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
  61. package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
  62. package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
  63. package/dist/editor/nodeViews/index.d.ts +6 -0
  64. package/dist/editor/plugins/index.d.ts +2 -0
  65. package/dist/editor/plugins/inputrules.d.ts +6 -0
  66. package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
  67. package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
  68. package/dist/editor/schema.d.ts +2 -0
  69. package/dist/editor/selectors/ai-selector.d.ts +0 -0
  70. package/dist/editor/selectors/color-selector.d.ts +10 -0
  71. package/dist/editor/selectors/link-selector.d.ts +8 -0
  72. package/dist/editor/selectors/node-selector.d.ts +15 -0
  73. package/dist/editor/selectors/text-buttons.d.ts +1 -0
  74. package/dist/editor/types.d.ts +5 -0
  75. package/dist/editor/useProseMirror.d.ts +16 -0
  76. package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
  77. package/dist/editor/utils/remove_classes.d.ts +1 -0
  78. package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
  79. package/dist/form/components/ErrorFocus.d.ts +1 -1
  80. package/dist/form/components/LocalChangesMenu.d.ts +2 -2
  81. package/dist/form/components/StorageUploadProgress.d.ts +1 -1
  82. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  83. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  84. package/dist/form/validation.d.ts +3 -2
  85. package/dist/hooks/index.d.ts +1 -0
  86. package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
  87. package/dist/hooks/useBuildNavigationController.d.ts +0 -1
  88. package/dist/hooks/useCollapsedGroups.d.ts +6 -3
  89. package/dist/hooks/useTranslation.d.ts +17 -0
  90. package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
  91. package/dist/index.d.ts +5 -0
  92. package/dist/index.es.js +31028 -16080
  93. package/dist/index.es.js.map +1 -1
  94. package/dist/index.umd.js +29955 -15028
  95. package/dist/index.umd.js.map +1 -1
  96. package/dist/internal/useRestoreScroll.d.ts +1 -1
  97. package/dist/locales/de.d.ts +2 -0
  98. package/dist/locales/en.d.ts +10 -0
  99. package/dist/locales/es.d.ts +10 -0
  100. package/dist/locales/fr.d.ts +2 -0
  101. package/dist/locales/hi.d.ts +2 -0
  102. package/dist/locales/it.d.ts +2 -0
  103. package/dist/locales/pt.d.ts +7 -0
  104. package/dist/preview/PropertyPreviewProps.d.ts +5 -0
  105. package/dist/preview/components/DatePreview.d.ts +13 -3
  106. package/dist/preview/components/ImagePreview.d.ts +5 -1
  107. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  108. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  109. package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
  110. package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
  111. package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
  112. package/dist/types/analytics.d.ts +1 -1
  113. package/dist/types/collections.d.ts +88 -2
  114. package/dist/types/customization_controller.d.ts +2 -1
  115. package/dist/types/datasource.d.ts +0 -1
  116. package/dist/types/entities.d.ts +1 -0
  117. package/dist/types/firecms.d.ts +2 -1
  118. package/dist/types/index.d.ts +1 -0
  119. package/dist/types/navigation.d.ts +2 -2
  120. package/dist/types/plugins.d.ts +69 -1
  121. package/dist/types/properties.d.ts +277 -12
  122. package/dist/types/storage.d.ts +9 -0
  123. package/dist/types/translations.d.ts +669 -0
  124. package/dist/util/__tests__/conditions.test.d.ts +1 -0
  125. package/dist/util/__tests__/objects.test.d.ts +1 -0
  126. package/dist/util/conditions.d.ts +26 -0
  127. package/dist/util/entities.d.ts +2 -3
  128. package/dist/util/index.d.ts +3 -1
  129. package/dist/util/lazy_eager.d.ts +7 -0
  130. package/dist/util/objects.d.ts +1 -0
  131. package/dist/util/property_utils.d.ts +2 -1
  132. package/dist/util/resolutions.d.ts +3 -3
  133. package/dist/util/useStorageUploadController.d.ts +11 -2
  134. package/package.json +52 -12
  135. package/src/app/Scaffold.tsx +20 -19
  136. package/src/components/AIIcon.tsx +41 -0
  137. package/src/components/ArrayContainer.tsx +7 -8
  138. package/src/components/ClearFilterSortButton.tsx +25 -19
  139. package/src/components/ConfirmationDialog.tsx +4 -4
  140. package/src/components/DeleteEntityDialog.tsx +12 -11
  141. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +82 -43
  142. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
  143. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
  144. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
  145. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
  146. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +24 -44
  147. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
  148. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
  149. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
  150. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
  151. package/src/components/EntityCollectionView/Board.tsx +324 -0
  152. package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
  153. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
  154. package/src/components/EntityCollectionView/BoardSortableList.tsx +174 -0
  155. package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
  156. package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
  157. package/src/components/EntityCollectionView/EntityCard.tsx +235 -0
  158. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +706 -0
  159. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +236 -0
  160. package/src/components/EntityCollectionView/EntityCollectionView.tsx +531 -209
  161. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +35 -22
  162. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +86 -15
  163. package/src/components/EntityCollectionView/FiltersDialog.tsx +252 -0
  164. package/src/components/EntityCollectionView/ViewModeToggle.tsx +202 -0
  165. package/src/components/EntityCollectionView/board_types.ts +113 -0
  166. package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
  167. package/src/components/EntityJsonPreview.tsx +2 -1
  168. package/src/components/EntityPreview.tsx +1 -1
  169. package/src/components/EntityView.tsx +3 -2
  170. package/src/components/ErrorBoundary.tsx +27 -15
  171. package/src/components/ErrorTooltip.tsx +2 -1
  172. package/src/components/HomePage/DefaultHomePage.tsx +65 -22
  173. package/src/components/HomePage/HomePageDnD.tsx +59 -42
  174. package/src/components/HomePage/NavigationCard.tsx +20 -18
  175. package/src/components/HomePage/NavigationGroup.tsx +20 -17
  176. package/src/components/HomePage/RenameGroupDialog.tsx +15 -15
  177. package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
  178. package/src/components/LanguageToggle.tsx +66 -0
  179. package/src/components/NotFoundPage.tsx +5 -3
  180. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +12 -17
  181. package/src/components/ReferenceWidget.tsx +5 -6
  182. package/src/components/SearchIconsView.tsx +3 -1
  183. package/src/components/SelectableTable/SelectableTable.tsx +75 -67
  184. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
  185. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +50 -40
  186. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +53 -40
  187. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +60 -58
  188. package/src/components/UnsavedChangesDialog.tsx +6 -6
  189. package/src/components/UserDisplay.tsx +4 -4
  190. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +387 -0
  191. package/src/components/VirtualTable/VirtualTable.tsx +277 -121
  192. package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
  193. package/src/components/VirtualTable/VirtualTableHeader.tsx +76 -64
  194. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +163 -42
  195. package/src/components/VirtualTable/VirtualTableProps.tsx +21 -2
  196. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  197. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
  198. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +19 -6
  199. package/src/components/VirtualTable/types.tsx +3 -0
  200. package/src/components/common/default_entity_actions.tsx +4 -0
  201. package/src/components/common/useColumnsIds.tsx +95 -3
  202. package/src/components/common/useDataSourceTableController.tsx +12 -4
  203. package/src/components/index.tsx +5 -0
  204. package/src/contexts/BreacrumbsContext.tsx +15 -8
  205. package/src/contexts/index.ts +10 -0
  206. package/src/core/DefaultAppBar.tsx +49 -32
  207. package/src/core/DefaultDrawer.tsx +49 -57
  208. package/src/core/DrawerNavigationGroup.tsx +120 -0
  209. package/src/core/DrawerNavigationItem.tsx +4 -3
  210. package/src/core/EntityEditView.tsx +94 -50
  211. package/src/core/EntityEditViewFormActions.tsx +24 -17
  212. package/src/core/EntitySidePanel.tsx +34 -30
  213. package/src/core/FireCMS.tsx +33 -6
  214. package/src/core/SideDialogs.tsx +4 -2
  215. package/src/core/field_configs.tsx +18 -11
  216. package/src/core/index.tsx +1 -0
  217. package/src/editor/components/SlashCommandMenu.tsx +516 -0
  218. package/src/editor/components/editor-bubble-item.tsx +32 -0
  219. package/src/editor/components/editor-bubble.tsx +118 -0
  220. package/src/editor/components/image-bubble.tsx +156 -0
  221. package/src/editor/components/index.ts +14 -0
  222. package/src/editor/components/table-bubble.tsx +165 -0
  223. package/src/editor/editor.tsx +455 -0
  224. package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
  225. package/src/editor/extensions/Image/index.ts +133 -0
  226. package/src/editor/extensions/Image.ts +159 -0
  227. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
  228. package/src/editor/extensions/clipboard.ts +72 -0
  229. package/src/editor/extensions/custom-keymap.ts +24 -0
  230. package/src/editor/extensions/drag-and-drop.tsx +480 -0
  231. package/src/editor/hooks/useProseMirror.ts +124 -0
  232. package/src/editor/hooks/useProseMirrorContext.ts +15 -0
  233. package/src/editor/index.ts +2 -0
  234. package/src/editor/markdown.ts +172 -0
  235. package/src/editor/nodeViews/ImageComponent.tsx +20 -0
  236. package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
  237. package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
  238. package/src/editor/nodeViews/index.ts +35 -0
  239. package/src/editor/plugins/index.ts +58 -0
  240. package/src/editor/plugins/inputrules.ts +82 -0
  241. package/src/editor/plugins/placeholderPlugin.ts +55 -0
  242. package/src/editor/plugins/slashCommandPlugin.ts +61 -0
  243. package/src/editor/schema.ts +240 -0
  244. package/src/editor/selectors/ai-selector.tsx +111 -0
  245. package/src/editor/selectors/color-selector.tsx +200 -0
  246. package/src/editor/selectors/link-selector.tsx +118 -0
  247. package/src/editor/selectors/node-selector.tsx +157 -0
  248. package/src/editor/selectors/text-buttons.tsx +86 -0
  249. package/src/editor/types.ts +6 -0
  250. package/src/editor/useProseMirror.ts +126 -0
  251. package/src/editor/utils/prosemirror-utils.ts +108 -0
  252. package/src/editor/utils/remove_classes.ts +17 -0
  253. package/src/editor/utils/useDebouncedCallback.ts +25 -0
  254. package/src/form/EntityForm.tsx +150 -75
  255. package/src/form/EntityFormActions.tsx +19 -12
  256. package/src/form/PropertyFieldBinding.tsx +68 -51
  257. package/src/form/components/ErrorFocus.tsx +3 -3
  258. package/src/form/components/LocalChangesMenu.tsx +19 -19
  259. package/src/form/components/StorageItemPreview.tsx +5 -3
  260. package/src/form/components/StorageUploadProgress.tsx +22 -6
  261. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
  262. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +22 -10
  263. package/src/form/field_bindings/BlockFieldBinding.tsx +26 -9
  264. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -17
  265. package/src/form/field_bindings/KeyValueFieldBinding.tsx +46 -25
  266. package/src/form/field_bindings/MapFieldBinding.tsx +88 -70
  267. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +93 -52
  268. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
  269. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
  270. package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
  271. package/src/form/field_bindings/RepeatFieldBinding.tsx +21 -6
  272. package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
  273. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +110 -92
  274. package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
  275. package/src/form/field_bindings/TextFieldBinding.tsx +77 -38
  276. package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
  277. package/src/form/validation.ts +245 -160
  278. package/src/hooks/index.tsx +1 -0
  279. package/src/hooks/useBreadcrumbsController.tsx +18 -0
  280. package/src/hooks/useBuildNavigationController.tsx +91 -41
  281. package/src/hooks/useCollapsedGroups.ts +18 -9
  282. package/src/hooks/useTranslation.ts +31 -0
  283. package/src/hooks/useValidateAuthenticator.tsx +1 -1
  284. package/src/i18n/FireCMSi18nProvider.tsx +160 -0
  285. package/src/index.ts +5 -0
  286. package/src/internal/useBuildDataSource.ts +68 -34
  287. package/src/internal/useBuildSideDialogsController.tsx +11 -8
  288. package/src/internal/useBuildSideEntityController.tsx +24 -24
  289. package/src/internal/useRestoreScroll.tsx +26 -14
  290. package/src/locales/de.ts +718 -0
  291. package/src/locales/en.ts +730 -0
  292. package/src/locales/es.ts +730 -0
  293. package/src/locales/fr.ts +718 -0
  294. package/src/locales/hi.ts +718 -0
  295. package/src/locales/it.ts +718 -0
  296. package/src/locales/pt.ts +727 -0
  297. package/src/preview/PropertyPreview.tsx +43 -33
  298. package/src/preview/PropertyPreviewProps.tsx +6 -0
  299. package/src/preview/components/DatePreview.tsx +72 -4
  300. package/src/preview/components/EmptyValue.tsx +1 -1
  301. package/src/preview/components/ImagePreview.tsx +37 -21
  302. package/src/preview/components/ReferencePreview.tsx +8 -2
  303. package/src/preview/components/StorageThumbnail.tsx +16 -12
  304. package/src/preview/components/UrlComponentPreview.tsx +32 -27
  305. package/src/preview/components/UserPreview.tsx +3 -1
  306. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
  307. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
  308. package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
  309. package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
  310. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
  311. package/src/routes/CustomCMSRoute.tsx +1 -0
  312. package/src/routes/FireCMSRoute.tsx +87 -65
  313. package/src/types/analytics.ts +10 -0
  314. package/src/types/collections.ts +97 -3
  315. package/src/types/customization_controller.tsx +2 -1
  316. package/src/types/datasource.ts +54 -56
  317. package/src/types/entities.ts +10 -0
  318. package/src/types/firecms.tsx +2 -1
  319. package/src/types/index.ts +1 -0
  320. package/src/types/navigation.ts +2 -2
  321. package/src/types/plugins.tsx +77 -1
  322. package/src/types/properties.ts +369 -37
  323. package/src/types/storage.ts +11 -1
  324. package/src/types/translations.ts +752 -0
  325. package/src/util/__tests__/conditions.test.ts +506 -0
  326. package/src/util/__tests__/objects.test.ts +196 -0
  327. package/src/util/callbacks.ts +6 -3
  328. package/src/util/collections.ts +51 -6
  329. package/src/util/conditions.ts +339 -0
  330. package/src/util/entities.ts +29 -30
  331. package/src/util/entity_cache.ts +2 -1
  332. package/src/util/index.ts +3 -1
  333. package/src/util/join_collections.ts +10 -8
  334. package/src/util/lazy_eager.tsx +33 -0
  335. package/src/util/objects.ts +46 -13
  336. package/src/util/{references.ts → previews.ts} +16 -2
  337. package/src/util/property_utils.tsx +37 -11
  338. package/src/util/resolutions.ts +62 -58
  339. package/src/util/useStorageUploadController.tsx +34 -30
  340. /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
@@ -40,7 +40,10 @@ import {
40
40
  useSnackbarController
41
41
  } from "../hooks";
42
42
  import { Alert, CheckIcon, Chip, cls, EditIcon, NotesIcon, paperMixin, Tooltip, Typography } from "@firecms/ui";
43
- import { Formex, FormexController, getIn, setIn, useCreateFormex } from "@firecms/formex";
43
+ import { Formex, FormexController, getIn, setIn, useCreateFormex,
44
+ useFormex
45
+ } from "@firecms/formex";
46
+ import { useTranslation } from "../hooks";
44
47
  import { useAnalyticsController } from "../hooks/useAnalyticsController";
45
48
  import { FormEntry, FormLayout, LabelWithIconAndTooltip, PropertyFieldBinding } from "../form";
46
49
  import { ValidationError } from "yup";
@@ -122,6 +125,35 @@ export function extractTouchedValues(values: any, touched: Record<string, boolea
122
125
  return acc;
123
126
  }
124
127
 
128
+ /**
129
+ * Recursively removes empty plain objects `{}` and empty arrays `[]` from a value tree.
130
+ * This prevents ghost containers created by `setIn` intermediate path construction
131
+ * (e.g. `{ address: {} }` when only `address.city` was touched but value is undefined)
132
+ * from falsely triggering the unsaved local changes indicator.
133
+ */
134
+ function removeEmptyContainers(obj: any): any {
135
+ if (Array.isArray(obj)) {
136
+ const cleaned = obj.map(removeEmptyContainers);
137
+ // Keep arrays even if they contain only nulls/undefined — that's intentional data
138
+ return cleaned;
139
+ }
140
+ if (obj && typeof obj === "object" && Object.getPrototypeOf(obj) === Object.prototype) {
141
+ const result: Record<string, any> = {};
142
+ for (const key of Object.keys(obj)) {
143
+ const cleaned = removeEmptyContainers(obj[key]);
144
+ // Skip empty plain objects
145
+ if (cleaned && typeof cleaned === "object" && !Array.isArray(cleaned)
146
+ && Object.getPrototypeOf(cleaned) === Object.prototype
147
+ && Object.keys(cleaned).length === 0) {
148
+ continue;
149
+ }
150
+ result[key] = cleaned;
151
+ }
152
+ return result;
153
+ }
154
+ return obj;
155
+ }
156
+
125
157
  export function getChanges<T extends object>(source: Partial<T>, comparison: Partial<T>): Partial<T> {
126
158
  const changes: Partial<T> = {};
127
159
 
@@ -181,30 +213,30 @@ export function getChanges<T extends object>(source: Partial<T>, comparison: Par
181
213
  }
182
214
 
183
215
  export function EntityForm<M extends Record<string, any>>({
184
- path,
185
- fullIdPath,
186
- entityId: entityIdProp,
187
- collection,
188
- onValuesModified,
189
- onIdChange,
190
- onSaved,
191
- entity,
192
- initialDirtyValues,
193
- onFormContextReady,
194
- forceActionsAtTheBottom,
195
- initialStatus,
196
- className,
197
- onStatusChange,
198
- onEntityChange,
199
- openEntityMode = "full_screen",
200
- formex: formexProp,
201
- disabled: disabledProp,
202
- Builder,
203
- EntityFormActionsComponent = EntityFormActions,
204
- showDefaultActions = true,
205
- showEntityPath = true,
206
- children
207
- }: EntityFormProps<M>) {
216
+ path,
217
+ fullIdPath,
218
+ entityId: entityIdProp,
219
+ collection,
220
+ onValuesModified,
221
+ onIdChange,
222
+ onSaved,
223
+ entity,
224
+ initialDirtyValues,
225
+ onFormContextReady,
226
+ forceActionsAtTheBottom,
227
+ initialStatus,
228
+ className,
229
+ onStatusChange,
230
+ onEntityChange,
231
+ openEntityMode = "full_screen",
232
+ formex: formexProp,
233
+ disabled: disabledProp,
234
+ Builder,
235
+ EntityFormActionsComponent = EntityFormActions,
236
+ showDefaultActions = true,
237
+ showEntityPath = true,
238
+ children
239
+ }: EntityFormProps<M>) {
208
240
 
209
241
  if (collection.customId && collection.formAutoSave) {
210
242
  console.warn(`The collection ${collection.path} has customId and formAutoSave enabled. This is not supported and formAutoSave will be ignored`);
@@ -212,6 +244,7 @@ export function EntityForm<M extends Record<string, any>>({
212
244
 
213
245
  const sideEntityController = useSideEntityController();
214
246
  const navigationController = useNavigationController();
247
+ const { t } = useTranslation();
215
248
 
216
249
  const navigateBack = useCallback(() => {
217
250
  if (openEntityMode === "side_panel") {
@@ -247,7 +280,7 @@ export function EntityForm<M extends Record<string, any>>({
247
280
  const context = useFireCMSContext();
248
281
  const analyticsController = useAnalyticsController();
249
282
 
250
- const [underlyingChanges] = useState<Partial<EntityValues<M>>>({});
283
+ const [underlyingChanges, setUnderlyingChanges] = useState<Partial<EntityValues<M>>>({});
251
284
 
252
285
  const [customIdLoading, setCustomIdLoading] = useState<boolean>(false);
253
286
 
@@ -328,14 +361,15 @@ export function EntityForm<M extends Record<string, any>>({
328
361
  return [initialValues, initialDirty];
329
362
  }, [autoApplyLocalChanges, localChangesDataRaw, baseInitialValues, initialDirtyValues]);
330
363
 
331
- const localChangesData = useMemo(() => {
332
- if (!localChangesDataRaw) {
333
- return undefined;
364
+ const hasLocalChanges = useMemo(() => {
365
+ if (localChangesCleared || !localChangesDataRaw || Object.keys(localChangesDataRaw).length === 0) {
366
+ return false;
334
367
  }
335
- return getChanges(localChangesDataRaw, initialValues);
336
- }, [localChangesDataRaw, initialValues]);
337
-
338
- const hasLocalChanges = !localChangesCleared && localChangesData && Object.keys(localChangesData).length > 0;
368
+ // Compare cached values against entity values to check for real differences
369
+ const entityValues = entity?.values ?? {};
370
+ const realChanges = getChanges(localChangesDataRaw as Partial<M>, entityValues as Partial<M>);
371
+ return Object.keys(realChanges).length > 0;
372
+ }, [localChangesCleared, localChangesDataRaw, entity?.values]);
339
373
 
340
374
  const formex: FormexController<M> = formexProp ?? useCreateFormex<M>({
341
375
  initialValues: initialValues as M,
@@ -355,8 +389,10 @@ export function EntityForm<M extends Record<string, any>>({
355
389
  onValuesChangeDeferred: (values: M, controller: FormexController<M>) => {
356
390
  const key = (status === "new" || status === "copy") ? path + "#new" : path + "/" + entityId;
357
391
  if (controller.dirty) {
358
- const touchedValues = extractTouchedValues(values, controller.touched);
359
- saveEntityToCache(key, touchedValues);
392
+ const touchedValues = removeEmptyContainers(extractTouchedValues(values, controller.touched));
393
+ if (touchedValues && Object.keys(touchedValues).length > 0) {
394
+ saveEntityToCache(key, touchedValues);
395
+ }
360
396
  }
361
397
  },
362
398
  validation: (values) => {
@@ -373,6 +409,15 @@ export function EntityForm<M extends Record<string, any>>({
373
409
  useEffect(() => {
374
410
 
375
411
  const handleKeyDown = (e: KeyboardEvent) => {
412
+ if (e.defaultPrevented) return;
413
+ const activeElement = document.activeElement as HTMLElement;
414
+ const isInput = activeElement && (
415
+ activeElement.tagName === "INPUT" ||
416
+ activeElement.tagName === "TEXTAREA" ||
417
+ activeElement.isContentEditable
418
+ );
419
+ if (isInput) return;
420
+
376
421
  const isUndo = (e.metaKey || e.ctrlKey) && !e.shiftKey && e.key.toLowerCase() === "z";
377
422
  const isRedo =
378
423
  ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === "z") ||
@@ -462,12 +507,12 @@ export function EntityForm<M extends Record<string, any>>({
462
507
  }, [entityId, path, snackbarController]);
463
508
 
464
509
  const saveEntity = ({
465
- values,
466
- previousValues,
467
- entityId,
468
- collection,
469
- path
470
- }: {
510
+ values,
511
+ previousValues,
512
+ entityId,
513
+ collection,
514
+ path
515
+ }: {
471
516
  collection: EntityCollection<M>,
472
517
  path: string,
473
518
  entityId: string | undefined,
@@ -500,13 +545,13 @@ export function EntityForm<M extends Record<string, any>>({
500
545
  };
501
546
 
502
547
  const onSaveEntityRequest = async ({
503
- collection,
504
- path,
505
- entityId,
506
- values,
507
- previousValues,
508
- autoSave
509
- }: EntityFormSaveParams<M>): Promise<void> => {
548
+ collection,
549
+ path,
550
+ entityId,
551
+ values,
552
+ previousValues,
553
+ autoSave
554
+ }: EntityFormSaveParams<M>): Promise<void> => {
510
555
  if (!status)
511
556
  return;
512
557
  if (autoSave) {
@@ -574,6 +619,7 @@ export function EntityForm<M extends Record<string, any>>({
574
619
  }, [snackbarController]);
575
620
 
576
621
  const pluginActions: React.ReactNode[] = [];
622
+ const pluginBeforeTitle: React.ReactNode[] = [];
577
623
  const plugins = customizationController.plugins;
578
624
 
579
625
  const actionsDisabled = disabled || formex.isSubmitting || (status === "existing" && !formex.dirty) || Boolean(disabledProp);
@@ -597,6 +643,12 @@ export function EntityForm<M extends Record<string, any>>({
597
643
  key={`actions_${plugin.key}`} {...actionProps} />
598
644
  : null
599
645
  )).filter(Boolean));
646
+ pluginBeforeTitle.push(...plugins.map((plugin) => (
647
+ plugin.form?.BeforeTitle
648
+ ? <plugin.form.BeforeTitle
649
+ key={`before_title_${plugin.key}`} {...actionProps} />
650
+ : null
651
+ )).filter(Boolean));
600
652
  }
601
653
 
602
654
  const titlePropertyKey = getEntityTitlePropertyKey(resolvedCollection, customizationController.propertyConfigs);
@@ -638,21 +690,42 @@ export function EntityForm<M extends Record<string, any>>({
638
690
  const modified = formex.dirty;
639
691
 
640
692
  const uniqueFieldValidator: CustomFieldValidator = useCallback(({
641
- name,
642
- value
643
- }) => dataSource.checkUniqueField(path, name, value, entityId, collection),
693
+ name,
694
+ value
695
+ }) => dataSource.checkUniqueField(path, name, value, entityId, collection),
644
696
  [dataSource, path, entityId]);
645
697
 
646
698
  const validationSchema = useMemo(() => entityId
647
- ? getYupEntitySchema(
648
- entityId,
649
- resolvedCollection.properties,
650
- uniqueFieldValidator)
651
- : undefined,
699
+ ? getYupEntitySchema(
700
+ entityId,
701
+ resolvedCollection.properties,
702
+ uniqueFieldValidator)
703
+ : undefined,
652
704
  [entityId, resolvedCollection.properties, uniqueFieldValidator]);
653
705
 
654
706
  useOnAutoSave(autoSave, formex, lastSavedValues, save);
655
707
 
708
+ // Detect external changes to the entity (e.g. from onSnapshot after Admin SDK writes)
709
+ const prevEntityValuesRef = useRef<EntityValues<M> | undefined>(entity?.values);
710
+ useEffect(() => {
711
+ if (!entity?.values || status !== "existing") return;
712
+ const prev = prevEntityValuesRef.current;
713
+ prevEntityValuesRef.current = entity.values;
714
+ if (prev && !equal(prev, entity.values)) {
715
+ // Compute the diff between the old and new entity values
716
+ const changes: Partial<EntityValues<M>> = {};
717
+ const allKeys = new Set([...Object.keys(prev), ...Object.keys(entity.values)]);
718
+ for (const key of allKeys) {
719
+ if (!equal((prev as any)[key], (entity.values as any)[key])) {
720
+ (changes as any)[key] = (entity.values as any)[key];
721
+ }
722
+ }
723
+ if (Object.keys(changes).length > 0) {
724
+ setUnderlyingChanges(changes);
725
+ }
726
+ }
727
+ }, [entity?.values, status]);
728
+
656
729
  useEffect(() => {
657
730
  if (!autoSave && !formex.isSubmitting && underlyingChanges && entity) {
658
731
  // we update the form fields from the Firestore data
@@ -706,8 +779,8 @@ export function EntityForm<M extends Record<string, any>>({
706
779
 
707
780
  return (
708
781
  <FormEntry propertyKey={key}
709
- widthPercentage={widthPercentage}
710
- key={`field_${key}`}>
782
+ widthPercentage={widthPercentage}
783
+ key={`field_${key}`}>
711
784
  <PropertyFieldBinding {...cmsFormFieldProps} />
712
785
  </FormEntry>
713
786
  );
@@ -720,7 +793,7 @@ export function EntityForm<M extends Record<string, any>>({
720
793
  throw new Error("When using additional fields you need to provide a Builder or a value");
721
794
  }
722
795
  const child = Builder
723
- ? <Builder entity={entity} context={context}/>
796
+ ? <Builder entity={entity} context={context} />
724
797
  : <div className={"w-full"}>
725
798
  {additionalField.value?.({
726
799
  entity,
@@ -732,9 +805,9 @@ export function EntityForm<M extends Record<string, any>>({
732
805
  <div key={`additional_${key}`} className={"w-full"}>
733
806
  <LabelWithIconAndTooltip
734
807
  propertyKey={key}
735
- icon={<NotesIcon size={"small"}/>}
808
+ icon={<NotesIcon size={"small"} />}
736
809
  title={additionalField.name}
737
- className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"}/>
810
+ className={"text-text-secondary dark:text-text-secondary-dark ml-3.5"} />
738
811
  <div
739
812
  className={cls(paperMixin, "w-full min-h-14 p-4 md:p-6 overflow-x-scroll no-scrollbar")}>
740
813
  <ErrorBoundary>
@@ -756,6 +829,8 @@ export function EntityForm<M extends Record<string, any>>({
756
829
 
757
830
  const formView = <ErrorBoundary>
758
831
  <>
832
+ {pluginBeforeTitle}
833
+
759
834
  {!Builder && <div className={"w-full py-2 flex flex-col items-start my-4 lg:my-6"}>
760
835
  <Typography
761
836
  className={"my-4 flex-grow line-clamp-1 " + (collection.hideIdFromForm ? "mb-6" : "")}
@@ -765,7 +840,7 @@ export function EntityForm<M extends Record<string, any>>({
765
840
 
766
841
  {!entity?.values && initialStatus === "existing" &&
767
842
  <Alert color={"warning"} size={"small"} outerClassName={"w-full mb-4 text-xs"}>
768
- This entity does not exist in the database
843
+ {t("this_entity_not_exist")}
769
844
  </Alert>}
770
845
 
771
846
  {showEntityPath && <Alert color={"base"} outerClassName={"w-full"} size={"small"}>
@@ -779,27 +854,27 @@ export function EntityForm<M extends Record<string, any>>({
779
854
  {children}
780
855
 
781
856
  {initialEntityId && !entity && initialStatus !== "new" && <Alert color={"info"} size={"small"}>
782
- This entity does not exist in the database
857
+ {t("this_entity_not_exist")}
783
858
  </Alert>}
784
859
 
785
860
  {!Builder && !collection.hideIdFromForm &&
786
861
  <CustomIdField customId={collection.customId}
787
- entityId={entityId}
788
- status={status}
789
- onChange={setEntityId}
790
- error={entityIdError}
791
- loading={customIdLoading}
792
- entity={entity}/>
862
+ entityId={entityId}
863
+ status={status}
864
+ onChange={setEntityId}
865
+ error={entityIdError}
866
+ loading={customIdLoading}
867
+ entity={entity} />
793
868
  }
794
869
 
795
870
  {entityId && formContext && <>
796
871
  <div className="mt-12 flex flex-col gap-8" ref={formRef}>
797
872
  {formFields()}
798
- <ErrorFocus containerRef={formRef}/>
873
+ <ErrorFocus containerRef={formRef} />
799
874
  </div>
800
875
  </>}
801
876
 
802
- {forceActionsAtTheBottom && <div className="h-16"/>}
877
+ {forceActionsAtTheBottom && <div className="h-16" />}
803
878
  </>
804
879
  </ErrorBoundary>;
805
880
 
@@ -851,7 +926,7 @@ export function EntityForm<M extends Record<string, any>>({
851
926
  <LocalChangesMenu
852
927
  cacheKey={status === "new" || status === "copy" ? path + "#new" : path + "/" + entityId}
853
928
  properties={resolvedCollection.properties}
854
- localChangesData={localChangesData as Partial<M>}
929
+ cachedData={localChangesDataRaw as Partial<M>}
855
930
  formex={formex}
856
931
  onClearLocalChanges={() => setLocalChangesCleared(true)}
857
932
  />}
@@ -859,12 +934,12 @@ export function EntityForm<M extends Record<string, any>>({
859
934
  {formex.dirty
860
935
  ? <Tooltip title={"This form has been modified"}>
861
936
  <Chip size={"small"} className={"py-1"} colorScheme={"orangeDarker"}>
862
- <EditIcon size={"smallest"}/>
937
+ <EditIcon size={"smallest"} />
863
938
  </Chip>
864
939
  </Tooltip>
865
940
  : <Tooltip title={"The current form is in sync with the database"}>
866
- <Chip size={"small"} className={"py-1"} >
867
- <CheckIcon size={"smallest"}/>
941
+ <Chip size={"small"} className={"py-1"}>
942
+ <CheckIcon size={"smallest"} />
868
943
  </Chip>
869
944
  </Tooltip>}
870
945
  </div>
@@ -19,6 +19,7 @@ import {
19
19
  } from "@firecms/ui";
20
20
  import { FormexController } from "@firecms/formex";
21
21
  import { useFireCMSContext, useSideEntityController } from "../hooks";
22
+ import { useTranslation } from "../hooks/useTranslation";
22
23
 
23
24
  export interface EntityFormActionsProps {
24
25
  fullPath: string;
@@ -56,6 +57,7 @@ export function EntityFormActions({
56
57
 
57
58
  const context = useFireCMSContext();
58
59
  const sideEntityController = useSideEntityController();
60
+ const { t } = useTranslation();
59
61
 
60
62
  return layout === "bottom"
61
63
  ? buildBottomActions({
@@ -72,7 +74,8 @@ export function EntityFormActions({
72
74
  openEntityMode,
73
75
  navigateBack,
74
76
  formContext,
75
- formex
77
+ formex,
78
+ t
76
79
  })
77
80
  : buildSideActions({
78
81
  fullPath,
@@ -88,7 +91,8 @@ export function EntityFormActions({
88
91
  openEntityMode,
89
92
  navigateBack,
90
93
  formContext,
91
- formex
94
+ formex,
95
+ t
92
96
  });
93
97
  }
94
98
 
@@ -108,6 +112,7 @@ type ActionsViewProps<M extends object> = {
108
112
  navigateBack: () => void;
109
113
  formContext: FormContext,
110
114
  formex: FormexController<any>;
115
+ t: (key: any, vars?: Record<string, string>) => string;
111
116
  };
112
117
 
113
118
  function buildBottomActions<M extends object>({
@@ -125,7 +130,8 @@ function buildBottomActions<M extends object>({
125
130
  openEntityMode,
126
131
  navigateBack,
127
132
  formContext,
128
- formex
133
+ formex,
134
+ t
129
135
  }: ActionsViewProps<M>) {
130
136
 
131
137
  const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
@@ -165,16 +171,16 @@ function buildBottomActions<M extends object>({
165
171
  <Button variant="text" disabled={disabled || formex.isSubmitting}
166
172
  color={"primary"}
167
173
  type="reset">
168
- {status === "existing" ? "Discard" : "Clear"}
174
+ {status === "existing" ? t("discard") : t("clear")}
169
175
  </Button>
170
176
  <Button variant={"filled"}
171
177
  color="primary"
172
178
  type="submit"
173
179
  disabled={disabled || formex.isSubmitting}
174
180
  startIcon={hasErrors ? <ErrorIcon/> : undefined}>
175
- {status === "existing" && "Save"}
176
- {status === "copy" && "Create copy"}
177
- {status === "new" && "Create"}
181
+ {status === "existing" && t("save")}
182
+ {status === "copy" && t("create_copy")}
183
+ {status === "new" && t("create")}
178
184
  </Button>
179
185
 
180
186
  </DialogActions>;
@@ -193,7 +199,8 @@ function buildSideActions<M extends object>({
193
199
  disabled,
194
200
  status,
195
201
  pluginActions,
196
- formex
202
+ formex,
203
+ t
197
204
  }: ActionsViewProps<M>) {
198
205
 
199
206
  const hasErrors = Object.keys(formex.errors).length > 0 && formex.submitCount > 0;
@@ -207,12 +214,12 @@ function buildSideActions<M extends object>({
207
214
  size={"large"}
208
215
  startIcon={hasErrors ? <ErrorIcon/> : undefined}
209
216
  disabled={disabled || formex.isSubmitting}>
210
- {status === "existing" && "Save"}
211
- {status === "copy" && "Create copy"}
212
- {status === "new" && "Create"}
217
+ {status === "existing" && t("save")}
218
+ {status === "copy" && t("create_copy")}
219
+ {status === "new" && t("create")}
213
220
  </LoadingButton>
214
221
  <Button fullWidth={true} variant="text" disabled={disabled || formex.isSubmitting} type="reset">
215
- {status === "existing" ? "Discard" : "Clear"}
222
+ {status === "existing" ? t("discard") : t("clear")}
216
223
  </Button>
217
224
 
218
225
  {pluginActions}