@rebasepro/admin 0.0.1-canary.eae7889 → 0.1.0
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-B2M9lCyL.js → CollectionEditorDialog-MbvXGzEq.js} +42 -31
- package/dist/CollectionEditorDialog-MbvXGzEq.js.map +1 -0
- package/dist/{CollectionsStudioView-WG6soyfs.js → CollectionsStudioView-D9X6aiAr.js} +12 -12
- package/dist/CollectionsStudioView-D9X6aiAr.js.map +1 -0
- package/dist/{ContentHomePage-CDF_a6Lp.js → ContentHomePage-CfVB1eUo.js} +26 -26
- package/dist/ContentHomePage-CfVB1eUo.js.map +1 -0
- package/dist/{ExportCollectionAction-Dc0VOWMN.js → ExportCollectionAction-CUwJg4F9.js} +2 -2
- package/dist/{ExportCollectionAction-Dc0VOWMN.js.map → ExportCollectionAction-CUwJg4F9.js.map} +1 -1
- package/dist/{ImportCollectionAction-DpCagAOy.js → ImportCollectionAction-DGa_SF_8.js} +2 -2
- package/dist/{ImportCollectionAction-DpCagAOy.js.map → ImportCollectionAction-DGa_SF_8.js.map} +1 -1
- package/dist/{PropertyEditView-DS67DxoT.js → PropertyEditView-C4nlYmAc.js} +82 -104
- package/dist/PropertyEditView-C4nlYmAc.js.map +1 -0
- package/dist/{RolesView-CIuYBimF.js → RolesView-CNWxnR8e.js} +7 -5
- package/dist/RolesView-CNWxnR8e.js.map +1 -0
- package/dist/{UsersView-B5zelXnH.js → UsersView-YiTIcXkA.js} +14 -35
- package/dist/UsersView-YiTIcXkA.js.map +1 -0
- package/dist/collection_editor/ConfigControllerProvider.d.ts +0 -4
- package/dist/collection_editor/types/collection_editor_controller.d.ts +6 -3
- package/dist/collection_editor/types/config_controller.d.ts +14 -7
- package/dist/collection_editor/ui/AddKanbanColumnAction.d.ts +3 -2
- package/dist/collection_editor/ui/CollectionViewHeaderAction.d.ts +3 -2
- package/dist/collection_editor/ui/EditorCollectionAction.d.ts +1 -1
- package/dist/collection_editor/ui/EditorCollectionActionStart.d.ts +1 -1
- package/dist/collection_editor/ui/EditorEntityAction.d.ts +1 -1
- package/dist/collection_editor/ui/KanbanSetupAction.d.ts +3 -2
- package/dist/collection_editor/ui/PropertyAddColumnComponent.d.ts +3 -2
- package/dist/collection_editor/ui/collection_editor/CollectionDetailsForm.d.ts +3 -4
- package/dist/collection_editor/ui/collection_editor/CollectionEditorDialog.d.ts +2 -3
- package/dist/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.d.ts +1 -2
- package/dist/collection_editor/ui/collection_editor/SubcollectionsEditTab.d.ts +3 -2
- package/dist/collection_editor_ui.js +3 -3
- package/dist/components/EntityCollectionTable/EntityCollectionTable.d.ts +1 -1
- package/dist/components/EntityCollectionTable/EntityCollectionTableProps.d.ts +1 -1
- package/dist/components/EntityCollectionTable/column_utils.d.ts +2 -2
- package/dist/components/EntityCollectionTable/fields/TableMultipleRelationField.d.ts +1 -1
- package/dist/components/EntityCollectionTable/fields/TableReferenceField.d.ts +1 -1
- package/dist/components/EntityCollectionTable/fields/TableRelationField.d.ts +1 -1
- package/dist/components/EntityCollectionTable/fields/TableRelationSelectorField.d.ts +2 -2
- package/dist/components/EntityCollectionTable/internal/CollectionTableToolbar.d.ts +5 -1
- package/dist/components/EntityCollectionView/EntityCollectionBoardView.d.ts +3 -2
- package/dist/components/EntityCollectionView/EntityCollectionView.d.ts +2 -1
- package/dist/components/EntityCollectionView/EntityCollectionViewActions.d.ts +4 -2
- package/dist/components/EntityCollectionView/EntityCollectionViewStartActions.d.ts +4 -2
- package/dist/components/EntityCollectionView/FiltersDialog.d.ts +2 -2
- package/dist/components/EntityCollectionView/SplitListView.d.ts +3 -2
- package/dist/components/EntityEditView.d.ts +9 -2
- package/dist/components/RebaseCMS.d.ts +1 -1
- package/dist/components/ReferenceTable/EntitySelectionTable.d.ts +2 -2
- package/dist/components/ReferenceWidget.d.ts +2 -2
- package/dist/components/RelationSelector.d.ts +1 -1
- package/dist/components/SelectableTable/SelectableTable.d.ts +2 -2
- package/dist/editor.js +2 -2
- package/dist/editor.js.map +1 -1
- package/dist/hooks/navigation/useNavigationRegistry.d.ts +2 -1
- package/dist/hooks/useEntityHistory.d.ts +1 -1
- package/dist/{index-CHxgwt6E.js → index-CtzpHzMQ.js} +11 -4
- package/dist/index-CtzpHzMQ.js.map +1 -0
- package/dist/{index-Dey5WJpO.js → index-DKlrVD1m.js} +3 -3
- package/dist/index-DKlrVD1m.js.map +1 -0
- package/dist/{index-CBhrgpR7.js → index-kHJXfLNI.js} +3 -3
- package/dist/index-kHJXfLNI.js.map +1 -0
- package/dist/index.js +79 -63
- package/dist/index.js.map +1 -1
- package/dist/{useEntityHistory-Dcj4zhGj.js → useEntityHistory-UVsSclfZ.js} +3 -1
- package/dist/useEntityHistory-UVsSclfZ.js.map +1 -0
- package/dist/util/navigation_utils.d.ts +10 -1
- package/dist/{util-BQ82ySL3.js → util-CwLmSpGp.js} +1653 -1257
- package/dist/util-CwLmSpGp.js.map +1 -0
- package/package.json +9 -17
- package/src/collection_editor/ConfigControllerProvider.tsx +19 -28
- package/src/collection_editor/types/collection_editor_controller.tsx +3 -3
- package/src/collection_editor/types/config_controller.tsx +7 -7
- package/src/collection_editor/ui/AddKanbanColumnAction.tsx +4 -4
- package/src/collection_editor/ui/CollectionViewHeaderAction.tsx +3 -3
- package/src/collection_editor/ui/EditorCollectionAction.tsx +3 -3
- package/src/collection_editor/ui/EditorCollectionActionStart.tsx +7 -7
- package/src/collection_editor/ui/EditorEntityAction.tsx +3 -3
- package/src/collection_editor/ui/HomePageEditorCollectionAction.tsx +4 -2
- package/src/collection_editor/ui/KanbanSetupAction.tsx +4 -3
- package/src/collection_editor/ui/MissingReferenceWidget.tsx +3 -2
- package/src/collection_editor/ui/NewCollectionButton.tsx +2 -1
- package/src/collection_editor/ui/NewCollectionCard.tsx +2 -1
- package/src/collection_editor/ui/PropertyAddColumnComponent.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/CollectionDetailsForm.tsx +5 -50
- package/src/collection_editor/ui/collection_editor/CollectionEditorDialog.tsx +12 -20
- package/src/collection_editor/ui/collection_editor/CollectionPropertiesEditorForm.tsx +1 -3
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +17 -2
- package/src/collection_editor/ui/collection_editor/CollectionRelationsTab.tsx +3 -3
- package/src/collection_editor/ui/collection_editor/CollectionStudioView.tsx +2 -1
- package/src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx +18 -12
- package/src/collection_editor/ui/collection_editor/DisplaySettingsForm.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/GetCodeDialog.tsx +1 -2
- package/src/collection_editor/ui/collection_editor/PropertyFieldPreview.tsx +6 -6
- package/src/collection_editor/ui/collection_editor/SubcollectionsEditTab.tsx +4 -4
- package/src/collection_editor/ui/collection_editor/properties/MapPropertyField.tsx +2 -2
- package/src/collection_editor/ui/collection_editor/properties/ReferencePropertyField.tsx +15 -49
- package/src/collection_editor/ui/collection_editor/properties/advanced/AdvancedPropertyValidation.tsx +4 -5
- package/src/collection_editor/ui/collection_editor/templates/pages_template.ts +1 -1
- package/src/collection_editor/ui/collection_editor/templates/products_template.ts +2 -2
- package/src/components/DefaultAppBar.tsx +2 -2
- package/src/components/DefaultDrawer.tsx +25 -17
- package/src/components/DrawerNavigationGroup.tsx +4 -4
- package/src/components/DrawerNavigationItem.tsx +6 -6
- package/src/components/EntityCollectionTable/EntityCollectionTable.tsx +4 -4
- package/src/components/EntityCollectionTable/EntityCollectionTableProps.tsx +1 -1
- package/src/components/EntityCollectionTable/PropertyTableCell.tsx +4 -4
- package/src/components/EntityCollectionTable/column_utils.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableMultipleRelationField.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableReferenceField.tsx +3 -3
- package/src/components/EntityCollectionTable/fields/TableRelationField.tsx +4 -4
- package/src/components/EntityCollectionTable/fields/TableRelationSelectorField.tsx +3 -3
- package/src/components/EntityCollectionTable/internal/CollectionTableToolbar.tsx +8 -2
- package/src/components/EntityCollectionTable/internal/EntityTableCell.tsx +1 -1
- package/src/components/EntityCollectionTable/internal/common.tsx +5 -5
- package/src/components/EntityCollectionTable/internal/popup_field/PopupFormField.tsx +1 -1
- package/src/components/EntityCollectionTable/table_bindings.tsx +45 -35
- package/src/components/EntityCollectionView/EntityBoardCard.tsx +18 -19
- package/src/components/EntityCollectionView/EntityCard.tsx +2 -2
- package/src/components/EntityCollectionView/EntityCollectionBoardView.tsx +42 -14
- package/src/components/EntityCollectionView/EntityCollectionCardView.tsx +4 -3
- package/src/components/EntityCollectionView/EntityCollectionListView.tsx +157 -54
- package/src/components/EntityCollectionView/EntityCollectionView.tsx +169 -75
- package/src/components/EntityCollectionView/EntityCollectionViewActions.tsx +23 -13
- package/src/components/EntityCollectionView/EntityCollectionViewStartActions.tsx +21 -12
- package/src/components/EntityCollectionView/FiltersDialog.tsx +7 -7
- package/src/components/EntityCollectionView/SplitListView.tsx +24 -8
- package/src/components/EntityCollectionView/useEntityPreviewSlots.ts +33 -5
- package/src/components/EntityEditView.tsx +85 -85
- package/src/components/EntitySidePanel.tsx +18 -10
- package/src/components/HomePage/ContentHomePage.tsx +24 -15
- package/src/components/HomePage/NavigationCard.tsx +4 -4
- package/src/components/HomePage/NavigationGroup.tsx +2 -2
- package/src/components/RebaseAuthGate.tsx +2 -0
- package/src/components/RebaseCMS.tsx +4 -3
- package/src/components/RebaseNavigation.tsx +8 -5
- package/src/components/ReferenceTable/EntitySelectionTable.tsx +4 -4
- package/src/components/ReferenceWidget.tsx +3 -3
- package/src/components/RelationSelector.tsx +33 -5
- package/src/components/SelectableTable/SelectableTable.tsx +6 -6
- package/src/components/UserSelector.tsx +1 -1
- package/src/components/admin/RolesView.tsx +10 -3
- package/src/components/admin/UsersView.tsx +13 -25
- package/src/components/app/Scaffold.tsx +4 -4
- package/src/components/field_configs.tsx +29 -32
- package/src/components/history/EntityHistoryView.tsx +12 -1
- package/src/editor/editor.tsx +2 -2
- package/src/form/EntityForm.tsx +5 -4
- package/src/form/PropertyFieldBinding.tsx +14 -10
- package/src/form/components/FieldHelperText.tsx +1 -1
- package/src/form/field_bindings/ArrayCustomShapedFieldBinding.tsx +3 -3
- package/src/form/field_bindings/ArrayOfReferencesFieldBinding.tsx +5 -5
- package/src/form/field_bindings/BlockFieldBinding.tsx +4 -4
- package/src/form/field_bindings/DateTimeFieldBinding.tsx +1 -1
- package/src/form/field_bindings/KeyValueFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MapFieldBinding.tsx +7 -7
- package/src/form/field_bindings/MarkdownEditorFieldBinding.tsx +1 -1
- package/src/form/field_bindings/MultipleRelationFieldBinding.tsx +3 -3
- package/src/form/field_bindings/ReferenceAsStringFieldBinding.tsx +7 -7
- package/src/form/field_bindings/ReferenceFieldBinding.tsx +2 -2
- package/src/form/field_bindings/RelationFieldBinding.tsx +4 -4
- package/src/form/field_bindings/RepeatFieldBinding.tsx +5 -5
- package/src/form/field_bindings/SelectFieldBinding.tsx +1 -1
- package/src/form/field_bindings/StorageUploadFieldBinding.tsx +1 -1
- package/src/form/field_bindings/SwitchFieldBinding.tsx +1 -1
- package/src/form/field_bindings/TextFieldBinding.tsx +7 -7
- package/src/form/field_bindings/UserSelectFieldBinding.tsx +1 -1
- package/src/form/useClearRestoreValue.tsx +1 -1
- package/src/form/validation.ts +1 -1
- package/src/hooks/navigation/contexts/CollectionRegistryContext.tsx +2 -1
- package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +15 -3
- package/src/hooks/navigation/useNavigationRegistry.ts +14 -3
- package/src/hooks/navigation/useResolvedViews.tsx +1 -3
- package/src/hooks/navigation/useTopLevelNavigation.ts +1 -1
- package/src/hooks/navigation/utils.ts +1 -1
- package/src/hooks/useEntityHistory.ts +7 -2
- package/src/preview/PropertyPreview.tsx +27 -23
- package/src/preview/components/StorageThumbnail.tsx +4 -1
- package/src/preview/property_previews/ArrayOfMapsPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfReferencesPreview.tsx +1 -1
- package/src/preview/property_previews/ArrayOfRelationsPreview.tsx +1 -1
- package/src/preview/property_previews/SkeletonPropertyComponent.tsx +3 -3
- package/src/preview/property_previews/StringPropertyPreview.tsx +3 -3
- package/src/routes/RebaseRoute.tsx +57 -11
- package/src/util/navigation_utils.ts +21 -2
- package/src/util/previews.ts +15 -6
- package/src/util/property_utils.tsx +3 -3
- package/dist/CollectionEditorDialog-B2M9lCyL.js.map +0 -1
- package/dist/CollectionsStudioView-WG6soyfs.js.map +0 -1
- package/dist/ContentHomePage-CDF_a6Lp.js.map +0 -1
- package/dist/PropertyEditView-DS67DxoT.js.map +0 -1
- package/dist/RolesView-CIuYBimF.js.map +0 -1
- package/dist/UsersView-B5zelXnH.js.map +0 -1
- package/dist/index-CBhrgpR7.js.map +0 -1
- package/dist/index-CHxgwt6E.js.map +0 -1
- package/dist/index-Dey5WJpO.js.map +0 -1
- package/dist/useEntityHistory-Dcj4zhGj.js.map +0 -1
- package/dist/util-BQ82ySL3.js.map +0 -1
|
@@ -19,9 +19,10 @@ import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable"
|
|
|
19
19
|
import { restrictToVerticalAxis, restrictToWindowEdges } from "@dnd-kit/modifiers";
|
|
20
20
|
import { RenameGroupDialog } from "./RenameGroupDialog";
|
|
21
21
|
import { toArray } from "@rebasepro/utils";
|
|
22
|
-
import { useCollapsedGroups, useCustomizationController, useTranslation, useSlot, useAdminModeController } from "@rebasepro/core";
|
|
22
|
+
import { useCollapsedGroups, buildCollapsedDefaults, useCustomizationController, useTranslation, useSlot, useAdminModeController, useRebaseRegistry } from "@rebasepro/core";
|
|
23
23
|
import { useRestoreScroll } from "@rebasepro/core";
|
|
24
|
-
|
|
24
|
+
|
|
25
|
+
import { BootstrapAdminBanner } from "@rebasepro/core";
|
|
25
26
|
import { useBreadcrumbsController, useCMSContext } from "../../index";
|
|
26
27
|
|
|
27
28
|
export const DEFAULT_GROUP_NAME = "Views";
|
|
@@ -45,7 +46,8 @@ export function ContentHomePage({
|
|
|
45
46
|
const { navigationStateController } = context;
|
|
46
47
|
const customizationController = useCustomizationController();
|
|
47
48
|
const adminModeController = useAdminModeController();
|
|
48
|
-
const
|
|
49
|
+
const registry = useRebaseRegistry();
|
|
50
|
+
|
|
49
51
|
const { resolvedSlots } = customizationController;
|
|
50
52
|
const breadcrumbs = useBreadcrumbsController();
|
|
51
53
|
const { t } = useTranslation();
|
|
@@ -61,19 +63,19 @@ export function ContentHomePage({
|
|
|
61
63
|
onNavigationEntriesUpdate = () => {}
|
|
62
64
|
} = navigationStateController.topLevelNavigation || {};
|
|
63
65
|
|
|
66
|
+
// Studio mode shows view-type entries (devViews) + admin entries (Users/Roles).
|
|
67
|
+
// Content mode shows collections, admin entries (Users/Roles), and custom entries — but not studio views.
|
|
64
68
|
const rawNavigationEntries = useMemo(() => {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}, [unFilteredNavigationEntries,
|
|
69
|
+
if (adminModeController.mode === "studio") {
|
|
70
|
+
return unFilteredNavigationEntries.filter(e => e.type === "view" || e.type === "admin");
|
|
71
|
+
}
|
|
72
|
+
return unFilteredNavigationEntries.filter(e => e.type !== "view");
|
|
73
|
+
}, [unFilteredNavigationEntries, adminModeController.mode]);
|
|
70
74
|
|
|
71
75
|
const groupOrderFromNavController = useMemo(() => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
});
|
|
76
|
-
}, [unFilteredGroupOrder, isStudioMode]);
|
|
76
|
+
const entryGroups = new Set(rawNavigationEntries.map(e => e.group).filter(Boolean));
|
|
77
|
+
return unFilteredGroupOrder.filter(g => entryGroups.has(g));
|
|
78
|
+
}, [unFilteredGroupOrder, rawNavigationEntries]);
|
|
77
79
|
|
|
78
80
|
const fuse = useRef<Fuse<NavigationEntry> | null>(null);
|
|
79
81
|
const [filteredUrls, setFilteredUrls] = useState<string[] | null>(null);
|
|
@@ -244,7 +246,11 @@ export function ContentHomePage({
|
|
|
244
246
|
...(adminGroupData ? [adminGroupData.name] : [])
|
|
245
247
|
], [items, adminGroupData]);
|
|
246
248
|
|
|
247
|
-
const
|
|
249
|
+
const collapsedDefaults = useMemo(
|
|
250
|
+
() => buildCollapsedDefaults(registry.cmsConfig?.navigationGroupMappings, "home"),
|
|
251
|
+
[registry.cmsConfig?.navigationGroupMappings]
|
|
252
|
+
);
|
|
253
|
+
const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupNames, "home", collapsedDefaults);
|
|
248
254
|
|
|
249
255
|
const {
|
|
250
256
|
sensors,
|
|
@@ -312,8 +318,11 @@ export function ContentHomePage({
|
|
|
312
318
|
Render
|
|
313
319
|
─────────────────────────────────────────────────────────────── */
|
|
314
320
|
return (
|
|
315
|
-
<div ref={containerRef} className="py-2 overflow-auto h-full w-full dark:bg-surface-800">
|
|
321
|
+
<div ref={containerRef} className="py-2 overflow-auto h-full w-full bg-surface-50 dark:bg-surface-800">
|
|
316
322
|
<Container maxWidth="6xl">
|
|
323
|
+
<div className="mb-4">
|
|
324
|
+
<BootstrapAdminBanner />
|
|
325
|
+
</div>
|
|
317
326
|
{/* search & actions */}
|
|
318
327
|
<div
|
|
319
328
|
className="w-full sticky py-4 transition-all duration-400 ease-in-out top-0 z-10 flex flex-row gap-4"
|
|
@@ -26,10 +26,10 @@ export const NavigationCard = React.memo(function NavigationCard({
|
|
|
26
26
|
return (
|
|
27
27
|
<Card
|
|
28
28
|
className={cls(
|
|
29
|
-
"group h-full p-
|
|
30
|
-
"border-surface-200
|
|
31
|
-
"hover
|
|
32
|
-
"hover:border-
|
|
29
|
+
"group h-full p-4 cursor-pointer transition-all duration-150 ease-in-out",
|
|
30
|
+
"border-surface-200 dark:border-surface-700/40",
|
|
31
|
+
"hover:shadow-md hover:shadow-black/[0.04]",
|
|
32
|
+
"hover:border-surface-300 dark:hover:border-primary/20",
|
|
33
33
|
shrink && "w-full max-w-full min-h-0 scale-75"
|
|
34
34
|
)}
|
|
35
35
|
onClick={() => {
|
|
@@ -40,8 +40,8 @@ export function NavigationGroup({
|
|
|
40
40
|
component={"h2"}
|
|
41
41
|
color="secondary"
|
|
42
42
|
className={cls(
|
|
43
|
-
"
|
|
44
|
-
"font-
|
|
43
|
+
"px-4 py-1 rounded",
|
|
44
|
+
"font-semibold text-[11px] uppercase tracking-wider text-surface-400 dark:text-surface-400"
|
|
45
45
|
)}
|
|
46
46
|
>
|
|
47
47
|
{currentGroupName}
|
|
@@ -27,6 +27,8 @@ export function RebaseAuthGate({ children }: { children: React.ReactNode }) {
|
|
|
27
27
|
const registry = useRebaseRegistry();
|
|
28
28
|
const authController = useAuthController();
|
|
29
29
|
|
|
30
|
+
console.log("[AuthGate] initialLoading:", authController?.initialLoading, "user:", authController?.user?.email ?? null);
|
|
31
|
+
|
|
30
32
|
if (authController?.initialLoading) {
|
|
31
33
|
return <CircularProgressCenter size={"large"}/>;
|
|
32
34
|
}
|
|
@@ -10,7 +10,7 @@ import type { RebaseCMSConfig } from "@rebasepro/types";
|
|
|
10
10
|
* is auto-wired as a native feature (slots, provider, Studio view) without
|
|
11
11
|
* needing any external plugin.
|
|
12
12
|
*/
|
|
13
|
-
export function RebaseCMS({ collections, homePage, entityViews, entityActions, plugins, collectionEditor }: RebaseCMSConfig) {
|
|
13
|
+
export function RebaseCMS({ collections, homePage, entityViews, entityActions, plugins, collectionEditor, navigationGroupMappings }: RebaseCMSConfig) {
|
|
14
14
|
const dispatch = useRebaseRegistryDispatch();
|
|
15
15
|
|
|
16
16
|
useLayoutEffect(() => {
|
|
@@ -19,9 +19,10 @@ homePage,
|
|
|
19
19
|
entityViews,
|
|
20
20
|
entityActions,
|
|
21
21
|
plugins,
|
|
22
|
-
collectionEditor
|
|
22
|
+
collectionEditor,
|
|
23
|
+
navigationGroupMappings });
|
|
23
24
|
return () => dispatch.unregisterCMS();
|
|
24
|
-
}, [dispatch, collections, homePage, entityViews, entityActions, plugins, collectionEditor]);
|
|
25
|
+
}, [dispatch, collections, homePage, entityViews, entityActions, plugins, collectionEditor, navigationGroupMappings]);
|
|
25
26
|
|
|
26
27
|
return null;
|
|
27
28
|
}
|
|
@@ -69,11 +69,14 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
69
69
|
const userConfigPersistence = useBuildLocalConfigurationPersistence();
|
|
70
70
|
|
|
71
71
|
// ── Collection Editor resolution ──────────────────────────────────
|
|
72
|
+
// The collection editor is ALWAYS enabled when Studio is registered.
|
|
73
|
+
// The `collectionEditor` CMS config is for fine-tuning (readOnly, auth, etc.),
|
|
74
|
+
// not for opting-in. When omitted, the editor defaults to enabled
|
|
75
|
+
// (read-only in production).
|
|
72
76
|
const collectionEditorConfig = registry.cmsConfig?.collectionEditor;
|
|
73
|
-
const collectionEditorEnabled = Boolean(collectionEditorConfig);
|
|
77
|
+
const collectionEditorEnabled = Boolean(collectionEditorConfig) || Boolean(registry.studioConfig);
|
|
74
78
|
const collectionEditorOptions: CollectionEditorOptions | undefined = useMemo(() => {
|
|
75
|
-
if (!collectionEditorConfig) return
|
|
76
|
-
if (collectionEditorConfig === true) return {};
|
|
79
|
+
if (collectionEditorConfig === true || !collectionEditorConfig) return {};
|
|
77
80
|
return collectionEditorConfig;
|
|
78
81
|
}, [collectionEditorConfig]);
|
|
79
82
|
|
|
@@ -103,7 +106,7 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
103
106
|
rebaseClient,
|
|
104
107
|
resolvedCollections,
|
|
105
108
|
collectionEditorEnabled ? {
|
|
106
|
-
readOnly: collectionEditorOptions?.readOnly,
|
|
109
|
+
readOnly: collectionEditorOptions?.readOnly ?? process.env.NODE_ENV === "production",
|
|
107
110
|
getAuthToken: collectionEditorOptions?.getAuthToken ?? authController?.getAuthToken
|
|
108
111
|
} : { readOnly: true }
|
|
109
112
|
);
|
|
@@ -117,7 +120,6 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
117
120
|
return {
|
|
118
121
|
slug: "schema",
|
|
119
122
|
name: "Edit collections",
|
|
120
|
-
group: "Database",
|
|
121
123
|
icon: "LayoutList",
|
|
122
124
|
nestedRoutes: true,
|
|
123
125
|
view: (
|
|
@@ -138,6 +140,7 @@ export function RebaseNavigation({ children }: RebaseNavigationProps) {
|
|
|
138
140
|
plugins: registry.cmsConfig?.plugins ?? EMPTY_PLUGINS,
|
|
139
141
|
collections: collectionsBuilder,
|
|
140
142
|
views: devViews,
|
|
143
|
+
navigationGroupMappings: registry.cmsConfig?.navigationGroupMappings,
|
|
141
144
|
authController: context.authController!,
|
|
142
145
|
data: context.data,
|
|
143
146
|
collectionRegistryController,
|
|
@@ -72,7 +72,7 @@ export interface EntitySelectionProps<M extends Record<string, unknown>> {
|
|
|
72
72
|
/**
|
|
73
73
|
* Allow selection of entities that pass the given filter only.
|
|
74
74
|
*/
|
|
75
|
-
|
|
75
|
+
fixedFilter?: FilterValues<string>;
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
78
|
* Use this description to indicate the user what to do in this dialog.
|
|
@@ -100,7 +100,7 @@ export function EntitySelectionTable<M extends Record<string, unknown>>(
|
|
|
100
100
|
path: pathInput,
|
|
101
101
|
selectedEntityIds: selectedEntityIdsProp,
|
|
102
102
|
description,
|
|
103
|
-
|
|
103
|
+
fixedFilter,
|
|
104
104
|
maxSelection
|
|
105
105
|
}: EntitySelectionProps<M>) {
|
|
106
106
|
|
|
@@ -259,7 +259,7 @@ export function EntitySelectionTable<M extends Record<string, unknown>>(
|
|
|
259
259
|
path,
|
|
260
260
|
collection,
|
|
261
261
|
entitiesDisplayedFirst,
|
|
262
|
-
|
|
262
|
+
fixedFilter,
|
|
263
263
|
updateUrl: false
|
|
264
264
|
});
|
|
265
265
|
|
|
@@ -288,7 +288,7 @@ export function EntitySelectionTable<M extends Record<string, unknown>>(
|
|
|
288
288
|
</Typography>}
|
|
289
289
|
defaultSize={collection.defaultSize}
|
|
290
290
|
properties={collection.properties}
|
|
291
|
-
|
|
291
|
+
fixedFilter={fixedFilter}
|
|
292
292
|
inlineEditing={false}
|
|
293
293
|
selectionController={selectionController}
|
|
294
294
|
actions={<EntitySelectionDialogActions
|
|
@@ -27,7 +27,7 @@ export type ReferenceWidgetProps<M extends Record<string, unknown>> = {
|
|
|
27
27
|
/**
|
|
28
28
|
* Allow selection of entities that pass the given filter only.
|
|
29
29
|
*/
|
|
30
|
-
|
|
30
|
+
fixedFilter?: FilterValues<string>;
|
|
31
31
|
size: PreviewSize;
|
|
32
32
|
className?: string;
|
|
33
33
|
includeId?: boolean;
|
|
@@ -46,7 +46,7 @@ export function ReferenceWidget<M extends Record<string, unknown>>({
|
|
|
46
46
|
onReferenceSelected,
|
|
47
47
|
onMultipleReferenceSelected,
|
|
48
48
|
previewProperties,
|
|
49
|
-
|
|
49
|
+
fixedFilter,
|
|
50
50
|
size,
|
|
51
51
|
className,
|
|
52
52
|
includeId,
|
|
@@ -89,7 +89,7 @@ export function ReferenceWidget<M extends Record<string, unknown>>({
|
|
|
89
89
|
collection,
|
|
90
90
|
onSingleEntitySelected,
|
|
91
91
|
onMultipleEntitiesSelected,
|
|
92
|
-
|
|
92
|
+
fixedFilter
|
|
93
93
|
}
|
|
94
94
|
);
|
|
95
95
|
|
|
@@ -37,7 +37,7 @@ export interface RelationSelectorProps {
|
|
|
37
37
|
invisible?: boolean;
|
|
38
38
|
|
|
39
39
|
relation: Relation;
|
|
40
|
-
|
|
40
|
+
fixedFilter?: FilterValues<string>;
|
|
41
41
|
pageSize?: number;
|
|
42
42
|
emptyPlaceholder?: string;
|
|
43
43
|
searchPlaceholder?: string;
|
|
@@ -60,7 +60,7 @@ export const RelationSelector = React.forwardRef<
|
|
|
60
60
|
useChips = true,
|
|
61
61
|
className,
|
|
62
62
|
relation,
|
|
63
|
-
|
|
63
|
+
fixedFilter,
|
|
64
64
|
pageSize,
|
|
65
65
|
emptyPlaceholder,
|
|
66
66
|
searchPlaceholder = "Search...",
|
|
@@ -83,6 +83,10 @@ export const RelationSelector = React.forwardRef<
|
|
|
83
83
|
// Track IDs that were set via local user interaction (onItemClick / handleClear / handleRemoveItem).
|
|
84
84
|
// When an incoming value change matches these IDs exactly, we skip async re-resolution.
|
|
85
85
|
const localSelectionIdsRef = useRef<string | null>(null);
|
|
86
|
+
// Snapshot of selected IDs captured when the popover opens.
|
|
87
|
+
// Used to sort the dropdown list so selected items appear at the top.
|
|
88
|
+
// Stays stable for the entire popover session so items don't jump around.
|
|
89
|
+
const pinnedIdsRef = useRef<Set<string> | null>(null);
|
|
86
90
|
|
|
87
91
|
const {
|
|
88
92
|
items: availableItems,
|
|
@@ -94,7 +98,7 @@ export const RelationSelector = React.forwardRef<
|
|
|
94
98
|
} = useRelationSelector({
|
|
95
99
|
path: collection.slug,
|
|
96
100
|
collection,
|
|
97
|
-
|
|
101
|
+
fixedFilter,
|
|
98
102
|
pageSize
|
|
99
103
|
});
|
|
100
104
|
|
|
@@ -323,6 +327,7 @@ relation } as RelationItem;
|
|
|
323
327
|
newSelected = [item];
|
|
324
328
|
setIsPopoverOpen(false);
|
|
325
329
|
isPopoverOpenRef.current = false;
|
|
330
|
+
pinnedIdsRef.current = null;
|
|
326
331
|
}
|
|
327
332
|
setSelectedItems(newSelected);
|
|
328
333
|
// Mark this fingerprint so the resolution effect skips async work
|
|
@@ -348,11 +353,13 @@ relation } as RelationItem;
|
|
|
348
353
|
if (disabled) return;
|
|
349
354
|
// We control open manually; only allow opening attempts from Radix (e.g. trigger press)
|
|
350
355
|
if (next) {
|
|
356
|
+
// Capture current selection so we can pin those items to the top of the list
|
|
357
|
+
pinnedIdsRef.current = new Set(selectedItems.map(i => String(i.id)));
|
|
351
358
|
setIsPopoverOpen(true);
|
|
352
359
|
isPopoverOpenRef.current = true;
|
|
353
360
|
}
|
|
354
361
|
// Ignore close attempts here; outside click/Escape handled manually; single select closes explicitly on selection.
|
|
355
|
-
}, [disabled]);
|
|
362
|
+
}, [disabled, selectedItems]);
|
|
356
363
|
|
|
357
364
|
// Outside click + Escape handling (simple and reliable)
|
|
358
365
|
useEffect(() => {
|
|
@@ -367,12 +374,14 @@ relation } as RelationItem;
|
|
|
367
374
|
// Outside
|
|
368
375
|
setIsPopoverOpen(false);
|
|
369
376
|
isPopoverOpenRef.current = false;
|
|
377
|
+
pinnedIdsRef.current = null;
|
|
370
378
|
}
|
|
371
379
|
|
|
372
380
|
function handleKey(ev: KeyboardEvent) {
|
|
373
381
|
if (ev.key === "Escape") {
|
|
374
382
|
setIsPopoverOpen(false);
|
|
375
383
|
isPopoverOpenRef.current = false;
|
|
384
|
+
pinnedIdsRef.current = null;
|
|
376
385
|
}
|
|
377
386
|
}
|
|
378
387
|
|
|
@@ -389,6 +398,7 @@ relation } as RelationItem;
|
|
|
389
398
|
const closePopover = useCallback(() => {
|
|
390
399
|
setIsPopoverOpen(false);
|
|
391
400
|
isPopoverOpenRef.current = false;
|
|
401
|
+
pinnedIdsRef.current = null;
|
|
392
402
|
}, []);
|
|
393
403
|
|
|
394
404
|
const resolvedPlaceholder = placeholder || emptyPlaceholder || <EmptyValue className={"ml-2"}/>;
|
|
@@ -412,6 +422,11 @@ relation } as RelationItem;
|
|
|
412
422
|
setIsPopoverOpen(o => {
|
|
413
423
|
const next = !o;
|
|
414
424
|
isPopoverOpenRef.current = next;
|
|
425
|
+
if (next) {
|
|
426
|
+
pinnedIdsRef.current = new Set(selectedItems.map(i => String(i.id)));
|
|
427
|
+
} else {
|
|
428
|
+
pinnedIdsRef.current = null;
|
|
429
|
+
}
|
|
415
430
|
return next;
|
|
416
431
|
});
|
|
417
432
|
}}
|
|
@@ -589,7 +604,20 @@ relation } as RelationItem;
|
|
|
589
604
|
</CommandPrimitive.Empty>
|
|
590
605
|
)}
|
|
591
606
|
<CommandPrimitive.Group>
|
|
592
|
-
{
|
|
607
|
+
{(() => {
|
|
608
|
+
// Sort items so that initially-selected (pinned) items appear first.
|
|
609
|
+
// We use the snapshot taken when the popover opened so items don't
|
|
610
|
+
// jump around as the user checks/unchecks.
|
|
611
|
+
const pinned = pinnedIdsRef.current;
|
|
612
|
+
const sortedItems = pinned && pinned.size > 0
|
|
613
|
+
? [...availableItems].sort((a, b) => {
|
|
614
|
+
const aP = pinned.has(String(a.id)) ? 0 : 1;
|
|
615
|
+
const bP = pinned.has(String(b.id)) ? 0 : 1;
|
|
616
|
+
return aP - bP;
|
|
617
|
+
})
|
|
618
|
+
: availableItems;
|
|
619
|
+
return sortedItems;
|
|
620
|
+
})().map((item) => {
|
|
593
621
|
const isSelected = selectedItems.some(v => String(v.id) === String(item.id));
|
|
594
622
|
return (
|
|
595
623
|
<CommandPrimitive.Item
|
|
@@ -66,7 +66,7 @@ export type SelectableTableProps<M extends Record<string, unknown>> = {
|
|
|
66
66
|
|
|
67
67
|
inlineEditing?: boolean;
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
fixedFilter?: FilterValues<keyof M extends string ? keyof M : never>;
|
|
70
70
|
|
|
71
71
|
highlightedRow?: (data: Entity<M>) => boolean;
|
|
72
72
|
|
|
@@ -158,7 +158,7 @@ export const SelectableTable = function SelectableTable<M extends Record<string,
|
|
|
158
158
|
initialScroll,
|
|
159
159
|
emptyComponent,
|
|
160
160
|
columns,
|
|
161
|
-
|
|
161
|
+
fixedFilter,
|
|
162
162
|
highlightedRow,
|
|
163
163
|
endAdornment,
|
|
164
164
|
AddColumnComponent,
|
|
@@ -225,8 +225,8 @@ export const SelectableTable = function SelectableTable<M extends Record<string,
|
|
|
225
225
|
|
|
226
226
|
const onFilterUpdate = useCallback((updatedFilterValues?: FilterValues<any>) => {
|
|
227
227
|
setFilterValues?.({ ...updatedFilterValues,
|
|
228
|
-
...
|
|
229
|
-
}, [
|
|
228
|
+
...fixedFilter } as FilterValues<any>);
|
|
229
|
+
}, [fixedFilter]);
|
|
230
230
|
|
|
231
231
|
const contextValue = useMemo(() => ({
|
|
232
232
|
setPopupCell: setPopupCell as ((cell?: SelectedCellProps<M>) => void),
|
|
@@ -264,7 +264,7 @@ export const SelectableTable = function SelectableTable<M extends Record<string,
|
|
|
264
264
|
checkFilterCombination={checkFilterCombination}
|
|
265
265
|
createFilterField={filterable ? createFilterField : undefined}
|
|
266
266
|
rowClassName={useCallback((entity: Entity<M>) => {
|
|
267
|
-
return highlightedRow?.(entity) ? "bg-surface-50
|
|
267
|
+
return highlightedRow?.(entity) ? "bg-surface-accent-50 dark:!bg-surface-accent-950" : "";
|
|
268
268
|
}, [highlightedRow])}
|
|
269
269
|
className="grow"
|
|
270
270
|
emptyComponent={emptyComponent}
|
|
@@ -312,7 +312,7 @@ function createFilterField({
|
|
|
312
312
|
path={baseProperty.path}
|
|
313
313
|
title={resolvedProperty?.name}
|
|
314
314
|
includeId={baseProperty.includeId}
|
|
315
|
-
previewProperties={baseProperty?.previewProperties}
|
|
315
|
+
previewProperties={baseProperty?.ui?.previewProperties}
|
|
316
316
|
hidden={hidden}
|
|
317
317
|
setHidden={setHidden}/>;
|
|
318
318
|
} else if (baseProperty.type === "relation" && baseProperty.relation) {
|
|
@@ -13,7 +13,7 @@ import { ConfirmationDialog } from "@rebasepro/core";
|
|
|
13
13
|
// RolesView Component
|
|
14
14
|
// ============================================
|
|
15
15
|
export function RolesView({ userManagement }: { userManagement: UserManagementDelegate }) {
|
|
16
|
-
const { roles, saveRole, deleteRole, loading, allowDefaultRolesCreation } = userManagement;
|
|
16
|
+
const { roles, saveRole, deleteRole, loading, allowDefaultRolesCreation, rolesError } = userManagement;
|
|
17
17
|
const snackbarController = useSnackbarController();
|
|
18
18
|
const { t } = useTranslation();
|
|
19
19
|
const breadcrumbs = useBreadcrumbsController();
|
|
@@ -139,9 +139,16 @@ isAdmin: false }
|
|
|
139
139
|
<TableCell colspan={3}>
|
|
140
140
|
<CenteredView className="flex flex-col gap-4 my-8 items-center">
|
|
141
141
|
<Typography variant="label">
|
|
142
|
-
{
|
|
142
|
+
{rolesError
|
|
143
|
+
? t("no_permission_to_view_roles")
|
|
144
|
+
: t("no_roles_yet")}
|
|
143
145
|
</Typography>
|
|
144
|
-
{
|
|
146
|
+
{rolesError && (
|
|
147
|
+
<Typography variant="caption" color="secondary">
|
|
148
|
+
{t("no_permission_description")}
|
|
149
|
+
</Typography>
|
|
150
|
+
)}
|
|
151
|
+
{!rolesError && allowDefaultRolesCreation && saveRole && (
|
|
145
152
|
<Button onClick={createDefaultRoles}>
|
|
146
153
|
{t("create_default_roles")}
|
|
147
154
|
</Button>
|
|
@@ -7,7 +7,7 @@ import { Button, Container, Dialog, DialogActions, DialogContent, DialogTitle, I
|
|
|
7
7
|
import { MailIcon, KeyRoundIcon, PlusIcon, Trash2Icon, CopyIcon, CheckCircleIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
|
|
8
8
|
import { RoleChip } from "./RoleChip";
|
|
9
9
|
import { UserManagementDelegate, Role, UserCreationResult } from "@rebasepro/types";
|
|
10
|
-
import { ConfirmationDialog } from "@rebasepro/core";
|
|
10
|
+
import { ConfirmationDialog, BootstrapAdminBanner } from "@rebasepro/core";
|
|
11
11
|
|
|
12
12
|
const PAGE_SIZE = 25;
|
|
13
13
|
|
|
@@ -17,7 +17,7 @@ const PAGE_SIZE = 25;
|
|
|
17
17
|
export function UsersView({ userManagement }: {
|
|
18
18
|
userManagement: UserManagementDelegate;
|
|
19
19
|
}) {
|
|
20
|
-
const { roles, saveUser, createUser, deleteUser, resetPassword, loading: delegateLoading, bootstrapAdmin } = userManagement;
|
|
20
|
+
const { roles, saveUser, createUser, deleteUser, resetPassword, loading: delegateLoading, bootstrapAdmin, usersError } = userManagement;
|
|
21
21
|
const snackbarController = useSnackbarController();
|
|
22
22
|
const { user: loggedInUser } = useAuthController();
|
|
23
23
|
const { t } = useTranslation();
|
|
@@ -247,28 +247,9 @@ message: error instanceof Error ? error.message : t("error_resetting_password")
|
|
|
247
247
|
}
|
|
248
248
|
};
|
|
249
249
|
|
|
250
|
-
if (delegateLoading) {
|
|
251
|
-
return <CenteredView><CircularProgress/></CenteredView>;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
250
|
return (
|
|
255
251
|
<Container className="w-full flex flex-col py-4 gap-4" maxWidth={"6xl"}>
|
|
256
|
-
|
|
257
|
-
{!hasAdmin && loggedInUser && bootstrapAdmin && (
|
|
258
|
-
<div className="bg-yellow-100 dark:bg-yellow-900 border border-yellow-400 dark:border-yellow-700 rounded p-4 flex items-center justify-between">
|
|
259
|
-
<div>
|
|
260
|
-
<Typography variant="label" className="text-yellow-800 dark:text-yellow-200">
|
|
261
|
-
{t("no_users_or_roles_defined")}
|
|
262
|
-
</Typography>
|
|
263
|
-
</div>
|
|
264
|
-
<Button
|
|
265
|
-
onClick={handleBootstrap}
|
|
266
|
-
disabled={bootstrapping}
|
|
267
|
-
>
|
|
268
|
-
{bootstrapping ? <CircularProgress size="small"/> : t("add_logged_user_as_admin")}
|
|
269
|
-
</Button>
|
|
270
|
-
</div>
|
|
271
|
-
)}
|
|
252
|
+
<BootstrapAdminBanner className="mb-4" />
|
|
272
253
|
|
|
273
254
|
<div className="flex items-center mt-12 mb-4 gap-4">
|
|
274
255
|
<Typography gutterBottom variant="h4" className="grow mb-0" component="h4">
|
|
@@ -310,7 +291,7 @@ message: error instanceof Error ? error.message : t("error_resetting_password")
|
|
|
310
291
|
<TableCell header className="w-24 text-right">{t("actions")}</TableCell>
|
|
311
292
|
</TableHeader>
|
|
312
293
|
<TableBody>
|
|
313
|
-
{tableLoading ? (
|
|
294
|
+
{(tableLoading || delegateLoading) ? (
|
|
314
295
|
[
|
|
315
296
|
{ email: "w-48",
|
|
316
297
|
name: "w-32",
|
|
@@ -394,13 +375,20 @@ roles: ["w-16", "w-16"] }
|
|
|
394
375
|
</TableRow>
|
|
395
376
|
)))}
|
|
396
377
|
|
|
397
|
-
{displayUsers.length === 0 && !tableLoading && (
|
|
378
|
+
{displayUsers.length === 0 && !tableLoading && !delegateLoading && (
|
|
398
379
|
<TableRow>
|
|
399
380
|
<TableCell colspan={5}>
|
|
400
381
|
<CenteredView className="flex flex-col gap-4 my-8 items-center">
|
|
401
382
|
<Typography variant="label">
|
|
402
|
-
{
|
|
383
|
+
{usersError
|
|
384
|
+
? t("no_permission_to_view_users")
|
|
385
|
+
: searchQuery ? t("no_users_found") : t("no_users_yet")}
|
|
403
386
|
</Typography>
|
|
387
|
+
{usersError && (
|
|
388
|
+
<Typography variant="caption" color="secondary">
|
|
389
|
+
{t("no_permission_description")}
|
|
390
|
+
</Typography>
|
|
391
|
+
)}
|
|
404
392
|
</CenteredView>
|
|
405
393
|
</TableCell>
|
|
406
394
|
</TableRow>
|
|
@@ -137,7 +137,7 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
137
137
|
{hasAppBar && <DrawerHeader/>}
|
|
138
138
|
|
|
139
139
|
<div
|
|
140
|
-
className={cls(defaultBorderMixin, "bg-
|
|
140
|
+
className={cls(defaultBorderMixin, "bg-surface-50 dark:bg-surface-800", "grow overflow-auto m-0", {
|
|
141
141
|
"lg:mt-4": !hasAppBar,
|
|
142
142
|
"mt-1 lg:m-0 lg:mx-2 lg:mb-2 lg:rounded-lg lg:border-t lg:border-x lg:border-solid": padding,
|
|
143
143
|
"border-t": hasAppBar && !padding
|
|
@@ -158,7 +158,7 @@ export const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(
|
|
|
158
158
|
|
|
159
159
|
const DrawerHeader = () => {
|
|
160
160
|
return (
|
|
161
|
-
<div className="flex flex-col min-h-
|
|
161
|
+
<div className="flex flex-col min-h-14"></div>
|
|
162
162
|
);
|
|
163
163
|
};
|
|
164
164
|
|
|
@@ -184,8 +184,8 @@ function DrawerWrapper(props: {
|
|
|
184
184
|
const { t } = useTranslation();
|
|
185
185
|
|
|
186
186
|
const innerDrawer = <div
|
|
187
|
-
className={cls("h-full
|
|
188
|
-
isFloating ? `absolute top-0 left-0 bottom-0 z-50 bg-surface-50 ${darkBgFloating} shadow-
|
|
187
|
+
className={cls("h-full overflow-hidden", defaultBorderMixin,
|
|
188
|
+
isFloating ? `absolute top-0 left-0 bottom-0 z-50 bg-surface-50 ${darkBgFloating} shadow-lg border-r` : `relative bg-surface-50 ${darkBg}`)}
|
|
189
189
|
style={{
|
|
190
190
|
width: visualWidth,
|
|
191
191
|
transition: "left 75ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, opacity 75ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, width 75ms cubic-bezier(0.4, 0, 0.6, 1) 0ms"
|