@rebasepro/cms 0.17.3 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/dist/{CollectionEditorDialog-B-akreOU.js → CollectionEditorDialog-BeX4b92r.js} +13 -7
- package/dist/{CollectionEditorDialog-B-akreOU.js.map → CollectionEditorDialog-BeX4b92r.js.map} +1 -1
- package/dist/{PropertyEditView-CiY84wkR.js → PropertyEditView-C7thfj4L.js} +3 -3
- package/dist/{PropertyEditView-CiY84wkR.js.map → PropertyEditView-C7thfj4L.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-DkAWda4N.js → RouterCollectionsStudioView-BtjzvB6E.js} +4 -4
- package/dist/{RouterCollectionsStudioView-DkAWda4N.js.map → RouterCollectionsStudioView-BtjzvB6E.js.map} +1 -1
- package/dist/{SchemaChangeDialog-DceT8QFX.js → SchemaChangeDialog-CkqK6KOC.js} +4 -2
- package/dist/{SchemaChangeDialog-DceT8QFX.js.map → SchemaChangeDialog-CkqK6KOC.js.map} +1 -1
- package/dist/collection_editor/api/generateCollectionApi.d.ts +1 -2
- package/dist/collection_editor_ui.d.ts +2 -0
- package/dist/collection_editor_ui.js +6 -5
- package/dist/collection_editor_ui.js.map +1 -1
- package/dist/components/DeleteEntityDialog.d.ts +2 -3
- package/dist/components/RebaseLayout.d.ts +11 -4
- package/dist/components/field_configs.d.ts +1 -1
- package/dist/editor/sanitize-html.d.ts +15 -0
- package/dist/editor.js +195 -10
- package/dist/editor.js.map +1 -1
- package/dist/{export-Ben8E355.js → export--arni_VY.js} +2 -2
- package/dist/{export-Ben8E355.js.map → export--arni_VY.js.map} +1 -1
- package/dist/form/components/LabelWithIcon.d.ts +10 -0
- package/dist/{history-DIEVd26f.js → history-C2TpoQwi.js} +2 -2
- package/dist/{history-DIEVd26f.js.map → history-C2TpoQwi.js.map} +1 -1
- package/dist/hooks/navigation/useBuildNavigationStateController.d.ts +1 -1
- package/dist/hooks/navigation/useResolvedViews.d.ts +1 -1
- package/dist/hooks/navigation/useTopLevelNavigation.d.ts +1 -1
- package/dist/{import-D25x7ko-.js → import-DTkXNoBg.js} +2 -2
- package/dist/{import-D25x7ko-.js.map → import-DTkXNoBg.js.map} +1 -1
- package/dist/index.js +78 -33
- package/dist/index.js.map +1 -1
- package/dist/util/propertyConfigMapper.d.ts +1 -1
- package/dist/util-CfLFggP7.js +57 -0
- package/dist/util-CfLFggP7.js.map +1 -0
- package/dist/{util-DVqnqlLn.js → util-DE1WQW6h.js} +134 -112
- package/dist/util-DE1WQW6h.js.map +1 -0
- package/package.json +42 -34
- package/dist/util-DVqnqlLn.js.map +0 -1
- package/src/collection_editor/CollectionEditorDialogsContext.tsx +0 -25
- package/src/collection_editor/ConfigControllerProvider.tsx +0 -395
- package/src/collection_editor/_cms_internals.ts +0 -41
- package/src/collection_editor/api/generateCollectionApi.ts +0 -126
- package/src/collection_editor/api/index.ts +0 -1
- package/src/collection_editor/extensibility_types.ts +0 -168
- package/src/collection_editor/index.ts +0 -108
- package/src/collection_editor/liveSchemaClient.ts +0 -285
- package/src/collection_editor/relation_kinds.ts +0 -44
- package/src/collection_editor/serializable_types.ts +0 -535
- package/src/collection_editor/serializable_utils.ts +0 -729
- package/src/collection_editor/types/collection_editor_controller.tsx +0 -62
- package/src/collection_editor/types/collection_inference.ts +0 -18
- package/src/collection_editor/types/config_controller.tsx +0 -121
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +0 -199
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +0 -51
- package/src/collection_editor/ui/EditorCollectionAction.tsx +0 -54
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +0 -90
- package/src/collection_editor/ui/EditorEntityAction.tsx +0 -50
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +0 -114
- package/src/collection_editor/ui/KanbanSetupAction.tsx +0 -43
- package/src/collection_editor/ui/MissingReferenceWidget.tsx +0 -35
- package/src/collection_editor/ui/NewCollectionButton.tsx +0 -27
- package/src/collection_editor/ui/NewCollectionCard.tsx +0 -48
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +0 -49
- package/src/collection_editor/ui/collection_editor/AICollectionGeneratorPopover.tsx +0 -260
- package/src/collection_editor/ui/collection_editor/AIModifiedPathsContext.tsx +0 -90
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +0 -388
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +0 -1098
- package/src/collection_editor/ui/collection_editor/CollectionEditorWelcomeView.tsx +0 -301
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +0 -172
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +0 -620
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +0 -530
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +0 -462
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +0 -104
- package/src/collection_editor/ui/collection_editor/CollectionYupValidation.tsx +0 -9
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +0 -199
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +0 -315
- package/src/collection_editor/ui/collection_editor/EntityActionsEditTab.tsx +0 -164
- package/src/collection_editor/ui/collection_editor/EntityActionsSelectDialog.tsx +0 -40
- package/src/collection_editor/ui/collection_editor/EntityCustomViewsSelectDialog.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +0 -373
- package/src/collection_editor/ui/collection_editor/GeneralSettingsForm.tsx +0 -288
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +0 -141
- package/src/collection_editor/ui/collection_editor/KanbanConfigSection.tsx +0 -194
- package/src/collection_editor/ui/collection_editor/LayoutModeSwitch.tsx +0 -53
- package/src/collection_editor/ui/collection_editor/PropertyEditView.tsx +0 -980
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +0 -164
- package/src/collection_editor/ui/collection_editor/PropertyTree.tsx +0 -364
- package/src/collection_editor/ui/collection_editor/RouterCollectionStudioView.tsx +0 -44
- package/src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx +0 -41
- package/src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx +0 -470
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +0 -256
- package/src/collection_editor/ui/collection_editor/SwitchControl.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/ViewModeSwitch.tsx +0 -68
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportDataPreview.tsx +0 -67
- package/src/collection_editor/ui/collection_editor/import/CollectionEditorImportMapping.tsx +0 -296
- package/src/collection_editor/ui/collection_editor/import/clean_import_data.ts +0 -57
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +0 -147
- package/src/collection_editor/ui/collection_editor/properties/BooleanPropertyField.tsx +0 -41
- package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +0 -113
- package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +0 -250
- package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +0 -126
- package/src/collection_editor/ui/collection_editor/properties/KeyValuePropertyField.tsx +0 -20
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +0 -153
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +0 -217
- package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +0 -117
- package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +0 -129
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +0 -335
- package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +0 -107
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +0 -403
- package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +0 -148
- package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +0 -91
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +0 -34
- package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +0 -49
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsEditor.tsx +0 -925
- package/src/collection_editor/ui/collection_editor/properties/conditions/ConditionsPanel.tsx +0 -28
- package/src/collection_editor/ui/collection_editor/properties/conditions/EnumConditionsEditor.tsx +0 -626
- package/src/collection_editor/ui/collection_editor/properties/conditions/index.ts +0 -6
- package/src/collection_editor/ui/collection_editor/properties/conditions/property_paths.ts +0 -93
- package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +0 -52
- package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +0 -63
- package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +0 -114
- package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +0 -154
- package/src/collection_editor/ui/collection_editor/properties/validation/ValidationPanel.tsx +0 -28
- package/src/collection_editor/ui/collection_editor/templates/blog_template.ts +0 -112
- package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +0 -183
- package/src/collection_editor/ui/collection_editor/templates/products_template.ts +0 -88
- package/src/collection_editor/ui/collection_editor/templates/users_template.ts +0 -42
- package/src/collection_editor/ui/collection_editor/util.ts +0 -28
- package/src/collection_editor/ui/collection_editor/utils/strings.ts +0 -1
- package/src/collection_editor/ui/collection_editor/utils/supported_fields.tsx +0 -39
- package/src/collection_editor/ui/collection_editor/utils/update_property_for_widget.ts +0 -276
- package/src/collection_editor/useCollectionEditorController.tsx +0 -9
- package/src/collection_editor/useCollectionsConfigController.tsx +0 -9
- package/src/collection_editor/useJsonCollectionsConfigController.tsx +0 -297
- package/src/collection_editor/useLiveSchemaEditing.tsx +0 -315
- package/src/collection_editor/useLocalCollectionsConfigController.tsx +0 -341
- package/src/collection_editor/useSafeSnackbarController.ts +0 -9
- package/src/collection_editor/validateCollectionJson.ts +0 -440
- package/src/collection_editor_ui.ts +0 -21
- package/src/components/AdditionalFieldValue.tsx +0 -68
- package/src/components/AdminModeSyncer.tsx +0 -56
- package/src/components/ArrayContainer.tsx +0 -542
- package/src/components/ClearFilterSortButton.tsx +0 -56
- package/src/components/CollectionEditorDialogs.tsx +0 -69
- package/src/components/CollectionPanel.tsx +0 -179
- package/src/components/CollectionTableBinding/CollectionRowActions.tsx +0 -244
- package/src/components/CollectionTableBinding/CollectionTableBinding.tsx +0 -394
- package/src/components/CollectionTableBinding/CollectionTableBindingProps.tsx +0 -172
- package/src/components/CollectionTableBinding/PropertyTableCell.tsx +0 -350
- package/src/components/CollectionTableBinding/column_utils.tsx +0 -155
- package/src/components/CollectionTableBinding/fields/TableMultipleRelationField.tsx +0 -131
- package/src/components/CollectionTableBinding/fields/TableReferenceField.tsx +0 -193
- package/src/components/CollectionTableBinding/fields/TableRelationField.tsx +0 -192
- package/src/components/CollectionTableBinding/fields/TableRelationSelectorField.tsx +0 -42
- package/src/components/CollectionTableBinding/fields/TableStorageUpload.tsx +0 -324
- package/src/components/CollectionTableBinding/fields/VirtualTableSelect.tsx +0 -132
- package/src/components/CollectionTableBinding/fields/VirtualTableUserSelect.tsx +0 -41
- package/src/components/CollectionTableBinding/index.tsx +0 -14
- package/src/components/CollectionTableBinding/internal/CollectionTableToolbar.tsx +0 -96
- package/src/components/CollectionTableBinding/internal/EntityTableCell.tsx +0 -309
- package/src/components/CollectionTableBinding/internal/EntityTableCellActions.tsx +0 -80
- package/src/components/CollectionTableBinding/internal/common.tsx +0 -74
- package/src/components/CollectionTableBinding/internal/popup_field/PopupFormField.tsx +0 -422
- package/src/components/CollectionTableBinding/internal/popup_field/useDraggable.tsx +0 -99
- package/src/components/CollectionTableBinding/internal/popup_field/useWindowSize.tsx +0 -22
- package/src/components/CollectionTableBinding/table_bindings.tsx +0 -350
- package/src/components/CollectionViewBinding/BoardCardBinding.tsx +0 -263
- package/src/components/CollectionViewBinding/CollectionBoardViewBinding.tsx +0 -662
- package/src/components/CollectionViewBinding/CollectionCardViewBinding.tsx +0 -159
- package/src/components/CollectionViewBinding/CollectionListViewBinding.tsx +0 -1430
- package/src/components/CollectionViewBinding/CollectionViewActions.tsx +0 -227
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +0 -1603
- package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +0 -240
- package/src/components/CollectionViewBinding/EntityCardBinding.tsx +0 -239
- package/src/components/CollectionViewBinding/FilterPresetsButton.tsx +0 -298
- package/src/components/CollectionViewBinding/FiltersDialog.tsx +0 -218
- package/src/components/CollectionViewBinding/SearchExplanation.tsx +0 -106
- package/src/components/CollectionViewBinding/SearchHighlight.tsx +0 -311
- package/src/components/CollectionViewBinding/SlotValue.tsx +0 -156
- package/src/components/CollectionViewBinding/SortButton.tsx +0 -354
- package/src/components/CollectionViewBinding/SplitListCloseButton.tsx +0 -49
- package/src/components/CollectionViewBinding/SplitListShowButton.tsx +0 -28
- package/src/components/CollectionViewBinding/SplitListView.tsx +0 -488
- package/src/components/CollectionViewBinding/SplitViewContext.tsx +0 -34
- package/src/components/CollectionViewBinding/ViewModeToggle.tsx +0 -250
- package/src/components/CollectionViewBinding/hooks/useCollectionInlineEditor.ts +0 -81
- package/src/components/CollectionViewBinding/hooks/useKanbanDragAndDrop.ts +0 -181
- package/src/components/CollectionViewBinding/useBoardDataController.tsx +0 -802
- package/src/components/CollectionViewBinding/usePreviewSlots.ts +0 -703
- package/src/components/CollectionViewBinding/useSelectionController.tsx +0 -40
- package/src/components/CollectionViewBinding/utils.ts +0 -22
- package/src/components/DefaultAppBar.tsx +0 -264
- package/src/components/DefaultDrawer.tsx +0 -593
- package/src/components/DeleteEntityDialog.tsx +0 -205
- package/src/components/DetailViewBinding.tsx +0 -731
- package/src/components/DrawerNavigationGroup.tsx +0 -141
- package/src/components/DrawerNavigationItem.tsx +0 -115
- package/src/components/EditFormActions.tsx +0 -303
- package/src/components/EditViewBinding.tsx +0 -1069
- package/src/components/EntityDisplayHeader.tsx +0 -170
- package/src/components/EntityIdentityBar.tsx +0 -428
- package/src/components/EntityInspector.tsx +0 -156
- package/src/components/EntityPreviewBinding.tsx +0 -432
- package/src/components/EntityPreviewNesting.tsx +0 -50
- package/src/components/EntityViewBinding.tsx +0 -374
- package/src/components/FieldCaption.tsx +0 -14
- package/src/components/HomePage/ContentHomePage.tsx +0 -586
- package/src/components/HomePage/FavouritesView.tsx +0 -60
- package/src/components/HomePage/HomePageDnD.tsx +0 -704
- package/src/components/HomePage/NavigationCard.tsx +0 -81
- package/src/components/HomePage/NavigationCardBinding.tsx +0 -107
- package/src/components/HomePage/NavigationGroup.tsx +0 -156
- package/src/components/HomePage/RenameGroupDialog.tsx +0 -123
- package/src/components/HomePage/SmallNavigationCard.tsx +0 -41
- package/src/components/HomePage/index.tsx +0 -5
- package/src/components/InlineEntityPreview.tsx +0 -149
- package/src/components/JsonPreviewBinding.tsx +0 -66
- package/src/components/PropertyCollectionView.tsx +0 -336
- package/src/components/PropertyConfigBadge.tsx +0 -28
- package/src/components/PropertyIdCopyTooltip.tsx +0 -47
- package/src/components/RebaseAuthGate.tsx +0 -44
- package/src/components/RebaseCMS.tsx +0 -30
- package/src/components/RebaseLayout.tsx +0 -80
- package/src/components/RebaseNavigation.tsx +0 -369
- package/src/components/RebaseRouteDefs.tsx +0 -127
- package/src/components/RebaseShell.tsx +0 -83
- package/src/components/ReferenceTable/SelectionTableBinding.tsx +0 -389
- package/src/components/ReferenceWidget.tsx +0 -156
- package/src/components/RelationSelector.tsx +0 -926
- package/src/components/SearchIconsView.tsx +0 -78
- package/src/components/SelectableTable/SelectableTable.tsx +0 -309
- package/src/components/SelectableTable/SelectableTableContext.tsx +0 -7
- package/src/components/SelectableTable/SelectionStore.ts +0 -43
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +0 -59
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +0 -146
- package/src/components/SelectableTable/filters/FilterFieldBinding.tsx +0 -190
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +0 -250
- package/src/components/SelectableTable/filters/RelationFilterField.tsx +0 -238
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +0 -282
- package/src/components/SelectableTable/filters/null_filter.ts +0 -63
- package/src/components/SideDialogs.tsx +0 -238
- package/src/components/SidePanelBinding.tsx +0 -361
- package/src/components/SidePanelProvider.tsx +0 -80
- package/src/components/UserSelector.tsx +0 -513
- package/src/components/admin/CreationResultDialog.tsx +0 -138
- package/src/components/admin/index.ts +0 -1
- package/src/components/app/AppBar.tsx +0 -17
- package/src/components/app/Drawer.tsx +0 -38
- package/src/components/app/Scaffold.tsx +0 -366
- package/src/components/app/index.ts +0 -4
- package/src/components/app/useApp.tsx +0 -36
- package/src/components/common/default_entity_actions.tsx +0 -440
- package/src/components/common/index.ts +0 -1
- package/src/components/field_configs.tsx +0 -506
- package/src/components/history/EntityHistoryEntry.tsx +0 -203
- package/src/components/history/EntityHistoryView.tsx +0 -206
- package/src/components/history/LastEditedByFormAction.tsx +0 -24
- package/src/components/history/LastEditedByIndicator.tsx +0 -95
- package/src/components/history/UserChip.tsx +0 -15
- package/src/components/history/index.tsx +0 -5
- package/src/components/index.ts +0 -63
- package/src/contexts/BreacrumbsContext.tsx +0 -45
- package/src/contexts/SideDialogsControllerContext.tsx +0 -5
- package/src/contexts/SidePanelControllerContext.tsx +0 -5
- package/src/data_export/export/BasicExportAction.tsx +0 -142
- package/src/data_export/export/ExportCollectionAction.tsx +0 -321
- package/src/data_export/export/export.ts +0 -295
- package/src/data_export/export/fetch_export_data.ts +0 -90
- package/src/data_export/export/index.ts +0 -4
- package/src/data_export/index.ts +0 -1
- package/src/data_import/components/DataNewPropertiesMapping.tsx +0 -261
- package/src/data_import/components/ImportFileUpload.tsx +0 -42
- package/src/data_import/components/ImportNewPropertyFieldPreview.tsx +0 -58
- package/src/data_import/components/ImportSaveInProgress.tsx +0 -121
- package/src/data_import/components/index.ts +0 -4
- package/src/data_import/hooks/index.ts +0 -1
- package/src/data_import/hooks/useImportConfig.tsx +0 -34
- package/src/data_import/import/ImportCollectionAction.tsx +0 -461
- package/src/data_import/import/index.ts +0 -1
- package/src/data_import/index.ts +0 -5
- package/src/data_import/types/column_mapping.ts +0 -32
- package/src/data_import/types/index.ts +0 -1
- package/src/data_import/utils/csv.ts +0 -153
- package/src/data_import/utils/data.ts +0 -181
- package/src/data_import/utils/file_headers.ts +0 -14
- package/src/data_import/utils/file_to_json.ts +0 -149
- package/src/data_import/utils/get_import_inference_type.ts +0 -33
- package/src/data_import/utils/get_properties_mapping.ts +0 -67
- package/src/data_import/utils/index.ts +0 -5
- package/src/data_import/utils/save_entities.ts +0 -138
- package/src/data_import/utils/transforms.ts +0 -70
- package/src/editor/components/SlashCommandMenu.tsx +0 -532
- package/src/editor/components/editor-bubble-item.tsx +0 -32
- package/src/editor/components/editor-bubble.tsx +0 -143
- package/src/editor/components/image-bubble.tsx +0 -183
- package/src/editor/components/index.ts +0 -14
- package/src/editor/components/table-bubble.tsx +0 -233
- package/src/editor/editor.tsx +0 -529
- package/src/editor/extensions/HighlightDecorationExtension.ts +0 -115
- package/src/editor/extensions/Image.ts +0 -159
- package/src/editor/extensions/TextLoadingDecorationExtension.tsx +0 -107
- package/src/editor/extensions/clipboard.ts +0 -72
- package/src/editor/extensions/custom-keymap.ts +0 -25
- package/src/editor/extensions/drag-and-drop.tsx +0 -508
- package/src/editor/hooks/useProseMirror.ts +0 -126
- package/src/editor/hooks/useProseMirrorContext.ts +0 -15
- package/src/editor/index.ts +0 -2
- package/src/editor/markdown-it-plugins.d.ts +0 -24
- package/src/editor/markdown.ts +0 -204
- package/src/editor/nodeViews/ImageComponent.tsx +0 -20
- package/src/editor/nodeViews/ReactNodeView.tsx +0 -89
- package/src/editor/nodeViews/TaskItemComponent.tsx +0 -30
- package/src/editor/nodeViews/index.ts +0 -35
- package/src/editor/plugins/index.ts +0 -58
- package/src/editor/plugins/inputrules.ts +0 -82
- package/src/editor/plugins/placeholderPlugin.ts +0 -55
- package/src/editor/plugins/slashCommandPlugin.ts +0 -65
- package/src/editor/schema.ts +0 -339
- package/src/editor/selectors/ai-selector.tsx +0 -110
- package/src/editor/selectors/color-selector.tsx +0 -199
- package/src/editor/selectors/link-selector.tsx +0 -122
- package/src/editor/selectors/node-selector.tsx +0 -159
- package/src/editor/selectors/text-buttons.tsx +0 -79
- package/src/editor/types.ts +0 -6
- package/src/editor/useProseMirror.ts +0 -125
- package/src/editor/utils/prosemirror-utils.ts +0 -113
- package/src/editor/utils/remove_classes.ts +0 -18
- package/src/editor/utils/useDebouncedCallback.ts +0 -25
- package/src/form/EntityForm.tsx +0 -761
- package/src/form/EntityFormActions.tsx +0 -160
- package/src/form/EntityFormBinding.tsx +0 -342
- package/src/form/PropertyFieldBinding.tsx +0 -348
- package/src/form/components/ErrorFocus.tsx +0 -44
- package/src/form/components/FieldBlock.tsx +0 -189
- package/src/form/components/FieldHelperText.tsx +0 -84
- package/src/form/components/FormRail.tsx +0 -153
- package/src/form/components/FormSections.tsx +0 -145
- package/src/form/components/LabelWithIcon.tsx +0 -43
- package/src/form/components/LabelWithIconAndTooltip.tsx +0 -28
- package/src/form/components/LocalChangesMenu.tsx +0 -147
- package/src/form/components/StorageItemPreview.tsx +0 -81
- package/src/form/components/StorageUploadProgress.tsx +0 -118
- package/src/form/components/index.tsx +0 -6
- package/src/form/components/useRailVisible.tsx +0 -47
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +0 -109
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +0 -172
- package/src/form/field_bindings/BinaryFieldBinding.tsx +0 -177
- package/src/form/field_bindings/BlockFieldBinding.tsx +0 -282
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +0 -78
- package/src/form/field_bindings/GeopointFieldBinding.tsx +0 -200
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +0 -574
- package/src/form/field_bindings/MapFieldBinding.tsx +0 -120
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +0 -259
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +0 -130
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +0 -168
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +0 -94
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +0 -146
- package/src/form/field_bindings/RelationFieldBinding.tsx +0 -202
- package/src/form/field_bindings/RepeatFieldBinding.tsx +0 -143
- package/src/form/field_bindings/SelectFieldBinding.tsx +0 -111
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +0 -521
- package/src/form/field_bindings/SwitchFieldBinding.tsx +0 -70
- package/src/form/field_bindings/TextFieldBinding.tsx +0 -189
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +0 -71
- package/src/form/field_bindings/VectorFieldBinding.tsx +0 -209
- package/src/form/form_utils.ts +0 -243
- package/src/form/index.tsx +0 -36
- package/src/form/useClearRestoreValue.tsx +0 -36
- package/src/form/useUndoableDiscard.ts +0 -39
- package/src/form/validation.ts +0 -583
- package/src/hooks/index.ts +0 -16
- package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +0 -22
- package/src/hooks/navigation/contexts/NavigationStateContext.tsx +0 -16
- package/src/hooks/navigation/contexts/UrlContext.tsx +0 -24
- package/src/hooks/navigation/contexts/index.ts +0 -14
- package/src/hooks/navigation/useAsyncResolver.ts +0 -100
- package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +0 -218
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +0 -134
- package/src/hooks/navigation/useBuildUrlController.tsx +0 -66
- package/src/hooks/navigation/useNavigationResolution.ts +0 -271
- package/src/hooks/navigation/useResolvedCollections.ts +0 -102
- package/src/hooks/navigation/useResolvedViews.tsx +0 -139
- package/src/hooks/navigation/useTopLevelNavigation.ts +0 -273
- package/src/hooks/navigation/utils.ts +0 -200
- package/src/hooks/useAdminContext.tsx +0 -83
- package/src/hooks/useBreadcrumbsController.tsx +0 -17
- package/src/hooks/useBuildSideDialogsController.tsx +0 -145
- package/src/hooks/useBuildSidePanel.tsx +0 -315
- package/src/hooks/useChildViewSource.ts +0 -46
- package/src/hooks/useEntityDisplay.tsx +0 -262
- package/src/hooks/useEntityDisplayTitle.tsx +0 -49
- package/src/hooks/useHistory.ts +0 -178
- package/src/hooks/useRecordActions.tsx +0 -69
- package/src/hooks/useResolvedNavigationFrom.tsx +0 -167
- package/src/hooks/useResolvedUsers.ts +0 -148
- package/src/hooks/useSelectionDialog.tsx +0 -58
- package/src/hooks/useSideDialogsController.tsx +0 -25
- package/src/hooks/useSidePanel.tsx +0 -13
- package/src/index.ts +0 -124
- package/src/preview/PropertyPreview.tsx +0 -331
- package/src/preview/compact_text.ts +0 -68
- package/src/preview/components/ArrayEnumPreview.tsx +0 -39
- package/src/preview/components/BooleanPreview.tsx +0 -28
- package/src/preview/components/DatePreview.tsx +0 -106
- package/src/preview/components/EmptyValue.tsx +0 -10
- package/src/preview/components/EnumValuesChip.tsx +0 -39
- package/src/preview/components/ImagePreview.tsx +0 -144
- package/src/preview/components/InlineEntityListPreview.tsx +0 -42
- package/src/preview/components/ReferencePreview.tsx +0 -235
- package/src/preview/components/RelationPreview.tsx +0 -271
- package/src/preview/components/StorageThumbnail.tsx +0 -147
- package/src/preview/components/UrlComponentPreview.tsx +0 -116
- package/src/preview/components/UserPreview.tsx +0 -30
- package/src/preview/components/date_fns_locales.ts +0 -125
- package/src/preview/index.ts +0 -26
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +0 -73
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +0 -67
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +0 -77
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +0 -49
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +0 -70
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +0 -79
- package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +0 -35
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +0 -79
- package/src/preview/property_previews/MapPropertyPreview.tsx +0 -198
- package/src/preview/property_previews/NumberPropertyPreview.tsx +0 -39
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +0 -276
- package/src/preview/property_previews/StringPropertyPreview.tsx +0 -70
- package/src/preview/util.ts +0 -39
- package/src/routes/CustomViewRoute.tsx +0 -33
- package/src/routes/RebaseRoute.tsx +0 -467
- package/src/routes/index.ts +0 -2
- package/src/types/components/EntityFormActionsProps.tsx +0 -20
- package/src/types/components/EntityFormProps.tsx +0 -119
- package/src/types/components/PropertyPreviewProps.tsx +0 -85
- package/src/types/components/formex.tsx +0 -2
- package/src/types/components/index.ts +0 -3
- package/src/types/fields.tsx +0 -340
- package/src/types/index.ts +0 -4
- package/src/util/dataControllerAdapter.ts +0 -88
- package/src/util/entity_actions.ts +0 -28
- package/src/util/index.ts +0 -5
- package/src/util/navigation_utils.ts +0 -89
- package/src/util/number_format.ts +0 -46
- package/src/util/previews.ts +0 -131
- package/src/util/propertyConfigMapper.ts +0 -134
- package/src/util/property_utils.tsx +0 -236
- package/src/util/resolutions.ts +0 -96
- package/src/util/view_constants.ts +0 -33
- package/src/util/view_mode.ts +0 -176
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
import React, { useMemo } from "react";
|
|
2
|
-
import type { SearchMatch } from "@rebasepro/types";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Showing a searcher *why* a row is in their results.
|
|
6
|
-
*
|
|
7
|
-
* A ranked list answers "which rows" and never "why this one". When the term is
|
|
8
|
-
* in the title that is self-evident; when it is in a field the list does not
|
|
9
|
-
* show — a certification, a nested answer, a note — the row looks arbitrary and
|
|
10
|
-
* the only way to find out is to open it. That is the whole reason this exists.
|
|
11
|
-
*
|
|
12
|
-
* Two jobs, and they are deliberately separate:
|
|
13
|
-
*
|
|
14
|
-
* 1. {@link Highlighted} marks the term inside a value the list already shows.
|
|
15
|
-
* 2. {@link offSlotMatch} finds a match in a field that has no slot, so the
|
|
16
|
-
* caller can put it where the subtitle would have gone.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
/** `<mark>` is Postgres's delimiter, and what `ts_headline` emits. */
|
|
20
|
-
const MARK = /(<mark>.*?<\/mark>)/g;
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Render a `ts_headline` snippet: text with `<mark>` around each hit.
|
|
24
|
-
*
|
|
25
|
-
* Split-and-render rather than `dangerouslySetInnerHTML`. The text around the
|
|
26
|
-
* marks is whatever a user typed into their own record, and the only markup it
|
|
27
|
-
* is allowed to carry is the highlight Postgres put there. Anything else stays
|
|
28
|
-
* inert text.
|
|
29
|
-
*/
|
|
30
|
-
/**
|
|
31
|
-
* Context kept before and after a hit, in characters.
|
|
32
|
-
*
|
|
33
|
-
* Asymmetric on purpose. The snippet renders on one truncated line, so anything
|
|
34
|
-
* before the hit competes with the hit itself for the width available — with a
|
|
35
|
-
* generous lead-in the mark is pushed off the right edge and the reader sees a
|
|
36
|
-
* fragment with nothing highlighted in it, which is worse than no snippet at
|
|
37
|
-
* all. Lead with just enough to not start abruptly, then run on.
|
|
38
|
-
*/
|
|
39
|
-
const SNIPPET_LEAD = 16;
|
|
40
|
-
const SNIPPET_TRAIL = 90;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Pull the first mark near the front of the snippet.
|
|
44
|
-
*
|
|
45
|
-
* The snippet renders on one truncated line whose width is not knowable here —
|
|
46
|
-
* a list column is wide, the same list beside an open record is not. Whatever
|
|
47
|
-
* precedes the mark competes with it for that width, and when the mark loses
|
|
48
|
-
* the reader gets a fragment of their record with nothing highlighted in it,
|
|
49
|
-
* which reads as the feature being broken rather than as a narrow column.
|
|
50
|
-
*
|
|
51
|
-
* `ts_headline` centres its fragment on the match, so roughly half the window
|
|
52
|
-
* is lead-in; that is the right shape for a paragraph and the wrong one for a
|
|
53
|
-
* line. Trimming here rather than asking Postgres for a smaller window keeps
|
|
54
|
-
* the trailing context, which is what actually explains the hit — and applies
|
|
55
|
-
* the same shape to the snippets built in the browser, so a row looks the same
|
|
56
|
-
* whichever path produced it.
|
|
57
|
-
*/
|
|
58
|
-
export function trimSnippetLead(text: string, lead: number = SNIPPET_LEAD): string {
|
|
59
|
-
const at = text.indexOf("<mark>");
|
|
60
|
-
if (at < 0 || at <= lead) return text;
|
|
61
|
-
// Trim the lead-in only. Running the word-boundary strip over the whole
|
|
62
|
-
// remainder eats the mark itself when the lead is short enough that the
|
|
63
|
-
// slice opens on `<mark>`, which has no space in it to stop at.
|
|
64
|
-
const head = text.slice(at - lead, at).replace(/^\S*\s/, "");
|
|
65
|
-
return "…" + head + text.slice(at);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function Snippet({ text, className }: { text: string; className?: string }) {
|
|
69
|
-
const parts = useMemo(() => trimSnippetLead(text).split(MARK), [text]);
|
|
70
|
-
return (
|
|
71
|
-
<span className={className}>
|
|
72
|
-
{parts.map((part, i) =>
|
|
73
|
-
part.startsWith("<mark>")
|
|
74
|
-
? (
|
|
75
|
-
<mark
|
|
76
|
-
key={i}
|
|
77
|
-
className="bg-amber-200/70 dark:bg-amber-400/30 text-inherit rounded-[3px] px-[1px]"
|
|
78
|
-
>
|
|
79
|
-
{part.slice(6, -7)}
|
|
80
|
-
</mark>
|
|
81
|
-
)
|
|
82
|
-
: <React.Fragment key={i}>{part}</React.Fragment>
|
|
83
|
-
)}
|
|
84
|
-
</span>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Mark every occurrence of the searched terms inside a plain value.
|
|
90
|
-
*
|
|
91
|
-
* Used for values the list already renders, where the server's snippet would be
|
|
92
|
-
* the wrong thing to show: the snippet is truncated to a fragment and folded to
|
|
93
|
-
* the indexed form, while the cell should keep the record's real text. So the
|
|
94
|
-
* terms are re-matched here, on the display value.
|
|
95
|
-
*
|
|
96
|
-
* Deliberately dumber than the server's matching, and it has to be: this cannot
|
|
97
|
-
* stem or unaccent without reimplementing the text search configuration in the
|
|
98
|
-
* browser and getting it subtly different. It marks what it can find as a
|
|
99
|
-
* prefix, case- and accent-insensitively, and marks nothing when it cannot —
|
|
100
|
-
* a highlight that is merely absent reads as "no hit in this field", which is
|
|
101
|
-
* the honest answer for a stem the browser cannot reproduce.
|
|
102
|
-
*/
|
|
103
|
-
export function Highlighted({ text, terms, className }: { text: string; terms: string[]; className?: string }) {
|
|
104
|
-
const segments = useMemo(() => splitOnTerms(text, terms), [text, terms]);
|
|
105
|
-
if (segments.length <= 1) return <span className={className}>{text}</span>;
|
|
106
|
-
return (
|
|
107
|
-
<span className={className}>
|
|
108
|
-
{segments.map((seg, i) =>
|
|
109
|
-
seg.hit
|
|
110
|
-
? (
|
|
111
|
-
<mark
|
|
112
|
-
key={i}
|
|
113
|
-
className="bg-amber-200/70 dark:bg-amber-400/30 text-inherit rounded-[3px] px-[1px]"
|
|
114
|
-
>
|
|
115
|
-
{seg.text}
|
|
116
|
-
</mark>
|
|
117
|
-
)
|
|
118
|
-
: <React.Fragment key={i}>{seg.text}</React.Fragment>
|
|
119
|
-
)}
|
|
120
|
-
</span>
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/** Strip diacritics so `gestion` marks `gestión`, mirroring the index's unaccent. */
|
|
125
|
-
const fold = (value: string): string =>
|
|
126
|
-
value.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
|
|
127
|
-
|
|
128
|
-
interface Segment { text: string; hit: boolean }
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Split `text` into hit / non-hit runs.
|
|
132
|
-
*
|
|
133
|
-
* Matches on the *folded* form but slices the original, so the marked text
|
|
134
|
-
* keeps its accents and case — `Gestión`, not `gestion`. Folding is
|
|
135
|
-
* length-preserving for the diacritics this handles, which is what makes the
|
|
136
|
-
* indices transferable; a fold that changed length would misalign the slices.
|
|
137
|
-
*/
|
|
138
|
-
export function splitOnTerms(text: string, terms: string[]): Segment[] {
|
|
139
|
-
const haystack = fold(text);
|
|
140
|
-
const needles = terms.map(fold).filter(t => t.length >= 2);
|
|
141
|
-
if (needles.length === 0) return [{ text, hit: false }];
|
|
142
|
-
|
|
143
|
-
// Word-start matches only. A search for "iso" marking the "iso" inside
|
|
144
|
-
// "revisor" is noise, and reads as a bug rather than a feature.
|
|
145
|
-
const bounds: [number, number][] = [];
|
|
146
|
-
for (const needle of needles) {
|
|
147
|
-
let from = 0;
|
|
148
|
-
for (;;) {
|
|
149
|
-
const at = haystack.indexOf(needle, from);
|
|
150
|
-
if (at === -1) break;
|
|
151
|
-
const before = at === 0 ? " " : haystack[at - 1];
|
|
152
|
-
if (!/[\p{L}\p{N}]/u.test(before)) bounds.push([at, at + needle.length]);
|
|
153
|
-
from = at + needle.length;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (bounds.length === 0) return [{ text, hit: false }];
|
|
157
|
-
|
|
158
|
-
// Merge overlaps so two terms hitting the same run mark it once.
|
|
159
|
-
bounds.sort((a, b) => a[0] - b[0]);
|
|
160
|
-
const merged: [number, number][] = [];
|
|
161
|
-
for (const [start, end] of bounds) {
|
|
162
|
-
const last = merged[merged.length - 1];
|
|
163
|
-
if (last && start <= last[1]) last[1] = Math.max(last[1], end);
|
|
164
|
-
else merged.push([start, end]);
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const segments: Segment[] = [];
|
|
168
|
-
let cursor = 0;
|
|
169
|
-
for (const [start, end] of merged) {
|
|
170
|
-
if (start > cursor) segments.push({ text: text.slice(cursor, start), hit: false });
|
|
171
|
-
segments.push({ text: text.slice(start, end), hit: true });
|
|
172
|
-
cursor = end;
|
|
173
|
-
}
|
|
174
|
-
if (cursor < text.length) segments.push({ text: text.slice(cursor), hit: false });
|
|
175
|
-
return segments;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
/**
|
|
179
|
-
* The terms a searcher typed, as things to look for in a rendered value.
|
|
180
|
-
*
|
|
181
|
-
* Quoted phrases stay whole; `-excluded` terms are dropped, since marking a
|
|
182
|
-
* word the user asked *not* to see would be actively wrong. `websearch_to_tsquery`
|
|
183
|
-
* reads the same syntax on the server.
|
|
184
|
-
*/
|
|
185
|
-
export function searchTerms(searchString: string | undefined): string[] {
|
|
186
|
-
if (!searchString) return [];
|
|
187
|
-
const terms: string[] = [];
|
|
188
|
-
for (const [, phrase, bare] of searchString.matchAll(/"([^"]+)"|(\S+)/g)) {
|
|
189
|
-
const term = phrase ?? bare;
|
|
190
|
-
if (!term || term.startsWith("-")) continue;
|
|
191
|
-
if (/^(or|and)$/i.test(term)) continue;
|
|
192
|
-
terms.push(term);
|
|
193
|
-
}
|
|
194
|
-
return terms;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* The best match to show when the term is nowhere the list already displays.
|
|
199
|
-
*
|
|
200
|
-
* `shownKeys` are the property paths the row is already rendering, so a match
|
|
201
|
-
* there needs no explaining — {@link Highlighted} marks it in place and the
|
|
202
|
-
* subtitle keeps its own job. Anything else is invisible, and one of those is
|
|
203
|
-
* what the subtitle slot gets replaced with.
|
|
204
|
-
*
|
|
205
|
-
* The first such match wins, and the server returns them in the order the
|
|
206
|
-
* collection declared its `search` fields — so the field an author put first is
|
|
207
|
-
* the one a reader sees, rather than whichever the database aggregated first.
|
|
208
|
-
*/
|
|
209
|
-
export function offSlotMatch(
|
|
210
|
-
matches: SearchMatch[] | undefined,
|
|
211
|
-
shownKeys: (string | undefined)[]
|
|
212
|
-
): SearchMatch | undefined {
|
|
213
|
-
if (!matches || matches.length === 0) return undefined;
|
|
214
|
-
const shown = new Set(shownKeys.filter((k): k is string => Boolean(k)));
|
|
215
|
-
return matches.find(m => !shown.has(m.field));
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// ── Finding the match locally ───────────────────────────────────────────────
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Where a search term appears in a row, computed from the row itself.
|
|
222
|
-
*
|
|
223
|
-
* The server can say this too — `_matches`, from `ts_headline` — and its answer
|
|
224
|
-
* is better, because it knows the stemming the index used. This exists because
|
|
225
|
-
* the admin cannot rely on getting it: rows reach the panel over three
|
|
226
|
-
* different transports (REST, the realtime socket, the offline cache) and only
|
|
227
|
-
* one of them carries query metadata. A feature that explains a result on some
|
|
228
|
-
* loads and not others is worse than one that always gives a slightly simpler
|
|
229
|
-
* answer.
|
|
230
|
-
*
|
|
231
|
-
* So: use the server's when it is there, fall back to this. Both produce the
|
|
232
|
-
* same `{ field, snippet }` shape, and this one marks with the same `<mark>`.
|
|
233
|
-
*/
|
|
234
|
-
export function localRowMatch(
|
|
235
|
-
values: Record<string, unknown> | undefined,
|
|
236
|
-
properties: Record<string, unknown> | undefined,
|
|
237
|
-
terms: string[],
|
|
238
|
-
shownKeys: (string | undefined)[]
|
|
239
|
-
): SearchMatch | undefined {
|
|
240
|
-
if (!values || !properties || terms.length === 0) return undefined;
|
|
241
|
-
const shown = new Set(shownKeys.filter((k): k is string => Boolean(k)));
|
|
242
|
-
|
|
243
|
-
// Declared order, so the field an author put first wins — the same rule the
|
|
244
|
-
// server's `_matches` follows.
|
|
245
|
-
for (const [key, property] of Object.entries(properties)) {
|
|
246
|
-
if (shown.has(key)) continue;
|
|
247
|
-
const found = findInValue(values[key], terms, key, property as { type?: string });
|
|
248
|
-
if (found) return found;
|
|
249
|
-
}
|
|
250
|
-
return undefined;
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
function findInValue(
|
|
254
|
-
value: unknown,
|
|
255
|
-
terms: string[],
|
|
256
|
-
path: string,
|
|
257
|
-
property: { type?: string } | undefined
|
|
258
|
-
): SearchMatch | undefined {
|
|
259
|
-
// An enum renders as a chip from a fixed vocabulary; marking inside one
|
|
260
|
-
// reads as noise, and `where` is the right tool for those anyway.
|
|
261
|
-
if (property && "enum" in property && property.enum) return undefined;
|
|
262
|
-
|
|
263
|
-
if (typeof value === "string") {
|
|
264
|
-
const snippet = snippetAround(value, terms);
|
|
265
|
-
return snippet ? { field: path, snippet } : undefined;
|
|
266
|
-
}
|
|
267
|
-
if (Array.isArray(value)) {
|
|
268
|
-
for (const item of value) {
|
|
269
|
-
const found = findInValue(item, terms, path, undefined);
|
|
270
|
-
if (found) return found;
|
|
271
|
-
}
|
|
272
|
-
return undefined;
|
|
273
|
-
}
|
|
274
|
-
if (value && typeof value === "object") {
|
|
275
|
-
// Nested maps: report the path the author would recognise, which is the
|
|
276
|
-
// dotted one the `search` block uses.
|
|
277
|
-
for (const [key, nested] of Object.entries(value as Record<string, unknown>)) {
|
|
278
|
-
const found = findInValue(nested, terms, `${path}.${key}`, undefined);
|
|
279
|
-
if (found) return found;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
return undefined;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
/**
|
|
286
|
-
* The text around the first hit, with every hit in view marked.
|
|
287
|
-
*
|
|
288
|
-
* Trimmed to a readable window rather than the whole field: a match in a long
|
|
289
|
-
* body should show the sentence it is in, not the first line of the document,
|
|
290
|
-
* and certainly not the document.
|
|
291
|
-
*/
|
|
292
|
-
export function snippetAround(text: string, terms: string[]): string | undefined {
|
|
293
|
-
const segments = splitOnTerms(text, terms);
|
|
294
|
-
const firstHit = segments.findIndex(s => s.hit);
|
|
295
|
-
if (firstHit === -1) return undefined;
|
|
296
|
-
|
|
297
|
-
const before = segments.slice(0, firstHit).map(s => s.text).join("");
|
|
298
|
-
const head = before.length > SNIPPET_LEAD
|
|
299
|
-
// Start at a word boundary so the snippet does not open mid-word.
|
|
300
|
-
? "…" + before.slice(before.length - SNIPPET_LEAD).replace(/^\S*\s/, "")
|
|
301
|
-
: before;
|
|
302
|
-
|
|
303
|
-
let out = head;
|
|
304
|
-
for (let i = firstHit; i < segments.length; i++) {
|
|
305
|
-
const seg = segments[i];
|
|
306
|
-
out += seg.hit ? `<mark>${seg.text}</mark>` : seg.text;
|
|
307
|
-
// Enough context after the hit to read it, then stop.
|
|
308
|
-
if (out.length > head.length + SNIPPET_TRAIL) { out += "…"; break; }
|
|
309
|
-
}
|
|
310
|
-
return out.trim();
|
|
311
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import type { PreviewSize } from "../../types/components/PropertyPreviewProps";
|
|
3
|
-
import { PropertyPreview } from "../../preview";
|
|
4
|
-
import { StorageThumbnail } from "../../preview/components/StorageThumbnail";
|
|
5
|
-
import { UrlComponentPreview } from "../../preview/components/UrlComponentPreview";
|
|
6
|
-
import { Chip } from "@rebasepro/ui";
|
|
7
|
-
import type { PreviewSlot } from "./usePreviewSlots";
|
|
8
|
-
|
|
9
|
-
export interface SlotValueProps {
|
|
10
|
-
slot: PreviewSlot | undefined;
|
|
11
|
-
size: PreviewSize;
|
|
12
|
-
/**
|
|
13
|
-
* Relations and references render as one line of linked text rather than as
|
|
14
|
-
* a card. Defaults to true: a slot is a line in a row or a card, and a
|
|
15
|
-
* relation that renders its own bordered card there — with its own id line
|
|
16
|
-
* and its own side-panel button — is a card inside a card.
|
|
17
|
-
*
|
|
18
|
-
* Pass `false` only for a slot with room for one, which in practice is
|
|
19
|
-
* none of them.
|
|
20
|
-
*/
|
|
21
|
-
textOnly?: boolean;
|
|
22
|
-
/** Images only: fill the container rather than fitting inside it. */
|
|
23
|
-
fill?: boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* One display slot, rendered.
|
|
28
|
-
*
|
|
29
|
-
* A slot's value arrives one of two ways and they cannot be rendered the same:
|
|
30
|
-
*
|
|
31
|
-
* - **From a property** — render it with that property's own preview, so an
|
|
32
|
-
* enum status keeps its colour, a date keeps its format and a storage path
|
|
33
|
-
* becomes a thumbnail. This is why a declared path beats a resolver whenever
|
|
34
|
-
* the value is actually on the record.
|
|
35
|
-
* - **From a resolver** — there is no property, because the value was computed
|
|
36
|
-
* or fetched. All that can be said about it is that it is text.
|
|
37
|
-
*
|
|
38
|
-
* The branch lives here, once, rather than at each of the fourteen places the
|
|
39
|
-
* list row, the card and the board card render a slot. That count is the reason:
|
|
40
|
-
* the last time a rule like this was inlined per call site, it drifted into
|
|
41
|
-
* seven versions.
|
|
42
|
-
*/
|
|
43
|
-
export function SlotValue({ slot, size, textOnly = true, fill }: SlotValueProps) {
|
|
44
|
-
|
|
45
|
-
if (!slot || slot.value === undefined || slot.value === null) return null;
|
|
46
|
-
|
|
47
|
-
if (!slot.property || !slot.propertyKey) {
|
|
48
|
-
// A computed image is still an image. "There is no property, so all that
|
|
49
|
-
// can be said about it is that it is text" holds for a title and fails
|
|
50
|
-
// here: `display.image` accepts "a storage path or a URL … so a resolver
|
|
51
|
-
// may return either", and both used to be printed as their own string
|
|
52
|
-
// inside the image frame.
|
|
53
|
-
if (slot.role === "image" && typeof slot.value === "string" && slot.value.trim()) {
|
|
54
|
-
return <ComputedImage value={slot.value.trim()} size={size} fill={fill}/>;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// Computed. Arrays (a `tags` resolver) join rather than rendering as
|
|
58
|
-
// "[object Object]" via String().
|
|
59
|
-
const text = Array.isArray(slot.value)
|
|
60
|
-
? slot.value.map(item => String(item)).join(", ")
|
|
61
|
-
: String(slot.value);
|
|
62
|
-
return <>{text}</>;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return <PropertyPreview
|
|
66
|
-
propertyKey={slot.propertyKey}
|
|
67
|
-
value={slot.value as never}
|
|
68
|
-
property={slot.property}
|
|
69
|
-
size={size}
|
|
70
|
-
textOnly={textOnly}
|
|
71
|
-
fill={fill}/>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* The `tags` slot, as chips beside the status.
|
|
76
|
-
*
|
|
77
|
-
* Honours both arms the same way the rest of the file does. A declared **path**
|
|
78
|
-
* goes through {@link SlotValue}, so an array of enum values keeps its own
|
|
79
|
-
* colours — that is the stated advantage of naming a property. A **resolver**
|
|
80
|
-
* returns bare strings with no property to render them as, so they become plain
|
|
81
|
-
* chips; a single string is accepted as one tag, which the role's type documents.
|
|
82
|
-
*
|
|
83
|
-
* Lives here rather than in the list, the card and the board card because that is
|
|
84
|
-
* three copies of the same decision, and this file exists to hold exactly one.
|
|
85
|
-
*/
|
|
86
|
-
export function TagChips({ slot, max = 4 }: { slot: PreviewSlot, max?: number }) {
|
|
87
|
-
|
|
88
|
-
if (slot.property && slot.propertyKey) {
|
|
89
|
-
return <SlotValue slot={slot} size="small"/>;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const values = (Array.isArray(slot.value) ? slot.value : [slot.value])
|
|
93
|
-
.filter(item => item !== undefined && item !== null && String(item).trim() !== "")
|
|
94
|
-
.map(item => String(item));
|
|
95
|
-
|
|
96
|
-
if (values.length === 0) return null;
|
|
97
|
-
|
|
98
|
-
const shown = values.slice(0, max);
|
|
99
|
-
const hidden = values.length - shown.length;
|
|
100
|
-
|
|
101
|
-
return <>
|
|
102
|
-
{shown.map(value => (
|
|
103
|
-
<Chip key={value}
|
|
104
|
-
size="smallest"
|
|
105
|
-
className="!text-[10px] !leading-tight !py-0 shrink-0 max-w-[100px] truncate">
|
|
106
|
-
{value}
|
|
107
|
-
</Chip>
|
|
108
|
-
))}
|
|
109
|
-
{hidden > 0 && (
|
|
110
|
-
<span className="text-[10px] text-surface-400 dark:text-surface-500 shrink-0">+{hidden}</span>
|
|
111
|
-
)}
|
|
112
|
-
</>;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Whether a computed image string can be fetched as-is, or has to be resolved
|
|
117
|
-
* through storage first.
|
|
118
|
-
*
|
|
119
|
-
* Exported because it is the whole decision: rendering either branch needs a
|
|
120
|
-
* provider (a storage source, a DOM), and the thing worth pinning is which
|
|
121
|
-
* branch a given string takes. `//host/x` is protocol-relative and equally
|
|
122
|
-
* fetchable; `data:` and `blob:` are already the bytes.
|
|
123
|
-
*/
|
|
124
|
-
export function isFetchableImageUrl(value: string): boolean {
|
|
125
|
-
return /^(https?:)?\/\//i.test(value) || /^(data|blob):/i.test(value);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* A string a resolver returned for the `image` role, rendered as a picture.
|
|
130
|
-
*
|
|
131
|
-
* Two things can arrive here and they need different handling, which is the whole
|
|
132
|
-
* reason a property-path image is preferable: a storage property knows which
|
|
133
|
-
* backend holds it, and a bare string does not.
|
|
134
|
-
*
|
|
135
|
-
* - An **absolute URL** is already fetchable. Rendering it through the storage
|
|
136
|
-
* layer would ask a bucket to sign a path that was never in it.
|
|
137
|
-
* - Anything else is read as a **storage path** on the default source, which is
|
|
138
|
-
* the only source a value with no property can be attributed to. A resolver
|
|
139
|
-
* pointing at a named source should name the property instead.
|
|
140
|
-
*/
|
|
141
|
-
function ComputedImage({ value, size, fill }: { value: string, size: PreviewSize, fill?: boolean }) {
|
|
142
|
-
const isAbsolute = isFetchableImageUrl(value);
|
|
143
|
-
|
|
144
|
-
if (isAbsolute) {
|
|
145
|
-
return <UrlComponentPreview previewType="image"
|
|
146
|
-
url={value}
|
|
147
|
-
size={size}
|
|
148
|
-
fill={fill}
|
|
149
|
-
hint={value}/>;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
return <StorageThumbnail storagePathOrDownloadUrl={value}
|
|
153
|
-
storeUrl={false}
|
|
154
|
-
size={size}
|
|
155
|
-
fill={fill}/>;
|
|
156
|
-
}
|