@rebasepro/admin 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (242) hide show
  1. package/LICENSE +21 -6
  2. package/dist/{CollectionEditorDialog-MbvXGzEq.js → CollectionEditorDialog-BXIh2AXg.js} +40 -31
  3. package/dist/CollectionEditorDialog-BXIh2AXg.js.map +1 -0
  4. package/dist/{CollectionsStudioView-D9X6aiAr.js → CollectionsStudioView-jR8iz_ja.js} +6 -8
  5. package/dist/CollectionsStudioView-jR8iz_ja.js.map +1 -0
  6. package/dist/{ContentHomePage-CfVB1eUo.js → ContentHomePage-BQZWuOFb.js} +5 -7
  7. package/dist/ContentHomePage-BQZWuOFb.js.map +1 -0
  8. package/dist/{ExportCollectionAction-CUwJg4F9.js → ExportCollectionAction-CMdiiv1L.js} +36 -38
  9. package/dist/ExportCollectionAction-CMdiiv1L.js.map +1 -0
  10. package/dist/{ImportCollectionAction-DGa_SF_8.js → ImportCollectionAction-C05lE0IW.js} +5 -7
  11. package/dist/ImportCollectionAction-C05lE0IW.js.map +1 -0
  12. package/dist/{PropertyEditView-C4nlYmAc.js → PropertyEditView-BB5xjnhZ.js} +261 -165
  13. package/dist/PropertyEditView-BB5xjnhZ.js.map +1 -0
  14. package/dist/{RolesView-CNWxnR8e.js → RolesView-CULIHWZ9.js} +22 -11
  15. package/dist/RolesView-CULIHWZ9.js.map +1 -0
  16. package/dist/{UsersView-YiTIcXkA.js → UsersView-D7_AtJ44.js} +7 -71
  17. package/dist/UsersView-D7_AtJ44.js.map +1 -0
  18. package/dist/collection_editor/ui/collection_editor/LayoutModeSwitch.d.ts +2 -2
  19. package/dist/collection_editor/ui/collection_editor/properties/VectorPropertyField.d.ts +3 -0
  20. package/dist/collection_editor_ui.js +5 -5
  21. package/dist/components/EntityCollectionTable/EntityCollectionRowActions.d.ts +1 -1
  22. package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
  23. package/dist/components/EntityCollectionView/EntityCollectionListView.d.ts +18 -2
  24. package/dist/components/EntityCollectionView/FilterPresetsButton.d.ts +21 -0
  25. package/dist/components/EntityDetailView.d.ts +31 -0
  26. package/dist/components/EntityEditView.d.ts +3 -2
  27. package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +1 -1
  28. package/dist/components/admin/CreationResultDialog.d.ts +5 -0
  29. package/dist/components/admin/RolesFilterSelect.d.ts +2 -0
  30. package/dist/components/admin/UserRolesSelectField.d.ts +2 -0
  31. package/dist/components/common/default_entity_actions.d.ts +7 -1
  32. package/dist/components/field_configs.d.ts +1 -1
  33. package/dist/components/index.d.ts +1 -0
  34. package/dist/data_import/utils/data.d.ts +1 -1
  35. package/dist/data_import/utils/file_headers.d.ts +6 -1
  36. package/dist/data_import/utils/file_to_json.d.ts +1 -11
  37. package/dist/data_import/utils/transforms.d.ts +11 -0
  38. package/dist/editor.js +2 -4
  39. package/dist/editor.js.map +1 -1
  40. package/dist/form/EntityForm.d.ts +1 -1
  41. package/dist/form/field_bindings/RelationFieldBinding.d.ts +1 -1
  42. package/dist/form/field_bindings/VectorFieldBinding.d.ts +11 -0
  43. package/dist/form/index.d.ts +1 -0
  44. package/dist/hooks/navigation/useResolvedViews.d.ts +2 -1
  45. package/dist/{index-CtzpHzMQ.js → index-BAM9KCmM.js} +4 -6
  46. package/dist/index-BAM9KCmM.js.map +1 -0
  47. package/dist/{index-DKlrVD1m.js → index-CoSNm3e3.js} +3 -3
  48. package/dist/index-CoSNm3e3.js.map +1 -0
  49. package/dist/{index-kHJXfLNI.js → index-D5OQhv-T.js} +3 -3
  50. package/dist/index-D5OQhv-T.js.map +1 -0
  51. package/dist/index.d.ts +4 -1
  52. package/dist/index.js +352 -148
  53. package/dist/index.js.map +1 -1
  54. package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
  55. package/dist/types/components/EntityFormProps.d.ts +2 -1
  56. package/dist/types/fields.d.ts +3 -3
  57. package/dist/util/navigation_utils.d.ts +1 -1
  58. package/dist/{util-CwLmSpGp.js → util-DtbWD7LF.js} +5312 -2580
  59. package/dist/util-DtbWD7LF.js.map +1 -0
  60. package/package.json +45 -39
  61. package/src/collection_editor/ConfigControllerProvider.tsx +1 -1
  62. package/src/collection_editor/ui/AddKanbanColumnAction.tsx +12 -2
  63. package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +1 -2
  64. package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -2
  65. package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -2
  66. package/src/collection_editor/ui/EditorEntityAction.tsx +1 -2
  67. package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +1 -2
  68. package/src/collection_editor/ui/NewCollectionButton.tsx +1 -2
  69. package/src/collection_editor/ui/NewCollectionCard.tsx +4 -6
  70. package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +1 -2
  71. package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +10 -2
  72. package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +18 -2
  73. package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +22 -7
  74. package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +16 -2
  75. package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +19 -9
  76. package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +13 -2
  77. package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +24 -2
  78. package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +22 -3
  79. package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +1 -2
  80. package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +11 -2
  81. package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +12 -2
  82. package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +16 -3
  83. package/src/collection_editor/ui/collection_editor/EnumForm.tsx +17 -2
  84. package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +18 -2
  85. package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
  86. package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +1 -2
  87. package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +17 -5
  88. package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +32 -6
  89. package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +7 -7
  90. package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +14 -2
  91. package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +16 -2
  92. package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +9 -2
  93. package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +1 -2
  94. package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +1 -2
  95. package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +9 -2
  96. package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +11 -2
  97. package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +34 -0
  98. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +15 -7
  99. package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +1 -2
  100. package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +15 -3
  101. package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +1 -1
  102. package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +1 -2
  103. package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -2
  104. package/src/collection_editor/validateCollectionJson.ts +9 -9
  105. package/src/components/AdminModeSyncer.tsx +1 -1
  106. package/src/components/ArrayContainer.tsx +19 -15
  107. package/src/components/ClearFilterSortButton.tsx +1 -2
  108. package/src/components/CollectionEditorDialogs.tsx +1 -1
  109. package/src/components/DefaultAppBar.tsx +15 -3
  110. package/src/components/DefaultDrawer.tsx +3 -3
  111. package/src/components/DrawerNavigationGroup.tsx +1 -2
  112. package/src/components/EntityCollectionTable/EntityCollectionRowActions.tsx +19 -9
  113. package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +2 -2
  114. package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
  115. package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +1 -2
  116. package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +1 -2
  117. package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +1 -2
  118. package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +1 -2
  119. package/src/components/EntityCollectionTable/fields/VirtualTableSelect.tsx +0 -1
  120. package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +15 -27
  121. package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +3 -4
  122. package/src/components/EntityCollectionTable/internal/EntityTableCellActions.tsx +1 -2
  123. package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +3 -5
  124. package/src/components/EntityCollectionTable/table_bindings.tsx +51 -45
  125. package/src/components/EntityCollectionView/Board.tsx +1 -2
  126. package/src/components/EntityCollectionView/BoardColumn.tsx +9 -2
  127. package/src/components/EntityCollectionView/BoardColumnTitle.tsx +5 -4
  128. package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
  129. package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +18 -16
  130. package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +16 -17
  131. package/src/components/EntityCollectionView/EntityCollectionListView.tsx +90 -21
  132. package/src/components/EntityCollectionView/EntityCollectionView.tsx +20 -11
  133. package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +6 -7
  134. package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +14 -5
  135. package/src/components/EntityCollectionView/FilterPresetsButton.tsx +292 -0
  136. package/src/components/EntityCollectionView/FiltersDialog.tsx +1 -2
  137. package/src/components/EntityCollectionView/SplitListView.tsx +76 -25
  138. package/src/components/EntityCollectionView/ViewModeToggle.tsx +20 -7
  139. package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +1 -1
  140. package/src/components/EntityCollectionView/useBoardDataController.tsx +74 -6
  141. package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +1 -1
  142. package/src/components/EntityDetailView.tsx +619 -0
  143. package/src/components/EntityEditView.tsx +29 -10
  144. package/src/components/EntityEditViewFormActions.tsx +20 -7
  145. package/src/components/EntityPreview.tsx +14 -5
  146. package/src/components/EntitySidePanel.tsx +116 -62
  147. package/src/components/EntityView.tsx +1 -2
  148. package/src/components/HomePage/ContentHomePage.tsx +1 -1
  149. package/src/components/HomePage/FavouritesView.tsx +1 -2
  150. package/src/components/HomePage/NavigationCard.tsx +1 -2
  151. package/src/components/HomePage/NavigationCardBinding.tsx +1 -2
  152. package/src/components/HomePage/NavigationGroup.tsx +1 -2
  153. package/src/components/HomePage/SmallNavigationCard.tsx +1 -2
  154. package/src/components/PropertyIdCopyTooltip.tsx +1 -2
  155. package/src/components/RebaseAuthGate.tsx +2 -2
  156. package/src/components/RebaseNavigation.tsx +9 -7
  157. package/src/components/ReferenceTable/EntitySelectionTable.tsx +12 -8
  158. package/src/components/RelationSelector.tsx +34 -6
  159. package/src/components/SearchIconsView.tsx +10 -2
  160. package/src/components/SelectableTable/SelectableTable.tsx +4 -4
  161. package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +1 -2
  162. package/src/components/SideDialogs.tsx +63 -38
  163. package/src/components/UserSelector.tsx +30 -6
  164. package/src/components/admin/CreationResultDialog.tsx +135 -0
  165. package/src/components/admin/RolesFilterSelect.tsx +45 -0
  166. package/src/components/admin/RolesView.tsx +53 -14
  167. package/src/components/admin/UserRolesSelectField.tsx +50 -0
  168. package/src/components/admin/UsersView.tsx +41 -124
  169. package/src/components/app/Scaffold.tsx +1 -2
  170. package/src/components/common/default_entity_actions.tsx +119 -12
  171. package/src/components/field_configs.tsx +39 -3
  172. package/src/components/history/EntityHistoryEntry.tsx +1 -2
  173. package/src/components/history/EntityHistoryView.tsx +1 -2
  174. package/src/components/index.ts +2 -0
  175. package/src/data_export/export/BasicExportAction.tsx +35 -38
  176. package/src/data_export/export/ExportCollectionAction.tsx +39 -40
  177. package/src/data_import/components/DataNewPropertiesMapping.tsx +15 -2
  178. package/src/data_import/components/ImportFileUpload.tsx +1 -2
  179. package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +1 -2
  180. package/src/data_import/import/ImportCollectionAction.tsx +21 -8
  181. package/src/data_import/utils/data.ts +23 -5
  182. package/src/data_import/utils/file_headers.ts +13 -89
  183. package/src/data_import/utils/file_to_json.ts +43 -68
  184. package/src/data_import/utils/transforms.ts +47 -0
  185. package/src/editor/components/SlashCommandMenu.tsx +17 -2
  186. package/src/editor/components/editor-bubble-item.tsx +1 -1
  187. package/src/editor/extensions/Image/index.ts +1 -1
  188. package/src/editor/extensions/Image.ts +1 -1
  189. package/src/editor/selectors/color-selector.tsx +1 -2
  190. package/src/editor/selectors/link-selector.tsx +1 -2
  191. package/src/editor/selectors/node-selector.tsx +16 -2
  192. package/src/editor/selectors/text-buttons.tsx +1 -2
  193. package/src/editor/utils/prosemirror-utils.ts +1 -1
  194. package/src/form/EntityForm.tsx +16 -6
  195. package/src/form/EntityFormActions.tsx +11 -3
  196. package/src/form/PropertyFieldBinding.tsx +5 -12
  197. package/src/form/components/FieldHelperText.tsx +1 -2
  198. package/src/form/components/LocalChangesMenu.tsx +17 -2
  199. package/src/form/components/StorageItemPreview.tsx +1 -2
  200. package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -2
  201. package/src/form/field_bindings/KeyValueFieldBinding.tsx +17 -2
  202. package/src/form/field_bindings/MapFieldBinding.tsx +1 -1
  203. package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +10 -3
  204. package/src/form/field_bindings/MultiSelectFieldBinding.tsx +1 -2
  205. package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -2
  206. package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
  207. package/src/form/field_bindings/RelationFieldBinding.tsx +150 -147
  208. package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
  209. package/src/form/field_bindings/SelectFieldBinding.tsx +1 -2
  210. package/src/form/field_bindings/TextFieldBinding.tsx +10 -2
  211. package/src/form/field_bindings/VectorFieldBinding.tsx +202 -0
  212. package/src/form/index.tsx +1 -0
  213. package/src/form/validation.ts +54 -2
  214. package/src/hooks/navigation/useBuildNavigationStateController.tsx +2 -1
  215. package/src/hooks/navigation/useResolvedViews.tsx +30 -15
  216. package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
  217. package/src/index.ts +6 -0
  218. package/src/preview/PropertyPreview.tsx +1 -1
  219. package/src/preview/components/ImagePreview.tsx +1 -1
  220. package/src/preview/components/UrlComponentPreview.tsx +1 -2
  221. package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
  222. package/src/preview/property_previews/SkeletonPropertyComponent.tsx +23 -24
  223. package/src/routes/RebaseRoute.tsx +64 -35
  224. package/src/types/components/EntityFormActionsProps.tsx +1 -1
  225. package/src/types/components/EntityFormProps.tsx +3 -1
  226. package/src/types/fields.tsx +4 -3
  227. package/src/util/navigation_utils.ts +4 -3
  228. package/src/util/previews.ts +1 -1
  229. package/src/util/property_utils.tsx +22 -6
  230. package/src/util/resolutions.ts +2 -2
  231. package/dist/CollectionEditorDialog-MbvXGzEq.js.map +0 -1
  232. package/dist/CollectionsStudioView-D9X6aiAr.js.map +0 -1
  233. package/dist/ContentHomePage-CfVB1eUo.js.map +0 -1
  234. package/dist/ExportCollectionAction-CUwJg4F9.js.map +0 -1
  235. package/dist/ImportCollectionAction-DGa_SF_8.js.map +0 -1
  236. package/dist/PropertyEditView-C4nlYmAc.js.map +0 -1
  237. package/dist/RolesView-CNWxnR8e.js.map +0 -1
  238. package/dist/UsersView-YiTIcXkA.js.map +0 -1
  239. package/dist/index-CtzpHzMQ.js.map +0 -1
  240. package/dist/index-DKlrVD1m.js.map +0 -1
  241. package/dist/index-kHJXfLNI.js.map +0 -1
  242. package/dist/util-CwLmSpGp.js.map +0 -1
@@ -9,8 +9,23 @@ import {
9
9
  import { useCMSContext } from "../../hooks";
10
10
  import { CollectionActionsProps, Entity, EntityCollection, ExportConfig, RebaseContext, User } from "@rebasepro/types";
11
11
  import { getDefaultValuesFor } from "@rebasepro/common";
12
- import { Alert, BooleanSwitchWithLabel, Button, CircularProgress, cls, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Tooltip , iconSize } from "@rebasepro/ui";
13
- import { DownloadIcon } from "lucide-react";
12
+ import {
13
+ Alert,
14
+ BooleanSwitchWithLabel,
15
+ Button,
16
+ CircularProgress,
17
+ Dialog,
18
+ DialogActions,
19
+ DialogContent,
20
+ DialogTitle,
21
+ DownloadIcon,
22
+ IconButton,
23
+ iconSize,
24
+ Label,
25
+ RadioGroup,
26
+ RadioGroupItem,
27
+ Tooltip
28
+ } from "@rebasepro/ui";
14
29
  import { downloadEntitiesExport } from "./export";
15
30
 
16
31
  const DOCS_LIMIT = 500;
@@ -70,7 +85,7 @@ export function ExportCollectionAction<M extends Record<string, unknown>, USER e
70
85
  return {
71
86
  [column.key]: await column.builder({
72
87
  entity,
73
- context: context as unknown as RebaseContext
88
+ context: context as RebaseContext
74
89
  })
75
90
  };
76
91
  }))).reduce((a, b) => ({ ...a,
@@ -87,7 +102,7 @@ export function ExportCollectionAction<M extends Record<string, unknown>, USER e
87
102
  return {
88
103
  [field.key]: await field.value({
89
104
  entity,
90
- context: context as unknown as RebaseContext
105
+ context: context as RebaseContext
91
106
  })
92
107
  };
93
108
  }))).reduce((a, b) => ({ ...a,
@@ -185,45 +200,29 @@ export function ExportCollectionAction<M extends Record<string, unknown>, USER e
185
200
 
186
201
  <div className={"flex flex-row gap-4"}>
187
202
  <div className={"p-4 flex flex-col"}>
188
- <div className="flex items-center">
189
- <input id="radio-csv" type="radio" value="csv" name="exportType"
190
- checked={exportType === "csv"}
191
- onChange={() => setExportType("csv")}
192
- className={cls("w-4 bg-surface-100 border-surface-300 dark:bg-surface-700 dark:border-surface-600")}/>
193
- <label htmlFor="radio-csv"
194
- className="p-2 text-sm font-medium text-surface-900 dark:text-surface-300">CSV</label>
195
- </div>
196
- <div className="flex items-center">
197
- <input id="radio-json" type="radio" value="json" name="exportType"
198
- checked={exportType === "json"}
199
- onChange={() => setExportType("json")}
200
- className={cls("w-4 bg-surface-100 border-surface-300 dark:bg-surface-700 dark:border-surface-600")}/>
201
- <label htmlFor="radio-json"
202
- className="p-2 text-sm font-medium text-surface-900 dark:text-surface-300">JSON</label>
203
- </div>
203
+ <RadioGroup value={exportType} onValueChange={(v) => setExportType(v as "csv" | "json")}>
204
+ <div className="flex items-center gap-2">
205
+ <RadioGroupItem value="csv" id="radio-csv"/>
206
+ <Label htmlFor="radio-csv">CSV</Label>
207
+ </div>
208
+ <div className="flex items-center gap-2">
209
+ <RadioGroupItem value="json" id="radio-json"/>
210
+ <Label htmlFor="radio-json">JSON</Label>
211
+ </div>
212
+ </RadioGroup>
204
213
  </div>
205
214
 
206
215
  <div className={"p-4 flex flex-col"}>
207
- <div className="flex items-center">
208
- <input id="radio-timestamp" type="radio" value="timestamp" name="dateExportType"
209
- checked={dateExportType === "timestamp"}
210
- onChange={() => setDateExportType("timestamp")}
211
- className={cls("w-4 bg-surface-100 border-surface-300 dark:bg-surface-700 dark:border-surface-600")}/>
212
- <label htmlFor="radio-timestamp"
213
- className="p-2 text-sm font-medium text-surface-900 dark:text-surface-300">Dates
214
- as
215
- timestamps ({dateRef.current.getTime()})</label>
216
- </div>
217
- <div className="flex items-center">
218
- <input id="radio-string" type="radio" value="string" name="dateExportType"
219
- checked={dateExportType === "string"}
220
- onChange={() => setDateExportType("string")}
221
- className={cls("w-4 bg-surface-100 border-surface-300 dark:bg-surface-700 dark:border-surface-600")}/>
222
- <label htmlFor="radio-string"
223
- className="p-2 text-sm font-medium text-surface-900 dark:text-surface-300">Dates
224
- as
225
- strings ({dateRef.current.toISOString()})</label>
226
- </div>
216
+ <RadioGroup value={dateExportType} onValueChange={(v) => setDateExportType(v as "timestamp" | "string")}>
217
+ <div className="flex items-center gap-2">
218
+ <RadioGroupItem value="timestamp" id="radio-timestamp"/>
219
+ <Label htmlFor="radio-timestamp">Dates as timestamps ({dateRef.current.getTime()})</Label>
220
+ </div>
221
+ <div className="flex items-center gap-2">
222
+ <RadioGroupItem value="string" id="radio-string"/>
223
+ <Label htmlFor="radio-string">Dates as strings ({dateRef.current.toISOString()})</Label>
224
+ </div>
225
+ </RadioGroup>
227
226
  </div>
228
227
  </div>
229
228
 
@@ -1,8 +1,21 @@
1
1
 
2
2
  import { getPropertyInPath } from "../../util";
3
3
  import { Properties, Property } from "@rebasepro/types";
4
- import { BooleanSwitchWithLabel, DateTimeField, ExpandablePanel, Select, SelectItem, Table, TableBody, TableCell, TableHeader, TableRow, TextField, Typography } from "@rebasepro/ui";
5
- import { ChevronRightIcon } from "lucide-react";
4
+ import {
5
+ BooleanSwitchWithLabel,
6
+ ChevronRightIcon,
7
+ DateTimeField,
8
+ ExpandablePanel,
9
+ Select,
10
+ SelectItem,
11
+ Table,
12
+ TableBody,
13
+ TableCell,
14
+ TableHeader,
15
+ TableRow,
16
+ TextField,
17
+ Typography
18
+ } from "@rebasepro/ui";
6
19
  import { getIn, setIn } from "@rebasepro/formex";
7
20
  import { ImportConfig } from "../types";
8
21
 
@@ -1,5 +1,4 @@
1
- import { FileUpload } from "@rebasepro/ui";
2
- import { UploadIcon } from "lucide-react";
1
+ import { FileUpload, UploadIcon } from "@rebasepro/ui";
3
2
  import { convertFileToJson } from "../utils/file_to_json";
4
3
  import { useSnackbarController } from "@rebasepro/core";
5
4
 
@@ -5,8 +5,7 @@ import {
5
5
  getFieldConfig,
6
6
  PropertyConfigBadge
7
7
  } from "../../components";
8
- import { ErrorBoundary, IconButton, TextField } from "@rebasepro/ui";
9
- import { PencilIcon } from "lucide-react";
8
+ import { ErrorBoundary, IconButton, PencilIcon, TextField } from "@rebasepro/ui";
10
9
 
11
10
  export function ImportNewPropertyFieldPreview({
12
11
  propertyKey,
@@ -13,8 +13,22 @@ import {
13
13
  } from "../../components";
14
14
  import { EntityCollectionTable } from "../../components/EntityCollectionTable/EntityCollectionTable";
15
15
  import { useCollectionRegistryController } from "../../hooks";
16
- import { Button, cls, defaultBorderMixin, Dialog, DialogActions, DialogContent, DialogTitle, IconButton, Select, SelectItem, Tooltip, Typography , iconSize } from "@rebasepro/ui";
17
- import { UploadIcon } from "lucide-react";
16
+ import {
17
+ Button,
18
+ cls,
19
+ defaultBorderMixin,
20
+ Dialog,
21
+ DialogActions,
22
+ DialogContent,
23
+ DialogTitle,
24
+ IconButton,
25
+ iconSize,
26
+ Select,
27
+ SelectItem,
28
+ Tooltip,
29
+ Typography,
30
+ UploadIcon
31
+ } from "@rebasepro/ui";
18
32
  import { buildEntityPropertiesFromData } from "@rebasepro/schema-inference";
19
33
  import { useImportConfig } from "../hooks";
20
34
  import { convertDataToEntity, getInferenceType } from "../utils";
@@ -66,7 +80,7 @@ export function ImportCollectionAction<M extends Record<string, unknown>, USER e
66
80
 
67
81
  if (data.length > 0) {
68
82
  const originProperties = await buildEntityPropertiesFromData(data, getInferenceType);
69
- importConfig.setOriginProperties(originProperties as any);
83
+ importConfig.setOriginProperties(originProperties as Properties);
70
84
 
71
85
  const headersMapping = buildHeadersMappingFromData(data, collection?.properties);
72
86
  importConfig.setHeadersMapping(headersMapping);
@@ -162,7 +176,7 @@ export function ImportCollectionAction<M extends Record<string, unknown>, USER e
162
176
 
163
177
  {step === "import_data_saving" && importConfig &&
164
178
  <ImportSaveInProgress importConfig={importConfig}
165
- collection={collection as unknown as EntityCollection}
179
+ collection={collection as EntityCollection}
166
180
  path={path}
167
181
  onImportSuccess={(importedCollection) => {
168
182
  handleClose();
@@ -406,12 +420,11 @@ function buildHeadersMappingFromData(objArr: object[], properties?: Properties)
406
420
  const headersMapping: Record<string, string> = {};
407
421
  objArr.filter(Boolean).forEach((obj) => {
408
422
  Object.keys(obj).forEach((key) => {
409
- // @ts-ignore
410
- const child = obj[key];
411
- if (typeof child === "object" && !Array.isArray(child)) {
423
+ const child = (obj as Record<string, unknown>)[key];
424
+ if (child != null && typeof child === "object" && !Array.isArray(child)) {
412
425
  const childProperty = properties?.[key];
413
426
  const childProperties = childProperty && "properties" in childProperty ? childProperty.properties : undefined;
414
- const childHeadersMapping = buildHeadersMappingFromData([child], childProperties);
427
+ const childHeadersMapping = buildHeadersMappingFromData([child as object], childProperties);
415
428
  Object.entries(childHeadersMapping).forEach(([subKey, mapping]) => {
416
429
  headersMapping[`${key}.${subKey}`] = `${key}.${mapping}`;
417
430
  });
@@ -1,5 +1,5 @@
1
1
  import { getPropertyInPath } from "../../util";
2
- import { AuthController, Entity, EntityCollection, EntityReference, CollectionRegistryController, Properties, Property } from "@rebasepro/types";
2
+ import { AuthController, Entity, EntityCollection, EntityReference, CollectionRegistryController, Properties, Property, Vector } from "@rebasepro/types";
3
3
  import { isPropertyBuilder } from "@rebasepro/common";
4
4
  import { unflattenObject } from "./file_to_json";
5
5
  import { getIn } from "@rebasepro/formex";
@@ -54,14 +54,13 @@ export function convertDataToEntity(authController: AuthController,
54
54
  };
55
55
  }
56
56
 
57
- export function flattenEntry(obj: any, parent = ""): any {
58
- return Object.keys(obj).reduce((acc, key) => {
57
+ export function flattenEntry(obj: Record<string, unknown>, parent = ""): Record<string, unknown> {
58
+ return Object.keys(obj).reduce<Record<string, unknown>>((acc, key) => {
59
59
  const prefixedKey = parent ? `${parent}.${key}` : key;
60
60
 
61
61
  if (typeof obj[key] === "object" && !(obj[key] instanceof Date) && obj[key] !== null && !Array.isArray(obj[key])) {
62
- Object.assign(acc, flattenEntry(obj[key], prefixedKey));
62
+ Object.assign(acc, flattenEntry(obj[key] as Record<string, unknown>, prefixedKey));
63
63
  } else {
64
- // @ts-ignore
65
64
  acc[prefixedKey] = obj[key];
66
65
  }
67
66
 
@@ -78,6 +77,25 @@ export function processValueMapping(authController: AuthController, value: any,
78
77
  const from = inferTypeFromValue(value);
79
78
  const to = usedProperty.type;
80
79
 
80
+ if (to === "vector") {
81
+ if (value && typeof value === "object" && "value" in value && Array.isArray(value.value)) {
82
+ return new Vector(value.value);
83
+ } else if (Array.isArray(value)) {
84
+ return new Vector(value.map(Number));
85
+ } else if (typeof value === "string") {
86
+ let cleaned = value.trim();
87
+ if (cleaned.startsWith("[") && cleaned.endsWith("]")) {
88
+ cleaned = cleaned.slice(1, -1);
89
+ }
90
+ if (cleaned === "") return null;
91
+ return new Vector(cleaned.split(",").map(v => {
92
+ const num = Number(v.trim());
93
+ return isNaN(num) ? 0 : num;
94
+ }));
95
+ }
96
+ return value;
97
+ }
98
+
81
99
  if (from === "array" && to === "array" && Array.isArray(value) && usedProperty.of && !Array.isArray(usedProperty.of) && !isPropertyBuilder(usedProperty.of)) {
82
100
  return value.map(v => processValueMapping(authController, v, navigation, usedProperty.of as Property));
83
101
  } else if (from === "string" && to === "number" && typeof value === "string") {
@@ -1,90 +1,14 @@
1
- import * as XLSX from "xlsx";
2
- export function getXLSXHeaders(sheet: any) {
3
- let header = 0; let offset = 1;
4
- const hdr = [];
5
- const o:any = {};
6
- if (sheet == null || sheet["!ref"] == null) return [];
7
- const range = o.range !== undefined ? o.range : sheet["!ref"];
8
- let r;
9
- if (o.header === 1) header = 1;
10
- else if (o.header === "A") header = 2;
11
- else if (Array.isArray(o.header)) header = 3;
12
- switch (typeof range) {
13
- case "string":
14
- r = safeDecodeRange(range);
15
- break;
16
- case "number":
17
- r = safeDecodeRange(sheet["!ref"]);
18
- r.s.r = range;
19
- break;
20
- default:
21
- r = range;
22
- }
23
- if (header > 0) offset = 0;
24
- const rr = XLSX.utils.encode_row(r.s.r);
25
- const cols = new Array(r.e.c - r.s.c + 1);
26
- for (let C = r.s.c; C <= r.e.c; ++C) {
27
- cols[C] = XLSX.utils.encode_col(C);
28
- const val = sheet[cols[C] + rr];
29
- switch (header) {
30
- case 1:
31
- hdr.push(C);
32
- break;
33
- case 2:
34
- hdr.push(cols[C]);
35
- break;
36
- case 3:
37
- hdr.push(o.header[C - r.s.c]);
38
- break;
39
- default:
40
- if (val === undefined) continue;
41
- hdr.push(XLSX.utils.format_cell(val));
42
- }
43
- }
44
- return hdr;
45
- }
46
-
47
- function safeDecodeRange(range:any) {
48
- const o = {
49
- s: {
50
- c: 0,
51
- r: 0
52
- },
53
- e: {
54
- c: 0,
55
- r: 0
56
- }
57
- };
58
- let idx = 0; let i = 0; let cc = 0;
59
- const len = range.length;
60
- for (idx = 0; i < len; ++i) {
61
- if ((cc = range.charCodeAt(i) - 64) < 1 || cc > 26) break;
62
- idx = 26 * idx + cc;
63
- }
64
- o.s.c = --idx;
65
-
66
- for (idx = 0; i < len; ++i) {
67
- if ((cc = range.charCodeAt(i) - 48) < 0 || cc > 9) break;
68
- idx = 10 * idx + cc;
69
- }
70
- o.s.r = --idx;
71
-
72
- if (i === len || range.charCodeAt(++i) === 58) {
73
- o.e.c = o.s.c;
74
- o.e.r = o.s.r;
75
- return o;
76
- }
77
-
78
- for (idx = 0; i !== len; ++i) {
79
- if ((cc = range.charCodeAt(i) - 64) < 1 || cc > 26) break;
80
- idx = 26 * idx + cc;
81
- }
82
- o.e.c = --idx;
83
-
84
- for (idx = 0; i !== len; ++i) {
85
- if ((cc = range.charCodeAt(i) - 48) < 0 || cc > 9) break;
86
- idx = 10 * idx + cc;
87
- }
88
- o.e.r = --idx;
89
- return o;
1
+ import type { Worksheet } from "exceljs";
2
+
3
+ /**
4
+ * Extract column headers from the first row of an ExcelJS worksheet.
5
+ * Returns an array of header strings in column order.
6
+ */
7
+ export function getWorksheetHeaders(worksheet: Worksheet): string[] {
8
+ const headers: string[] = [];
9
+ const headerRow = worksheet.getRow(1);
10
+ headerRow.eachCell({ includeEmpty: false }, (cell, colNumber) => {
11
+ headers[colNumber - 1] = cell.text ?? `Column${colNumber}`;
12
+ });
13
+ return headers.filter(Boolean);
90
14
  }
@@ -1,5 +1,9 @@
1
- import * as XLSX from "xlsx";
2
- import { getXLSXHeaders } from "./file_headers";
1
+ import ExcelJS from "exceljs";
2
+ import { getWorksheetHeaders } from "./file_headers";
3
+ import { mapJsonParse, unflattenObject } from "./transforms";
4
+
5
+ // Re-export for backwards compat (tests import from this file)
6
+ export { unflattenObject } from "./transforms";
3
7
 
4
8
  type ConversionResult = {
5
9
  data: object[];
@@ -18,7 +22,6 @@ export function convertFileToJson(file: File): Promise<ConversionResult> {
18
22
  if (!Array.isArray(jsonData)) {
19
23
  reject(new Error("JSON file should contain an array of objects"));
20
24
  } else {
21
- // Assuming all objects in the array have the same structure/order
22
25
  const propertiesOrder = jsonData.length > 0 ? Object.keys(jsonData[0]) : [];
23
26
  resolve({
24
27
  data: jsonData,
@@ -34,73 +37,45 @@ export function convertFileToJson(file: File): Promise<ConversionResult> {
34
37
  } else {
35
38
  console.debug("Converting Excel file to JSON", file.name);
36
39
  const reader = new FileReader();
37
- reader.onload = function (e) {
38
- const data = new Uint8Array(e.target?.result as ArrayBuffer);
39
- const workbook = XLSX.read(data, {
40
- type: "array",
41
- codepage: 65001,
42
- cellDates: true
43
- });
44
- const worksheetName = workbook.SheetNames[0];
45
- const worksheet = workbook.Sheets[worksheetName];
46
- const parsedData: Array<any> = XLSX.utils.sheet_to_json(worksheet);
47
- const headers = getXLSXHeaders(worksheet);
48
- const cleanedData = parsedData.map(mapJsonParse);
49
- const jsonData = cleanedData.map(unflattenObject);
50
- resolve({
51
- data: jsonData,
52
- propertiesOrder: headers
53
- });
54
- };
55
- reader.readAsArrayBuffer(file);
56
- }
57
- });
58
- }
59
-
60
- function mapJsonParse(obj: Record<string, any>) {
61
- return Object.keys(obj).reduce((acc: Record<string, any>, key) => {
62
- try {
63
- acc[key] = JSON.parse(obj[key]);
64
- } catch (e) {
65
- acc[key] = obj[key];
66
- }
67
- return acc;
68
- }, {});
69
- }
70
-
71
- /**
72
- * Take an object with keys of type `address.street`, `address.city` and
73
- * convert it to an object with nested objects like `{ address: { street: ..., city: ... } }`
74
- * @param flatObj
75
- */
76
- export function unflattenObject(flatObj: { [key: string]: any }) {
77
- return Object.keys(flatObj).reduce((nestedObj, key) => {
78
- let currentObj = nestedObj;
79
- const keyParts = key.split(".");
80
- keyParts.forEach((keyPart, i) => {
40
+ reader.onload = async function (e) {
41
+ try {
42
+ const buffer = e.target?.result as ArrayBuffer;
43
+ const workbook = new ExcelJS.Workbook();
44
+ await workbook.xlsx.load(buffer);
45
+ const worksheet = workbook.worksheets[0];
46
+ if (!worksheet) {
47
+ reject(new Error("No worksheets found in file"));
48
+ return;
49
+ }
81
50
 
82
- if (/^[\w]+\[\d+\]$/.test(keyPart)) {
83
- const mainPropertyName = keyPart.slice(0, keyPart.indexOf("["));
84
- const index = parseInt(keyPart.slice(keyPart.indexOf("[") + 1, keyPart.indexOf("]")));
51
+ const headers = getWorksheetHeaders(worksheet);
85
52
 
86
- if (!currentObj[mainPropertyName]) {
87
- currentObj[mainPropertyName] = []
88
- }
53
+ // Convert rows to JSON objects (skip header row)
54
+ const parsedData: Array<Record<string, any>> = [];
55
+ worksheet.eachRow({ includeEmpty: false }, (row, rowNumber) => {
56
+ if (rowNumber === 1) return;
57
+ const obj: Record<string, any> = {};
58
+ row.eachCell({ includeEmpty: false }, (cell, colNumber) => {
59
+ const header = headers[colNumber - 1];
60
+ if (header) {
61
+ obj[header] = cell.value;
62
+ }
63
+ });
64
+ parsedData.push(obj);
65
+ });
89
66
 
90
- if (i !== keyParts.length - 1) {
91
- currentObj[mainPropertyName][index] = currentObj[mainPropertyName][index] || {};
92
- currentObj = currentObj[mainPropertyName][index];
93
- } else {
94
- currentObj[mainPropertyName][index] = flatObj[key];
67
+ const cleanedData = parsedData.map(mapJsonParse);
68
+ const jsonData = cleanedData.map(unflattenObject);
69
+ resolve({
70
+ data: jsonData,
71
+ propertiesOrder: headers
72
+ });
73
+ } catch (err) {
74
+ console.error("Error parsing Excel file", err);
75
+ reject(err);
95
76
  }
96
- } else if (i !== keyParts.length - 1) {
97
- currentObj[keyPart] = currentObj[keyPart] || {};
98
- currentObj = currentObj[keyPart];
99
- } else {
100
- currentObj[keyPart] = flatObj[key];
101
- }
102
-
103
- });
104
- return nestedObj;
105
- }, {} as { [key: string]: any });
77
+ };
78
+ reader.readAsArrayBuffer(file);
79
+ }
80
+ });
106
81
  }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Take an object with keys of type `address.street`, `address.city` and
3
+ * convert it to an object with nested objects like `{ address: { street: ..., city: ... } }`
4
+ * @param flatObj
5
+ */
6
+ export function unflattenObject(flatObj: { [key: string]: any }) {
7
+ return Object.keys(flatObj).reduce((nestedObj, key) => {
8
+ let currentObj = nestedObj;
9
+ const keyParts = key.split(".");
10
+ keyParts.forEach((keyPart, i) => {
11
+
12
+ if (/^[\w]+\[\d+\]$/.test(keyPart)) {
13
+ const mainPropertyName = keyPart.slice(0, keyPart.indexOf("["));
14
+ const index = parseInt(keyPart.slice(keyPart.indexOf("[") + 1, keyPart.indexOf("]")));
15
+
16
+ if (!currentObj[mainPropertyName]) {
17
+ currentObj[mainPropertyName] = []
18
+ }
19
+
20
+ if (i !== keyParts.length - 1) {
21
+ currentObj[mainPropertyName][index] = currentObj[mainPropertyName][index] || {};
22
+ currentObj = currentObj[mainPropertyName][index];
23
+ } else {
24
+ currentObj[mainPropertyName][index] = flatObj[key];
25
+ }
26
+ } else if (i !== keyParts.length - 1) {
27
+ currentObj[keyPart] = currentObj[keyPart] || {};
28
+ currentObj = currentObj[keyPart];
29
+ } else {
30
+ currentObj[keyPart] = flatObj[key];
31
+ }
32
+
33
+ });
34
+ return nestedObj;
35
+ }, {} as { [key: string]: any });
36
+ }
37
+
38
+ export function mapJsonParse(obj: Record<string, any>) {
39
+ return Object.keys(obj).reduce((acc: Record<string, any>, key) => {
40
+ try {
41
+ acc[key] = JSON.parse(obj[key]);
42
+ } catch (e) {
43
+ acc[key] = obj[key];
44
+ }
45
+ return acc;
46
+ }, {});
47
+ }
@@ -4,8 +4,23 @@ import { Fragment, DOMParser } from "prosemirror-model";
4
4
  import { useProseMirrorContext } from "../hooks/useProseMirrorContext";
5
5
  import { autoUpdate, computePosition, flip, offset, shift, type VirtualElement } from "@floating-ui/dom";
6
6
  import { SlashCommandPluginKey } from "../plugins/slashCommandPlugin";
7
- import { cls, defaultBorderMixin , iconSize } from "@rebasepro/ui";
8
- import { CheckSquareIcon, Heading1Icon, Heading2Icon, Heading3Icon, Wand2Icon, TableIcon, TypeIcon, ListIcon, ListOrderedIcon, QuoteIcon, CodeIcon, ImageIcon } from "lucide-react";
7
+ import {
8
+ CheckSquareIcon,
9
+ cls,
10
+ CodeIcon,
11
+ defaultBorderMixin,
12
+ Heading1Icon,
13
+ Heading2Icon,
14
+ Heading3Icon,
15
+ iconSize,
16
+ ImageIcon,
17
+ ListIcon,
18
+ ListOrderedIcon,
19
+ QuoteIcon,
20
+ TableIcon,
21
+ TypeIcon,
22
+ Wand2Icon
23
+ } from "@rebasepro/ui";
9
24
  import { setBlockType, wrapIn } from "prosemirror-commands";
10
25
  import { wrapInList } from "prosemirror-schema-list";
11
26
  import { schema } from "../schema";
@@ -1,5 +1,5 @@
1
1
  import { type ComponentPropsWithoutRef, type ReactNode, forwardRef } from "react";
2
- import { Slot } from "@radix-ui/react-slot";
2
+ import { Slot } from "@rebasepro/ui";
3
3
  import { useProseMirrorContext } from "../hooks/useProseMirrorContext";
4
4
 
5
5
  interface EditorBubbleItemProps {
@@ -69,7 +69,7 @@ export const createDropImagePlugin = (upload: UploadFn): Plugin => {
69
69
  const images = files.filter(file => /image/i.test(file.type));
70
70
 
71
71
  if (images.length === 0) {
72
- console.log("No images found in dropped files");
72
+ console.debug("No images found in dropped files");
73
73
  return false;
74
74
  }
75
75
 
@@ -99,7 +99,7 @@ export const createDropImagePlugin = (upload: UploadFn): Plugin => {
99
99
  const images = files.filter(file => /image/i.test(file.type));
100
100
 
101
101
  if (images.length === 0) {
102
- console.log("No images found in dropped files");
102
+ console.debug("No images found in dropped files");
103
103
  return false;
104
104
  }
105
105
 
@@ -1,7 +1,6 @@
1
1
  import type { Dispatch, SetStateAction } from "react";
2
2
  import { EditorBubbleItem } from "../components";
3
- import { Button, Popover } from "@rebasepro/ui";
4
- import { CheckIcon, ChevronDownIcon } from "lucide-react";
3
+ import { Button, CheckIcon, ChevronDownIcon, Popover } from "@rebasepro/ui";
5
4
  import { useProseMirrorContext } from "../hooks/useProseMirrorContext";
6
5
  import { isMarkActive, getMarkAttributes, setMark, unsetMark } from "../utils/prosemirror-utils";
7
6
  import { schema } from "../schema";
@@ -1,6 +1,5 @@
1
1
  import { useEffect, useRef } from "react";
2
- import { Button, cls, focusedDisabled, Popover , iconSize } from "@rebasepro/ui";
3
- import { CheckIcon, Trash2Icon } from "lucide-react";
2
+ import { Button, CheckIcon, cls, focusedDisabled, iconSize, Popover, Trash2Icon } from "@rebasepro/ui";
4
3
  import { useTranslation } from "@rebasepro/core";
5
4
  import { useProseMirrorContext } from "../hooks/useProseMirrorContext";
6
5
  import { getMarkAttributes, isMarkActive, setMark, unsetMark } from "../utils/prosemirror-utils";
@@ -3,8 +3,22 @@ import { EditorState, Transaction } from "prosemirror-state";
3
3
  import { EditorBubbleItem } from "../components";
4
4
  import { useTranslation } from "@rebasepro/core";
5
5
 
6
- import { Button, Popover , iconSize } from "@rebasepro/ui";
7
- import { CheckSquareIcon, Heading3Icon, Heading1Icon, Heading2Icon, CheckIcon, CodeIcon, ListIcon, ListOrderedIcon, QuoteIcon, ChevronDownIcon, TypeIcon } from "lucide-react";
6
+ import {
7
+ Button,
8
+ CheckIcon,
9
+ CheckSquareIcon,
10
+ ChevronDownIcon,
11
+ CodeIcon,
12
+ Heading1Icon,
13
+ Heading2Icon,
14
+ Heading3Icon,
15
+ iconSize,
16
+ ListIcon,
17
+ ListOrderedIcon,
18
+ Popover,
19
+ QuoteIcon,
20
+ TypeIcon
21
+ } from "@rebasepro/ui";
8
22
  import { useProseMirrorContext } from "../hooks/useProseMirrorContext";
9
23
  import { isNodeActive } from "../utils/prosemirror-utils";
10
24
  import { schema } from "../schema";