@rebasepro/admin 0.2.1 → 0.2.4
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/dist/{CollectionEditorDialog-BXIh2AXg.js → CollectionEditorDialog-D0VqpLPO.js} +73 -256
- package/dist/CollectionEditorDialog-D0VqpLPO.js.map +1 -0
- package/dist/{CollectionsStudioView-jR8iz_ja.js → CollectionsStudioView-Bc3Rxxc2.js} +5 -4
- package/dist/{CollectionsStudioView-jR8iz_ja.js.map → CollectionsStudioView-Bc3Rxxc2.js.map} +1 -1
- package/dist/{ExportCollectionAction-CMdiiv1L.js → ExportCollectionAction-Ckc-09BQ.js} +4 -3
- package/dist/ExportCollectionAction-Ckc-09BQ.js.map +1 -0
- package/dist/{ImportCollectionAction-C05lE0IW.js → ImportCollectionAction-BqjIrC3Z.js} +3 -2
- package/dist/{ImportCollectionAction-C05lE0IW.js.map → ImportCollectionAction-BqjIrC3Z.js.map} +1 -1
- package/dist/{PropertyEditView-BB5xjnhZ.js → PropertyEditView-CvRSV-A2.js} +430 -445
- package/dist/PropertyEditView-CvRSV-A2.js.map +1 -0
- package/dist/collection_editor/ConfigControllerProvider.d.ts +0 -5
- package/dist/collection_editor/index.d.ts +0 -1
- package/dist/collection_editor/types/collection_editor_controller.d.ts +0 -2
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +3 -3
- package/dist/collection_editor/ui/collection_editor/properties/RelationPropertyField.d.ts +1 -7
- package/dist/collection_editor_ui.js +3 -3
- package/dist/components/ArrayContainer.d.ts +2 -2
- package/dist/components/DefaultAppBar.d.ts +18 -1
- package/dist/components/DefaultDrawer.d.ts +51 -3
- package/dist/components/EntityCollectionTable/fields/TableStorageUpload.d.ts +2 -2
- package/dist/components/EntityCollectionTable/internal/EntityTableCell.d.ts +2 -2
- package/dist/components/EntityCollectionTable/table_bindings.d.ts +4 -3
- package/dist/components/EntityCollectionView/hooks/useKanbanDragAndDrop.d.ts +4 -3
- package/dist/components/EntityEditView.d.ts +2 -1
- package/dist/components/HomePage/HomePageDnD.d.ts +3 -3
- package/dist/components/PropertyCollectionView.d.ts +1 -1
- package/dist/components/PropertyIdCopyTooltip.d.ts +1 -1
- package/dist/components/SelectableTable/SelectionStore.d.ts +4 -1
- package/dist/components/SelectableTable/filters/BooleanFilterField.d.ts +2 -2
- package/dist/components/SelectableTable/filters/DateTimeFilterField.d.ts +2 -2
- package/dist/components/SelectableTable/filters/ReferenceFilterField.d.ts +2 -2
- package/dist/components/SelectableTable/filters/StringNumberFilterField.d.ts +2 -2
- package/dist/components/admin/RolesView.d.ts +3 -3
- package/dist/components/admin/UsersView.d.ts +3 -3
- package/dist/components/app/Drawer.d.ts +8 -1
- package/dist/data_export/export/export.d.ts +3 -3
- package/dist/editor/components/editor-bubble.d.ts +5 -1
- package/dist/editor/components/image-bubble.d.ts +5 -1
- package/dist/editor/components/index.d.ts +3 -3
- package/dist/editor/components/table-bubble.d.ts +5 -1
- package/dist/editor/nodeViews/ReactNodeView.d.ts +4 -1
- package/dist/editor/useProseMirror.d.ts +2 -2
- package/dist/editor/utils/remove_classes.d.ts +1 -1
- package/dist/editor.js +15 -14
- package/dist/editor.js.map +1 -1
- package/dist/form/EntityForm.d.ts +2 -2
- package/dist/form/components/StorageUploadProgress.d.ts +2 -2
- package/dist/form/field_bindings/MultiSelectFieldBinding.d.ts +1 -1
- package/dist/form/field_bindings/StorageUploadFieldBinding.d.ts +1 -1
- package/dist/form/validation.d.ts +3 -3
- package/dist/hooks/navigation/useResolvedCollections.d.ts +6 -0
- package/dist/hooks/navigation/useResolvedViews.d.ts +3 -4
- package/dist/{index-BAM9KCmM.js → index-BCcLwgfe.js} +3 -2
- package/dist/{index-BAM9KCmM.js.map → index-BCcLwgfe.js.map} +1 -1
- package/dist/{index-D5OQhv-T.js → index-DY2k5TtG.js} +3 -3
- package/dist/index-DY2k5TtG.js.map +1 -0
- package/dist/{index-CoSNm3e3.js → index-UQOMHwt1.js} +3 -3
- package/dist/index-UQOMHwt1.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2813 -372
- package/dist/index.js.map +1 -1
- package/dist/{markdown-z2Ir7Cgo.js → markdown-DD2JDU1X.js} +2 -2
- package/dist/markdown-DD2JDU1X.js.map +1 -0
- package/dist/preview/components/UrlComponentPreview.d.ts +1 -0
- package/dist/types/components/EntityFormActionsProps.d.ts +1 -1
- package/dist/types/components/EntityFormProps.d.ts +2 -2
- package/dist/types/fields.d.ts +1 -1
- package/dist/{util-DtbWD7LF.js → util-ZM9gQuCv.js} +2104 -2071
- package/dist/util-ZM9gQuCv.js.map +1 -0
- package/package.json +10 -9
- package/src/collection_editor/ConfigControllerProvider.tsx +3 -13
- package/src/collection_editor/index.ts +1 -3
- package/src/collection_editor/types/collection_editor_controller.tsx +0 -3
- package/src/collection_editor/ui/EditorCollectionAction.tsx +1 -6
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +1 -6
- package/src/collection_editor/ui/EditorEntityAction.tsx +1 -6
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +7 -14
- package/src/collection_editor/ui/NewCollectionCard.tsx +1 -5
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +3 -8
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +1 -10
- package/src/collection_editor/ui/collection_editor/CollectionJsonImportDialog.tsx +8 -12
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +21 -21
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +4 -4
- package/src/collection_editor/ui/collection_editor/EnumForm.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/properties/BlockPropertyField.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/properties/CommonPropertyFields.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/properties/DateTimePropertyField.tsx +8 -8
- package/src/collection_editor/ui/collection_editor/properties/EnumPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/MarkdownPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/NumberPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/RelationPropertyField.tsx +37 -57
- package/src/collection_editor/ui/collection_editor/properties/RepeatPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/StoragePropertyField.tsx +8 -8
- package/src/collection_editor/ui/collection_editor/properties/StringPropertyField.tsx +5 -5
- package/src/collection_editor/ui/collection_editor/properties/UrlPropertyField.tsx +3 -2
- package/src/collection_editor/ui/collection_editor/properties/VectorPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/validation/ArrayPropertyValidation.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/validation/GeneralPropertyValidation.tsx +1 -1
- package/src/collection_editor/ui/collection_editor/properties/validation/NumberPropertyValidation.tsx +4 -7
- package/src/collection_editor/ui/collection_editor/properties/validation/StringPropertyValidation.tsx +4 -4
- package/src/collection_editor/validateCollectionJson.ts +88 -1
- package/src/components/ArrayContainer.tsx +3 -3
- package/src/components/DefaultAppBar.tsx +52 -31
- package/src/components/DefaultDrawer.tsx +279 -66
- package/src/components/DrawerNavigationItem.tsx +1 -1
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +6 -5
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +9 -7
- package/src/components/EntityCollectionTable/fields/TableStorageUpload.tsx +5 -5
- package/src/components/EntityCollectionTable/fields/VirtualTableNumberInput.tsx +12 -9
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +2 -2
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +1 -1
- package/src/components/EntityCollectionTable/table_bindings.tsx +5 -4
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +6 -4
- package/src/components/EntityCollectionView/hooks/useCollectionInlineEditor.ts +1 -1
- package/src/components/EntityCollectionView/hooks/useKanbanDragAndDrop.ts +7 -6
- package/src/components/EntityDetailView.tsx +46 -24
- package/src/components/EntityEditView.tsx +51 -28
- package/src/components/EntityEditViewFormActions.tsx +4 -4
- package/src/components/EntityPreview.tsx +9 -4
- package/src/components/HomePage/HomePageDnD.tsx +3 -2
- package/src/components/PropertyCollectionView.tsx +1 -1
- package/src/components/PropertyIdCopyTooltip.tsx +1 -1
- package/src/components/RebaseLayout.tsx +5 -1
- package/src/components/RebaseNavigation.tsx +2 -2
- package/src/components/RebaseRouteDefs.tsx +4 -7
- package/src/components/RebaseShell.tsx +16 -13
- package/src/components/SearchIconsView.tsx +1 -8
- package/src/components/SelectableTable/SelectableTable.tsx +8 -11
- package/src/components/SelectableTable/SelectionStore.ts +1 -1
- package/src/components/SelectableTable/filters/BooleanFilterField.tsx +3 -3
- package/src/components/SelectableTable/filters/DateTimeFilterField.tsx +3 -3
- package/src/components/SelectableTable/filters/ReferenceFilterField.tsx +5 -5
- package/src/components/SelectableTable/filters/StringNumberFilterField.tsx +3 -3
- package/src/components/SideEntityProvider.tsx +2 -1
- package/src/components/admin/RolesView.tsx +7 -2
- package/src/components/admin/UsersView.tsx +12 -6
- package/src/components/app/Drawer.tsx +9 -1
- package/src/components/app/Scaffold.tsx +5 -1
- package/src/data_export/export/export.ts +17 -17
- package/src/data_import/components/DataNewPropertiesMapping.tsx +1 -1
- package/src/editor/components/editor-bubble.tsx +32 -9
- package/src/editor/components/image-bubble.tsx +27 -11
- package/src/editor/components/index.ts +3 -3
- package/src/editor/components/table-bubble.tsx +79 -17
- package/src/editor/extensions/HighlightDecorationExtension.ts +3 -2
- package/src/editor/nodeViews/ReactNodeView.tsx +1 -1
- package/src/editor/nodeViews/TaskItemComponent.tsx +9 -8
- package/src/editor/schema.ts +135 -59
- package/src/editor/selectors/link-selector.tsx +8 -5
- package/src/editor/useProseMirror.ts +2 -2
- package/src/editor/utils/remove_classes.ts +6 -5
- package/src/form/EntityForm.tsx +15 -15
- package/src/form/EntityFormActions.tsx +2 -2
- package/src/form/PropertyFieldBinding.tsx +64 -64
- package/src/form/components/FieldHelperText.tsx +4 -4
- package/src/form/components/StorageUploadProgress.tsx +2 -2
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +1 -1
- package/src/form/field_bindings/BlockFieldBinding.tsx +54 -53
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +290 -289
- package/src/form/field_bindings/MapFieldBinding.tsx +2 -2
- package/src/form/field_bindings/MultiSelectFieldBinding.tsx +2 -2
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +1 -1
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +8 -6
- package/src/form/field_bindings/RelationFieldBinding.tsx +4 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +1 -1
- package/src/form/field_bindings/SelectFieldBinding.tsx +1 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +84 -84
- package/src/form/field_bindings/SwitchFieldBinding.tsx +16 -16
- package/src/form/field_bindings/TextFieldBinding.tsx +77 -73
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +17 -17
- package/src/form/validation.ts +43 -43
- package/src/hooks/navigation/useBuildNavigationStateController.tsx +3 -5
- package/src/hooks/navigation/useResolvedCollections.ts +27 -7
- package/src/hooks/navigation/useResolvedViews.tsx +24 -44
- package/src/index.ts +2 -0
- package/src/preview/PropertyPreview.tsx +2 -2
- package/src/preview/components/ImagePreview.tsx +2 -1
- package/src/preview/components/UrlComponentPreview.tsx +11 -2
- package/src/preview/components/UserPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +2 -2
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +4 -4
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayOfStorageComponentsPreview.tsx +3 -3
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +3 -2
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +6 -8
- package/src/preview/property_previews/ArrayPropertyEnumPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +3 -3
- package/src/preview/property_previews/MapPropertyPreview.tsx +4 -3
- package/src/preview/property_previews/NumberPropertyPreview.tsx +5 -3
- package/src/preview/property_previews/StringPropertyPreview.tsx +10 -8
- package/src/types/components/EntityFormActionsProps.tsx +1 -1
- package/src/types/components/EntityFormProps.tsx +2 -2
- package/src/types/fields.tsx +2 -2
- package/dist/CollectionEditorDialog-BXIh2AXg.js.map +0 -1
- package/dist/ContentHomePage-BQZWuOFb.js +0 -1784
- package/dist/ContentHomePage-BQZWuOFb.js.map +0 -1
- package/dist/ExportCollectionAction-CMdiiv1L.js.map +0 -1
- package/dist/PropertyEditView-BB5xjnhZ.js.map +0 -1
- package/dist/RoleChip-QtUFXeTp.js +0 -67
- package/dist/RoleChip-QtUFXeTp.js.map +0 -1
- package/dist/RolesView-CULIHWZ9.js +0 -437
- package/dist/RolesView-CULIHWZ9.js.map +0 -1
- package/dist/UsersView-D7_AtJ44.js +0 -408
- package/dist/UsersView-D7_AtJ44.js.map +0 -1
- package/dist/collection_editor/types/config_permissions.d.ts +0 -19
- package/dist/index-CoSNm3e3.js.map +0 -1
- package/dist/index-D5OQhv-T.js.map +0 -1
- package/dist/markdown-z2Ir7Cgo.js.map +0 -1
- package/dist/util-DtbWD7LF.js.map +0 -1
- package/src/collection_editor/types/config_permissions.ts +0 -20
|
@@ -44,8 +44,27 @@ export type DefaultAppBarProps<ADDITIONAL_PROPS = object> = {
|
|
|
44
44
|
|
|
45
45
|
dropDownActions?: React.ReactNode;
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Whether to render the dark/light/system mode toggle in the app bar.
|
|
49
|
+
* Set to `false` when the drawer owns this action.
|
|
50
|
+
* @default true
|
|
51
|
+
*/
|
|
47
52
|
includeModeToggle?: boolean;
|
|
48
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Whether to render the language switcher in the app bar.
|
|
56
|
+
* Set to `false` when the drawer owns this action.
|
|
57
|
+
* @default true
|
|
58
|
+
*/
|
|
59
|
+
includeLanguageToggle?: boolean;
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Whether to render the user avatar / menu in the app bar.
|
|
63
|
+
* Set to `false` when the drawer owns this action.
|
|
64
|
+
* @default true
|
|
65
|
+
*/
|
|
66
|
+
includeUserMenu?: boolean;
|
|
67
|
+
|
|
49
68
|
className?: string;
|
|
50
69
|
|
|
51
70
|
style?: React.CSSProperties;
|
|
@@ -67,6 +86,8 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
67
86
|
startAdornment,
|
|
68
87
|
dropDownActions,
|
|
69
88
|
includeModeToggle = true,
|
|
89
|
+
includeLanguageToggle = true,
|
|
90
|
+
includeUserMenu = true,
|
|
70
91
|
className,
|
|
71
92
|
style,
|
|
72
93
|
user: userProp,
|
|
@@ -193,8 +214,6 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
193
214
|
</div>
|
|
194
215
|
{startAdornment}
|
|
195
216
|
|
|
196
|
-
{startAdornment}
|
|
197
|
-
|
|
198
217
|
<div className={"grow"}/>
|
|
199
218
|
|
|
200
219
|
{endAdornment &&
|
|
@@ -202,7 +221,7 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
202
221
|
{endAdornment}
|
|
203
222
|
</ErrorBoundary>}
|
|
204
223
|
|
|
205
|
-
<LanguageToggle/>
|
|
224
|
+
{includeLanguageToggle && <LanguageToggle/>}
|
|
206
225
|
|
|
207
226
|
{includeModeToggle &&
|
|
208
227
|
<Menu
|
|
@@ -220,34 +239,36 @@ export const DefaultAppBar = function DefaultAppBar({
|
|
|
220
239
|
size={iconSize.smallest}/>{t("system_mode")}</MenuItem>
|
|
221
240
|
</Menu>}
|
|
222
241
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
{
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
242
|
+
|
|
243
|
+
{includeUserMenu &&
|
|
244
|
+
<Menu trigger={<div aria-label="User menu" role="button">{avatarComponent}</div>}>
|
|
245
|
+
{user && <div className={"px-4 py-2 mb-2"}>
|
|
246
|
+
{user.displayName && <Typography variant={"body1"} color={"secondary"}>
|
|
247
|
+
{user.displayName}
|
|
248
|
+
</Typography>}
|
|
249
|
+
{user.email && <Typography variant={"body2"} color={"secondary"}>
|
|
250
|
+
{user.email}
|
|
251
|
+
</Typography>}
|
|
252
|
+
</div>}
|
|
253
|
+
|
|
254
|
+
{dropDownActions}
|
|
255
|
+
|
|
256
|
+
{!dropDownActions && <>
|
|
257
|
+
<MenuItem onClick={() => navigate("/settings")}>
|
|
258
|
+
<SettingsIcon/>
|
|
259
|
+
{t("account_settings")}
|
|
260
|
+
</MenuItem>
|
|
261
|
+
<MenuItem onClick={async () => {
|
|
262
|
+
await authController.signOut();
|
|
263
|
+
// replace current route with home
|
|
264
|
+
navigate("/");
|
|
265
|
+
}}>
|
|
266
|
+
<LogOutIcon/>
|
|
267
|
+
{t("log_out")}
|
|
268
|
+
</MenuItem>
|
|
269
|
+
</>}
|
|
270
|
+
|
|
271
|
+
</Menu>}
|
|
251
272
|
|
|
252
273
|
</div>
|
|
253
274
|
);
|
|
@@ -1,32 +1,77 @@
|
|
|
1
1
|
import type { NavigationEntry, NavigationResult } from "@rebasepro/types";
|
|
2
2
|
import React, { useMemo } from "react";
|
|
3
3
|
|
|
4
|
-
import { useCollapsedGroups, buildCollapsedDefaults, useLargeLayout, useAdminModeController, useTranslation, useSlot, useRebaseContext, useAnalyticsController, useRebaseRegistry } from "@rebasepro/core";
|
|
4
|
+
import { useCollapsedGroups, buildCollapsedDefaults, useLargeLayout, useAdminModeController, useAuthController, useModeController, useTranslation, useSlot, useRebaseContext, useAnalyticsController, useRebaseRegistry } from "@rebasepro/core";
|
|
5
5
|
import { useUrlController } from "../hooks/navigation/contexts/UrlContext";
|
|
6
6
|
import { useNavigationStateController } from "../hooks/navigation/contexts/NavigationStateContext";
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
import { Link, useNavigate } from "react-router-dom";
|
|
10
10
|
import { AnalyticsEvent } from "@rebasepro/types";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
Avatar,
|
|
13
|
+
ChevronsLeftIcon,
|
|
14
|
+
ChevronsRightIcon,
|
|
15
|
+
cls,
|
|
16
|
+
iconSize,
|
|
17
|
+
IconButton,
|
|
18
|
+
LanguagesIcon,
|
|
19
|
+
LogOutIcon,
|
|
20
|
+
Menu,
|
|
21
|
+
MenuItem,
|
|
22
|
+
MoonIcon,
|
|
23
|
+
Separator,
|
|
24
|
+
SettingsIcon,
|
|
25
|
+
Skeleton,
|
|
26
|
+
SunIcon,
|
|
27
|
+
SunMoonIcon,
|
|
28
|
+
Tooltip,
|
|
29
|
+
Typography
|
|
30
|
+
} from "@rebasepro/ui";
|
|
12
31
|
import { DrawerNavigationGroup } from "./DrawerNavigationGroup";
|
|
13
|
-
import { RebaseLogo } from "@rebasepro/core";
|
|
32
|
+
import { LanguageToggle, RebaseLogo } from "@rebasepro/core";
|
|
14
33
|
import { useApp } from "./app/useApp";
|
|
15
34
|
|
|
16
35
|
/**
|
|
17
|
-
* Default drawer used in the CMS
|
|
36
|
+
* Default drawer used in the CMS.
|
|
37
|
+
*
|
|
38
|
+
* When no `children` are provided, renders the full CMS navigation
|
|
39
|
+
* (collection groups, mode switch, plugin slots).
|
|
40
|
+
*
|
|
41
|
+
* When `children` **are** provided, renders the shared drawer shell
|
|
42
|
+
* (logo, scrollable area, footer actions, collapse toggle) with the
|
|
43
|
+
* custom content injected in the scrollable area. This lets consumers
|
|
44
|
+
* like the SaaS dashboard reuse the identical structural layout while
|
|
45
|
+
* supplying their own navigation items.
|
|
46
|
+
*
|
|
18
47
|
* @group Core
|
|
19
48
|
*/
|
|
20
49
|
export function DefaultDrawer({
|
|
21
50
|
title,
|
|
22
51
|
logo,
|
|
23
52
|
logoDestination,
|
|
53
|
+
children,
|
|
54
|
+
footerActions,
|
|
24
55
|
className,
|
|
25
56
|
style
|
|
26
57
|
}: {
|
|
27
58
|
title?: React.ReactNode;
|
|
28
59
|
logo?: string;
|
|
29
60
|
logoDestination?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Custom navigation content for the drawer.
|
|
63
|
+
* When provided, replaces the default CMS navigation (collection groups,
|
|
64
|
+
* mode switch, slots). The shared shell (logo, scroll area, footer
|
|
65
|
+
* actions, collapse toggle) is still rendered around it.
|
|
66
|
+
*/
|
|
67
|
+
children?: React.ReactNode;
|
|
68
|
+
/**
|
|
69
|
+
* Custom content for the drawer footer actions area (language, theme, user menu).
|
|
70
|
+
* - `undefined` — renders the default `DrawerFooterActions`.
|
|
71
|
+
* - `null` — renders nothing (hides the footer actions).
|
|
72
|
+
* - `ReactNode` — renders the provided custom content.
|
|
73
|
+
*/
|
|
74
|
+
footerActions?: React.ReactNode | null;
|
|
30
75
|
className?: string;
|
|
31
76
|
style?: React.CSSProperties;
|
|
32
77
|
}) {
|
|
@@ -36,13 +81,11 @@ export function DefaultDrawer({
|
|
|
36
81
|
drawerOpen,
|
|
37
82
|
openDrawer,
|
|
38
83
|
closeDrawer,
|
|
39
|
-
closeHover,
|
|
40
84
|
logo: appLogo
|
|
41
85
|
} = useApp();
|
|
42
86
|
|
|
43
87
|
const resolvedLogo = logo ?? appLogo;
|
|
44
88
|
|
|
45
|
-
const [adminMenuOpen, setAdminMenuOpen] = React.useState(false);
|
|
46
89
|
const scrollRef = React.useRef<HTMLDivElement>(null);
|
|
47
90
|
const [scrolled, setScrolled] = React.useState(false);
|
|
48
91
|
|
|
@@ -52,6 +95,64 @@ export function DefaultDrawer({
|
|
|
52
95
|
}
|
|
53
96
|
};
|
|
54
97
|
|
|
98
|
+
return (
|
|
99
|
+
<div role="navigation" aria-label="Main navigation" className={cls("flex flex-col h-full relative grow w-full", className)} style={style}>
|
|
100
|
+
|
|
101
|
+
<DrawerLogo
|
|
102
|
+
logo={resolvedLogo}
|
|
103
|
+
title={title}
|
|
104
|
+
logoDestination={logoDestination}
|
|
105
|
+
drawerOpen={drawerOpen}
|
|
106
|
+
drawerHovered={drawerHovered}
|
|
107
|
+
/>
|
|
108
|
+
|
|
109
|
+
<div
|
|
110
|
+
ref={scrollRef}
|
|
111
|
+
onScroll={handleScroll}
|
|
112
|
+
className={"flex-grow min-h-0 overflow-y-auto overflow-x-hidden no-scrollbar px-2"}
|
|
113
|
+
style={{
|
|
114
|
+
maskImage: scrolled
|
|
115
|
+
? "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)"
|
|
116
|
+
: "linear-gradient(to bottom, black 0, black calc(100% - 20px), transparent 100%)"
|
|
117
|
+
}}>
|
|
118
|
+
{children ?? <CMSNavigationContent />}
|
|
119
|
+
</div>
|
|
120
|
+
|
|
121
|
+
{footerActions !== null && (
|
|
122
|
+
footerActions !== undefined
|
|
123
|
+
? footerActions
|
|
124
|
+
: <DrawerFooterActions
|
|
125
|
+
drawerOpen={drawerOpen}
|
|
126
|
+
drawerHovered={drawerHovered}
|
|
127
|
+
/>
|
|
128
|
+
)}
|
|
129
|
+
|
|
130
|
+
<DrawerToggle
|
|
131
|
+
drawerOpen={drawerOpen}
|
|
132
|
+
drawerHovered={drawerHovered}
|
|
133
|
+
openDrawer={openDrawer}
|
|
134
|
+
closeDrawer={closeDrawer}
|
|
135
|
+
/>
|
|
136
|
+
</div>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Default CMS navigation content — rendered inside DefaultDrawer when no
|
|
142
|
+
* custom `children` are provided. Contains the mode switch, navigation
|
|
143
|
+
* groups, and header / footer plugin slots.
|
|
144
|
+
*/
|
|
145
|
+
function CMSNavigationContent() {
|
|
146
|
+
|
|
147
|
+
const {
|
|
148
|
+
drawerHovered,
|
|
149
|
+
drawerOpen,
|
|
150
|
+
closeDrawer,
|
|
151
|
+
closeHover
|
|
152
|
+
} = useApp();
|
|
153
|
+
|
|
154
|
+
const [adminMenuOpen, setAdminMenuOpen] = React.useState(false);
|
|
155
|
+
|
|
55
156
|
const analyticsController = useAnalyticsController();
|
|
56
157
|
const navigationState = useNavigationStateController();
|
|
57
158
|
const context = useRebaseContext();
|
|
@@ -94,8 +195,6 @@ context });
|
|
|
94
195
|
if (!navigationState.topLevelNavigation)
|
|
95
196
|
return null;
|
|
96
197
|
|
|
97
|
-
const groups = navigationState.topLevelNavigation.groups;
|
|
98
|
-
|
|
99
198
|
const onItemClick = (view: NavigationEntry) => {
|
|
100
199
|
const eventName: AnalyticsEvent = view.type === "collection"
|
|
101
200
|
? "drawer_navigate_to_collection"
|
|
@@ -108,69 +207,37 @@ context });
|
|
|
108
207
|
}
|
|
109
208
|
};
|
|
110
209
|
|
|
111
|
-
const isStudioDark = adminModeController.mode === "studio";
|
|
112
210
|
const drawerVisuallyOpen = drawerOpen || drawerHovered;
|
|
113
211
|
|
|
114
212
|
return (
|
|
115
213
|
<>
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
<DrawerLogo
|
|
119
|
-
logo={resolvedLogo}
|
|
120
|
-
title={title}
|
|
121
|
-
logoDestination={logoDestination}
|
|
214
|
+
{registry.studioConfig && (
|
|
215
|
+
<DrawerModeSwitch
|
|
122
216
|
drawerOpen={drawerOpen}
|
|
123
217
|
drawerHovered={drawerHovered}
|
|
124
218
|
/>
|
|
219
|
+
)}
|
|
125
220
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
221
|
+
{headerSlot}
|
|
222
|
+
|
|
223
|
+
{groupsToRender.map((group) => {
|
|
224
|
+
const entriesInGroup = filteredEntries.filter(e => e.group === group);
|
|
225
|
+
return (
|
|
226
|
+
<DrawerNavigationGroup
|
|
227
|
+
key={`drawer_group_${group}`}
|
|
228
|
+
group={group}
|
|
229
|
+
entries={entriesInGroup}
|
|
230
|
+
collapsed={isGroupCollapsed(group)}
|
|
231
|
+
onToggleCollapsed={() => toggleGroupCollapsed(group)}
|
|
232
|
+
drawerOpen={drawerVisuallyOpen}
|
|
233
|
+
tooltipsOpen={tooltipsOpen}
|
|
234
|
+
adminMenuOpen={adminMenuOpen}
|
|
235
|
+
onItemClick={onItemClick}
|
|
130
236
|
/>
|
|
131
|
-
)
|
|
132
|
-
|
|
133
|
-
{headerSlot}
|
|
134
|
-
|
|
135
|
-
<div
|
|
136
|
-
ref={scrollRef}
|
|
137
|
-
onScroll={handleScroll}
|
|
138
|
-
className={"flex-grow min-h-0 overflow-y-auto overflow-x-hidden no-scrollbar"}
|
|
139
|
-
style={{
|
|
140
|
-
maskImage: scrolled
|
|
141
|
-
? "linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)"
|
|
142
|
-
: "linear-gradient(to bottom, black 0, black calc(100% - 20px), transparent 100%)"
|
|
143
|
-
}}>
|
|
144
|
-
|
|
145
|
-
{groupsToRender.map((group) => {
|
|
146
|
-
const entriesInGroup = filteredEntries.filter(e => e.group === group);
|
|
147
|
-
return (
|
|
148
|
-
<DrawerNavigationGroup
|
|
149
|
-
key={`drawer_group_${group}`}
|
|
150
|
-
group={group}
|
|
151
|
-
entries={entriesInGroup}
|
|
152
|
-
collapsed={isGroupCollapsed(group)}
|
|
153
|
-
onToggleCollapsed={() => toggleGroupCollapsed(group)}
|
|
154
|
-
drawerOpen={drawerVisuallyOpen}
|
|
155
|
-
tooltipsOpen={tooltipsOpen}
|
|
156
|
-
adminMenuOpen={adminMenuOpen}
|
|
157
|
-
onItemClick={onItemClick}
|
|
158
|
-
/>
|
|
159
|
-
);
|
|
160
|
-
})}
|
|
161
|
-
|
|
162
|
-
</div>
|
|
163
|
-
|
|
164
|
-
{footerSlot}
|
|
165
|
-
|
|
166
|
-
<DrawerToggle
|
|
167
|
-
drawerOpen={drawerOpen}
|
|
168
|
-
drawerHovered={drawerHovered}
|
|
169
|
-
openDrawer={openDrawer}
|
|
170
|
-
closeDrawer={closeDrawer}
|
|
171
|
-
/>
|
|
172
|
-
</div>
|
|
237
|
+
);
|
|
238
|
+
})}
|
|
173
239
|
|
|
240
|
+
{footerSlot}
|
|
174
241
|
</>
|
|
175
242
|
);
|
|
176
243
|
}
|
|
@@ -178,7 +245,7 @@ context });
|
|
|
178
245
|
export function DrawerLogo({
|
|
179
246
|
logo,
|
|
180
247
|
title,
|
|
181
|
-
logoDestination,
|
|
248
|
+
logoDestination = "/",
|
|
182
249
|
drawerOpen,
|
|
183
250
|
drawerHovered
|
|
184
251
|
}: {
|
|
@@ -189,7 +256,6 @@ export function DrawerLogo({
|
|
|
189
256
|
drawerHovered: boolean;
|
|
190
257
|
}) {
|
|
191
258
|
|
|
192
|
-
const urlController = useUrlController();
|
|
193
259
|
const showFullContent = drawerOpen || (drawerHovered && !drawerOpen);
|
|
194
260
|
|
|
195
261
|
return (
|
|
@@ -197,7 +263,7 @@ export function DrawerLogo({
|
|
|
197
263
|
{/* Logo — always visible */}
|
|
198
264
|
<Link
|
|
199
265
|
className="shrink-0 flex items-center justify-center w-[56px] h-[40px]"
|
|
200
|
-
to={logoDestination
|
|
266
|
+
to={logoDestination}
|
|
201
267
|
>
|
|
202
268
|
{logo
|
|
203
269
|
? <img src={logo} alt="Logo" className="w-[28px] h-[28px] object-contain"/>
|
|
@@ -215,7 +281,7 @@ export function DrawerLogo({
|
|
|
215
281
|
{title && (
|
|
216
282
|
<Link
|
|
217
283
|
className="visited:text-inherit dark:visited:text-inherit block truncate"
|
|
218
|
-
to={logoDestination
|
|
284
|
+
to={logoDestination}
|
|
219
285
|
>
|
|
220
286
|
{typeof title === "string"
|
|
221
287
|
? <Typography variant="subtitle1" noWrap className="truncate">{title}</Typography>
|
|
@@ -271,8 +337,18 @@ export function DrawerToggle({
|
|
|
271
337
|
aria-expanded={isExpanded}
|
|
272
338
|
aria-label={isExpanded ? t("collapse") : t("expand")}
|
|
273
339
|
onClick={() => isExpanded ? closeDrawer() : openDrawer()}
|
|
340
|
+
onKeyDown={(e) => {
|
|
341
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
342
|
+
e.preventDefault();
|
|
343
|
+
if (isExpanded) {
|
|
344
|
+
closeDrawer();
|
|
345
|
+
} else {
|
|
346
|
+
openDrawer();
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}}
|
|
274
350
|
>
|
|
275
|
-
<div className="shrink-0 flex items-center justify-center w-[
|
|
351
|
+
<div className="shrink-0 flex items-center justify-center w-[44px] h-[24px] text-surface-500 dark:text-surface-400">
|
|
276
352
|
{isExpanded
|
|
277
353
|
? <ChevronsLeftIcon size={iconSize.small}/>
|
|
278
354
|
: <ChevronsRightIcon size={iconSize.small}/>
|
|
@@ -353,3 +429,140 @@ function DrawerModeSwitch({
|
|
|
353
429
|
</div>
|
|
354
430
|
);
|
|
355
431
|
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Footer actions rendered at the bottom of the drawer, above the collapse/expand toggle.
|
|
435
|
+
* Replaces the app bar icons (language, theme, user avatar) with a drawer-native layout
|
|
436
|
+
* that adapts between collapsed (icons only) and expanded (full labels + user bar) states.
|
|
437
|
+
*
|
|
438
|
+
* @group Core
|
|
439
|
+
*/
|
|
440
|
+
export function DrawerFooterActions({
|
|
441
|
+
drawerOpen,
|
|
442
|
+
drawerHovered,
|
|
443
|
+
/**
|
|
444
|
+
* Custom content to render inside the user dropdown menu.
|
|
445
|
+
* When provided, these items are appended after the user info header
|
|
446
|
+
* and before the default Sign Out item.
|
|
447
|
+
*/
|
|
448
|
+
dropDownActions,
|
|
449
|
+
/**
|
|
450
|
+
* Override the user object displayed in the footer.
|
|
451
|
+
* When omitted, falls back to `authController.user`.
|
|
452
|
+
*/
|
|
453
|
+
user: userProp
|
|
454
|
+
}: {
|
|
455
|
+
drawerOpen: boolean;
|
|
456
|
+
drawerHovered: boolean;
|
|
457
|
+
dropDownActions?: React.ReactNode;
|
|
458
|
+
user?: import("@rebasepro/types").User;
|
|
459
|
+
}) {
|
|
460
|
+
const authController = useAuthController();
|
|
461
|
+
const {
|
|
462
|
+
mode,
|
|
463
|
+
setMode
|
|
464
|
+
} = useModeController();
|
|
465
|
+
const navigate = useNavigate();
|
|
466
|
+
const { t } = useTranslation();
|
|
467
|
+
|
|
468
|
+
const user = userProp ?? authController.user;
|
|
469
|
+
const showFullContent = drawerOpen || drawerHovered;
|
|
470
|
+
const isFloating = drawerHovered && !drawerOpen;
|
|
471
|
+
const portalRef = React.useRef<HTMLDivElement>(null);
|
|
472
|
+
|
|
473
|
+
// User avatar
|
|
474
|
+
let avatarComponent: React.ReactElement | null;
|
|
475
|
+
if (user) {
|
|
476
|
+
const initial = user?.displayName
|
|
477
|
+
? user.displayName[0].toUpperCase()
|
|
478
|
+
: (user?.email ? user.email[0].toUpperCase() : "A");
|
|
479
|
+
avatarComponent = <Avatar src={user.photoURL ?? undefined} className="w-8 h-8 text-xs">
|
|
480
|
+
{initial}
|
|
481
|
+
</Avatar>;
|
|
482
|
+
} else if (user === undefined || authController.initialLoading) {
|
|
483
|
+
avatarComponent = <Skeleton className="w-8 h-8 rounded-full"/>;
|
|
484
|
+
} else {
|
|
485
|
+
avatarComponent = null;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return (
|
|
489
|
+
<div className="shrink-0 pb-1" ref={portalRef}>
|
|
490
|
+
{avatarComponent && (
|
|
491
|
+
<div className="flex items-center px-[16px] py-1">
|
|
492
|
+
<Menu
|
|
493
|
+
trigger={
|
|
494
|
+
<div
|
|
495
|
+
className={cls(
|
|
496
|
+
"shrink-0 flex items-center justify-center w-[44px] cursor-pointer",
|
|
497
|
+
"rounded-md py-1",
|
|
498
|
+
"hover:bg-surface-accent-100 dark:hover:bg-surface-800",
|
|
499
|
+
"transition-colors duration-150"
|
|
500
|
+
)}
|
|
501
|
+
role="button"
|
|
502
|
+
tabIndex={0}
|
|
503
|
+
aria-label={t("user_menu") || "User menu"}
|
|
504
|
+
>
|
|
505
|
+
{avatarComponent}
|
|
506
|
+
</div>
|
|
507
|
+
}
|
|
508
|
+
side="top"
|
|
509
|
+
align="start"
|
|
510
|
+
>
|
|
511
|
+
{user && <div className="px-4 py-2 mb-1">
|
|
512
|
+
{user.displayName && <Typography variant="body1" color="secondary">
|
|
513
|
+
{user.displayName}
|
|
514
|
+
</Typography>}
|
|
515
|
+
{user.email && <Typography variant="body2" color="secondary">
|
|
516
|
+
{user.email}
|
|
517
|
+
</Typography>}
|
|
518
|
+
</div>}
|
|
519
|
+
|
|
520
|
+
{dropDownActions}
|
|
521
|
+
|
|
522
|
+
{!dropDownActions && <>
|
|
523
|
+
<MenuItem onClick={() => navigate("/settings")}>
|
|
524
|
+
<SettingsIcon/>
|
|
525
|
+
{t("account_settings")}
|
|
526
|
+
</MenuItem>
|
|
527
|
+
<MenuItem onClick={async () => {
|
|
528
|
+
await authController.signOut();
|
|
529
|
+
navigate("/");
|
|
530
|
+
}}>
|
|
531
|
+
<LogOutIcon/>
|
|
532
|
+
{t("log_out")}
|
|
533
|
+
</MenuItem>
|
|
534
|
+
</>}
|
|
535
|
+
</Menu>
|
|
536
|
+
|
|
537
|
+
{/* Language + Theme — only when expanded */}
|
|
538
|
+
{showFullContent && (
|
|
539
|
+
<div className="flex items-center gap-0">
|
|
540
|
+
<LanguageToggle/>
|
|
541
|
+
<Menu
|
|
542
|
+
trigger={
|
|
543
|
+
<IconButton
|
|
544
|
+
color="inherit"
|
|
545
|
+
aria-label={t("toggle_theme") || "Toggle theme"}
|
|
546
|
+
className="text-surface-500 dark:text-surface-400"
|
|
547
|
+
>
|
|
548
|
+
{mode === "dark"
|
|
549
|
+
? <MoonIcon size={iconSize.small}/>
|
|
550
|
+
: mode === "light"
|
|
551
|
+
? <SunIcon size={iconSize.small}/>
|
|
552
|
+
: <SunMoonIcon size={iconSize.small}/>}
|
|
553
|
+
</IconButton>
|
|
554
|
+
}
|
|
555
|
+
portalContainer={portalRef.current}
|
|
556
|
+
side="top"
|
|
557
|
+
>
|
|
558
|
+
<MenuItem onClick={() => setMode("dark")}><MoonIcon size={iconSize.smallest}/> {t("dark_mode")}</MenuItem>
|
|
559
|
+
<MenuItem onClick={() => setMode("light")}><SunIcon size={iconSize.smallest}/> {t("light_mode")}</MenuItem>
|
|
560
|
+
<MenuItem onClick={() => setMode("system")}><SunMoonIcon size={iconSize.smallest}/> {t("system_mode")}</MenuItem>
|
|
561
|
+
</Menu>
|
|
562
|
+
</div>
|
|
563
|
+
)}
|
|
564
|
+
</div>
|
|
565
|
+
)}
|
|
566
|
+
</div>
|
|
567
|
+
);
|
|
568
|
+
}
|
|
@@ -33,7 +33,7 @@ export function DrawerNavigationItem({
|
|
|
33
33
|
width: "100%",
|
|
34
34
|
transition: drawerOpen ? "width 150ms ease-in" : undefined
|
|
35
35
|
}}
|
|
36
|
-
className={({ isActive }:
|
|
36
|
+
className={({ isActive }: { isActive: boolean }) => cls("rounded-md truncate",
|
|
37
37
|
"hover:bg-surface-100 dark:hover:bg-surface-800/60 text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white",
|
|
38
38
|
"flex flex-row items-center",
|
|
39
39
|
drawerOpen ? "pr-4 h-[30px]" : "h-[30px]",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AdditionalFieldDelegate } from "@rebasepro/types";
|
|
2
2
|
import React, { useCallback, useMemo, useRef } from "react";
|
|
3
|
-
import { CollectionSize, Entity, RebaseContext, User } from "@rebasepro/types";
|
|
3
|
+
import { CollectionSize, Entity, RebaseContext, User, Property } from "@rebasepro/types";
|
|
4
4
|
import { PropertyTableCell } from "./PropertyTableCell";
|
|
5
5
|
import { ErrorBoundary } from "@rebasepro/ui";
|
|
6
6
|
import { useRebaseContext, useLargeLayout } from "@rebasepro/core";
|
|
@@ -138,11 +138,12 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
138
138
|
|
|
139
139
|
const propertyKey = column.key;
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
const columnCustom = column.custom as { disabled?: boolean; resolvedProperty?: Property } | undefined;
|
|
142
|
+
let disabled: boolean = columnCustom?.disabled ?? false;
|
|
142
143
|
const property = getPropertyFor?.({
|
|
143
144
|
propertyKey,
|
|
144
145
|
entity
|
|
145
|
-
}) ??
|
|
146
|
+
}) ?? columnCustom?.resolvedProperty;
|
|
146
147
|
if (!property?.ui?.disabled) {
|
|
147
148
|
disabled = false;
|
|
148
149
|
}
|
|
@@ -231,7 +232,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
231
232
|
disabledTooltip={"This column can't be edited directly"}
|
|
232
233
|
sortableNodeRef={sortableNodeRef}
|
|
233
234
|
sortableStyle={sortableStyle}
|
|
234
|
-
sortableAttributes={sortableAttributes}
|
|
235
|
+
sortableAttributes={sortableAttributes as Record<string, string | number | undefined>}
|
|
235
236
|
isDragging={isDragging}
|
|
236
237
|
isDraggable={isDraggable}
|
|
237
238
|
frozen={frozen}
|
|
@@ -337,7 +338,7 @@ export const EntityCollectionTable = function EntityCollectionTable<M extends Re
|
|
|
337
338
|
disabled={true}
|
|
338
339
|
sortableNodeRef={props.sortableNodeRef}
|
|
339
340
|
sortableStyle={props.sortableStyle}
|
|
340
|
-
sortableAttributes={props.sortableAttributes}
|
|
341
|
+
sortableAttributes={props.sortableAttributes as Record<string, string | number | undefined>}
|
|
341
342
|
isDragging={props.isDragging}
|
|
342
343
|
isDraggable={props.isDraggable}
|
|
343
344
|
frozen={props.frozen}>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCellSelected } from "../SelectableTable/SelectionStore";
|
|
1
|
+
import { useCellSelected, createSelectionStore } from "../SelectableTable/SelectionStore";
|
|
2
2
|
import type { ArrayProperty, NumberProperty, Property, ReferenceProperty, StringProperty } from "@rebasepro/types";
|
|
3
3
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { deepEqual as equal } from "fast-equals"
|
|
@@ -76,7 +76,9 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
76
76
|
setPopupCell
|
|
77
77
|
} = useSelectableTableController();
|
|
78
78
|
|
|
79
|
-
const
|
|
79
|
+
const dummySelectionStore = useMemo(() => createSelectionStore(), []);
|
|
80
|
+
const activeSelectionStore = selectionStore || dummySelectionStore;
|
|
81
|
+
const selected = useCellSelected(activeSelectionStore, propertyKey, entity.path, entity.id);
|
|
80
82
|
|
|
81
83
|
const [internalValue, setInternalValue] = useState<any | null>(value);
|
|
82
84
|
const internalValueRef = useRef(value);
|
|
@@ -114,13 +116,13 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
114
116
|
[onValueUpdated, value]
|
|
115
117
|
);
|
|
116
118
|
|
|
117
|
-
const saveValues = async (value:
|
|
119
|
+
const saveValues = async (value: unknown) => {
|
|
118
120
|
if (equal(value, internalValueRef.current))
|
|
119
121
|
return;
|
|
120
122
|
const result = await validation.safeParseAsync(value);
|
|
121
123
|
if (result.success) {
|
|
122
124
|
setValidationError(undefined);
|
|
123
|
-
internalValueRef.current = value;
|
|
125
|
+
internalValueRef.current = value as T;
|
|
124
126
|
if (onValueChange) {
|
|
125
127
|
try {
|
|
126
128
|
onValueChange({
|
|
@@ -153,9 +155,9 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
153
155
|
});
|
|
154
156
|
}, [internalValue, validation, propertyKey, property, entity]);
|
|
155
157
|
|
|
156
|
-
const updateValue = (newValue:
|
|
158
|
+
const updateValue = (newValue: unknown | null) => {
|
|
157
159
|
|
|
158
|
-
let updatedValue:
|
|
160
|
+
let updatedValue: unknown;
|
|
159
161
|
if (newValue === undefined) {
|
|
160
162
|
updatedValue = null;
|
|
161
163
|
} else {
|
|
@@ -165,7 +167,7 @@ export const PropertyTableCell = React.memo<PropertyTableCellProps<any>>(
|
|
|
165
167
|
saveValues(updatedValue);
|
|
166
168
|
};
|
|
167
169
|
|
|
168
|
-
useClearRestoreValue<
|
|
170
|
+
useClearRestoreValue<unknown>({
|
|
169
171
|
property,
|
|
170
172
|
value: internalValue,
|
|
171
173
|
setValue: updateValue
|