@firecms/core 3.0.1 → 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 (334) 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/VirtualTableCell.d.ts +6 -0
  32. package/dist/components/VirtualTable/VirtualTableHeader.d.ts +4 -1
  33. package/dist/components/VirtualTable/VirtualTableHeaderRow.d.ts +1 -1
  34. package/dist/components/VirtualTable/VirtualTableProps.d.ts +17 -1
  35. package/dist/components/VirtualTable/fields/VirtualTableDateField.d.ts +1 -0
  36. package/dist/components/VirtualTable/types.d.ts +3 -0
  37. package/dist/components/index.d.ts +4 -0
  38. package/dist/contexts/index.d.ts +10 -0
  39. package/dist/core/DrawerNavigationGroup.d.ts +45 -0
  40. package/dist/core/index.d.ts +1 -0
  41. package/dist/editor/components/SlashCommandMenu.d.ts +6 -0
  42. package/dist/editor/components/editor-bubble-item.d.ts +8 -0
  43. package/dist/editor/components/editor-bubble.d.ts +8 -0
  44. package/dist/editor/components/image-bubble.d.ts +5 -0
  45. package/dist/editor/components/index.d.ts +16 -0
  46. package/dist/editor/components/table-bubble.d.ts +5 -0
  47. package/dist/editor/editor.d.ts +30 -0
  48. package/dist/editor/extensions/HighlightDecorationExtension.d.ts +24 -0
  49. package/dist/editor/extensions/Image/index.d.ts +6 -0
  50. package/dist/editor/extensions/Image.d.ts +6 -0
  51. package/dist/editor/extensions/TextLoadingDecorationExtension.d.ts +16 -0
  52. package/dist/editor/extensions/clipboard.d.ts +7 -0
  53. package/dist/editor/extensions/custom-keymap.d.ts +1 -0
  54. package/dist/editor/extensions/drag-and-drop.d.ts +9 -0
  55. package/dist/editor/hooks/useProseMirror.d.ts +13 -0
  56. package/dist/editor/hooks/useProseMirrorContext.d.ts +9 -0
  57. package/dist/editor/index.d.ts +2 -0
  58. package/dist/editor/markdown.d.ts +5 -0
  59. package/dist/editor/nodeViews/ImageComponent.d.ts +3 -0
  60. package/dist/editor/nodeViews/ReactNodeView.d.ts +29 -0
  61. package/dist/editor/nodeViews/TaskItemComponent.d.ts +3 -0
  62. package/dist/editor/nodeViews/index.d.ts +6 -0
  63. package/dist/editor/plugins/index.d.ts +2 -0
  64. package/dist/editor/plugins/inputrules.d.ts +6 -0
  65. package/dist/editor/plugins/placeholderPlugin.d.ts +3 -0
  66. package/dist/editor/plugins/slashCommandPlugin.d.ts +12 -0
  67. package/dist/editor/schema.d.ts +2 -0
  68. package/dist/editor/selectors/ai-selector.d.ts +0 -0
  69. package/dist/editor/selectors/color-selector.d.ts +10 -0
  70. package/dist/editor/selectors/link-selector.d.ts +8 -0
  71. package/dist/editor/selectors/node-selector.d.ts +15 -0
  72. package/dist/editor/selectors/text-buttons.d.ts +1 -0
  73. package/dist/editor/types.d.ts +5 -0
  74. package/dist/editor/useProseMirror.d.ts +16 -0
  75. package/dist/editor/utils/prosemirror-utils.d.ts +6 -0
  76. package/dist/editor/utils/remove_classes.d.ts +1 -0
  77. package/dist/editor/utils/useDebouncedCallback.d.ts +1 -0
  78. package/dist/form/components/ErrorFocus.d.ts +1 -1
  79. package/dist/form/field_bindings/MapFieldBinding.d.ts +1 -1
  80. package/dist/form/field_bindings/MarkdownEditorFieldBinding.d.ts +1 -1
  81. package/dist/form/validation.d.ts +3 -2
  82. package/dist/hooks/index.d.ts +1 -0
  83. package/dist/hooks/useBreadcrumbsController.d.ts +16 -0
  84. package/dist/hooks/useBuildNavigationController.d.ts +0 -1
  85. package/dist/hooks/useCollapsedGroups.d.ts +6 -3
  86. package/dist/hooks/useTranslation.d.ts +17 -0
  87. package/dist/i18n/FireCMSi18nProvider.d.ts +33 -0
  88. package/dist/index.d.ts +5 -0
  89. package/dist/index.es.js +30146 -15178
  90. package/dist/index.es.js.map +1 -1
  91. package/dist/index.umd.js +30032 -15085
  92. package/dist/index.umd.js.map +1 -1
  93. package/dist/internal/useRestoreScroll.d.ts +1 -1
  94. package/dist/locales/de.d.ts +2 -0
  95. package/dist/locales/en.d.ts +10 -0
  96. package/dist/locales/es.d.ts +10 -0
  97. package/dist/locales/fr.d.ts +2 -0
  98. package/dist/locales/hi.d.ts +2 -0
  99. package/dist/locales/it.d.ts +2 -0
  100. package/dist/locales/pt.d.ts +7 -0
  101. package/dist/preview/PropertyPreviewProps.d.ts +5 -0
  102. package/dist/preview/components/DatePreview.d.ts +13 -3
  103. package/dist/preview/components/ImagePreview.d.ts +5 -1
  104. package/dist/preview/components/StorageThumbnail.d.ts +2 -1
  105. package/dist/preview/components/UrlComponentPreview.d.ts +2 -1
  106. package/dist/preview/property_previews/ArrayOfStorageComponentsPreview.d.ts +1 -1
  107. package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
  108. package/dist/preview/property_previews/SkeletonPropertyComponent.d.ts +1 -1
  109. package/dist/types/analytics.d.ts +1 -1
  110. package/dist/types/collections.d.ts +88 -2
  111. package/dist/types/customization_controller.d.ts +2 -1
  112. package/dist/types/datasource.d.ts +0 -1
  113. package/dist/types/firecms.d.ts +2 -1
  114. package/dist/types/index.d.ts +1 -0
  115. package/dist/types/navigation.d.ts +2 -2
  116. package/dist/types/plugins.d.ts +69 -1
  117. package/dist/types/properties.d.ts +268 -12
  118. package/dist/types/storage.d.ts +1 -0
  119. package/dist/types/translations.d.ts +669 -0
  120. package/dist/util/__tests__/conditions.test.d.ts +1 -0
  121. package/dist/util/__tests__/objects.test.d.ts +1 -0
  122. package/dist/util/conditions.d.ts +26 -0
  123. package/dist/util/entities.d.ts +2 -3
  124. package/dist/util/index.d.ts +3 -1
  125. package/dist/util/lazy_eager.d.ts +7 -0
  126. package/dist/util/objects.d.ts +1 -0
  127. package/dist/util/property_utils.d.ts +2 -1
  128. package/dist/util/resolutions.d.ts +3 -3
  129. package/dist/util/useStorageUploadController.d.ts +10 -1
  130. package/package.json +51 -12
  131. package/src/app/Scaffold.tsx +20 -19
  132. package/src/components/AIIcon.tsx +41 -0
  133. package/src/components/ArrayContainer.tsx +7 -8
  134. package/src/components/ClearFilterSortButton.tsx +25 -19
  135. package/src/components/ConfirmationDialog.tsx +4 -4
  136. package/src/components/DeleteEntityDialog.tsx +12 -11
  137. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +82 -43
  138. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +130 -79
  139. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +121 -104
  140. package/src/components/EntityCollectionTable/PropertyTableCell.tsx +132 -103
  141. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +6 -3
  142. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +24 -44
  143. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +90 -49
  144. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -1
  145. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -2
  146. package/src/components/EntityCollectionTable/internal/popup_field/useDraggable.tsx +11 -11
  147. package/src/components/EntityCollectionView/Board.tsx +324 -0
  148. package/src/components/EntityCollectionView/BoardColumn.tsx +158 -0
  149. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +45 -0
  150. package/src/components/EntityCollectionView/BoardSortableList.tsx +174 -0
  151. package/src/components/EntityCollectionView/CollectionDataErrorBanner.tsx +43 -0
  152. package/src/components/EntityCollectionView/EntityBoardCard.tsx +212 -0
  153. package/src/components/EntityCollectionView/EntityCard.tsx +235 -0
  154. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +706 -0
  155. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +236 -0
  156. package/src/components/EntityCollectionView/EntityCollectionView.tsx +531 -209
  157. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +35 -22
  158. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +86 -15
  159. package/src/components/EntityCollectionView/FiltersDialog.tsx +252 -0
  160. package/src/components/EntityCollectionView/ViewModeToggle.tsx +202 -0
  161. package/src/components/EntityCollectionView/board_types.ts +113 -0
  162. package/src/components/EntityCollectionView/useBoardDataController.tsx +490 -0
  163. package/src/components/EntityJsonPreview.tsx +2 -1
  164. package/src/components/EntityView.tsx +3 -2
  165. package/src/components/ErrorBoundary.tsx +27 -15
  166. package/src/components/ErrorTooltip.tsx +2 -1
  167. package/src/components/HomePage/DefaultHomePage.tsx +65 -22
  168. package/src/components/HomePage/HomePageDnD.tsx +59 -42
  169. package/src/components/HomePage/NavigationCard.tsx +20 -18
  170. package/src/components/HomePage/NavigationGroup.tsx +20 -17
  171. package/src/components/HomePage/RenameGroupDialog.tsx +15 -15
  172. package/src/components/HomePage/SmallNavigationCard.tsx +10 -9
  173. package/src/components/LanguageToggle.tsx +66 -0
  174. package/src/components/NotFoundPage.tsx +5 -3
  175. package/src/components/ReferenceTable/ReferenceSelectionTable.tsx +12 -17
  176. package/src/components/ReferenceWidget.tsx +5 -6
  177. package/src/components/SearchIconsView.tsx +3 -1
  178. package/src/components/SelectableTable/SelectableTable.tsx +75 -67
  179. package/src/components/SelectableTable/filters/BooleanFilterField.tsx +7 -6
  180. package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +50 -40
  181. package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +53 -40
  182. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +60 -58
  183. package/src/components/UnsavedChangesDialog.tsx +6 -6
  184. package/src/components/UserDisplay.tsx +4 -4
  185. package/src/components/VirtualTable/VirtualTable.performance.test.tsx +1 -0
  186. package/src/components/VirtualTable/VirtualTable.tsx +275 -119
  187. package/src/components/VirtualTable/VirtualTableCell.tsx +18 -2
  188. package/src/components/VirtualTable/VirtualTableHeader.tsx +76 -64
  189. package/src/components/VirtualTable/VirtualTableHeaderRow.tsx +163 -42
  190. package/src/components/VirtualTable/VirtualTableProps.tsx +21 -2
  191. package/src/components/VirtualTable/VirtualTableRow.tsx +1 -1
  192. package/src/components/VirtualTable/fields/VirtualTableDateField.tsx +3 -0
  193. package/src/components/VirtualTable/fields/VirtualTableSelect.tsx +19 -6
  194. package/src/components/VirtualTable/types.tsx +3 -0
  195. package/src/components/common/default_entity_actions.tsx +4 -0
  196. package/src/components/common/useColumnsIds.tsx +95 -3
  197. package/src/components/common/useDataSourceTableController.tsx +12 -4
  198. package/src/components/index.tsx +5 -0
  199. package/src/contexts/BreacrumbsContext.tsx +15 -8
  200. package/src/contexts/index.ts +10 -0
  201. package/src/core/DefaultAppBar.tsx +49 -32
  202. package/src/core/DefaultDrawer.tsx +49 -57
  203. package/src/core/DrawerNavigationGroup.tsx +120 -0
  204. package/src/core/DrawerNavigationItem.tsx +4 -3
  205. package/src/core/EntityEditView.tsx +94 -50
  206. package/src/core/EntityEditViewFormActions.tsx +24 -17
  207. package/src/core/EntitySidePanel.tsx +34 -30
  208. package/src/core/FireCMS.tsx +33 -6
  209. package/src/core/SideDialogs.tsx +4 -2
  210. package/src/core/field_configs.tsx +18 -11
  211. package/src/core/index.tsx +1 -0
  212. package/src/editor/components/SlashCommandMenu.tsx +516 -0
  213. package/src/editor/components/editor-bubble-item.tsx +32 -0
  214. package/src/editor/components/editor-bubble.tsx +118 -0
  215. package/src/editor/components/image-bubble.tsx +156 -0
  216. package/src/editor/components/index.ts +14 -0
  217. package/src/editor/components/table-bubble.tsx +165 -0
  218. package/src/editor/editor.tsx +455 -0
  219. package/src/editor/extensions/HighlightDecorationExtension.ts +114 -0
  220. package/src/editor/extensions/Image/index.ts +133 -0
  221. package/src/editor/extensions/Image.ts +159 -0
  222. package/src/editor/extensions/TextLoadingDecorationExtension.tsx +107 -0
  223. package/src/editor/extensions/clipboard.ts +72 -0
  224. package/src/editor/extensions/custom-keymap.ts +24 -0
  225. package/src/editor/extensions/drag-and-drop.tsx +480 -0
  226. package/src/editor/hooks/useProseMirror.ts +124 -0
  227. package/src/editor/hooks/useProseMirrorContext.ts +15 -0
  228. package/src/editor/index.ts +2 -0
  229. package/src/editor/markdown.ts +172 -0
  230. package/src/editor/nodeViews/ImageComponent.tsx +20 -0
  231. package/src/editor/nodeViews/ReactNodeView.tsx +89 -0
  232. package/src/editor/nodeViews/TaskItemComponent.tsx +29 -0
  233. package/src/editor/nodeViews/index.ts +35 -0
  234. package/src/editor/plugins/index.ts +58 -0
  235. package/src/editor/plugins/inputrules.ts +82 -0
  236. package/src/editor/plugins/placeholderPlugin.ts +55 -0
  237. package/src/editor/plugins/slashCommandPlugin.ts +61 -0
  238. package/src/editor/schema.ts +240 -0
  239. package/src/editor/selectors/ai-selector.tsx +111 -0
  240. package/src/editor/selectors/color-selector.tsx +200 -0
  241. package/src/editor/selectors/link-selector.tsx +118 -0
  242. package/src/editor/selectors/node-selector.tsx +157 -0
  243. package/src/editor/selectors/text-buttons.tsx +86 -0
  244. package/src/editor/types.ts +6 -0
  245. package/src/editor/useProseMirror.ts +126 -0
  246. package/src/editor/utils/prosemirror-utils.ts +108 -0
  247. package/src/editor/utils/remove_classes.ts +17 -0
  248. package/src/editor/utils/useDebouncedCallback.ts +25 -0
  249. package/src/form/EntityForm.tsx +149 -67
  250. package/src/form/EntityFormActions.tsx +19 -12
  251. package/src/form/PropertyFieldBinding.tsx +68 -51
  252. package/src/form/components/ErrorFocus.tsx +3 -3
  253. package/src/form/components/LocalChangesMenu.tsx +13 -13
  254. package/src/form/components/StorageItemPreview.tsx +5 -3
  255. package/src/form/components/StorageUploadProgress.tsx +18 -3
  256. package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +18 -5
  257. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +22 -10
  258. package/src/form/field_bindings/BlockFieldBinding.tsx +26 -9
  259. package/src/form/field_bindings/DateTimeFieldBinding.tsx +18 -17
  260. package/src/form/field_bindings/KeyValueFieldBinding.tsx +46 -25
  261. package/src/form/field_bindings/MapFieldBinding.tsx +88 -70
  262. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +93 -52
  263. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +15 -1
  264. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +25 -11
  265. package/src/form/field_bindings/ReferenceFieldBinding.tsx +25 -11
  266. package/src/form/field_bindings/RepeatFieldBinding.tsx +21 -6
  267. package/src/form/field_bindings/SelectFieldBinding.tsx +7 -5
  268. package/src/form/field_bindings/StorageUploadFieldBinding.tsx +110 -92
  269. package/src/form/field_bindings/SwitchFieldBinding.tsx +31 -14
  270. package/src/form/field_bindings/TextFieldBinding.tsx +77 -38
  271. package/src/form/field_bindings/UserSelectFieldBinding.tsx +7 -5
  272. package/src/form/validation.ts +245 -160
  273. package/src/hooks/index.tsx +1 -0
  274. package/src/hooks/useBreadcrumbsController.tsx +18 -0
  275. package/src/hooks/useBuildNavigationController.tsx +91 -41
  276. package/src/hooks/useCollapsedGroups.ts +18 -9
  277. package/src/hooks/useTranslation.ts +31 -0
  278. package/src/hooks/useValidateAuthenticator.tsx +1 -1
  279. package/src/i18n/FireCMSi18nProvider.tsx +160 -0
  280. package/src/index.ts +5 -0
  281. package/src/internal/useBuildDataSource.ts +68 -34
  282. package/src/internal/useBuildSideDialogsController.tsx +11 -8
  283. package/src/internal/useBuildSideEntityController.tsx +24 -24
  284. package/src/internal/useRestoreScroll.tsx +26 -14
  285. package/src/locales/de.ts +718 -0
  286. package/src/locales/en.ts +730 -0
  287. package/src/locales/es.ts +730 -0
  288. package/src/locales/fr.ts +718 -0
  289. package/src/locales/hi.ts +718 -0
  290. package/src/locales/it.ts +718 -0
  291. package/src/locales/pt.ts +727 -0
  292. package/src/preview/PropertyPreview.tsx +43 -33
  293. package/src/preview/PropertyPreviewProps.tsx +6 -0
  294. package/src/preview/components/DatePreview.tsx +72 -4
  295. package/src/preview/components/EmptyValue.tsx +1 -1
  296. package/src/preview/components/ImagePreview.tsx +37 -21
  297. package/src/preview/components/ReferencePreview.tsx +2 -1
  298. package/src/preview/components/StorageThumbnail.tsx +16 -12
  299. package/src/preview/components/UrlComponentPreview.tsx +32 -27
  300. package/src/preview/components/UserPreview.tsx +3 -1
  301. package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +9 -7
  302. package/src/preview/property_previews/ArrayOfStringsPreview.tsx +11 -9
  303. package/src/preview/property_previews/ArrayPropertyPreview.tsx +26 -24
  304. package/src/preview/property_previews/MapPropertyPreview.tsx +49 -27
  305. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +61 -56
  306. package/src/routes/CustomCMSRoute.tsx +1 -0
  307. package/src/routes/FireCMSRoute.tsx +87 -65
  308. package/src/types/analytics.ts +10 -0
  309. package/src/types/collections.ts +97 -3
  310. package/src/types/customization_controller.tsx +2 -1
  311. package/src/types/datasource.ts +54 -56
  312. package/src/types/firecms.tsx +2 -1
  313. package/src/types/index.ts +1 -0
  314. package/src/types/navigation.ts +2 -2
  315. package/src/types/plugins.tsx +77 -1
  316. package/src/types/properties.ts +359 -37
  317. package/src/types/storage.ts +2 -1
  318. package/src/types/translations.ts +752 -0
  319. package/src/util/__tests__/conditions.test.ts +506 -0
  320. package/src/util/__tests__/objects.test.ts +196 -0
  321. package/src/util/callbacks.ts +6 -3
  322. package/src/util/collections.ts +51 -6
  323. package/src/util/conditions.ts +339 -0
  324. package/src/util/entities.ts +29 -30
  325. package/src/util/entity_cache.ts +2 -1
  326. package/src/util/index.ts +3 -1
  327. package/src/util/join_collections.ts +10 -8
  328. package/src/util/lazy_eager.tsx +33 -0
  329. package/src/util/objects.ts +46 -13
  330. package/src/util/{references.ts → previews.ts} +16 -2
  331. package/src/util/property_utils.tsx +37 -11
  332. package/src/util/resolutions.ts +62 -58
  333. package/src/util/useStorageUploadController.tsx +23 -29
  334. /package/dist/util/{references.d.ts → previews.d.ts} +0 -0
@@ -0,0 +1,172 @@
1
+ import {
2
+ MarkdownParser,
3
+ MarkdownSerializer,
4
+ defaultMarkdownParser,
5
+ defaultMarkdownSerializer
6
+ } from "prosemirror-markdown";
7
+ import markdownIt from "markdown-it";
8
+ // @ts-ignore
9
+ import markdownItTaskLists from "markdown-it-task-lists";
10
+ // @ts-ignore
11
+ import markdownItMark from "markdown-it-mark";
12
+ // @ts-ignore
13
+ import markdownItIns from "markdown-it-ins";
14
+
15
+ import { schema } from "./schema";
16
+
17
+ const parserTokens: any = {
18
+ ...defaultMarkdownParser.tokens,
19
+ em: { mark: "italic" },
20
+ strong: { mark: "bold" },
21
+ html_inline: { ignore: true, noCloseToken: true },
22
+ html_block: { ignore: true, noCloseToken: true },
23
+ s: {
24
+ mark: "strike",
25
+ },
26
+ task_list: {
27
+ block: "task_list",
28
+ },
29
+ task_item: {
30
+ block: "task_item",
31
+ getAttrs: (tok: any) => ({ checked: tok.attrGet("checked") === "true" }),
32
+ },
33
+ mark: {
34
+ mark: "highlight"
35
+ },
36
+ ins: {
37
+ mark: "underline"
38
+ },
39
+ table: { block: "table" },
40
+ thead: { ignore: true },
41
+ tbody: { ignore: true },
42
+ tr: { block: "table_row" },
43
+ th: { block: "table_header" },
44
+ td: { block: "table_cell" }
45
+ };
46
+
47
+ const md = markdownIt({ html: false })
48
+ .use(markdownItTaskLists)
49
+ .use(markdownItMark)
50
+ .use(markdownItIns);
51
+
52
+ // Unwrap images from paragraphs so they can be parsed as block nodes by ProseMirror
53
+ md.core.ruler.after("inline", "image-to-block", (state: any) => {
54
+ const tokens = state.tokens;
55
+ for (let i = tokens.length - 2; i >= 1; i--) {
56
+ if (
57
+ tokens[i - 1] && tokens[i - 1].type === "paragraph_open" &&
58
+ tokens[i] && tokens[i].type === "inline" &&
59
+ tokens[i + 1] && tokens[i + 1].type === "paragraph_close"
60
+ ) {
61
+ const inlineTokens = tokens[i].children || [];
62
+ if (inlineTokens.length === 1 && inlineTokens[0].type === "image") {
63
+ state.tokens.splice(i - 1, 3, inlineTokens[0]);
64
+ // No need to adjust index when looping backward!
65
+ }
66
+ }
67
+ }
68
+ });
69
+
70
+ // Wrap inline tokens inside table cells into paragraphs to satisfy ProseMirror table cell schema (block+)
71
+ md.core.ruler.after("inline", "tables-wrap-paragraphs", (state: any) => {
72
+ const tokens = state.tokens;
73
+ for (let i = tokens.length - 1; i >= 0; i--) {
74
+ if (tokens[i].type === "td_open" || tokens[i].type === "th_open") {
75
+ let closeIndex = i + 1;
76
+ while (closeIndex < tokens.length && tokens[closeIndex].type !== "td_close" && tokens[closeIndex].type !== "th_close") {
77
+ closeIndex++;
78
+ }
79
+ if (closeIndex < tokens.length) {
80
+ const pOpen = new state.Token("paragraph_open", "p", 1);
81
+ pOpen.block = true;
82
+ const pClose = new state.Token("paragraph_close", "p", -1);
83
+ pClose.block = true;
84
+
85
+ state.tokens.splice(closeIndex, 0, pClose);
86
+ state.tokens.splice(i + 1, 0, pOpen);
87
+ }
88
+ }
89
+ }
90
+ });
91
+
92
+ export const markdownParser = new MarkdownParser(schema, md, parserTokens);
93
+
94
+
95
+ export const markdownSerializer = new MarkdownSerializer(
96
+ {
97
+ ...defaultMarkdownSerializer.nodes,
98
+ // Add custom serialization for task lists
99
+ task_list(state, node) {
100
+ state.renderList(node, " ", () => "- ");
101
+ },
102
+ task_item(state, node) {
103
+ state.write(`[${node.attrs.checked ? "x" : " "}] `);
104
+ state.renderContent(node);
105
+ },
106
+ horizontal_rule(state, node) {
107
+ state.write(node.attrs.markup || "---");
108
+ state.closeBlock(node);
109
+ },
110
+ image(state, node) {
111
+ const rawSrc = node.attrs.src || "";
112
+ const src = rawSrc.replace(/ /g, "%20");
113
+ state.write("![" + state.esc(node.attrs.alt || "") + "](" + src.replace(/[\(\)]/g, "\\$&") +
114
+ (node.attrs.title ? ' "' + node.attrs.title.replace(/"/g, '\\"') + '"' : "") + ")");
115
+ state.closeBlock(node);
116
+ },
117
+ table(state, node) {
118
+ node.forEach((row, _, i) => {
119
+ row.forEach((cell, _, j) => {
120
+ state.write(j === 0 ? "| " : " ");
121
+ let cellContent = "";
122
+ const oldWrite = state.write.bind(state);
123
+ state.write = (s: string) => { cellContent += s; };
124
+
125
+ let first = true;
126
+ cell.forEach((block: any) => {
127
+ if (!first) cellContent += "<br>";
128
+ state.renderInline(block);
129
+ first = false;
130
+ });
131
+
132
+ state.write = oldWrite;
133
+ state.write(cellContent.replace(/\|/g, "\\|"));
134
+ state.write(" |");
135
+ });
136
+ state.write("\n");
137
+ if (i === 0) {
138
+ row.forEach((cell, _, j) => {
139
+ state.write(j === 0 ? "|---|" : "---|");
140
+ });
141
+ state.write("\n");
142
+ }
143
+ });
144
+ state.closeBlock(node);
145
+ },
146
+ table_row() {},
147
+ table_cell() {},
148
+ table_header() {}
149
+ },
150
+ {
151
+ ...defaultMarkdownSerializer.marks,
152
+ bold: defaultMarkdownSerializer.marks.strong,
153
+ italic: defaultMarkdownSerializer.marks.em,
154
+ strike: { open: "~~", close: "~~", mixable: true, expelEnclosingWhitespace: true },
155
+ highlight: { open: "==", close: "==", mixable: true, expelEnclosingWhitespace: true },
156
+ underline: { open: "++", close: "++", mixable: true, expelEnclosingWhitespace: true },
157
+ link: {
158
+ ...defaultMarkdownSerializer.marks.link,
159
+ close(state: any, mark, parent, index) {
160
+ const inAutolink = state.inAutolink;
161
+ state.inAutolink = undefined;
162
+ const href = mark.attrs.href.replace(/ /g, "%20");
163
+ return inAutolink ? ">"
164
+ : "](" + href.replace(/[\(\)"]/g, "\\$&") + (mark.attrs.title ? ` "${mark.attrs.title.replace(/"/g, '\\"')}"` : "") + ")";
165
+ }
166
+ },
167
+ // textStyle (colored text from HTML) has no markdown equivalent — emit content as-is
168
+ textStyle: { open: "", close: "", mixable: true, expelEnclosingWhitespace: true },
169
+ }
170
+ );
171
+ export const parser = markdownParser;
172
+ export const serializer = markdownSerializer;
@@ -0,0 +1,20 @@
1
+ import React from "react";
2
+ import { ReactNodeViewProps } from "./ReactNodeView";
3
+ import { cls, defaultBorderMixin } from "@firecms/ui";
4
+
5
+ export const ImageComponent: React.FC<ReactNodeViewProps> = ({ node, view, getPos }) => {
6
+ // If the node is selected
7
+ const selected = view.state.selection.from === getPos();
8
+
9
+ return (
10
+ <img
11
+ src={node.attrs.src}
12
+ alt={node.attrs.alt || ""}
13
+ title={node.attrs.title || ""}
14
+ className={cls(
15
+ "rounded-lg max-w-full !m-0",
16
+ selected ? "" : ""
17
+ )}
18
+ />
19
+ );
20
+ };
@@ -0,0 +1,89 @@
1
+ import React, { ReactNode } from "react";
2
+ import { createRoot, Root } from "react-dom/client";
3
+ import { Node as ProseMirrorNode } from "prosemirror-model";
4
+ import { EditorView, NodeView } from "prosemirror-view";
5
+
6
+ export interface ReactNodeViewProps {
7
+ node: ProseMirrorNode;
8
+ view: EditorView;
9
+ getPos: () => number | undefined;
10
+ }
11
+
12
+ export type ReactNodeViewComponent = React.FC<ReactNodeViewProps>;
13
+
14
+ /**
15
+ * A utility class that implements the ProseMirror NodeView interface but delegates rendering
16
+ * to a React component.
17
+ * Note: This uses createRoot, so it does not automatically inherit React Contexts.
18
+ * If contexts are needed, wrap them manually or use a portal-based approach instead.
19
+ */
20
+ export class ReactNodeView implements NodeView {
21
+ public node: ProseMirrorNode;
22
+ public view: EditorView;
23
+ public getPos: () => number | undefined;
24
+ public dom: HTMLElement;
25
+ public contentDOM?: HTMLElement;
26
+ private root: Root;
27
+ private Component: ReactNodeViewComponent;
28
+
29
+ constructor(
30
+ node: ProseMirrorNode,
31
+ view: EditorView,
32
+ getPos: () => number | undefined,
33
+ Component: ReactNodeViewComponent,
34
+ as: string = "div",
35
+ className?: string,
36
+ contentDOMElement?: HTMLElement
37
+ ) {
38
+ this.node = node;
39
+ this.view = view;
40
+ this.getPos = getPos;
41
+ this.Component = Component;
42
+
43
+ this.dom = document.createElement(as);
44
+ if (className) this.dom.className = className;
45
+ if (contentDOMElement) {
46
+ this.contentDOM = contentDOMElement;
47
+ }
48
+
49
+ const container = document.createElement("div");
50
+ // We render React next to contentDOM
51
+ this.dom.appendChild(container);
52
+ if (this.contentDOM) {
53
+ this.dom.appendChild(this.contentDOM);
54
+ }
55
+
56
+ this.root = createRoot(container);
57
+ this.render();
58
+ }
59
+
60
+ private render() {
61
+ this.root.render(
62
+ <this.Component
63
+ node={this.node}
64
+ view={this.view}
65
+ getPos={this.getPos}
66
+ />
67
+ );
68
+ }
69
+
70
+ update(node: ProseMirrorNode): boolean {
71
+ if (node.type !== this.node.type) {
72
+ return false;
73
+ }
74
+ this.node = node;
75
+ this.render();
76
+ return true;
77
+ }
78
+
79
+ destroy() {
80
+ this.root.unmount();
81
+ }
82
+
83
+ ignoreMutation(mutation: any) {
84
+ if (!this.contentDOM) {
85
+ return true;
86
+ }
87
+ return !this.contentDOM.contains(mutation.target);
88
+ }
89
+ }
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+ import { ReactNodeViewProps } from "./ReactNodeView";
3
+
4
+ export const TaskItemComponent: React.FC<ReactNodeViewProps> = ({ node, view, getPos }) => {
5
+ const checked = node.attrs.checked;
6
+
7
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
8
+ const pos = getPos();
9
+ if (typeof pos !== "number") return;
10
+
11
+ view.dispatch(
12
+ view.state.tr.setNodeMarkup(pos, undefined, {
13
+ ...node.attrs,
14
+ checked: e.target.checked
15
+ })
16
+ );
17
+ };
18
+
19
+ return (
20
+ <label contentEditable={false} className="flex items-start select-none px-1">
21
+ <input
22
+ type="checkbox"
23
+ checked={checked}
24
+ onChange={handleChange}
25
+ className="mt-1 flex-shrink-0 cursor-pointer"
26
+ />
27
+ </label>
28
+ );
29
+ };
@@ -0,0 +1,35 @@
1
+ import { Node as ProseMirrorNode } from "prosemirror-model";
2
+ import { EditorView, NodeView } from "prosemirror-view";
3
+ import { ReactNodeView, ReactNodeViewComponent } from "./ReactNodeView";
4
+ import { TaskItemComponent } from "./TaskItemComponent";
5
+ import { ImageComponent } from "./ImageComponent";
6
+
7
+ function createReactNodeView(
8
+ Component: ReactNodeViewComponent,
9
+ as: string = "div",
10
+ className?: string,
11
+ createContentDOM?: () => HTMLElement
12
+ ) {
13
+ return (node: ProseMirrorNode, view: EditorView, getPos: () => number | undefined): NodeView => {
14
+ const contentDOM = createContentDOM ? createContentDOM() : undefined;
15
+ return new ReactNodeView(node, view, getPos, Component, as, className, contentDOM);
16
+ };
17
+ }
18
+
19
+ export const nodeViews = {
20
+ task_item: createReactNodeView(
21
+ TaskItemComponent,
22
+ "li",
23
+ "flex items-start",
24
+ () => {
25
+ const dom = document.createElement("div");
26
+ dom.className = "flex-grow min-w-0";
27
+ return dom;
28
+ }
29
+ ),
30
+ image: createReactNodeView(
31
+ ImageComponent,
32
+ "span",
33
+ "inline-block w-full"
34
+ )
35
+ };
@@ -0,0 +1,58 @@
1
+ import { keymap } from "prosemirror-keymap";
2
+ import { history, undo, redo } from "prosemirror-history";
3
+ import { slashCommandPlugin } from "./slashCommandPlugin";
4
+ import { dragHandlePlugin, globalDragDropPlugin } from "../extensions/drag-and-drop";
5
+ import { baseKeymap, setBlockType, toggleMark, chainCommands, exitCode, joinUp, joinDown, lift, selectParentNode } from "prosemirror-commands";
6
+ import { highlightDecorationPlugin } from "../extensions/HighlightDecorationExtension";
7
+ import { textLoadingDecorationPlugin } from "../extensions/TextLoadingDecorationExtension";
8
+ import { splitListItem, liftListItem, sinkListItem } from "prosemirror-schema-list";
9
+ import { schema } from "../schema";
10
+ import { Plugin } from "prosemirror-state";
11
+ import { gapCursor } from "prosemirror-gapcursor";
12
+ import { dropCursor } from "prosemirror-dropcursor";
13
+ import { markdownInputRules } from "./inputrules";
14
+ import { placeholderPlugin } from "./placeholderPlugin";
15
+ import { goToNextCell } from "prosemirror-tables";
16
+
17
+ const customKeymap = {
18
+ "Tab": goToNextCell(1),
19
+ "Shift-Tab": goToNextCell(-1),
20
+ "Mod-z": undo,
21
+ "Mod-y": redo,
22
+ "Shift-Mod-z": redo,
23
+ "Mod-b": toggleMark(schema.marks.bold),
24
+ "Mod-i": toggleMark(schema.marks.italic),
25
+ "Mod-u": toggleMark(schema.marks.underline),
26
+ "Mod-Shift-s": toggleMark(schema.marks.strike),
27
+ "Mod-e": toggleMark(schema.marks.code),
28
+ "Mod-Shift-h": toggleMark(schema.marks.highlight),
29
+
30
+ "Enter": splitListItem(schema.nodes.list_item),
31
+ "Shift-Enter": splitListItem(schema.nodes.task_item),
32
+
33
+ "Mod-[": liftListItem(schema.nodes.list_item),
34
+ "Mod-]": sinkListItem(schema.nodes.list_item),
35
+
36
+ "Shift-Mod-8": setBlockType(schema.nodes.bullet_list),
37
+ "Shift-Mod-9": setBlockType(schema.nodes.ordered_list),
38
+
39
+ "Mod-Alt-1": setBlockType(schema.nodes.heading, { level: 1 }),
40
+ "Mod-Alt-2": setBlockType(schema.nodes.heading, { level: 2 }),
41
+ "Mod-Alt-3": setBlockType(schema.nodes.heading, { level: 3 }),
42
+
43
+ "Mod-Alt-0": setBlockType(schema.nodes.paragraph),
44
+ };
45
+
46
+ export const corePlugins: Plugin[] = [
47
+ history(),
48
+ keymap(customKeymap),
49
+ keymap(baseKeymap),
50
+ globalDragDropPlugin(),
51
+ gapCursor(),
52
+ slashCommandPlugin(),
53
+ dragHandlePlugin(),
54
+ highlightDecorationPlugin(),
55
+ textLoadingDecorationPlugin(),
56
+ markdownInputRules,
57
+ placeholderPlugin("Press '/' for commands")
58
+ ];
@@ -0,0 +1,82 @@
1
+ import {
2
+ inputRules,
3
+ wrappingInputRule,
4
+ textblockTypeInputRule,
5
+ smartQuotes,
6
+ emDash,
7
+ ellipsis,
8
+ InputRule,
9
+ } from "prosemirror-inputrules";
10
+ import { schema } from "../schema";
11
+ import { MarkType } from "prosemirror-model";
12
+
13
+ const blockQuoteRule = wrappingInputRule(/^\s*>\s$/, schema.nodes.blockquote);
14
+
15
+ const orderedListRule = wrappingInputRule(
16
+ /^(\d+)\.\s$/,
17
+ schema.nodes.ordered_list,
18
+ (match) => ({ order: +match[1] }),
19
+ (match, node) => node.childCount + node.attrs.order === +match[1]
20
+ );
21
+
22
+ const bulletListRule = wrappingInputRule(/^\s*([-+*])\s$/, schema.nodes.bullet_list);
23
+
24
+ const taskListRule = wrappingInputRule(/^\s*(\[ \])\s$/, schema.nodes.task_list);
25
+
26
+ const codeBlockRule = textblockTypeInputRule(/^```$/, schema.nodes.code_block);
27
+
28
+ const headingRule = textblockTypeInputRule(
29
+ new RegExp("^(#{1,6})\\s$"),
30
+ schema.nodes.heading,
31
+ (match) => ({ level: match[1].length })
32
+ );
33
+
34
+ const horizontalRuleInputRule = new InputRule(
35
+ /^(?:---|—-|___\s|\*\*\*\s)$/,
36
+ (state, match, start, end) => {
37
+ const tr = state.tr;
38
+ tr.replaceWith(start - 1, end, schema.nodes.horizontal_rule.create());
39
+ return tr;
40
+ }
41
+ );
42
+
43
+ function markInputRule(regexp: RegExp, markType: MarkType, getAttrs?: (match: RegExpMatchArray) => Record<string, any>) {
44
+ return new InputRule(regexp, (state, match, start, end) => {
45
+ const attrs = getAttrs instanceof Function ? getAttrs(match) : getAttrs;
46
+ const tr = state.tr;
47
+ if (match[1]) {
48
+ const textStart = start + match[0].indexOf(match[1]);
49
+ const textEnd = textStart + match[1].length;
50
+ if (textEnd < end) tr.delete(textEnd, end);
51
+ if (textStart > start) tr.delete(start, textStart);
52
+ end = start + match[1].length;
53
+ }
54
+ tr.addMark(start, end, markType.create(attrs));
55
+ tr.removeStoredMark(markType);
56
+ return tr;
57
+ });
58
+ }
59
+
60
+ const strongRule = markInputRule(/(?:\*\*|__)([^*_]+)(?:\*\*|__)$/, schema.marks.bold);
61
+ const emRule = markInputRule(/(?:^|[^*_])(?:\*|_)([^*_]+)(?:\*|_)$/, schema.marks.italic);
62
+ const codeRule = markInputRule(/(?:`)([^`]+)(?:`)$/, schema.marks.code);
63
+ const strikeRule = markInputRule(/(?:~~)([^~]+)(?:~~)$/, schema.marks.strike);
64
+
65
+ export const markdownInputRules = inputRules({
66
+ rules: [
67
+ ...smartQuotes,
68
+ ellipsis,
69
+ emDash,
70
+ blockQuoteRule,
71
+ orderedListRule,
72
+ bulletListRule,
73
+ codeBlockRule,
74
+ headingRule,
75
+ taskListRule,
76
+ horizontalRuleInputRule,
77
+ strongRule,
78
+ emRule,
79
+ codeRule,
80
+ strikeRule
81
+ ],
82
+ });
@@ -0,0 +1,55 @@
1
+ import { Plugin, PluginKey } from "prosemirror-state";
2
+ import { Decoration, DecorationSet } from "prosemirror-view";
3
+ import { Node } from "prosemirror-model";
4
+
5
+ export const placeholderPluginKey = new PluginKey("placeholderPlugin");
6
+
7
+ function isNodeEmpty(node: Node) {
8
+ const defaultContent = node.type.createAndFill()
9
+ if (!defaultContent) return true
10
+ return node.content.eq(defaultContent.content)
11
+ }
12
+
13
+ export function placeholderPlugin(text: string) {
14
+ return new Plugin({
15
+ key: placeholderPluginKey,
16
+ props: {
17
+ decorations: (state) => {
18
+ const doc = state.doc;
19
+ const decorations: Decoration[] = [];
20
+ const isEmptyDoc = doc.childCount === 1 && doc.firstChild?.isTextblock && doc.firstChild.content.size === 0;
21
+ const { anchor } = state.selection;
22
+
23
+ doc.descendants((node, pos) => {
24
+ const isEmpty = !node.isLeaf && isNodeEmpty(node);
25
+
26
+ if (isEmpty) {
27
+ // Only show placeholder on the node that contains the cursor.
28
+ // For a single-node empty doc, always show it (editor-empty state).
29
+ const nodeEnd = pos + node.nodeSize;
30
+ const hasCursor = anchor >= pos && anchor <= nodeEnd;
31
+
32
+ if (!hasCursor && !isEmptyDoc) {
33
+ return false;
34
+ }
35
+
36
+ const classes = ["is-empty"];
37
+ if (isEmptyDoc) {
38
+ classes.push("is-editor-empty");
39
+ }
40
+
41
+ decorations.push(
42
+ Decoration.node(pos, pos + node.nodeSize, {
43
+ class: classes.join(" "),
44
+ "data-placeholder": text
45
+ })
46
+ );
47
+ }
48
+ return false; // Stop descending
49
+ });
50
+
51
+ return DecorationSet.create(doc, decorations);
52
+ }
53
+ }
54
+ });
55
+ }
@@ -0,0 +1,61 @@
1
+ import { Plugin, PluginKey, TextSelection } from "prosemirror-state";
2
+
3
+ export const SlashCommandPluginKey = new PluginKey("slash-command");
4
+
5
+ export interface SlashCommandState {
6
+ active: boolean;
7
+ range?: { from: number; to: number };
8
+ query?: string;
9
+ dismissed?: boolean;
10
+ }
11
+
12
+ export function slashCommandPlugin() {
13
+ return new Plugin({
14
+ key: SlashCommandPluginKey,
15
+ state: {
16
+ init(): SlashCommandState {
17
+ return { active: false };
18
+ },
19
+ apply(tr, value, oldState, newState): SlashCommandState {
20
+ const meta = tr.getMeta(SlashCommandPluginKey);
21
+ if (meta !== undefined) {
22
+ return meta;
23
+ }
24
+
25
+ const { selection } = newState;
26
+ if (!(selection instanceof TextSelection) || !selection.empty) {
27
+ return { active: false };
28
+ }
29
+
30
+ // Make sure we are in a paragraph or heading block, not a code_block for example
31
+ const $anchor = selection.$anchor;
32
+ if ($anchor.parent.type.name === "code_block") {
33
+ return { active: false };
34
+ }
35
+
36
+ const textBefore = $anchor.parent.textBetween(
37
+ Math.max(0, $anchor.parentOffset - 20),
38
+ $anchor.parentOffset,
39
+ undefined,
40
+ "\ufffc"
41
+ );
42
+ const match = textBefore.match(/(?:\s|^)(\/)([a-zA-Z0-9]*)$/);
43
+
44
+ if (!match) {
45
+ return { active: false };
46
+ }
47
+
48
+ // If the user previously dismissed this slash command, keep it dismissed
49
+ if (value.dismissed) {
50
+ return { active: false, dismissed: true };
51
+ }
52
+
53
+ // match[1] is the slash, match[2] is the query
54
+ const query = match[2];
55
+ const from = $anchor.pos - query.length - 1;
56
+ const to = $anchor.pos;
57
+ return { active: true, range: { from, to }, query };
58
+ },
59
+ }
60
+ });
61
+ }