@rebasepro/admin 0.15.0 → 0.16.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-Dxx0ZaDk.js → CollectionEditorDialog-D2Vf4C3-.js} +7 -7
- package/dist/{CollectionEditorDialog-Dxx0ZaDk.js.map → CollectionEditorDialog-D2Vf4C3-.js.map} +1 -1
- package/dist/{PropertyEditView-D6xNTm0d.js → PropertyEditView-D3NBsK9_.js} +4 -13
- package/dist/PropertyEditView-D3NBsK9_.js.map +1 -0
- package/dist/{RouterCollectionsStudioView-C4vSn9Pu.js → RouterCollectionsStudioView-hPB54l3Q.js} +4 -4
- package/dist/{RouterCollectionsStudioView-C4vSn9Pu.js.map → RouterCollectionsStudioView-hPB54l3Q.js.map} +1 -1
- package/dist/collection_editor_ui.js +4 -4
- package/dist/components/CollectionViewBinding/CollectionViewStartActions.d.ts +9 -1
- package/dist/components/RelationSelector.d.ts +8 -0
- package/dist/{export-BZi1MzQ5.js → export-oauWlxuu.js} +2 -2
- package/dist/{export-BZi1MzQ5.js.map → export-oauWlxuu.js.map} +1 -1
- package/dist/form/useUndoableDiscard.d.ts +15 -0
- package/dist/{history-B5pkfldE.js → history-C2cqc0bw.js} +2 -2
- package/dist/{history-B5pkfldE.js.map → history-C2cqc0bw.js.map} +1 -1
- package/dist/{import-CXpuYo-T.js → import-Bxv5JPm-.js} +2 -2
- package/dist/{import-CXpuYo-T.js.map → import-Bxv5JPm-.js.map} +1 -1
- package/dist/index.js +17 -25
- package/dist/index.js.map +1 -1
- package/dist/{util-BKtHPLe4.js → util-C4qsI1QV.js} +163 -55
- package/dist/util-C4qsI1QV.js.map +1 -0
- package/package.json +12 -9
- package/src/collection_editor/ui/collection_editor/CollectionRLSTab.tsx +4 -4
- package/src/components/CollectionPanel.tsx +1 -1
- package/src/components/CollectionViewBinding/CollectionListViewBinding.tsx +1 -1
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +3 -11
- package/src/components/CollectionViewBinding/CollectionViewStartActions.tsx +32 -2
- package/src/components/CollectionViewBinding/EntityCardBinding.tsx +10 -8
- package/src/components/DefaultAppBar.tsx +0 -10
- package/src/components/DetailViewBinding.tsx +18 -1
- package/src/components/EditViewBinding.tsx +26 -2
- package/src/components/ReferenceTable/SelectionTableBinding.tsx +10 -1
- package/src/components/RelationSelector.tsx +115 -3
- package/src/contexts/BreacrumbsContext.tsx +4 -21
- package/src/form/EntityForm.tsx +8 -3
- package/src/form/components/FormRail.tsx +15 -4
- package/src/form/useUndoableDiscard.ts +39 -0
- package/src/preview/components/StorageThumbnail.tsx +35 -1
- package/src/routes/RebaseRoute.tsx +2 -10
- package/dist/PropertyEditView-D6xNTm0d.js.map +0 -1
- package/dist/util-BKtHPLe4.js.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/routes/CustomViewRoute.tsx","../src/routes/RebaseRoute.tsx","../src/components/ReferenceWidget.tsx","../src/hooks/useBuildSideDialogsController.tsx","../src/components/SidePanelProvider.tsx","../src/components/AdminModeSyncer.tsx","../src/components/app/useApp.tsx","../src/components/DefaultAppBar.tsx","../src/components/app/AppBar.tsx","../src/components/DrawerNavigationItem.tsx","../src/components/DrawerNavigationGroup.tsx","../src/components/DefaultDrawer.tsx","../src/components/app/Drawer.tsx","../src/components/app/Scaffold.tsx","../src/components/RebaseAdmin.tsx","../src/components/RebaseAuthGate.tsx","../src/collection_editor/useLocalCollectionsConfigController.tsx","../src/components/RebaseNavigation.tsx","../src/components/RebaseLayout.tsx","../src/components/HomePage/FavouritesView.tsx","../src/components/HomePage/NavigationGroup.tsx","../src/components/HomePage/NavigationCard.tsx","../src/components/HomePage/NavigationCardBinding.tsx","../src/components/HomePage/HomePageDnD.tsx","../src/components/HomePage/RenameGroupDialog.tsx","../src/components/HomePage/ContentHomePage.tsx","../src/components/CollectionEditorDialogs.tsx","../src/components/RebaseRouteDefs.tsx","../src/components/RebaseShell.tsx","../src/components/CollectionPanel.tsx","../src/util/propertyConfigMapper.ts","../src/util/dataControllerAdapter.ts","../src/collection_editor/useJsonCollectionsConfigController.tsx","../src/collection_editor/ui/MissingReferenceWidget.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport type { AppView } from \"@rebasepro/admin-types\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\n\nexport function CustomViewRoute({ view }: {\n view: AppView\n}) {\n\n const breadcrumbs = useBreadcrumbsController();\n const urlController = useUrlController();\n\n // Use a ref to avoid breadcrumbs identity in the dep array —\n // breadcrumbs.set() creates a new context value each call, which would\n // re-trigger this effect and cause an infinite render loop.\n const breadcrumbsRef = useRef(breadcrumbs);\n breadcrumbsRef.current = breadcrumbs;\n\n useEffect(() => {\n breadcrumbsRef.current.set({\n breadcrumbs: [{\n title: view.name,\n url: urlController.buildAppUrlPath(view.slug)\n }]\n });\n }, [view.slug, urlController]);\n\n if (typeof view.view === 'function') {\n const ViewComponent = view.view;\n return <ViewComponent />;\n }\n return <>{view.view}</>;\n}\n","\nimport type { ViewMode, AdminCollection } from \"@rebasepro/admin-types\";\nimport { useLocation } from \"react-router\";\nimport { EditViewBinding } from \"../components/EditViewBinding\";\nimport { DetailViewBinding } from \"../components/DetailViewBinding\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useNavigate } from \"react-router\";\nimport { CollectionViewBinding } from \"../components/CollectionViewBinding/CollectionViewBinding\";\nimport { ErrorView, NotFoundPage, useUserConfigurationPersistence, useComponentOverride, useNavigationBlocker } from \"@rebasepro/app\";\nimport { resolveOpenEntityMode, resolveViewMode } from \"../util/view_mode\";\nimport { UnsavedChangesDialog } from \"@rebasepro/app\";\nimport { CenteredView, CircularProgressCenter } from \"@rebasepro/ui\";\nimport { NavigationViewCollectionInternal, NavigationViewEntityCustomInternal, NavigationViewInternal } from \"@rebasepro/app\";\nimport { getNavigationEntriesFromPath } from \"@rebasepro/app\";\nimport { toArray } from \"@rebasepro/utils\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\n\nexport function RebaseRoute() {\n\n const location = useLocation();\n const collectionRegistry = useCollectionRegistryController();\n const urlController = useUrlController();\n const breadcrumbs = useBreadcrumbsController();\n const userConfigPersistence = useUserConfigurationPersistence();\n const ResolvedCollectionView = useComponentOverride(\"Collection.View\", CollectionViewBinding);\n\n const hash = location.hash;\n const isSidePanel = hash.includes(\"#side\");\n const isNew = hash.includes(\"#new\") || hash.includes(\"#new_side\");\n const isCopy = hash.includes(\"#copy\");\n const isFullScreen = hash.includes(\"#full\");\n\n const pathname = location.pathname;\n const navigationPath = urlController.urlPathToDataPath(pathname);\n\n const navigationEntries = getNavigationEntriesFromPath({\n path: navigationPath,\n collections: collectionRegistry.collections ?? []\n });\n\n useEffect(() => {\n const lastEntry = navigationEntries[navigationEntries.length - 1];\n const isViewingCollection = lastEntry?.type === \"collection\";\n\n breadcrumbs.set({\n breadcrumbs: navigationEntries.map((entry, index) => {\n const isLastEntry = index === navigationEntries.length - 1;\n\n if (entry.type === \"entity\") {\n return ({\n title: String(entry.entityId),\n url: urlController.buildUrlCollectionPath(entry.path)\n // count: undefined (not applicable for entities)\n });\n } else if (entry.type === \"custom_view\") {\n return ({\n title: String(entry.view.name ?? entry.view.key),\n url: urlController.buildUrlCollectionPath(entry.path)\n // count: undefined (not applicable for custom views)\n });\n } else if (entry.type === \"collection\") {\n const showCount = isLastEntry && isViewingCollection;\n return ({\n title: entry.collection.name,\n url: urlController.buildUrlCollectionPath(entry.path),\n id: entry.path,\n ...(showCount ? { count: null } : {})\n });\n } else {\n throw new Error(\"Unexpected navigation entry type\");\n }\n })\n });\n }, [navigationEntries.map(entry => entry.path).join(\",\")]);\n\n if (isNew) {\n // New entities always use full-screen mode, even for split-layout collections\n return <EntityFullScreenRoute\n pathname={pathname}\n navigationEntries={navigationEntries}\n isNew={true}\n isCopy={false}\n />;\n }\n\n if (navigationEntries.length === 1 && navigationEntries[0].type === \"collection\") {\n let collection: AdminCollection<any> | undefined;\n collection = collectionRegistry.getCollection(navigationEntries[0].id);\n if (!collection)\n collection = collectionRegistry.getCollection(navigationEntries[0].slug);\n if (!collection) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n return <UnresolvedCollectionView path={navigationEntries[0].slug}/>;\n }\n return <ResolvedCollectionView\n key={`collection_view_${collection.slug}`}\n {...collection}\n parentCollectionSlugs={[]} parentEntityIds={[]}\n path={collection.slug}\n updateUrl={true}\n Actions={toArray(collection.Actions)}/>\n }\n\n if (isSidePanel) {\n const lastCollectionEntry = [...navigationEntries].reverse().find((entry) => entry.type === \"collection\");\n if (lastCollectionEntry) {\n let collection: AdminCollection<any> | undefined;\n const firstEntry = navigationEntries[0] as NavigationViewCollectionInternal<any>;\n collection = collectionRegistry.getCollection(firstEntry.id);\n if (!collection)\n collection = collectionRegistry.getCollection(firstEntry.slug);\n if (!collection) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n return <UnresolvedCollectionView path={firstEntry.slug}/>;\n }\n return <ResolvedCollectionView\n key={`collection_view_${collection.slug}`}\n {...collection}\n parentCollectionSlugs={[]} parentEntityIds={[]}\n path={collection.slug}\n updateUrl={true}\n Actions={toArray(collection.Actions)}/>;\n }\n }\n\n // Check if this is a simple entity route (collection + entity) for a split-layout collection.\n // If so, render the collection view with the entity shown in the split detail panel\n // instead of the full-screen editor. This keeps the master-detail UX with clean URLs.\n //\n // Also handles subcollection tabs: /c/customers/39/orders produces 3 entries\n // (collection→entity→subcollection). We extract the subcollection slug as selectedTab.\n const lastEntityEntry = navigationEntries.find((entry) => entry.type === \"entity\");\n const firstCollectionEntry = navigationEntries[0];\n if (\n !isFullScreen &&\n !isCopy &&\n firstCollectionEntry?.type === \"collection\" &&\n lastEntityEntry?.type === \"entity\" &&\n (navigationEntries.length === 2 || navigationEntries.length === 3)\n ) {\n let collection: AdminCollection<any> | undefined;\n collection = collectionRegistry.getCollection(firstCollectionEntry.id);\n if (!collection)\n collection = collectionRegistry.getCollection(firstCollectionEntry.slug);\n\n const effectiveOpenMode = collection\n ? resolveOpenEntityMode({\n collection,\n viewMode: resolveViewMode({\n collection,\n search: location.search,\n savedViewMode: userConfigPersistence?.getCollectionConfig(collection.slug)?.defaultViewMode as ViewMode | undefined\n })\n })\n : undefined;\n if (collection && effectiveOpenMode === \"split\") {\n // Extract subcollection tab from the 3rd entry if present\n let selectedTab: string | undefined;\n if (navigationEntries.length === 3) {\n const thirdEntry = navigationEntries[2];\n if (thirdEntry.type === \"collection\") {\n selectedTab = thirdEntry.collection.slug;\n } else if (thirdEntry.type === \"custom_view\") {\n selectedTab = thirdEntry.view.key;\n }\n }\n // Fallback: check for unregistered tabs (e.g. __json, __rebase_history)\n // that aren't parsed as navigation entries\n if (!selectedTab && (navigationEntries.length === 2) && lastEntityEntry) {\n const entityIdStr = String(lastEntityEntry.entityId);\n const entityIdIdx = pathname.lastIndexOf(`/${entityIdStr}`);\n if (entityIdIdx >= 0) {\n const afterEntity = pathname.substring(entityIdIdx + 1 + entityIdStr.length);\n const trailingSegment = afterEntity.startsWith(\"/\") ? afterEntity.substring(1) : afterEntity;\n if (trailingSegment.length > 0) {\n selectedTab = trailingSegment;\n }\n }\n }\n return <ResolvedCollectionView\n key={`collection_view_${collection.slug}`}\n {...collection}\n parentCollectionSlugs={[]} parentEntityIds={[]}\n path={collection.slug}\n updateUrl={true}\n selectedEntityId={lastEntityEntry.entityId}\n selectedTab={selectedTab}\n Actions={toArray(collection.Actions)}/>;\n }\n }\n\n return <EntityFullScreenRoute\n pathname={pathname}\n navigationEntries={navigationEntries}\n isNew={isNew}\n isCopy={isCopy}\n />;\n\n}\n\nfunction getSelectedTabFromUrl(isNew: boolean, lastCustomView: NavigationViewCollectionInternal<any> | NavigationViewEntityCustomInternal<any> | undefined) {\n if (isNew) {\n return undefined;\n } else if (lastCustomView) {\n if (lastCustomView.type === \"custom_view\") {\n return lastCustomView.view.key;\n } else if (lastCustomView.type === \"collection\") {\n return lastCustomView.id ?? lastCustomView.slug;\n }\n }\n return undefined;\n}\n\nfunction EntityFullScreenRoute({\n pathname,\n navigationEntries,\n isNew,\n isCopy\n}: {\n pathname: string;\n navigationEntries: NavigationViewInternal[],\n isNew: boolean,\n isCopy: boolean\n}) {\n\n const collectionRegistry = useCollectionRegistryController();\n const urlController = useUrlController();\n const navigate = useNavigate();\n const location = useLocation();\n const userConfigPersistence = useUserConfigurationPersistence();\n\n // defaultValues may be carried via location.state when openNewDocument() is called\n // for full-screen mode. We read it once on mount — after that, the form owns its state.\n const defaultValues = (location.state as { defaultValues?: Record<string, unknown> } | null)?.defaultValues;\n\n // Preserve the current hash (e.g. #full) across tab/save navigations\n const hash = location.hash;\n\n const navigationPath = urlController.urlPathToDataPath(pathname);\n\n // is navigating away blocked\n const blocked = useRef(false);\n\n const lastEntityEntry = [...navigationEntries].reverse().find((entry) => entry.type === \"entity\");\n const navigationEntriesAfterEntity = lastEntityEntry ? navigationEntries.slice(navigationEntries.indexOf(lastEntityEntry) + 1) : [];\n\n const lastCustomView = [...navigationEntriesAfterEntity].reverse().find(\n (entry) => entry.type === \"custom_view\" || entry.type === \"collection\"\n ) as NavigationViewCollectionInternal<any> | NavigationViewEntityCustomInternal<any> | undefined;\n\n const entityId = lastEntityEntry && \"entityId\" in lastEntityEntry ? lastEntityEntry.entityId : undefined;\n\n // Derive tab from navigation entries (works for registered custom views)\n let urlTab = getSelectedTabFromUrl(isNew, lastCustomView);\n\n // Fallback: internal tabs like __json or __rebase_history aren't registered as\n // entity views, so the navigation parser ignores them. Check the raw pathname\n // for a trailing segment after the entity ID to catch those cases.\n if (!urlTab && entityId && !isNew) {\n const entityIdStr = String(entityId);\n const entityIdIdx = pathname.lastIndexOf(`/${entityIdStr}`);\n if (entityIdIdx >= 0) {\n const afterEntity = pathname.substring(entityIdIdx + 1 + entityIdStr.length);\n const trailingSegment = afterEntity.startsWith(\"/\") ? afterEntity.substring(1) : afterEntity;\n if (trailingSegment.length > 0 && trailingSegment !== \"edit\") {\n urlTab = trailingSegment;\n }\n }\n }\n\n const [selectedTab, setSelectedTab] = useState<string | undefined>(urlTab);\n\n const parentCollectionSlugs = collectionRegistry.getParentCollectionSlugs(navigationPath);\n const parentEntityIds = collectionRegistry.getParentEntityIds(navigationPath);\n useEffect(() => {\n if (urlTab !== selectedTab) {\n setSelectedTab(urlTab);\n }\n }, [urlTab]);\n\n const basePath = !entityId || isNew\n ? pathname\n : pathname.substring(0, pathname.lastIndexOf(`/${entityId}`));\n\n const entityPath = basePath + `/${entityId}`;\n\n const blocker = useNavigationBlocker(useCallback(({\n currentLocation,\n nextLocation\n }) => {\n if (nextLocation.pathname.startsWith(entityPath))\n return false;\n\n // Side panel overlay navigations preserve the underlying form via\n // base_location in router state — no data is lost in either direction.\n\n // Opening a side panel (e.g. clicking a relation arrow)\n const nextHash = nextLocation.hash;\n if (nextHash === \"#side\" || nextHash === \"#new_side\")\n return false;\n\n // Closing a side panel (navigate(-1) back to the form's own path)\n const currentHash = currentLocation.hash;\n if ((currentHash === \"#side\" || currentHash === \"#new_side\") &&\n (nextLocation.pathname === basePath ||\n nextLocation.pathname.startsWith(entityPath)))\n return false;\n\n return blocked.current;\n }, [entityPath, basePath]));\n\n const lastCollectionEntry = [...navigationEntries].reverse().find((entry) => entry.type === \"collection\");\n\n if (isNew && !lastCollectionEntry) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n throw new Error(\"INTERNAL: No collection found in the navigation\");\n }\n\n if (!isNew && !lastEntityEntry) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n return <NotFoundPage/>;\n }\n\n const rawCollection = isNew\n ? (lastCollectionEntry && \"collection\" in lastCollectionEntry ? lastCollectionEntry.collection : undefined)!\n : (lastEntityEntry && \"parentCollection\" in lastEntityEntry ? lastEntityEntry.parentCollection : undefined)!;\n const collection = collectionRegistry.getCollection(rawCollection.slug) || rawCollection;\n const fullIdPath = isNew ? lastCollectionEntry!.slug : lastEntityEntry!.slug;\n const collectionPath = urlController.resolveDatabasePathsFrom(fullIdPath);\n const isEditRoute = pathname.endsWith(\"/edit\") || pathname.split(\"/\").pop() === \"edit\";\n // Determine if this is a detail-view-first collection showing the view page\n const isDetailMode = collection.defaultEntityAction === \"view\" && !isNew && !isCopy && entityId && !isEditRoute;\n\n // A record is full screen either because its collection has no list to show\n // beside it, or because the user folded that list away. Only the second is\n // reversible, and it is reversible by dropping `#full` alone: this is the\n // same URL the split route reads, so the same conditions decide it.\n const splitListAvailable = !isNew && !isCopy && entityId !== undefined &&\n navigationEntries[0]?.type === \"collection\" &&\n (navigationEntries.length === 2 || navigationEntries.length === 3) &&\n resolveOpenEntityMode({\n collection,\n viewMode: resolveViewMode({\n collection,\n search: location.search,\n savedViewMode: userConfigPersistence?.getCollectionConfig(collection.slug)?.defaultViewMode as ViewMode | undefined\n })\n }) === \"split\";\n\n const showList = splitListAvailable\n ? () => navigate({\n pathname,\n search: location.search,\n hash: \"\"\n })\n : undefined;\n\n if (isDetailMode) {\n return <>\n <DetailViewBinding\n key={collection.slug + \"_view_\" + entityId}\n entityId={entityId}\n collection={collection}\n layout={\"full_screen\"}\n path={collectionPath}\n selectedTab={selectedTab ?? undefined}\n onShowList={showList}\n onEditClick={() => {\n const editUrl = urlController.buildUrlCollectionPath(`${collectionPath}/${entityId}`) + \"/edit\";\n navigate(editUrl + hash);\n }}\n onTabChange={(params) => {\n setSelectedTab(params.selectedTab);\n const newSelectedTab = params.selectedTab;\n if (newSelectedTab) {\n navigate(`${basePath}/${entityId}/${newSelectedTab}${hash}`, { replace: true });\n } else {\n navigate(`${basePath}/${entityId}${hash}`, { replace: true });\n }\n }}\n parentCollectionSlugs={parentCollectionSlugs}\n parentEntityIds={parentEntityIds}\n />\n </>;\n }\n\n return <>\n <EditViewBinding\n key={collection.slug + \"_\" + (isNew ? \"new\" : (isCopy ? entityId + \"_copy\" : entityId))}\n entityId={isNew ? undefined : entityId}\n collection={collection}\n layout={\"full_screen\"}\n path={collectionPath}\n copy={isCopy}\n selectedTab={selectedTab ?? undefined}\n onShowList={showList}\n defaultValues={isNew ? defaultValues : undefined}\n onValuesModified={(modified) => blocked.current = modified}\n navigateBack={() => {\n const detailUrl = urlController.buildUrlCollectionPath(`${collectionPath}/${entityId}`);\n navigate(detailUrl + hash);\n }}\n onSaved={(params) => {\n const newSelectedTab = params.selectedTab;\n const newEntityId = params.entityId;\n const savedHash = isNew ? \"\" : hash;\n if (newSelectedTab) {\n navigate(`${basePath}/${newEntityId}/${newSelectedTab}${savedHash}`, { replace: true });\n } else {\n navigate(`${basePath}/${newEntityId}${savedHash}`, { replace: true });\n }\n }}\n onTabChange={(params) => {\n setSelectedTab(params.selectedTab);\n if (isNew) {\n return;\n }\n const newSelectedTab = params.selectedTab;\n if (newSelectedTab) {\n navigate(`${basePath}/${entityId}/${newSelectedTab}${hash}`, { replace: true });\n } else {\n navigate(`${basePath}/${entityId}${hash}`, { replace: true });\n }\n }}\n parentCollectionSlugs={parentCollectionSlugs} parentEntityIds={parentEntityIds}\n />\n\n <UnsavedChangesDialog\n open={blocker?.state === \"blocked\"}\n handleOk={() => blocker?.proceed?.()}\n handleCancel={() => blocker?.reset?.()}\n body={\"You have unsaved changes in this entity.\"}/>\n </>;\n}\n\n/**\n * Shown when a URL names a collection the registry cannot resolve.\n *\n * This used to be `return null`, which renders an empty pane inside the app\n * chrome: the sidebar, the nav highlight and the breadcrumb all still work,\n * because those read the collections array directly, while the view itself is\n * blank. Nothing is thrown, and the only trace is a `console.debug` — so the\n * panel looks like it lost its data rather than like it failed to find the\n * collection, and there is no string to search for.\n *\n * A slug containing slashes went unresolvable this way and cost an afternoon to\n * find. The lookup is fixed; this is the part that made it expensive.\n */\nfunction UnresolvedCollectionView({ path }: { path: string }) {\n // Warn, not debug: this is a route that renders nothing useful, and it\n // should be visible at the console's default level.\n useEffect(() => {\n console.warn(\n `[rebase] No collection is registered for \"${path}\", so this route has nothing to render. ` +\n \"Check that the collection is in the collections array and that its slug matches the URL.\"\n );\n }, [path]);\n\n return <CenteredView>\n <ErrorView\n title={\"Collection not found\"}\n error={`Nothing is registered for \"${path}\".`}\n tooltip={\"The URL names a collection the panel does not know about. It may have been renamed or removed from the collections array, or the slug may not match the path.\"}/>\n </CenteredView>;\n}\n","import { useSelectionDialog } from \"../hooks/useSelectionDialog\";\n\nimport React, { useCallback, useMemo } from \"react\";\n\nimport { Entity, EntityReference, FilterValues } from \"@rebasepro/types\";\nimport type { PreviewSize } from \"../types/components/PropertyPreviewProps\";\nimport { getReferenceFrom } from \"@rebasepro/common\";\nimport { ReferencePreview } from \"../preview\";\nimport { Button, cls } from \"@rebasepro/ui\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport type ReferenceWidgetProps<M extends Record<string, unknown>> = {\n name?: string,\n multiselect?: boolean,\n value: EntityReference | EntityReference[] | null,\n onReferenceSelected?: (params: {\n reference: EntityReference | null,\n entity: Entity<M> | null\n }) => void,\n onMultipleReferenceSelected?: (params: {\n references: EntityReference[] | null,\n entities: Entity<M>[] | null\n }) => void,\n path: string,\n disabled?: boolean,\n previewProperties?: string[];\n /**\n * Allow selection of entities that pass the given filter only.\n */\n fixedFilter?: FilterValues<string>;\n size: PreviewSize;\n className?: string;\n includeId?: boolean;\n includeEntityLink?: boolean;\n};\n\n/**\n * This field allows selecting reference/s.\n */\nexport function ReferenceWidget<M extends Record<string, unknown>>({\n name,\n multiselect = false,\n path,\n disabled,\n value,\n onReferenceSelected,\n onMultipleReferenceSelected,\n previewProperties,\n fixedFilter,\n size,\n className,\n includeId,\n includeEntityLink\n}: ReferenceWidgetProps<M>) {\n\n const collectionRegistryController = useCollectionRegistryController();\n\n const collection: AdminCollection | undefined = useMemo(() => {\n return collectionRegistryController.getCollection(path);\n }, [path, collectionRegistryController.getCollection]);\n\n const onSingleEntitySelected = useCallback((entity: Entity<M> | null) => {\n if (disabled)\n return;\n if (onReferenceSelected) {\n const reference = entity ? getReferenceFrom(entity) : null;\n onReferenceSelected?.({\n reference,\n entity\n });\n }\n }, [disabled, onReferenceSelected]);\n\n const onMultipleEntitiesSelected = useCallback((entities: Entity<M>[]) => {\n if (disabled)\n return;\n if (onMultipleReferenceSelected) {\n const references = entities ? entities.map(e => getReferenceFrom(e)) : null;\n onMultipleReferenceSelected({\n references,\n entities\n });\n }\n }, [disabled, onReferenceSelected]);\n\n const referenceDialogController = useSelectionDialog({\n multiselect,\n path,\n collection,\n onSingleEntitySelected,\n onMultipleEntitiesSelected,\n fixedFilter\n }\n );\n\n const clearValue = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n if (multiselect) {\n onMultipleEntitiesSelected([]);\n } else {\n onSingleEntitySelected(null);\n }\n }, [onReferenceSelected]);\n\n let child: React.ReactNode;\n\n const onEntryClick = () => {\n if (disabled)\n return;\n referenceDialogController.open();\n };\n\n if (Array.isArray(value)) {\n child = <div className={\"flex flex-col gap-4\"}>\n {value.map((ref, index) => {\n return <ReferencePreview\n key={`reference_preview_${index}`}\n onClick={onEntryClick}\n reference={ref}\n disabled={disabled}\n previewProperties={previewProperties}\n size={size}\n includeId={includeId}\n includeEntityLink={includeEntityLink}/>\n })}\n </div>\n } else if (value?.isEntityReference && value?.isEntityReference()) {\n child = <ReferencePreview\n reference={value}\n onClick={onEntryClick}\n disabled={disabled}\n previewProperties={previewProperties}\n size={size}\n includeId={includeId}\n includeEntityLink={includeEntityLink}/>\n\n }\n return <div className={cls(\"text-sm font-medium\",\n \"min-w-80 flex flex-col gap-4\",\n \"relative transition-colors duration-200 ease-in rounded-xs font-medium\",\n disabled ? \"bg-opacity-50\" : \"hover:bg-opacity-75\",\n \"dark:text-white/50 text-text-primary/50 dark:text-text-primary-dark/50 dark:text-white/50\",\n className\n )}>\n\n {child}\n {!value && <div className=\"justify-center text-left\">\n <Button disabled={disabled}\n onClick={onEntryClick}>\n Edit {name}\n </Button>\n </div>}\n\n </div>;\n}\n","import type { SideDialogPanelProps, SideDialogsController } from \"../hooks/useSideDialogsController\";\nimport { useCallback, useEffect, useRef, useState, useMemo } from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\n;\nimport { deepEqual as equal } from \"fast-equals\"\nimport { Location } from \"react-router\";\n\ninterface SideDialogLocationState {\n base_location?: Location;\n panels?: string[];\n}\n\nexport function useBuildSideDialogsController(): SideDialogsController {\n\n const location = useLocation();\n const navigate = useNavigate();\n\n const locationRef = useRef(location);\n locationRef.current = location;\n\n const [sidePanels, setSidePanels] = useState<SideDialogPanelProps[]>([]);\n const sidePanelsRef = useRef<SideDialogPanelProps[]>(sidePanels);\n\n const routesStore = useRef<Record<string, SideDialogPanelProps>>({});\n const routesCount = useRef<number>(0);\n\n const updateSidePanels = useCallback((newPanels: SideDialogPanelProps[]) => {\n sidePanelsRef.current = newPanels;\n setSidePanels(newPanels);\n }, []);\n\n useEffect(() => {\n const state = location.state as SideDialogLocationState | null;\n const panelKeys: string[] = state?.panels ?? [];\n const newPanels = panelKeys\n .map(key => routesStore.current[key])\n .filter(p => Boolean(p)) as SideDialogPanelProps[];\n if (!equal(sidePanelsRef.current.map(p => p.key), newPanels.map(p => p.key))) {\n updateSidePanels(newPanels);\n // If all panels were cleared via explicit navigation (full-screen expand),\n // reset routesCount so close() doesn't fire navigate(-1)\n if (newPanels.length === 0) {\n routesCount.current = 0;\n }\n }\n }, [location]);\n\n const close = useCallback(() => {\n\n const currentPanels = sidePanelsRef.current;\n if (currentPanels.length === 0)\n return;\n\n const lastSidePanel = currentPanels[currentPanels.length - 1];\n const updatedPanels = [...currentPanels.slice(0, -1)];\n updateSidePanels(updatedPanels);\n\n if (routesCount.current > 0) {\n if (lastSidePanel.urlPath) // if it has a url path, we need to navigate back, don't remove this code\n navigate(-1);\n routesCount.current--;\n } else if (lastSidePanel.parentUrlPath) {\n const baseLocation = (locationRef.current.state as SideDialogLocationState | null)?.base_location ?? locationRef.current;\n navigate(\n lastSidePanel.parentUrlPath,\n {\n replace: true,\n state: {\n base_location: baseLocation,\n panels: updatedPanels.map(p => p.key)\n }\n }\n );\n }\n }, [navigate]);\n\n const open = useCallback((panelProps: SideDialogPanelProps | SideDialogPanelProps[]) => {\n\n const newPanels: SideDialogPanelProps[] = Array.isArray(panelProps) ? panelProps : [panelProps];\n\n newPanels.forEach((panel) => {\n routesStore.current[panel.key] = panel;\n });\n routesCount.current = routesCount.current + newPanels.length;\n\n const baseLocation = (locationRef.current.state as SideDialogLocationState | null)?.base_location ?? locationRef.current;\n\n const currentPanels = sidePanelsRef.current;\n const updatedPanels = [...currentPanels, ...newPanels];\n updateSidePanels(updatedPanels);\n\n newPanels.forEach((panel) => {\n if (panel.urlPath) {\n navigate(\n panel.urlPath,\n {\n state: {\n base_location: baseLocation,\n panels: updatedPanels.map(p => p.key)\n }\n }\n );\n }\n });\n\n }, [navigate]);\n\n const replace = useCallback((panelProps: SideDialogPanelProps | SideDialogPanelProps[]) => {\n\n const newPanels: SideDialogPanelProps[] = Array.isArray(panelProps) ? panelProps : [panelProps];\n newPanels.forEach((panel) => {\n routesStore.current[panel.key] = panel;\n });\n\n const baseLocation = (locationRef.current.state as SideDialogLocationState | null)?.base_location ?? locationRef.current;\n\n const currentPanels = sidePanelsRef.current;\n const updatedPanels = [...currentPanels.slice(0, -newPanels.length), ...newPanels];\n updateSidePanels(updatedPanels);\n\n newPanels.forEach((panel) => {\n if (panel.urlPath) {\n navigate(\n panel.urlPath,\n {\n replace: true,\n state: {\n base_location: baseLocation,\n panels: updatedPanels.map(p => p.key)\n }\n }\n );\n }\n });\n\n }, [navigate]);\n\n return useMemo(() => ({\n sidePanels,\n setSidePanels: updateSidePanels,\n close,\n open,\n replace\n }), [sidePanels, updateSidePanels, close, open, replace]);\n}\n","import type { SidePanelController } from \"@rebasepro/admin-types\";\nimport React from \"react\";\nimport { useBuildSidePanel } from \"../hooks/useBuildSidePanel\";\nimport { useBuildSideDialogsController } from \"../hooks/useBuildSideDialogsController\";\nimport { SidePanelControllerContext } from \"../hooks/useSidePanel\";\nimport { SideDialogsControllerContext } from \"../contexts/SideDialogsControllerContext\";\nimport { BreadcrumbsProvider } from \"../contexts/BreacrumbsContext\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useNavigationStateController } from \"../hooks/navigation/contexts/NavigationStateContext\";\nimport { useAuthController, useBridgeRegistration, NavigationBlockerProvider } from \"@rebasepro/app\";\n\n/**\n * Provider that builds the SidePanelController and makes it available\n * via the SidePanelControllerContext from @rebasepro/app.\n *\n * After the admin extraction refactor, `useBuildSidePanel` lives\n * in the admin package while the context it feeds into lives in core.\n * This provider bridges the two: place it inside the `<Rebase>` tree and\n * above any component that calls `useSidePanel()`.\n *\n * Also auto-registers the side entity controller and breadcrumbs into the\n * self-assembling Studio bridge (when a StudioBridgeRegistryProvider is\n * mounted above in the tree).\n *\n * @example\n * ```tsx\n * <Rebase ...>\n * {({ loading }) => (\n * <SidePanelProvider>\n * <RebaseRoutes>\n * ...\n * </RebaseRoutes>\n * </SidePanelProvider>\n * )}\n * </Rebase>\n * ```\n *\n * @group Components\n */\nexport function SidePanelProvider({ children }: { children: React.ReactNode }) {\n const collectionRegistryController = useCollectionRegistryController();\n const urlController = useUrlController();\n const navigationStateController = useNavigationStateController();\n const sideDialogsController = useBuildSideDialogsController();\n const authController = useAuthController();\n\n const sidePanelController = useBuildSidePanel(\n collectionRegistryController,\n urlController,\n navigationStateController,\n sideDialogsController,\n authController\n );\n\n return (\n <NavigationBlockerProvider>\n <BreadcrumbsProvider>\n <SideDialogsControllerContext.Provider value={sideDialogsController}>\n <SidePanelControllerContext.Provider value={sidePanelController}>\n <BridgeAutoRegistrar sidePanelController={sidePanelController}/>\n {children}\n </SidePanelControllerContext.Provider>\n </SideDialogsControllerContext.Provider>\n </BreadcrumbsProvider>\n </NavigationBlockerProvider>\n );\n}\n\n/**\n * Internal component that auto-registers side entity and breadcrumbs\n * into the Studio bridge. Must be a child of BreadcrumbsProvider.\n */\nfunction BridgeAutoRegistrar({ sidePanelController }: { sidePanelController: SidePanelController }) {\n const breadcrumbs = useBreadcrumbsController();\n useBridgeRegistration(\"sidePanelController\", sidePanelController);\n useBridgeRegistration(\"breadcrumbs\", breadcrumbs);\n return null;\n}\n","import type { AppView } from \"@rebasepro/admin-types\";\nimport React, { useEffect } from \"react\";\nimport { useLocation } from \"react-router\";\n;\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useAdminModeController } from \"@rebasepro/app\";\nexport interface AdminModeSyncerProps {\n /**\n * Map of views designated as 'Studio' views.\n * Navigating to any of these views will automatically flag the admin mode as \"studio\".\n */\n devViews?: AppView[];\n}\n\n/**\n * A highly customizable utility component that observes react-router routes and\n * actively shifts the internal Rebase `adminModeController` context to match\n * the user's active window segment (e.g., Content vs Studio mode).\n *\n * Placing this anywhere safely inside the Rebase layout automatically triggers\n * UI mode synchronization.\n */\nexport function AdminModeSyncer({ devViews }: AdminModeSyncerProps) {\n const location = useLocation();\n const urlController = useUrlController();\n const adminModeController = useAdminModeController();\n\n // Keep track of the current mode using a ref to avoid adding it to the dependency array\n const currentModeRef = React.useRef(adminModeController.mode);\n currentModeRef.current = adminModeController.mode;\n\n // Stable ref for setMode so it doesn't trigger the effect\n const setModeRef = React.useRef(adminModeController.setMode);\n setModeRef.current = adminModeController.setMode;\n\n useEffect(() => {\n const path = location.pathname;\n const isContentRoute = urlController.isUrlCollectionPath(path) || path === urlController.basePath;\n\n // Check both devViews slugs AND the studio home path (/s or basePath/s)\n const studioHomePath = urlController.basePath === \"/\" ? \"/s\" : `${urlController.basePath}/s`;\n const isStudioRoute = path === studioHomePath || path.startsWith(studioHomePath + \"/\") || devViews?.some(view => {\n const viewPath = urlController.buildAppUrlPath(view.slug);\n return path.startsWith(`${viewPath}/`) || path === viewPath;\n });\n\n if (isStudioRoute && currentModeRef.current !== \"studio\") {\n setModeRef.current(\"studio\");\n } else if (isContentRoute && currentModeRef.current !== \"content\") {\n setModeRef.current(\"content\");\n }\n }, [location.pathname, urlController, devViews]);\n\n return null;\n}\n\n","import React from \"react\";\n\n/**\n * This context represents the state of the app in terms of layout.\n * @group Core\n */\nexport type AppState = {\n hasDrawer: boolean,\n drawerHovered: boolean,\n drawerOpen: boolean,\n openDrawer: () => void,\n closeDrawer: () => void,\n closeHover: () => void,\n autoOpenDrawer?: boolean,\n logo?: string\n}\n\nexport const AppContext = React.createContext<AppState>({\n hasDrawer: false,\n drawerHovered: false,\n drawerOpen: false,\n openDrawer: () => {\n throw new Error(\"openDrawer not implemented\");\n },\n closeDrawer: () => {\n throw new Error(\"closeDrawer not implemented\");\n },\n closeHover: () => {\n throw new Error(\"closeHover not implemented\");\n },\n autoOpenDrawer: false\n});\n\nexport function useApp() {\n return React.useContext(AppContext);\n}\n","\nimport React from \"react\";\n\nimport { Link, useNavigate } from \"react-router\";\nimport { RebaseLogo, LanguageToggle } from \"@rebasepro/app\";\nimport { ErrorBoundary, iconSize } from \"@rebasepro/ui\";\nimport {\n Avatar,\n cls,\n IconButton,\n LogOutIcon,\n Menu,\n MenuItem,\n MoonIcon,\n SettingsIcon,\n Skeleton,\n SunIcon,\n SunMoonIcon,\n Typography\n} from \"@rebasepro/ui\";\nimport { useAuthController, useLargeLayout, useModeController, useAdminModeController, useTranslation } from \"@rebasepro/app\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { User } from \"@rebasepro/types\";\nimport { useApp } from \"./app/useApp\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\nimport { UserSettingsView } from \"@rebasepro/app\";\n\nexport type DefaultAppBarProps<ADDITIONAL_PROPS = object> = {\n\n /**\n * The content of the app bar, usually a title or logo. This includes a link to the home page.\n */\n title?: React.ReactNode;\n\n /**\n * A component that gets rendered on the upper side to the end of the main toolbar\n */\n endAdornment?: React.ReactNode;\n\n /**\n * A component that gets rendered on the upper side to the start of the main toolbar\n */\n startAdornment?: React.ReactNode;\n\n dropDownActions?: React.ReactNode;\n\n /**\n * Whether to render the dark/light/system mode toggle in the app bar.\n * Set to `false` when the drawer owns this action.\n * @default true\n */\n includeModeToggle?: boolean;\n\n /**\n * Whether to render the language switcher in the app bar.\n * Set to `false` when the drawer owns this action.\n * @default true\n */\n includeLanguageToggle?: boolean;\n\n /**\n * Whether to render the user avatar / menu in the app bar.\n * Set to `false` when the drawer owns this action.\n * @default true\n */\n includeUserMenu?: boolean;\n\n className?: string;\n\n style?: React.CSSProperties;\n\n logo?: string;\n\n user?: User;\n} & ADDITIONAL_PROPS;\n\n/**\n * This component renders the main app bar of Rebase.\n * You will likely not need to use this component directly.\n *\n\n */\nexport const DefaultAppBar = function DefaultAppBar({\n title,\n endAdornment,\n startAdornment,\n dropDownActions,\n includeModeToggle = true,\n includeLanguageToggle = true,\n includeUserMenu = true,\n className,\n style,\n user: userProp,\n logo: logoProp\n}: DefaultAppBarProps) {\n\n const {\n hasDrawer,\n drawerOpen,\n logo: appLogo\n } = useApp();\n\n const logo = logoProp ?? appLogo;\n\n const navigation = useUrlController();\n\n const breadcrumbs = useBreadcrumbsController();\n\n const authController = useAuthController();\n const adminModeController = useAdminModeController();\n const {\n mode,\n setMode\n } = useModeController();\n\n const navigate = useNavigate();\n\n const largeLayout = useLargeLayout();\n\n const user = userProp ?? authController.user;\n const { t } = useTranslation();\n\n let avatarComponent: React.ReactElement | null;\n\n if (user) {\n const initial = user?.displayName\n ? user.displayName[0].toUpperCase()\n : (user?.email ? user.email[0].toUpperCase() : \"A\");\n avatarComponent = <Avatar src={user.photoURL ?? undefined}>\n {initial}\n </Avatar>;\n } else if (user === undefined || authController.initialLoading) {\n avatarComponent = <div className={\"p-1 flex justify-center\"}>\n <Skeleton className={\"w-10 h-10 rounded-full\"}/>\n </div>;\n } else {\n avatarComponent = null;\n }\n\n\n return (\n <div\n style={style}\n role=\"banner\"\n className={cls(\"w-full h-14 transition-all ease-in duration-75 absolute top-0 max-w-full overflow-x-auto no-scrollbar\",\n \"flex flex-row gap-2 px-4 items-center\",\n \"backdrop-blur-sm bg-surface-50/95 dark:bg-surface-900/80\",\n {\n \"pl-[19rem]\": drawerOpen && largeLayout,\n \"pl-24\": hasDrawer && !(drawerOpen && largeLayout),\n \"z-10\": largeLayout,\n \"duration-100\": drawerOpen && largeLayout\n },\n className)}>\n\n {navigation && (!hasDrawer || title) && <div className=\"mr-2 hidden lg:block\">\n <Link\n className=\"visited:text-inherit dark:visited:text-inherit block\"\n to={navigation?.basePath ?? \"/\"}\n >\n <div className={\"flex flex-row gap-4\"}>\n {!hasDrawer && (logo\n ? <img src={logo}\n alt=\"Logo\"\n className={cls(\"w-[32px] h-[32px] object-contain\")}/>\n : <RebaseLogo width={\"32px\"} height={\"32px\"}/>)}\n\n {typeof title === \"string\"\n ? <Typography variant=\"subtitle1\"\n noWrap>\n {title}\n </Typography>\n : title}\n </div>\n </Link>\n </div>}\n\n <div className=\"mr-8 hidden lg:block\">\n <nav aria-label=\"Breadcrumb\">\n <div className={\"flex flex-row gap-2 items-center\"}>\n {breadcrumbs.breadcrumbs.map((breadcrumb, index) => {\n return <React.Fragment key={breadcrumb.url + \"_\" + index}>\n {index > 0 && (\n <Typography variant={\"caption\"} color={\"secondary\"}>\n /\n </Typography>\n )}\n <Link\n key={index}\n className=\"visited:text-inherit dark:visited:text-inherit block\"\n to={breadcrumb.url}\n >\n <div className=\"flex flex-row items-center gap-2 whitespace-nowrap\">\n <Typography variant={\"body2\"}>\n {breadcrumb.title}\n </Typography>\n {/* Show count badge for collection breadcrumbs: undefined = not applicable, null = loading, number = count */}\n {breadcrumb.count !== undefined && (\n breadcrumb.count !== null ? (\n <span className=\"text-xs text-surface-accent-500 dark:text-surface-accent-400 bg-surface-100 dark:bg-surface-800 px-1 py-0 rounded\">\n {breadcrumb.count}\n </span>\n ) : (\n <Skeleton className=\"w-8 h-4 rounded-md\"/>\n )\n )}\n </div>\n </Link>\n </React.Fragment>;\n })}\n </div>\n </nav>\n </div>\n {startAdornment}\n\n <div className={\"grow\"}/>\n\n {endAdornment &&\n <ErrorBoundary>\n {endAdornment}\n </ErrorBoundary>}\n\n {includeLanguageToggle && <LanguageToggle/>}\n\n {includeModeToggle &&\n <Menu\n trigger={<IconButton\n color=\"inherit\"\n aria-label=\"Toggle theme\"\n>\n {mode === \"dark\"\n ? <MoonIcon size={iconSize.small}/>\n : <SunIcon size={iconSize.small}/>}\n </IconButton>}>\n <MenuItem onClick={() => setMode(\"dark\")}><MoonIcon size={iconSize.smallest}/> {t(\"dark_mode\")}</MenuItem>\n <MenuItem onClick={() => setMode(\"light\")}><SunIcon size={iconSize.smallest}/> {t(\"light_mode\")} </MenuItem>\n <MenuItem onClick={() => setMode(\"system\")}> <SunMoonIcon\n size={iconSize.smallest}/>{t(\"system_mode\")}</MenuItem>\n </Menu>}\n\n\n {includeUserMenu &&\n <Menu trigger={<div aria-label=\"User menu\" role=\"button\">{avatarComponent}</div>}>\n {user && <div className={\"px-4 py-2 mb-2\"}>\n {user.displayName && <Typography variant={\"body1\"} color={\"secondary\"}>\n {user.displayName}\n </Typography>}\n {user.email && <Typography variant={\"body2\"} color={\"secondary\"}>\n {user.email}\n </Typography>}\n </div>}\n\n {dropDownActions}\n\n {!dropDownActions && <>\n <MenuItem onClick={() => navigate(\"/settings\")}>\n <SettingsIcon/>\n {t(\"account_settings\")}\n </MenuItem>\n <MenuItem onClick={async () => {\n await authController.signOut();\n // replace current route with home\n navigate(\"/\");\n }}>\n <LogOutIcon/>\n {t(\"log_out\")}\n </MenuItem>\n </>}\n\n </Menu>}\n\n </div>\n );\n}\n","import { DefaultAppBar, DefaultAppBarProps } from \"../DefaultAppBar\";\n/**\n * This component renders the main app bar of Rebase.\n */\nexport function AppBar({\n children,\n ...props\n}: {\n children?: React.ReactNode,\n className?: string,\n style?: React.CSSProperties\n} & DefaultAppBarProps) {\n const usedChildren = children ?? <DefaultAppBar {...props}/>;\n return <>{usedChildren}</>;\n}\n\nAppBar.componentType = \"AppBar\";\n","import React from \"react\";\n\nimport { NavLink } from \"react-router\";\nimport { cls, Tooltip } from \"@rebasepro/ui\";\n\n/**\n * Props of a drawer navigation row, named so an app overriding\n * `Shell.DrawerNavigationItem` can type its wrapper against them.\n */\nexport type DrawerNavigationItemProps = {\n icon: React.ReactElement,\n name: string,\n /** @deprecated No longer read: the tooltip is uncontrolled. */\n tooltipsOpen?: boolean,\n drawerOpen: boolean,\n /** @deprecated No longer read: the tooltip is uncontrolled. */\n adminMenuOpen?: boolean,\n url: string,\n onClick?: () => void,\n /**\n * Drop the row's icon and indent the label into the space it occupied, so the\n * row reads as a child of the group header above it.\n *\n * Nothing in the framework sets this: the stock drawer always passes `false`,\n * and an app that wants the categorised look opts into it by overriding\n * `Shell.DrawerNavigationItem` and deciding for itself which rows get it.\n */\n indented?: boolean,\n};\n\nexport function DrawerNavigationItem({\n name,\n icon,\n drawerOpen,\n url,\n onClick,\n indented = false\n}: DrawerNavigationItemProps) {\n\n // Indented rows give up the icon rather than keeping it *and* indenting: a\n // per-row icon repeated down a group is what flattens the hierarchy, since\n // every row then reads at the weight of the category above it. The indent is\n // the same 44px the icon occupied, so labels stay on the original grid and the\n // rail width does not change.\n const iconWrap = indented\n ? <div className={\"shrink-0 w-[44px] h-[30px]\"} aria-hidden={true}/>\n : <div\n className={\"shrink-0 flex items-center justify-center w-[44px] h-[30px] text-surface-500 dark:text-text-secondary-dark [&>svg]:size-4 group-hover/nav:text-primary transition-colors duration-150\"}>\n {icon}\n </div>;\n\n const [wantsTooltip, setWantsTooltip] = React.useState(false);\n\n // Radix will not report a close it never noticed: while the tooltip is masked\n // the pointer can leave the row without `onOpenChange(false)` ever firing. So\n // the stale `true` is dropped on the way *into* the masked state — otherwise\n // it surfaces the moment the mask lifts, as a tooltip hanging over a rail the\n // pointer left long ago.\n if (drawerOpen && wantsTooltip) setWantsTooltip(false);\n\n const listItem = <div>\n <NavLink\n onClick={onClick}\n // The label below is `hidden` (display:none) while the rail is\n // collapsed, which takes it out of the accessibility tree along with\n // the row's only text — a collapsed rail was a column of links with no\n // accessible name at all. The tooltip does not cover this: Radix wires\n // a trigger to its content with `aria-describedby`, which is a\n // description rather than a name, and only while the tooltip is open —\n // and this one is masked shut whenever the drawer is open.\n //\n // Named unconditionally rather than only when collapsed: expanded, this\n // is the same string the row already displays, so the accessible name\n // stays stable across the transition instead of appearing with it.\n aria-label={name}\n style={{\n width: \"100%\",\n transition: drawerOpen ? \"width 150ms ease-in\" : undefined\n }}\n className={({ isActive }: { isActive: boolean }) => cls(\"rounded-lg truncate group/nav\",\n \"hover:bg-primary/5 dark:hover:bg-primary/5 text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white\",\n \"flex flex-row items-center\",\n drawerOpen ? \"pr-4 h-[30px]\" : \"h-[30px]\",\n \"font-medium text-[13px]\",\n isActive ? \"bg-primary/8 dark:bg-primary/10 text-primary dark:text-primary [&_div]:text-primary\" : \"\"\n )}\n to={url}\n >\n\n {iconWrap}\n\n <div\n className={cls(\n \"text-text-primary dark:text-surface-200\",\n drawerOpen ? \"opacity-100\" : \"opacity-0 hidden\",\n \"font-inherit truncate space-x-2\"\n )}>\n {name}\n </div>\n </NavLink>\n </div>;\n\n // Per row, and always controlled. The old shared flag could only say \"every\n // tooltip\" or \"none\", and the state it needed was unreachable, so no entry\n // tooltip ever opened — leaving a bare rail of unlabelled icons. Radix decides\n // when this one wants to be open, from the pointer and from focus; the drawer\n // only masks it once the label says the same thing.\n //\n // Masked rather than withheld: dropping `open`, or the title, would move the\n // tooltip between controlled and uncontrolled as the drawer opens, which\n // strands the old state — a tooltip left up over a pointer nowhere near it.\n return <Tooltip\n open={!drawerOpen && wantsTooltip}\n onOpenChange={setWantsTooltip}\n side=\"right\"\n title={name}>\n {listItem}\n </Tooltip>;\n}\n","import type { NavigationEntry } from \"@rebasepro/admin-types\";\nimport React from \"react\";\nimport { ChevronDownIcon, cls, iconSize, Typography } from \"@rebasepro/ui\";\n\nimport { IconForView, getIcon } from \"@rebasepro/app\";\nimport { DrawerNavigationItem } from \"./DrawerNavigationItem\";\nimport { useTranslation, useComponentOverride } from \"@rebasepro/app\";\n\nexport interface DrawerNavigationGroupProps {\n /**\n * Group name to display in header\n */\n group: string;\n /**\n * Navigation entries in this group\n */\n entries: NavigationEntry[];\n /**\n * Whether the group is collapsed\n */\n collapsed: boolean;\n /**\n * Callback when collapse state should toggle\n */\n onToggleCollapsed: () => void;\n /**\n * Whether the drawer is in open (expanded) state\n */\n drawerOpen: boolean;\n /**\n * @deprecated No longer read. Entry tooltips are uncontrolled — they follow the\n * pointer and focus, and are suppressed wherever the label is already visible.\n */\n tooltipsOpen?: boolean;\n /**\n * @deprecated No longer read. See {@link tooltipsOpen}.\n */\n adminMenuOpen?: boolean;\n /**\n * Optional actions to render in the group header (e.g., \"Add collection\" button)\n */\n headerActions?: React.ReactNode;\n /**\n * Optional callback when a navigation item is clicked\n */\n onItemClick?: (entry: NavigationEntry) => void;\n /**\n * Hide the group header (title and expandable panel)\n */\n hideHeader?: boolean;\n /**\n * Lucide icon name for the group header, from `NavigationGroupMapping.icon`.\n *\n * It decorates the header and nothing else: the entries below are untouched and\n * keep their own icons. An app that wants the categorised look — rows giving up\n * their icons to indent under the group — builds it in its own drawer, by\n * overriding `Shell.DrawerNavigationItem` and passing `indented`.\n */\n icon?: string;\n}\n\n/**\n * Shared drawer navigation group component used by both DefaultDrawer and RebaseCloudDrawer.\n * Renders a collapsible group with header and navigation items.\n */\nexport function DrawerNavigationGroup({\n group,\n entries,\n collapsed,\n onToggleCollapsed,\n drawerOpen,\n headerActions,\n onItemClick,\n hideHeader,\n icon\n}: DrawerNavigationGroupProps) {\n const { t } = useTranslation();\n const ResolvedDrawerNavigationItem = useComponentOverride(\"Shell.DrawerNavigationItem\", DrawerNavigationItem);\n\n // The icon decorates the header, and stops there. It used to also strip the\n // entries of theirs and indent them, which made a per-app styling choice into\n // framework behaviour: every project that labelled a group with an icon lost the\n // icons on its rows, with nothing to turn it off. An app that wants that look\n // now opts into it in its own drawer — see `indented` on\n // {@link DrawerNavigationItem}.\n const groupIcon = !hideHeader && drawerOpen ? getIcon(icon, undefined, undefined, \"small\") : undefined;\n return (\n <div\n className={\"my-2 mx-2 flex flex-col\"}\n key={`drawer_group_${group}`}\n >\n {/* Group Header */}\n {!hideHeader && (\n <div\n className={cls(\"pl-3 pr-2 py-0.5 flex flex-row items-center transition-colors\",\n drawerOpen ? \"cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-800/40 rounded-lg\" : \"opacity-0 invisible pointer-events-none\"\n )}\n onClick={drawerOpen ? onToggleCollapsed : undefined}\n >\n <ChevronDownIcon\n size={iconSize.small}\n className={cls(\n \"text-surface-400 dark:text-surface-400 transition-transform duration-200 mr-1\",\n collapsed ? \"-rotate-90\" : \"rotate-0\"\n )}\n />\n {groupIcon && (\n <span className=\"shrink-0 mr-2 flex items-center text-surface-600 dark:text-surface-300 [&>svg]:size-4\">\n {groupIcon}\n </span>\n )}\n <Typography\n variant={\"caption\"}\n color={\"secondary\"}\n className=\"font-semibold text-[11px] uppercase tracking-wider flex-grow line-clamp-1 text-surface-400 dark:text-surface-400\"\n >\n {(group || t(\"views_group\"))}\n </Typography>\n {headerActions && (\n <div onClick={(e) => e.stopPropagation()}>\n {headerActions}\n </div>\n )}\n </div>\n )}\n\n {/* Collapsible Content */}\n <div\n className={cls(\n \"transition-all duration-200 ease-in-out\",\n \"overflow-hidden\",\n !hideHeader && \"dark:bg-transparent\",\n \"rounded-lg\",\n (!hideHeader && collapsed) ? \"max-h-0 opacity-0\" : \"max-h-[2000px] opacity-100\"\n )}\n >\n {entries.map((entry) => (\n <ResolvedDrawerNavigationItem\n key={entry.id}\n icon={<IconForView collectionOrView={entry.collection ?? entry.view} size={\"small\"}/>}\n drawerOpen={drawerOpen}\n onClick={() => onItemClick?.(entry)}\n url={entry.url}\n name={entry.name}\n />\n ))}\n </div>\n </div>\n );\n}\n","import type { NavigationEntry, NavigationResult } from \"@rebasepro/admin-types\";\nimport React, { useMemo } from \"react\";\n\nimport { useCollapsedGroups, buildCollapsedDefaults, useLargeLayout, useAdminModeController, useAuthController, useModeController, useTranslation, useSlot, useRebaseContext, useAnalyticsController, useRebaseRegistry, useComponentOverride } from \"@rebasepro/app\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useNavigationStateController } from \"../hooks/navigation/contexts/NavigationStateContext\";\n\n\nimport { Link, useNavigate } from \"react-router\";\nimport { AnalyticsEvent } from \"@rebasepro/admin-types\";\nimport {\n Avatar,\n ChevronsLeftIcon,\n ChevronsRightIcon,\n cls,\n iconSize,\n IconButton,\n LanguagesIcon,\n LogOutIcon,\n Menu,\n MenuItem,\n MoonIcon,\n Separator,\n SettingsIcon,\n Skeleton,\n SunIcon,\n SunMoonIcon,\n Tooltip,\n Typography\n} from \"@rebasepro/ui\";\nimport { DrawerNavigationGroup } from \"./DrawerNavigationGroup\";\nimport { LanguageToggle, RebaseLogo } from \"@rebasepro/app\";\nimport { useApp } from \"./app/useApp\";\n\n/**\n * Default drawer used in the admin.\n *\n * When no `children` are provided, renders the full admin navigation\n * (collection groups, mode switch, plugin slots).\n *\n * When `children` **are** provided, renders the shared drawer shell\n * (logo, scrollable area, footer actions, collapse toggle) with the\n * custom content injected in the scrollable area. This lets consumers\n * like the SaaS dashboard reuse the identical structural layout while\n * supplying their own navigation items.\n *\n * @group Core\n */\nexport function DefaultDrawer({\n title,\n logo,\n logoDestination,\n children,\n footerActions,\n className,\n style\n}: {\n title?: React.ReactNode;\n logo?: string;\n logoDestination?: string;\n /**\n * Custom navigation content for the drawer.\n * When provided, replaces the default admin navigation (collection groups,\n * mode switch, slots). The shared shell (logo, scroll area, footer\n * actions, collapse toggle) is still rendered around it.\n */\n children?: React.ReactNode;\n /**\n * Custom content for the drawer footer actions area (language, theme, user menu).\n * - `undefined` — renders the default `DrawerFooterActions`.\n * - `null` — renders nothing (hides the footer actions).\n * - `ReactNode` — renders the provided custom content.\n */\n footerActions?: React.ReactNode | null;\n className?: string;\n style?: React.CSSProperties;\n}) {\n\n const {\n drawerHovered,\n drawerOpen,\n openDrawer,\n closeDrawer,\n logo: appLogo\n } = useApp();\n\n const resolvedLogo = logo ?? appLogo;\n\n const scrollRef = React.useRef<HTMLDivElement>(null);\n const [scrolled, setScrolled] = React.useState(false);\n\n const handleScroll = () => {\n if (scrollRef.current) {\n setScrolled(scrollRef.current.scrollTop > 0);\n }\n };\n\n return (\n <div role=\"navigation\" aria-label=\"Main navigation\" className={cls(\"flex flex-col h-full relative grow w-full\", className)} style={style}>\n\n <DrawerLogo\n logo={resolvedLogo}\n title={title}\n logoDestination={logoDestination}\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n />\n\n <div\n ref={scrollRef}\n onScroll={handleScroll}\n className={\"flex-grow min-h-0 overflow-y-auto overflow-x-hidden no-scrollbar px-2\"}\n style={{\n maskImage: scrolled\n ? \"linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)\"\n : \"linear-gradient(to bottom, black 0, black calc(100% - 20px), transparent 100%)\"\n }}>\n {children ?? <AdminNavigationContent />}\n </div>\n\n {footerActions !== null && (\n footerActions !== undefined\n ? footerActions\n : <DrawerFooterActions\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n />\n )}\n\n <DrawerToggle\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n openDrawer={openDrawer}\n closeDrawer={closeDrawer}\n />\n </div>\n );\n}\n\n/**\n * Default admin navigation content — rendered inside DefaultDrawer when no\n * custom `children` are provided. Contains the mode switch, navigation\n * groups, and header / footer plugin slots.\n */\nfunction AdminNavigationContent() {\n\n const {\n drawerHovered,\n drawerOpen,\n closeDrawer,\n closeHover\n } = useApp();\n\n const analyticsController = useAnalyticsController();\n const navigationState = useNavigationStateController();\n const context = useRebaseContext();\n\n const largeLayout = useLargeLayout();\n const adminModeController = useAdminModeController();\n const registry = useRebaseRegistry();\n const ResolvedDrawerNavigationGroup = useComponentOverride(\"Shell.DrawerNavigationGroup\", DrawerNavigationGroup);\n\n const allNavigationEntries = navigationState.topLevelNavigation?.navigationEntries ?? [];\n\n // Build a set of Studio-only dev view slugs so we can distinguish them from\n // admin custom views added via <RebaseAdmin views={...}> or plugins.\n const studioViewSlugs = useMemo(() => {\n const slugs = new Set<string>();\n (registry.studioConfig?.devViews ?? []).forEach(v => slugs.add(v.slug));\n // The schema view is also a Studio dev view (auto-injected when collectionEditor is enabled)\n if (registry.studioConfig && registry.cmsConfig?.collectionEditor) slugs.add(\"schema\");\n return slugs;\n }, [registry.studioConfig, registry.cmsConfig?.collectionEditor]);\n\n // Studio mode shows Studio dev views + admin entries (Users/Roles).\n // Content mode shows collections, admin custom views, and admin entries — but not Studio dev views.\n const filteredEntries = adminModeController.mode === \"studio\"\n ? allNavigationEntries.filter(e => (e.type === \"view\" && studioViewSlugs.has(e.slug)) || e.type === \"admin\")\n : allNavigationEntries.filter(e => e.type !== \"view\" || !studioViewSlugs.has(e.slug));\n\n // Derive groups from the filtered entries, preserving the order from topLevelNavigation.groups\n const entryGroups = new Set(filteredEntries.map(e => e.group).filter(Boolean));\n const orderedGroups = navigationState.topLevelNavigation?.groups ?? [];\n const groupsToRender = [\n ...orderedGroups.filter(g => entryGroups.has(g)),\n ...[...entryGroups].filter(g => !orderedGroups.includes(g))\n ];\n\n // Group header icons, declared on `navigationGroupMappings`. Keyed by name\n // because that is what a navigation entry's `group` holds.\n const groupIcons = useMemo(() => {\n const icons = new Map<string, string>();\n (registry.cmsConfig?.navigationGroupMappings ?? []).forEach(mapping => {\n if (mapping.icon) icons.set(mapping.name, mapping.icon);\n });\n return icons;\n }, [registry.cmsConfig?.navigationGroupMappings]);\n\n // Collapsible groups state - using \"drawer\" namespace for independent state from home page\n const collapsedDefaults = useMemo(\n () => buildCollapsedDefaults(registry.cmsConfig?.navigationGroupMappings, \"drawer\"),\n [registry.cmsConfig?.navigationGroupMappings]\n );\n const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupsToRender, \"drawer\", collapsedDefaults);\n\n const headerSlot = useSlot(\"navigation.header\", { drawerOpen,\ndrawerHovered,\ncontext });\n const footerSlot = useSlot(\"navigation.footer\", { drawerOpen,\ndrawerHovered,\ncontext });\n\n if (!navigationState.topLevelNavigation)\n return null;\n\n const onItemClick = (view: NavigationEntry) => {\n const eventName: AnalyticsEvent = view.type === \"collection\"\n ? \"drawer_navigate_to_collection\"\n : (view.type === \"view\" ? \"drawer_navigate_to_view\" : \"unmapped_event\");\n analyticsController.onAnalyticsEvent?.(eventName, { url: view.url });\n if (!largeLayout) {\n closeDrawer();\n } else if (!drawerOpen) {\n closeHover();\n }\n };\n\n const drawerVisuallyOpen = drawerOpen || drawerHovered;\n\n return (\n <>\n {registry.studioConfig && (\n <DrawerModeSwitch\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n />\n )}\n\n {headerSlot}\n\n {groupsToRender.map((group) => {\n const entriesInGroup = filteredEntries.filter(e => e.group === group);\n return (\n <ResolvedDrawerNavigationGroup\n key={`drawer_group_${group}`}\n group={group}\n entries={entriesInGroup}\n collapsed={isGroupCollapsed(group)}\n onToggleCollapsed={() => toggleGroupCollapsed(group)}\n drawerOpen={drawerVisuallyOpen}\n onItemClick={onItemClick}\n icon={groupIcons.get(group)}\n />\n );\n })}\n\n {footerSlot}\n </>\n );\n}\n\nexport function DrawerLogo({\n logo,\n title,\n logoDestination = \"/\",\n drawerOpen,\n drawerHovered\n}: {\n logo?: string;\n title?: React.ReactNode;\n logoDestination?: string;\n drawerOpen: boolean;\n drawerHovered: boolean;\n}) {\n\n const showFullContent = drawerOpen || drawerHovered;\n const { t } = useTranslation();\n\n return (\n <div className=\"flex flex-row items-center shrink-0 pt-4 pb-0 px-2\">\n {/* Logo — always visible */}\n {/* Named explicitly because neither branch below carries text: the\n stock `RebaseLogo` is a bare <svg> with no <title>, and a custom\n `logo` only ever gets the generic alt \"Logo\", which names the image\n rather than saying where the link goes. The title link beside it is\n no help either — it renders only when a `title` is set. */}\n <Link\n className=\"shrink-0 flex items-center justify-center w-[56px] h-[40px]\"\n to={logoDestination}\n aria-label={t(\"home\") || \"Home\"}\n >\n {logo\n ? <img src={logo} alt=\"Logo\" className=\"w-[28px] h-[28px] object-contain\"/>\n : <RebaseLogo width=\"28px\" height=\"28px\"/>\n }\n </Link>\n\n {/* Title (fades in when expanded or hovered) */}\n <div\n className={cls(\n \"flex flex-row items-center overflow-hidden transition-all duration-200 ease-in-out\",\n showFullContent ? \"opacity-100 w-full ml-1\" : \"opacity-0 w-0 ml-0\"\n )}\n >\n {title && (\n <Link\n className=\"visited:text-inherit dark:visited:text-inherit block truncate\"\n to={logoDestination}\n >\n {typeof title === \"string\"\n ? <Typography variant=\"subtitle1\" noWrap className=\"truncate\">{title}</Typography>\n : title\n }\n </Link>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Toggle button at the bottom of the drawer.\n * Uses double-chevron icons to indicate collapse/expand direction.\n */\nexport function DrawerToggle({\n drawerOpen,\n drawerHovered,\n openDrawer,\n closeDrawer\n}: {\n drawerOpen: boolean;\n drawerHovered: boolean;\n openDrawer: () => void;\n closeDrawer: () => void;\n}) {\n const isExpanded = drawerOpen;\n const isHovered = drawerHovered && !drawerOpen;\n const showFullContent = isExpanded || isHovered;\n\n const [wantsTooltip, setWantsTooltip] = React.useState(false);\n // See {@link DrawerNavigationItem}: a masked tooltip never hears the pointer\n // leave, so the stale state is dropped as the mask goes on.\n if (showFullContent && wantsTooltip) setWantsTooltip(false);\n\n const { t } = useTranslation();\n\n return (\n <div className=\"shrink-0 mt-auto px-4 pt-0.5 pb-2\">\n <Tooltip\n title={isExpanded ? t(\"collapse\") : t(\"expand\")}\n // The row spells out \"Collapse\"/\"Expand\" itself whenever it is wide\n // enough to show the label — expanded, or floating open under the\n // pointer. A tooltip repeating that word is noise; it earns its\n // place only on a bare rail, where the chevron stands alone.\n //\n // Masked, not withheld: see {@link DrawerNavigationItem} for why\n // this stays controlled in both states.\n open={!showFullContent && wantsTooltip}\n onOpenChange={setWantsTooltip}\n side=\"right\"\n sideOffset={12}\n asChild={true}\n >\n <button\n type=\"button\"\n className={cls(\n \"flex flex-row items-center rounded-lg cursor-pointer w-full\",\n \"hover:bg-surface-accent-100 dark:hover:bg-surface-800\",\n \"transition-colors duration-150\",\n \"py-2\"\n )}\n aria-expanded={isExpanded}\n aria-label={isExpanded ? t(\"collapse\") : t(\"expand\")}\n onClick={() => isExpanded ? closeDrawer() : openDrawer()}\n >\n <div className=\"shrink-0 flex items-center justify-center w-[44px] h-[24px] text-surface-500 dark:text-surface-400\">\n {isExpanded\n ? <ChevronsLeftIcon size={iconSize.small}/>\n : <ChevronsRightIcon size={iconSize.small}/>\n }\n </div>\n <div className={cls(\n \"overflow-hidden transition-all duration-200 ease-in-out\",\n showFullContent ? \"opacity-100 w-auto\" : \"opacity-0 w-0\"\n )}>\n <Typography\n variant=\"body2\"\n className=\"text-surface-500 dark:text-surface-400 select-none whitespace-nowrap\"\n >\n {isExpanded ? t(\"collapse\") : t(\"expand\")}\n </Typography>\n </div>\n </button>\n </Tooltip>\n </div>\n );\n}\n\n/**\n * Segmented Content / Studio switch rendered inside the drawer.\n * Animates in/out with the drawer open state via opacity + max-height.\n */\nfunction DrawerModeSwitch({\n drawerOpen,\n drawerHovered\n}: {\n drawerOpen: boolean;\n drawerHovered: boolean;\n}) {\n const adminModeController = useAdminModeController();\n const urlController = useUrlController();\n const navigate = useNavigate();\n const showSwitch = drawerOpen || drawerHovered;\n\n return (\n <div\n className={cls(\n \"shrink-0 overflow-hidden transition-all duration-200 ease-in-out px-3\",\n showSwitch ? \"opacity-100 h-7 mt-2 mb-0\" : \"opacity-0 pointer-events-none h-7 mt-2 mb-0\"\n )}\n >\n <div role=\"group\" aria-label=\"Content mode\" className=\"flex bg-surface-100 dark:bg-surface-900 rounded-lg p-0.5 border border-surface-200 dark:border-surface-700/60\">\n <button\n onClick={() => {\n adminModeController.setMode(\"content\");\n navigate(urlController.basePath ?? \"/\");\n }}\n aria-pressed={adminModeController.mode === \"content\"}\n className={cls(\n \"flex-1 px-3 py-0.5 text-xs font-semibold rounded-md transition-all text-center\",\n adminModeController.mode === \"content\"\n ? \"bg-white dark:bg-surface-800 shadow-sm text-primary dark:text-primary-400\"\n : \"text-surface-500 hover:text-surface-900 dark:hover:text-white\"\n )}\n >\n Content\n </button>\n <button\n onClick={() => {\n adminModeController.setMode(\"studio\");\n navigate(urlController.basePath === \"/\" ? \"/s\" : `${urlController.basePath ?? \"\"}/s`);\n }}\n aria-pressed={adminModeController.mode === \"studio\"}\n className={cls(\n \"flex-1 px-3 py-0.5 text-xs font-semibold rounded-md transition-all text-center\",\n adminModeController.mode === \"studio\"\n ? \"bg-white dark:bg-surface-800 shadow-sm text-primary dark:text-primary-400\"\n : \"text-surface-500 hover:text-surface-900 dark:hover:text-white\"\n )}\n >\n Studio\n </button>\n </div>\n </div>\n );\n}\n\n/**\n * Footer actions rendered at the bottom of the drawer, above the collapse/expand toggle.\n * Replaces the app bar icons (language, theme, user avatar) with a drawer-native layout\n * that adapts between collapsed (icons only) and expanded (full labels + user bar) states.\n *\n * @group Core\n */\nexport function DrawerFooterActions({\n drawerOpen,\n drawerHovered,\n /**\n * Custom content to render inside the user dropdown menu.\n * When provided, these items are appended after the user info header\n * and before the default Sign Out item.\n */\n dropDownActions,\n /**\n * Override the user object displayed in the footer.\n * When omitted, falls back to `authController.user`.\n */\n user: userProp\n}: {\n drawerOpen: boolean;\n drawerHovered: boolean;\n dropDownActions?: React.ReactNode;\n user?: import(\"@rebasepro/types\").User;\n}) {\n const authController = useAuthController();\n const {\n mode,\n setMode\n } = useModeController();\n const navigate = useNavigate();\n const { t } = useTranslation();\n\n const user = userProp ?? authController.user;\n const showFullContent = drawerOpen || drawerHovered;\n const isFloating = drawerHovered && !drawerOpen;\n const portalRef = React.useRef<HTMLDivElement>(null);\n\n // User avatar\n let avatarComponent: React.ReactElement | null;\n if (user) {\n const initial = user?.displayName\n ? user.displayName[0].toUpperCase()\n : (user?.email ? user.email[0].toUpperCase() : \"A\");\n avatarComponent = <Avatar src={user.photoURL ?? undefined} className=\"w-8 h-8 text-xs\">\n {initial}\n </Avatar>;\n } else if (user === undefined || authController.initialLoading) {\n avatarComponent = <Skeleton className=\"w-8 h-8 rounded-full\"/>;\n } else {\n avatarComponent = null;\n }\n\n return (\n <div className=\"shrink-0 pt-2 pb-0\" ref={portalRef}>\n {avatarComponent && (\n <div className=\"flex items-center px-[16px] py-1\">\n <Menu\n trigger={\n <div\n className={cls(\n \"shrink-0 flex items-center justify-center w-[44px] cursor-pointer\",\n \"rounded-md py-1\",\n \"hover:bg-surface-accent-100 dark:hover:bg-surface-800\",\n \"transition-colors duration-150\"\n )}\n role=\"button\"\n tabIndex={0}\n aria-label={t(\"user_menu\") || \"User menu\"}\n >\n {avatarComponent}\n </div>\n }\n side=\"top\"\n align=\"start\"\n >\n {user && <div className=\"px-4 py-2 mb-1\">\n {user.displayName && <Typography variant=\"body1\" color=\"secondary\">\n {user.displayName}\n </Typography>}\n {user.email && <Typography variant=\"body2\" color=\"secondary\">\n {user.email}\n </Typography>}\n </div>}\n\n {dropDownActions}\n\n {!dropDownActions && <>\n <MenuItem onClick={() => navigate(\"/settings\")}>\n <SettingsIcon/>\n {t(\"account_settings\")}\n </MenuItem>\n <MenuItem onClick={async () => {\n await authController.signOut();\n navigate(\"/\");\n }}>\n <LogOutIcon/>\n {t(\"log_out\")}\n </MenuItem>\n </>}\n </Menu>\n\n {/* Language + Theme — only when expanded */}\n {showFullContent && (\n <div className=\"flex items-center gap-0\">\n <LanguageToggle/>\n <Menu\n trigger={\n <IconButton\n color=\"inherit\"\n aria-label={t(\"toggle_theme\") || \"Toggle theme\"}\n className=\"text-surface-500 dark:text-surface-400\"\n >\n {mode === \"dark\"\n ? <MoonIcon size={iconSize.small}/>\n : mode === \"light\"\n ? <SunIcon size={iconSize.small}/>\n : <SunMoonIcon size={iconSize.small}/>}\n </IconButton>\n }\n portalContainer={portalRef.current}\n side=\"top\"\n >\n <MenuItem onClick={() => setMode(\"dark\")}><MoonIcon size={iconSize.smallest}/> {t(\"dark_mode\")}</MenuItem>\n <MenuItem onClick={() => setMode(\"light\")}><SunIcon size={iconSize.smallest}/> {t(\"light_mode\")}</MenuItem>\n <MenuItem onClick={() => setMode(\"system\")}><SunMoonIcon size={iconSize.smallest}/> {t(\"system_mode\")}</MenuItem>\n </Menu>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { DefaultDrawer } from \"../DefaultDrawer\";\n\n/**\n * This component is in charge of rendering the drawer.\n * If you add this component under your {@link Scaffold}, it will be rendered\n * as a drawer, and the open and close functionality will be handled automatically.\n * If you want to customise the drawer, you can create your own component and pass it as a child.\n * For custom drawers, you can use the {@link useApp} to open and close the drawer.\n *\n */\nexport function Drawer({\n children,\n title,\n logo,\n logoDestination,\n footerActions,\n className,\n style\n }: {\n children?: React.ReactNode,\n title?: React.ReactNode,\n logo?: string,\n logoDestination?: string,\n /**\n * Custom content for the drawer footer actions area (language, theme, user menu).\n * - `undefined` — renders the default `DrawerFooterActions`.\n * - `null` — renders nothing (hides the footer actions).\n * - `ReactNode` — renders the provided custom content.\n */\n footerActions?: React.ReactNode | null,\n className?: string,\n style?: React.CSSProperties\n}) {\n const usedChildren = children ?? <DefaultDrawer title={title} logo={logo} logoDestination={logoDestination} footerActions={footerActions} className={className} style={style}/>;\n return <>{usedChildren}</>;\n}\n\nDrawer.componentType = \"Drawer\";\n","import React, { PropsWithChildren, useCallback, useMemo } from \"react\";\nimport { cls, defaultBorderMixin, IconButton, Sheet, Tooltip } from \"@rebasepro/ui\";\nimport { ChevronLeftIcon, ErrorBoundary, MenuIcon } from \"@rebasepro/ui\";\nimport { deepEqual as equal } from \"fast-equals\"\n\nimport { useLargeLayout, useAdminModeController, useTranslation } from \"@rebasepro/app\";\nimport { useUrlController } from \"../../hooks/navigation/contexts/UrlContext\";\nimport { AppContext } from \"./useApp\";\n\nexport const DRAWER_WIDTH = 280;\n\n/**\n * Namespaced by base path: two admins served from one origin are two different\n * navigations, and a single key would have them overwrite each other's drawer.\n */\nexport function drawerOpenStorageKey(basePath: string | undefined) {\n return `rebase-drawer-open:${basePath || \"/\"}`;\n}\n\n/** `null` when the user has never toggled the drawer, or storage is unavailable. */\nfunction readStoredDrawerOpen(key: string): boolean | null {\n if (typeof window === \"undefined\") return null;\n try {\n const stored = window.localStorage.getItem(key);\n return stored === null ? null : stored === \"true\";\n } catch (e) {\n // Storage can be blocked: private mode, sandboxed iframe, cookie policy.\n return null;\n }\n}\n\nfunction writeStoredDrawerOpen(key: string, open: boolean) {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, String(open));\n } catch (e) {\n // Same as above: a drawer that forgets is better than a crash.\n }\n}\n\n/**\n * @group Core\n */\nexport interface ScaffoldProps {\n\n /**\n * Expand the collapsed drawer while the pointer is over it. On by default —\n * pass `false` to keep the rail a rail until the user clicks the toggle.\n */\n autoOpenDrawer?: boolean;\n\n /**\n * Start with the drawer expanded rather than collapsed to icons.\n *\n * Distinct from {@link autoOpenDrawer}, which is a hover behaviour: this one\n * only seeds the very first visit. Once the user toggles the drawer, that\n * choice is stored in `localStorage` and wins over this prop on every load.\n *\n * Ignored on small layouts, where an expanded drawer covers the content it is\n * meant to navigate.\n */\n defaultDrawerOpen?: boolean;\n\n /**\n * Logo to be displayed in the top bar and drawer.\n * Note that this has no effect if you are using a custom AppBar or Drawer.\n */\n logo?: string;\n\n /**\n * If true, the main content will be padded in large layouts. Defaults to true.\n */\n padding?: boolean;\n\n className?: string;\n\n style?: React.CSSProperties;\n}\n\n/**\n * This view acts as a scaffold for Rebase.\n *\n * It is in charge of displaying the navigation drawer, top bar and main\n * collection views.\n * This component needs a parent {@link Rebase}\n *\n * @param props\n\n * @group Core\n */\nexport const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(\n function Scaffold(props: PropsWithChildren<ScaffoldProps>) {\n\n const {\n children,\n autoOpenDrawer = true,\n defaultDrawerOpen = false,\n logo,\n className,\n style,\n padding = true\n } = props;\n\n const drawerChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === \"Drawer\");\n if (drawerChildren.length > 1) {\n throw Error(\"Only one Drawer component is allowed in Scaffold\");\n }\n const appBarChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === \"AppBar\");\n if (appBarChildren.length > 1) {\n throw Error(\"Only one AppBar component is allowed in Scaffold\");\n }\n const otherChildren = React.Children.toArray(children)\n .filter((child: any) => child.type.componentType !== \"Drawer\" && child.type.componentType !== \"AppBar\");\n const includeDrawer = drawerChildren.length > 0;\n const largeLayout = useLargeLayout();\n\n const storageKey = drawerOpenStorageKey(useUrlController().basePath);\n\n // Seeded once, deliberately: a `useEffect` syncing this to the prop would\n // re-expand the drawer under a user who had just collapsed it.\n const [drawerOpen, setDrawerOpenState] = React.useState(defaultDrawerOpen && largeLayout);\n const [onHover, setOnHover] = React.useState(false);\n\n // The stored choice is a client-only fact, so it is applied after the first\n // render rather than seeded into it: reading storage while rendering would\n // make the client disagree with server-rendered HTML. A layout effect runs\n // before paint, so the drawer still arrives in its remembered state.\n // `defaultDrawerOpen` seeds the very first visit and is ignored after that.\n React.useLayoutEffect(() => {\n const stored = readStoredDrawerOpen(storageKey);\n if (stored === null) return;\n setDrawerOpenState(stored && largeLayout);\n // Deliberately not re-run on `largeLayout`: crossing the breakpoint is\n // the effect below, and re-running here would undo a user's toggle.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [storageKey]);\n\n // One piece of state drives two different things: the expanded rail on\n // large layouts, and the modal sheet on small ones. Carrying an expanded\n // rail across the breakpoint would drop that sheet, overlay and all, over\n // the content — so the crossing resets it, and widening again restores\n // whatever the user last chose.\n const wasLargeLayout = React.useRef(largeLayout);\n React.useEffect(() => {\n if (wasLargeLayout.current === largeLayout) return;\n wasLargeLayout.current = largeLayout;\n setDrawerOpenState(largeLayout ? (readStoredDrawerOpen(storageKey) ?? defaultDrawerOpen) : false);\n }, [largeLayout, defaultDrawerOpen, storageKey]);\n\n const setDrawerOpen = useCallback((open: boolean) => {\n setDrawerOpenState(open);\n // Small layouts render the drawer as a modal sheet. Remembering that\n // one would greet the next load with an overlay over the content.\n if (!largeLayout) return;\n writeStoredDrawerOpen(storageKey, open);\n }, [largeLayout, storageKey]);\n\n // The pointer has left, but a popover the drawer opened is still up, so the\n // collapse is owed rather than cancelled. See `setOnHoverFalse`.\n const collapseWhenPopoverCloses = React.useRef(false);\n\n const setOnHoverTrue = useCallback(() => {\n // Hover expansion is the default; `autoOpenDrawer={false}` opts out for\n // admins that want the rail to stay a rail until the toggle is clicked.\n if (!autoOpenDrawer) return;\n collapseWhenPopoverCloses.current = false;\n setOnHover(true);\n }, [autoOpenDrawer]);\n const setOnHoverFalse = useCallback(() => {\n // Don't collapse the drawer out from under an open popover/dropdown —\n // its content is portalled outside the drawer, so reaching for it reads\n // as a mouseleave. The collapse is owed until that popover closes.\n if (document.querySelector(\"[data-radix-popper-content-wrapper]\")) {\n collapseWhenPopoverCloses.current = true;\n return;\n }\n collapseWhenPopoverCloses.current = false;\n setOnHover(false);\n }, []);\n\n // Nothing fires a second mouseleave when the popover finally closes, so the\n // owed collapse has to be noticed rather than waited for. Only mounted\n // while the drawer is actually floating open.\n React.useEffect(() => {\n if (!onHover) return;\n const collapseIfOwed = () => {\n if (!collapseWhenPopoverCloses.current) return;\n if (document.querySelector(\"[data-radix-popper-content-wrapper]\")) return;\n collapseWhenPopoverCloses.current = false;\n setOnHover(false);\n };\n const observer = new MutationObserver(collapseIfOwed);\n observer.observe(document.body, {\n childList: true,\n subtree: true\n });\n return () => observer.disconnect();\n }, [onHover]);\n\n const handleDrawerOpen = useCallback(() => {\n setDrawerOpen(true);\n }, [setDrawerOpen]);\n\n const handleDrawerClose = useCallback(() => {\n setDrawerOpen(false);\n }, [setDrawerOpen]);\n\n const computedDrawerOpen: boolean = drawerOpen;\n const computedDrawerHovered = Boolean(largeLayout && onHover);\n\n const adminModeController = useAdminModeController();\n const isStudioDark = adminModeController.mode === \"studio\";\n\n\n const hasAppBar = Boolean(appBarChildren.length > 0);\n const appContextValue = useMemo(() => ({\n hasDrawer: Boolean(includeDrawer),\n drawerOpen: computedDrawerOpen,\n drawerHovered: computedDrawerHovered,\n openDrawer: handleDrawerOpen,\n closeDrawer: handleDrawerClose,\n closeHover: setOnHoverFalse,\n logo\n }), [includeDrawer, computedDrawerOpen, computedDrawerHovered, handleDrawerOpen, handleDrawerClose, setOnHoverFalse, logo]);\n\n return (\n <AppContext.Provider value={appContextValue}>\n <div\n className={cls(\"flex h-screen w-screen overflow-hidden\",\n \"bg-surface-50 dark:bg-surface-900\",\n \"text-surface-900 dark:text-white\", className)}\n style={{\n paddingTop: \"env(safe-area-inset-top)\",\n paddingLeft: \"env(safe-area-inset-left)\",\n paddingRight: \"env(safe-area-inset-right)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n height: \"100dvh\",\n ...style\n }}>\n {appBarChildren}\n\n <DrawerWrapper\n displayed={includeDrawer}\n onMouseEnter={setOnHoverTrue}\n onMouseMove={setOnHoverTrue}\n onMouseLeave={setOnHoverFalse}\n open={drawerOpen}\n hovered={onHover}\n isStudioDark={isStudioDark}\n setDrawerOpen={setDrawerOpen}>\n {includeDrawer && drawerChildren}\n </DrawerWrapper>\n\n <main\n className=\"flex flex-col grow overflow-auto\">\n\n {hasAppBar && <DrawerHeader/>}\n\n <div\n className={cls(defaultBorderMixin, \"bg-surface-50 dark:bg-surface-800\", \"grow overflow-auto m-0\", {\n \"mt-1 lg:m-0 lg:mx-2 lg:mb-2 lg:rounded-lg lg:border-t lg:border-x lg:border-solid\": padding,\n // No app bar means no DrawerHeader spacer above, so inset the\n // panel by the same amount as its sides and bottom.\n // Must come after the padding classes, which reset lg margins.\n \"lg:mt-2\": !hasAppBar && padding,\n \"lg:mt-4\": !hasAppBar && !padding,\n \"border-t\": hasAppBar && !padding\n })}>\n\n <ErrorBoundary>\n {otherChildren}\n </ErrorBoundary>\n\n </div>\n </main>\n </div>\n </AppContext.Provider>\n );\n },\n equal\n)\n\nconst DrawerHeader = () => {\n return (\n <div className=\"flex flex-col min-h-14\"></div>\n );\n};\n\nfunction DrawerWrapper(props: {\n children: React.ReactNode,\n displayed: boolean,\n open: boolean,\n logo?: string,\n hovered: boolean,\n isStudioDark: boolean,\n setDrawerOpen: (open: boolean) => void,\n onMouseEnter: () => void,\n onMouseMove: () => void,\n onMouseLeave: () => void\n}) {\n\n const layoutWidth = !props.displayed ? 0 : (props.open ? DRAWER_WIDTH : 72);\n const visualWidth = !props.displayed ? 0 : ((props.open || props.hovered) ? DRAWER_WIDTH : 72);\n\n const isFloating = props.hovered && !props.open;\n const darkBg = \"dark:bg-surface-900\";\n const darkBgFloating = \"dark:bg-surface-900\";\n const { t } = useTranslation();\n\n const innerDrawer = <div\n className={cls(\"h-full overflow-hidden\", defaultBorderMixin,\n isFloating ? `absolute top-0 left-0 bottom-0 z-50 bg-surface-50 ${darkBgFloating} shadow-lg border-r` : `relative bg-surface-50 ${darkBg}`)}\n style={{\n width: visualWidth,\n 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\"\n }}\n >\n\n <div className={\"flex flex-col h-full\"}>\n {props.children}\n </div>\n\n </div>;\n\n const largeLayout = useLargeLayout();\n if (!largeLayout) {\n if (!props.displayed)\n return null;\n return <>\n <IconButton\n color=\"inherit\"\n aria-label={t(\"open_menu\")}\n onClick={() => props.setDrawerOpen(true)}\n className=\"absolute sm:top-2 sm:left-4 top-1 left-2\"\n >\n <MenuIcon/>\n </IconButton>\n <Sheet side={\"left\"}\n transparent={true}\n open={props.open}\n onOpenChange={props.setDrawerOpen}\n title={t(\"navigation_drawer\")}\n overlayClassName={\"bg-white/80 dark:bg-surface-900/80\"}\n >\n {innerDrawer}\n </Sheet>\n </>;\n }\n\n return (\n <div\n className=\"z-20 relative flex-shrink-0 overflow-visible\"\n onMouseEnter={props.onMouseEnter}\n onMouseMove={props.onMouseMove}\n onMouseLeave={props.onMouseLeave}\n style={{\n width: layoutWidth,\n minWidth: layoutWidth,\n 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\"\n }}>\n\n {innerDrawer}\n\n </div>\n );\n}\n","import React, { useLayoutEffect } from \"react\";\nimport { useRebaseRegistryDispatch } from \"@rebasepro/app\";\nimport type { RebaseAdminConfig } from \"@rebasepro/admin-types\";\n\n/**\n * Declarative component to configure the admin in Rebase.\n * Renders nothing — purely registers config into the RebaseRegistry.\n *\n * When `collectionEditor` is provided, the built-in visual schema editor\n * is auto-wired as a native feature (slots, provider, Studio view) without\n * needing any external plugin.\n */\nexport function RebaseAdmin({ collections, views, homePage, entityViews, collectionViews, entityActions, collectionEditor, navigationGroupMappings, basePath }: RebaseAdminConfig) {\n const dispatch = useRebaseRegistryDispatch();\n\n useLayoutEffect(() => {\n dispatch.registerAdmin({ collections,\nviews,\nhomePage,\nentityViews,\ncollectionViews,\nentityActions,\ncollectionEditor,\nnavigationGroupMappings,\nbasePath });\n return () => dispatch.unregisterAdmin();\n }, [dispatch, collections, views, homePage, entityViews, collectionViews, entityActions, collectionEditor, navigationGroupMappings, basePath]);\n\n return null;\n}\n","import React from \"react\";\nimport {\n useRebaseRegistry,\n useAuthController\n} from \"@rebasepro/app\";\nimport { CircularProgressCenter } from \"@rebasepro/ui\";\nimport { LoginView } from \"@rebasepro/app\";\nimport type { AuthControllerExtended } from \"@rebasepro/admin-types\";\n\n/**\n * Auth gate component that handles the authentication flow.\n *\n * - Shows a loading spinner while `authController.initialLoading` is true.\n * - Shows the login view when no user is authenticated.\n * - Renders `children` when a user is authenticated.\n *\n * **Independently usable**: Use this alone when you want auth gating\n * without the full admin layout or navigation.\n *\n * @example\n * ```tsx\n * <RebaseAuthGate>\n * <MyCustomApp />\n * </RebaseAuthGate>\n * ```\n */\nexport function RebaseAuthGate({ children }: { children: React.ReactNode }) {\n const registry = useRebaseRegistry();\n const authController = useAuthController();\n\n\n if (authController?.initialLoading) {\n return <CircularProgressCenter size={\"large\"}/>;\n }\n\n if (!authController?.user) {\n const ActiveLoginView = registry.authConfig?.loginView ?? (\n <LoginView authController={authController as AuthControllerExtended}/>\n );\n return <>{ActiveLoginView}</>;\n }\n\n return <>{children}</>;\n}\n","import { CollectionsConfigController, SaveCollectionParams, UpdateCollectionParams, DeleteCollectionParams, SavePropertyParams, DeletePropertyParams, UpdatePropertiesOrderParams } from \"./types/config_controller\";\nimport { Properties } from \"@rebasepro/types\";\nimport { getSubcollections } from \"@rebasepro/common\";\n\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\nimport { DEFAULT_API_PATH } from \"@rebasepro/app\";\n\n/**\n * What the backend said about its schema editor, and how sure we are.\n *\n * `unknown` covers both \"still asking\" and \"could not ask\" — a backend too old\n * to have the endpoint, or one that is unreachable. Those fall back to the\n * build-mode guess below rather than locking the editor for someone whose\n * editor used to work.\n */\ntype SchemaEditorAvailability =\n | { state: \"unknown\" }\n | { state: \"known\", enabled: boolean, reason?: string };\n\n/**\n * The guess this hook used to make on its own.\n *\n * `process.env.NODE_ENV` here is the *frontend bundle's* build mode. Whether\n * the schema editor exists is decided by a different process entirely — the\n * server's own `NODE_ENV`, its `collectionsDir`, whether its collections were\n * introspected, whether `ts-morph` is installed. The two disagree in every\n * ordinary setup: a dev frontend against a deployed API, a `baas` project, a\n * hosted console. When they did, the editor offered itself and every save came\n * back `404 Not Found`. It is kept only as the answer for a backend too old to\n * be asked.\n */\nconst buildModeGuess = (): boolean => process.env.NODE_ENV === \"production\";\n\nexport function useLocalCollectionsConfigController(\n clientOrUrl: any,\n baseCollections: AdminCollection[] = [],\n options?: {\n readOnly?: boolean;\n getAuthToken?: () => Promise<string | null>;\n /**\n * Identity of the signed-in user, if any.\n *\n * Only used to re-ask the backend when it changes: whether the editor\n * will accept a write depends on who is asking, and the answer to an\n * anonymous probe does not survive a sign-in.\n */\n authKey?: string | null;\n }\n): CollectionsConfigController {\n\n const parsedCollections = baseCollections;\n\n // Store latest options in a ref to prevent stale closures in the `request` function\n // due to useMemo caching the saveCollection function.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // `/api` only by default — a backend configured with another `basePath`\n // mounts the schema editor under that instead.\n const clientBaseUrl = typeof clientOrUrl === \"string\"\n ? clientOrUrl\n : (clientOrUrl?.baseUrl ?? \"\");\n const clientApiPath = (typeof clientOrUrl === \"object\" && clientOrUrl !== null && clientOrUrl.apiPath)\n || DEFAULT_API_PATH;\n const editorUrl = `${String(clientBaseUrl).replace(/\\/$/, \"\")}${clientApiPath}/schema-editor`;\n\n const resolveToken = async (): Promise<string | null> => {\n let token = optionsRef.current?.getAuthToken ? await optionsRef.current.getAuthToken() : null;\n if (!token && typeof clientOrUrl === \"object\" && clientOrUrl !== null && clientOrUrl.resolveToken) {\n token = await clientOrUrl.resolveToken();\n }\n return token ?? null;\n };\n\n const request = async (endpoint: string, payload: Record<string, unknown>) => {\n try {\n const token = await resolveToken();\n\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${editorUrl}${endpoint}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload)\n });\n if (!response.ok) {\n const text = await response.text();\n let err: Record<string, unknown> = {};\n try {\n err = JSON.parse(text);\n } catch (e) {\n // ignore json parse error\n }\n\n if (Object.keys(err).length === 0) {\n err = { message: text };\n }\n console.error(\"dev server error payload:\", err);\n const errObj = err.error as Record<string, unknown> | string | undefined;\n const errMessage = typeof errObj === \"object\" && errObj !== null\n ? (errObj.message as string)\n : (typeof errObj === \"string\" ? errObj : (err.message as string | undefined));\n throw new Error(errMessage || \"Error communicating with local dev server\");\n }\n } catch (e) {\n console.error(\"fetch request failed\", e);\n throw e;\n }\n };\n\n // ── Ask the backend whether it will accept an edit ────────────────\n const forcedReadOnly = options?.readOnly;\n const authKey = options?.authKey ?? null;\n const [availability, setAvailability] = useState<SchemaEditorAvailability>({ state: \"unknown\" });\n\n useEffect(() => {\n // Nothing to ask about: the caller has already decided.\n if (forcedReadOnly === true) return;\n\n let cancelled = false;\n (async () => {\n try {\n const token = await resolveToken();\n const response = await fetch(`${editorUrl}/status`, {\n headers: token ? { Authorization: `Bearer ${token}` } : {}\n });\n if (cancelled) return;\n\n // A backend from before the endpoint existed. Guessing from the\n // bundle's build mode is wrong, but it is what that backend's\n // admin panel has always done, and locking the editor for\n // someone whose editor works would be worse.\n if (response.status === 404) {\n setAvailability({ state: \"unknown\" });\n return;\n }\n\n const body = await response.json().catch(() => ({})) as {\n enabled?: boolean,\n reason?: string,\n error?: { message?: string }\n };\n if (cancelled) return;\n\n if (response.ok) {\n setAvailability({\n state: \"known\",\n enabled: body.enabled === true,\n reason: body.reason\n });\n } else {\n // 401/403 (not an admin) or 501 (no auth configured at all)\n // — all of them mean this session cannot edit collections,\n // and the body says why better than we could.\n setAvailability({\n state: \"known\",\n enabled: false,\n reason: body.error?.message\n ?? `The backend refused to say whether collections are editable (HTTP ${response.status}).`\n });\n }\n } catch {\n if (!cancelled) setAvailability({ state: \"unknown\" });\n }\n })();\n\n return () => { cancelled = true; };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editorUrl, forcedReadOnly, authKey]);\n\n const readOnly = forcedReadOnly\n ?? (availability.state === \"known\" ? !availability.enabled : buildModeGuess());\n\n const readOnlyReason = availability.state === \"known\" && availability.reason\n ? availability.reason\n : \"Collections can only be edited against a backend running the schema editor, which is off in production.\";\n\n return useMemo(() => ({\n loading: false,\n readOnly,\n readOnlyReason,\n collections: parsedCollections,\n getCollection: (id: string) => {\n const found = parsedCollections.find(c => (c as AdminCollection & { id?: string }).id === id || c.slug === id);\n if (found) return found;\n throw Error(`Collection ${id} not found in local mode`);\n },\n\n saveCollection: async ({ id, collectionData }: SaveCollectionParams) => {\n await request(\"/collection/save\", { collectionId: id,\ncollectionData });\n },\n updateCollection: async ({ id, collectionData }: UpdateCollectionParams) => {\n await request(\"/collection/save\", { collectionId: id,\ncollectionData });\n },\n deleteCollection: async ({ id }: DeleteCollectionParams) => {\n await request(\"/collection/delete\", { collectionId: id });\n },\n\n // The follow-up write carries exactly one key, and `partial` is what says\n // so. Read as a whole-collection save it deletes everything it does not\n // mention — `securityRules` first, which then falls back to the\n // directory default and widens who can read the collection.\n saveProperty: async ({ path, propertyKey, property, newPropertiesOrder }: SavePropertyParams) => {\n await request(\"/property/save\", { collectionId: path,\npropertyKey,\npropertyConfig: property });\n if (newPropertiesOrder) {\n await request(\"/collection/save\", { collectionId: path,\ncollectionData: { propertiesOrder: newPropertiesOrder },\npartial: true });\n }\n },\n deleteProperty: async ({ path, propertyKey, newPropertiesOrder }: DeletePropertyParams) => {\n await request(\"/property/delete\", { collectionId: path,\npropertyKey });\n if (newPropertiesOrder) {\n await request(\"/collection/save\", { collectionId: path,\ncollectionData: { propertiesOrder: newPropertiesOrder },\npartial: true });\n }\n },\n\n updatePropertiesOrder: async ({ collection, fullPath, newPropertiesOrder }: UpdatePropertiesOrderParams) => {\n const collectionId = (collection as AdminCollection & { id?: string }).id || fullPath.split(\"/\").pop();\n await request(\"/collection/save\", { collectionId,\ncollectionData: { propertiesOrder: newPropertiesOrder },\npartial: true });\n },\n updateKanbanColumnsOrder: async () => {\n // Kanban order mapping logic can be added later if needed natively.\n },\n\n navigationEntries: [],\n saveNavigationEntries: async () => { }\n }), [clientOrUrl, parsedCollections, readOnly, readOnlyReason, options?.getAuthToken]);\n}\n","import React, { useMemo, useRef, useEffect, useCallback, useContext, Suspense } from \"react\";\nimport {\n useRebaseRegistry,\n useRebaseContext,\n useAuthController,\n useCustomizationController,\n useAdminModeController,\n useBuildLocalConfigurationPersistence,\n useRebaseClient,\n useData,\n useDataSources,\n CollectionResolverRegistrationContext,\n StudioBridgeRegistryProvider,\n useBridgeRegistration,\n CustomizationControllerContext,\n RebaseDataContext\n} from \"@rebasepro/app\";\nimport { buildRoutedRebaseData, resolveDataSource } from \"@rebasepro/common\";\nimport { CircularProgressCenter, lazyChunk } from \"@rebasepro/ui\";\n\nimport type { AppView, CollectionCustomView, CollectionEditorOptions, EntityCustomView, EntityAction, RebasePlugin, AdminCollection } from \"@rebasepro/admin-types\";\nimport type { CollectionRegistryController } from \"@rebasepro/types\";\nimport type { UrlController, NavigationStateController } from \"@rebasepro/admin-types\";\n\nconst EMPTY_PLUGINS: RebasePlugin[] = [];\nconst EMPTY_COLLECTIONS: AdminCollection[] = [];\n\nimport { useBuildNavigationStateController } from \"../hooks/navigation/useBuildNavigationStateController\";\nimport { useBuildUrlController } from \"../hooks/navigation/useBuildUrlController\";\nimport { useBuildCollectionRegistryController } from \"../hooks/navigation/useBuildCollectionRegistryController\";\n\nimport { CollectionRegistryContext } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { UrlContext } from \"../hooks/navigation/contexts/UrlContext\";\nimport { NavigationStateContext } from \"../hooks/navigation/contexts/NavigationStateContext\";\n\nimport { SidePanelProvider } from \"./SidePanelProvider\";\n\n// Collection editor internals — used when collectionEditor is enabled\nimport { useLocalCollectionsConfigController } from \"../collection_editor/useLocalCollectionsConfigController\";\nimport { ConfigControllerProvider } from \"../collection_editor/ConfigControllerProvider\";\nimport { useCollectionsConfigController } from \"../collection_editor/useCollectionsConfigController\";\n\n// Lazy-load the schema view — only fetched when studio schema tool is active\nconst CollectionsStudioView = lazyChunk(() =>\n import(\"../collection_editor/ui/collection_editor/RouterCollectionsStudioView\")\n .then(m => ({ default: m.RouterCollectionsStudioView }))\n);\n\nexport interface RebaseNavigationProps {\n children: React.ReactNode;\n}\n\n/**\n * Navigation layer — builds and provides all admin navigation controllers:\n * collection registry, URL controller, navigation state, side entity,\n * and the self-assembling Studio bridge.\n *\n * Also handles the collection editor config controller when enabled.\n *\n * **Independently usable**: Use this when you need admin navigation\n * (entity tables, side panels) in a custom layout.\n *\n * @example\n * ```tsx\n * <RebaseNavigation>\n * <MyCustomLayout>\n * <CollectionViewBinding ... />\n * </MyCustomLayout>\n * </RebaseNavigation>\n * ```\n */\nexport function RebaseNavigation({ children }: RebaseNavigationProps) {\n const registry = useRebaseRegistry();\n const context = useRebaseContext();\n const adminModeController = useAdminModeController();\n const userConfigPersistence = useBuildLocalConfigurationPersistence();\n\n // ── Collection Editor resolution ──────────────────────────────────\n // The collection editor is ALWAYS enabled when Studio is registered.\n // The `collectionEditor` admin config is for fine-tuning (readOnly, auth, etc.),\n // not for opting-in. When omitted, the editor defaults to enabled\n // (read-only in production).\n const collectionEditorConfig = registry.cmsConfig?.collectionEditor;\n const collectionEditorEnabled = Boolean(collectionEditorConfig) || Boolean(registry.studioConfig);\n const collectionEditorOptions: CollectionEditorOptions | undefined = useMemo(() => {\n if (collectionEditorConfig === true || !collectionEditorConfig) return {};\n return collectionEditorConfig;\n }, [collectionEditorConfig]);\n\n // ── Combine admin and Studio Configs ────────────────────────────────\n const cmsCollections = registry.cmsConfig?.collections ?? EMPTY_COLLECTIONS;\n\n // ── Build the navigation controllers ──────────────────────────────\n const collectionsBuilder = useMemo(() => Array.isArray(cmsCollections) ? () => [...cmsCollections] : cmsCollections, [cmsCollections]);\n\n const dataSources = useDataSources();\n const collectionRegistryController = useBuildCollectionRegistryController({ userConfigPersistence, dataSources: dataSources.registry });\n\n // ── Multi-data-source routing ─────────────────────────────────────\n // Combine the default data source (server transport) with the registered\n // direct/custom sources from <Rebase> and route each collection by its\n // resolved data-source key, looked up by path against the collection\n // registry. A stable resolver ref keeps the routed data instance\n // referentially stable across registry rebuilds, so data-effect\n // dependencies don't thrash.\n const defaultData = useData();\n const getCollectionRef = useRef(collectionRegistryController.getCollection);\n getCollectionRef.current = collectionRegistryController.getCollection;\n\n // Hand the data layer a way to read this registry. It was built by <Rebase>,\n // above us, and needs a collection's primary keys to give its rows an\n // address — rows themselves carry only columns.\n //\n // Registered during render, not in an effect: the views that fetch rows are\n // below us, and their effects run before ours, so an effect here would bind\n // after the first page had already been converted. The call only assigns a\n // ref, so repeating it per render is free.\n const registerCollectionResolver = useContext(CollectionResolverRegistrationContext);\n const resolveCollection = useCallback(\n (slug: string) => getCollectionRef.current(slug),\n []);\n registerCollectionResolver(resolveCollection);\n const routedData = useMemo(() => buildRoutedRebaseData({\n defaultData,\n sources: dataSources.sources,\n resolveKey: (slugOrPath) => resolveDataSource(getCollectionRef.current(slugOrPath), dataSources.registry).key\n }), [defaultData, dataSources]);\n\n // Normalize the configured mount prefix to a leading-slash, no-trailing-slash\n // form (e.g. \"admin\" or \"/admin/\" -> \"/admin\"); empty/\"/\" stays \"/\".\n const basePath = useMemo(() => {\n const raw = registry.cmsConfig?.basePath;\n if (!raw || raw === \"/\") return \"/\";\n const trimmed = raw.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n return trimmed ? `/${trimmed}` : \"/\";\n }, [registry.cmsConfig?.basePath]);\n\n const urlController = useBuildUrlController({\n basePath,\n baseCollectionPath: \"/c\",\n collectionRegistryController\n });\n\n // ── Build config controller internally when collection editor is enabled ──\n const rebaseClient = useRebaseClient();\n const authController = useAuthController();\n const resolvedCollections = useMemo(\n () => Array.isArray(cmsCollections) ? cmsCollections : [],\n [cmsCollections]\n );\n\n // ── Dev-only data-source sanity check ─────────────────────────────\n // Warn about data sources declared with a direct/custom transport that\n // have no client-side driver — these silently fall back to the default\n // (server) source, a common source of misrouting. Unambiguous: it never\n // false-positives on server-mediated sources (which intentionally have\n // no client driver).\n useEffect(() => {\n if (process.env.NODE_ENV === \"production\") return;\n const { registry, sources } = dataSources;\n const missing = Object.values(registry)\n .filter((d) => (d.transport === \"direct\" || d.transport === \"custom\") && !sources[d.key])\n .map((d) => d.key);\n if (missing.length > 0) {\n console.warn(\n `[Rebase] These data source(s) declare a direct/custom transport but have no client-side driver and will fall back to the default data source: ${missing.map(k => `\"${k}\"`).join(\", \")}. ` +\n `Provide a \\`driver\\` for them in \\`dataSources\\` on <Rebase>.`\n );\n }\n }, [dataSources]);\n\n // `readOnly` is left undefined unless the developer set it: the controller\n // asks the backend whether its schema editor will accept a write, which is\n // the only process that knows. Deciding it here from `process.env.NODE_ENV`\n // — the *frontend bundle's* build mode — is what made the editor offer\n // itself against production backends, `baas` projects and servers without\n // `ts-morph`, and turned every save into a bare 404.\n const internalConfigController = useLocalCollectionsConfigController(\n rebaseClient,\n resolvedCollections,\n collectionEditorEnabled ? {\n readOnly: collectionEditorOptions?.readOnly,\n getAuthToken: collectionEditorOptions?.getAuthToken ?? authController?.getAuthToken,\n authKey: authController?.user?.uid ?? null\n } : { readOnly: true }\n );\n\n // ── Auto-inject schema view into Studio devViews ──────────────────\n const schemaView: AppView | undefined = useMemo(() => {\n if (!collectionEditorEnabled) return undefined;\n // Only inject when Studio is registered and includes \"schema\" tool (or all tools)\n const studioTools = registry.studioConfig?.tools ?? [\"sql\", \"js\", \"rls\", \"schema\", \"storage\"];\n if (!registry.studioConfig || !studioTools.includes(\"schema\")) return undefined;\n return {\n slug: \"schema\",\n name: \"Edit collections\",\n group: \"Database\",\n icon: \"LayoutList\",\n nestedRoutes: true,\n // Reads the controller from context at render time rather than\n // capturing it here. A view is a React *element*, and the\n // navigation state controller resolves the view list once and holds\n // on to the elements it resolved — so a controller passed as a prop\n // is frozen at whatever it was on the first render, forever. That\n // hid every later change: the editor stayed writable after the\n // backend said it was read-only, and the collection list never\n // refreshed. Everything else in the editor already reads this from\n // `ConfigControllerProvider`, which wraps this subtree.\n view: (\n <Suspense fallback={<CircularProgressCenter/>}>\n <CollectionsStudioViewFromContext/>\n </Suspense>\n )\n };\n }, [collectionEditorEnabled, registry.studioConfig]);\n\n const devViews = useMemo(() => {\n const base = registry.studioConfig?.devViews ?? [];\n if (schemaView) return [...base, schemaView];\n return base;\n }, [registry.studioConfig?.devViews, schemaView]);\n\n // Merge admin-registered views with Studio dev views.\n // Order: admin views (developer's primary content) → Studio dev views (tooling).\n // Plugin views are merged later inside resolveAppViews.\n const cmsViews = registry.cmsConfig?.views;\n const mergedViews = useMemo(() => {\n if (!cmsViews) return devViews;\n if (Array.isArray(cmsViews) && cmsViews.length === 0) return devViews;\n // When cmsViews is a builder function, wrap it to append devViews after resolution\n if (typeof cmsViews === \"function\") {\n return async (params: Parameters<typeof cmsViews>[0]) => {\n const resolved = await cmsViews(params) ?? [];\n return [...resolved, ...devViews];\n };\n }\n return [...cmsViews, ...devViews];\n }, [cmsViews, devViews]);\n\n const parentCustomizationController = useCustomizationController();\n\n const navigationStateController = useBuildNavigationStateController({\n plugins: parentCustomizationController.plugins ?? EMPTY_PLUGINS,\n collections: collectionsBuilder,\n views: mergedViews,\n navigationGroupMappings: registry.cmsConfig?.navigationGroupMappings,\n authController: context.authController!,\n data: routedData,\n collectionRegistryController,\n urlController,\n adminMode: adminModeController?.mode\n });\n\n // ── Merge admin-registered entityViews/entityActions into the customization controller ──\n // The <Rebase> component builds the customizationController from its own props,\n // but entity views passed to <RebaseAdmin> are stored in the registry and not\n // automatically merged. We re-provide an enriched controller here so that\n // downstream consumers (EditViewBinding, side panels, etc.) can resolve\n // string-keyed entity views like \"blog_preview\".\n const enrichedCustomizationController = useMemo(() => {\n const cmsEntityViews = (registry.cmsConfig?.entityViews ?? []) as EntityCustomView[];\n const cmsEntityActions = (registry.cmsConfig?.entityActions ?? []) as EntityAction[];\n // Collection view modes ride the same channel, for the same reason:\n // `admin.customViews: [\"map\"]` has to find the component somewhere.\n const cmsCollectionViews = (registry.cmsConfig?.collectionViews ?? []) as CollectionCustomView[];\n if (cmsEntityViews.length === 0 && cmsEntityActions.length === 0 && cmsCollectionViews.length === 0) {\n return parentCustomizationController;\n }\n return {\n ...parentCustomizationController,\n entityViews: [\n ...(parentCustomizationController.entityViews ?? []),\n ...cmsEntityViews.filter(v => !(parentCustomizationController.entityViews ?? []).some(ev => ev.key === v.key))\n ],\n entityActions: [\n ...(parentCustomizationController.entityActions ?? []),\n ...cmsEntityActions.filter(a => !(parentCustomizationController.entityActions ?? []).some(ea => ea.key === a.key))\n ],\n collectionViews: [\n ...(parentCustomizationController.collectionViews ?? []),\n ...cmsCollectionViews.filter(v => !(parentCustomizationController.collectionViews ?? []).some(cv => cv.key === v.key))\n ]\n };\n }, [parentCustomizationController, registry.cmsConfig?.entityViews, registry.cmsConfig?.entityActions, registry.cmsConfig?.collectionViews]);\n\n // ── Inner content with all context providers ──────────────────────\n // Re-provide RebaseDataContext with the routed data so that every admin\n // consumer (list/entity views, references, board, import/export, and\n // `context.data`) is routed to the correct driver by collection path.\n const navigationContent = (\n <RebaseDataContext.Provider value={routedData}>\n <CustomizationControllerContext.Provider value={enrichedCustomizationController}>\n <StudioBridgeRegistryProvider>\n <CollectionRegistryContext.Provider value={collectionRegistryController}>\n <UrlContext.Provider value={urlController}>\n <NavigationStateContext.Provider value={navigationStateController}>\n <SidePanelProvider>\n <BridgeAutoRegistrar\n collectionRegistryController={collectionRegistryController}\n urlController={urlController}\n navigationStateController={navigationStateController}\n canWriteToCodebase={!internalConfigController.readOnly}\n />\n {children}\n </SidePanelProvider>\n </NavigationStateContext.Provider>\n </UrlContext.Provider>\n </CollectionRegistryContext.Provider>\n </StudioBridgeRegistryProvider>\n </CustomizationControllerContext.Provider>\n </RebaseDataContext.Provider>\n );\n\n // ── Wrap with ConfigControllerProvider when collection editor is enabled ──\n if (collectionEditorEnabled) {\n return (\n <ConfigControllerProvider\n collectionConfigController={internalConfigController}\n pathSuggestions={collectionEditorOptions?.pathSuggestions}\n >\n {navigationContent}\n </ConfigControllerProvider>\n );\n }\n\n return navigationContent;\n}\n\n/**\n * The injected \"Edit collections\" view, bound to the live config controller.\n *\n * Exists so the element stored in the navigation state does not close over a\n * controller instance — see the comment at its construction site.\n */\nfunction CollectionsStudioViewFromContext() {\n const configController = useCollectionsConfigController();\n return <CollectionsStudioView configController={configController}/>;\n}\n\n/**\n * Internal component that auto-registers admin controllers into the\n * self-assembling Studio bridge. Must be rendered inside both the\n * navigation contexts and the StudioBridgeRegistryProvider.\n */\nfunction BridgeAutoRegistrar({\n collectionRegistryController,\n urlController,\n navigationStateController,\n canWriteToCodebase\n}: {\n collectionRegistryController: CollectionRegistryController;\n urlController: UrlController;\n navigationStateController: NavigationStateController;\n canWriteToCodebase: boolean;\n}) {\n useBridgeRegistration(\"collectionRegistry\", collectionRegistryController);\n useBridgeRegistration(\"urlController\", urlController);\n useBridgeRegistration(\"navigationState\", navigationStateController);\n\n // Studio tools that would write into the project's collection source — the\n // RLS editor's policy save for a mapped table, its \"Import to codebase\" —\n // ask the bridge whether that write can land. The default is `true`, which\n // is what an admin panel sitting next to its own `collectionsDir` assumes;\n // it is wrong for exactly the same backends that make the collection editor\n // read-only, so the two now answer from one source.\n const capabilities = useMemo(() => ({ codebase: canWriteToCodebase }), [canWriteToCodebase]);\n useBridgeRegistration(\"capabilities\", capabilities);\n return null;\n}\n","import React from \"react\";\nimport { Outlet } from \"react-router\";\nimport {\n useAdminModeController,\n useComponentOverride,\n useRebaseRegistry\n} from \"@rebasepro/app\";\n\nimport { Scaffold } from \"./app/Scaffold\";\nimport { Drawer } from \"./app/Drawer\";\nimport { SideDialogs } from \"./SideDialogs\";\nimport { AdminModeSyncer } from \"./AdminModeSyncer\";\nimport type { AppView } from \"@rebasepro/admin-types\";\n\nexport interface RebaseLayoutProps {\n /** Title shown in the drawer. */\n title?: string;\n /** Top bar. Only rendered if provided — pass `<AppBar/>` for the default one. */\n appBar?: React.ReactNode;\n /** Custom Drawer to override the default. */\n drawer?: React.ReactNode;\n /** Expand the drawer while the pointer is over it. On by default; pass `false` to opt out. Not a load-time default — that is `defaultDrawerOpen`. */\n autoOpenDrawer?: boolean;\n /** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */\n defaultDrawerOpen?: boolean;\n /** Path to the logo shown in the drawer and top bar. Falls back to the Rebase mark. */\n logo?: string;\n /** Dev views passed to AdminModeSyncer (resolved from RebaseNavigation). */\n devViews?: AppView[];\n}\n\n/**\n * Layout layer — provides the Scaffold, Drawer, and SideDialogs.\n *\n * Wraps the route outlet with the standard Rebase admin layout.\n * Override the drawer via props; pass `appBar` to add a top bar (there is\n * none by default — the drawer owns navigation and user actions).\n *\n * **Independently usable**: Use this when you want the Rebase layout\n * without its default route definitions.\n *\n * @example\n * ```tsx\n * <RebaseLayout title=\"My Admin\" appBar={<AppBar/>}>\n * <Route path=\"/\" element={<MyHomePage />} />\n * <Route path=\"/custom\" element={<CustomView />} />\n * </RebaseLayout>\n * ```\n */\nexport function RebaseLayout(props: RebaseLayoutProps) {\n const {\n title = \"Rebase\",\n appBar,\n drawer,\n autoOpenDrawer = true,\n defaultDrawerOpen = false,\n logo,\n devViews = []\n } = props;\n\n const adminModeController = useAdminModeController();\n const ResolvedDrawer = useComponentOverride(\"Shell.Drawer\", Drawer);\n\n const ActiveDrawer = drawer ?? (\n <ResolvedDrawer\n title={title}\n logoDestination={adminModeController.mode === \"studio\" ? \"/s\" : \"/\"}\n />\n );\n\n return (\n <Scaffold autoOpenDrawer={autoOpenDrawer} defaultDrawerOpen={defaultDrawerOpen} logo={logo}>\n <AdminModeSyncer devViews={devViews}/>\n {appBar}\n {ActiveDrawer}\n <Outlet/>\n <SideDialogs/>\n </Scaffold>\n );\n}\n","import type { NavigationEntry } from \"@rebasepro/admin-types\";\nimport { useNavigate } from \"react-router\";\n;\nimport { Chip, Collapse, StarIcon } from \"@rebasepro/ui\";\nimport { useUserConfigurationPersistence } from \"@rebasepro/app\";\nimport { useNavigationStateController } from \"../../hooks/navigation/contexts/NavigationStateContext\";\n\nfunction NavigationChip({ entry }: { entry: NavigationEntry }) {\n\n const navigate = useNavigate();\n const userConfigurationPersistence = useUserConfigurationPersistence();\n\n if (!userConfigurationPersistence)\n return null;\n\n const favourite = userConfigurationPersistence.favouritePaths.includes(entry.slug);\n const onIconClick = (e: React.SyntheticEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (favourite) {\n userConfigurationPersistence.setFavouritePaths(\n userConfigurationPersistence.favouritePaths.filter(p => p !== entry.slug)\n );\n } else {\n userConfigurationPersistence.setFavouritePaths(\n [...userConfigurationPersistence.favouritePaths, entry.slug]\n );\n }\n };\n return <Chip\n key={entry.slug}\n onClick={() => navigate(entry.url)}\n icon={<StarIcon\n onClick={onIconClick}\n size={\"small\"}\n className={favourite ? \"text-secondary\" : \"text-surface-400 dark:text-surface-500\"}/>\n }>\n {entry.name}\n </Chip>;\n}\n\nexport function FavouritesView({ hidden }: { hidden: boolean }) {\n\n const navigationStateController = useNavigationStateController();\n const userConfigurationPersistence = useUserConfigurationPersistence();\n\n if (!userConfigurationPersistence)\n return null;\n\n const favouriteCollections = (userConfigurationPersistence?.favouritePaths ?? [])\n .map((path) => navigationStateController.topLevelNavigation?.navigationEntries.find((entry) => entry.slug === path))\n .filter(Boolean) as NavigationEntry[];\n\n return <Collapse in={favouriteCollections.length > 0}>\n <div className=\"flex flex-row flex-wrap gap-2 pb-2 min-h-[32px]\">\n {favouriteCollections.map((entry) => <NavigationChip key={entry.slug}\n entry={entry}/>)}\n </div>\n </Collapse>;\n}\n","import React, { PropsWithChildren, useState } from \"react\";\nimport { cls, ExpandablePanel, IconButton, iconSize, PencilIcon, Typography } from \"@rebasepro/ui\";\nimport { useTranslation } from \"@rebasepro/app\";\n\nexport function NavigationGroup({\n children,\n group,\n minimised,\n isPreview,\n isPotentialCardDropTarget,\n onEditGroup,\n dndDisabled,\n collapsed,\n onToggleCollapsed\n}: PropsWithChildren<{\n group: string | undefined,\n minimised?: boolean,\n isPreview?: boolean,\n isPotentialCardDropTarget?: boolean,\n onEditGroup?: (groupName: string) => void;\n dndDisabled?: boolean;\n collapsed?: boolean;\n onToggleCollapsed?: () => void;\n}>) {\n\n const { t } = useTranslation();\n const [isHovered, setIsHovered] = useState(false);\n const currentGroupName = group ?? t(\"views_group\");\n\n // Show caret only when not in preview and there is a toggle handler\n const showCaret = !isPreview && !!onToggleCollapsed;\n\n // Helper for the title content (left side)\n const TitleContent = (\n <div className={cls(\"flex items-center\", isPreview ? \"px-1 py-0.5\" : \"\")}\n >\n <Typography\n variant={isPreview ? \"body2\" : \"caption\"}\n component={\"h2\"}\n color=\"secondary\"\n className={cls(\n \"px-4 py-1 rounded\",\n \"font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70\"\n )}\n >\n {currentGroupName}\n </Typography>\n {!isPreview && onEditGroup && !dndDisabled && (\n <IconButton\n size=\"smallest\"\n onClick={(e) => {\n e.stopPropagation(); // Prevent toggle on click\n onEditGroup(currentGroupName);\n }}\n className={cls(\"ml-2 \", isHovered ? \"opacity-100\" : \"opacity-0\", \"transition-opacity duration-100\")}\n >\n <PencilIcon size={iconSize.smallest}/>\n </IconButton>\n )}\n </div>\n );\n\n return (\n <div className={cls(\n !isPotentialCardDropTarget ? \"my-10\" : \"my-6\",\n \"transition-all duration-200 ease-in-out\"\n )}\n >\n {/* Preview: static header + content (no caret / no collapse) */}\n {isPreview && (\n <>\n <div\n className={cls(\n \"flex items-center justify-between w-full\",\n \"p-4 py-2\"\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {TitleContent}\n </div>\n {children}\n </>\n )}\n\n {/* Interactive collapsible version when a toggle handler is provided */}\n {!isPreview && showCaret && (\n <ExpandablePanel\n invisible\n expanded={!collapsed}\n onExpandedChange={(open) => {\n if (open !== !collapsed) {\n onToggleCollapsed?.();\n }\n }}\n className={cls(\"mt-6\")}\n titleClassName={cls(\n \"min-h-0 p-0 border-none\",\n \"rounded flex items-center justify-between w-full\",\n \"hover:bg-transparent\",\n \"cursor-pointer select-none\",\n collapsed && \"bg-surface-100 dark:bg-surface-900/50\"\n )}\n innerClassName={cls(\"mt-4\", !minimised ? \"pt-0\" : \"\")}\n title={\n <div\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n className=\"flex items-center\"\n >\n {TitleContent}\n </div>\n }\n >\n {minimised ? (\n <div className={cls(\"mt-4 p-8 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg\")}\n style={{ minHeight: \"50px\" }}>\n </div>\n ) : (\n <div className={cls(\"mt-4\", !minimised ? \"pt-0\" : \"\")}>\n {children}\n </div>\n )}\n </ExpandablePanel>\n )}\n\n {/* Non-collapsible (no caret) runtime, keep old behavior */}\n {!isPreview && !showCaret && (\n <>\n <div\n className={cls(\n \"flex items-center justify-between w-full\",\n \"mt-6\"\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {TitleContent}\n </div>\n\n {!collapsed && (\n minimised ? (\n <div className={cls(\"mt-4 p-8 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg\")}\n style={{ minHeight: \"50px\" }}>\n </div>\n ) : (\n <div className={cls(\"mt-4\", !minimised ? \"pt-0\" : \"\")}>\n {children}\n </div>\n )\n )}\n </>\n )}\n </div>\n );\n}\n","import { ArrowRightIcon, Card, cls, iconSize, Markdown, Typography } from \"@rebasepro/ui\";\nimport React from \"react\";\n\nexport type NavigationCardProps = {\n name: string,\n description?: string;\n actions: React.ReactNode;\n icon: React.ReactNode;\n additionalContent?: React.ReactNode;\n onClick?: () => void,\n shrink?: boolean\n};\n\n// Wrap the component with React.memo\nexport const NavigationCard = React.memo(function NavigationCard({\n name,\n description,\n icon,\n actions,\n additionalContent,\n onClick,\n shrink\n}: NavigationCardProps) {\n\n return (\n <Card\n className={cls(\n \"group h-full p-4 cursor-pointer transition-colors duration-150 ease-in-out\",\n \"hover:bg-primary/5 dark:hover:bg-primary/5\",\n shrink && \"w-full max-w-full min-h-0 scale-75\"\n )}\n onClick={() => {\n onClick?.();\n }}\n >\n\n <div className=\"flex flex-col h-full\">\n {/* Header: title + icon left, actions right */}\n <div className=\"flex items-center w-full justify-between mb-1\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center justify-center w-5 h-5 text-surface-400 dark:text-surface-500 transition-colors duration-150 group-hover:text-primary dark:group-hover:text-primary\">\n {icon}\n </div>\n <Typography variant=\"subtitle1\"\n component=\"h2\">\n {name}\n </Typography>\n </div>\n\n <div\n className=\"flex items-center gap-0.5\"\n onClick={(event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n }}>\n {actions}\n </div>\n </div>\n\n {/* Description */}\n <div className=\"pl-8\">\n {description && <Typography variant=\"caption\"\n color=\"secondary\"\n component=\"div\">\n <Markdown source={description} size={\"small\"}/>\n </Typography>}\n </div>\n\n {additionalContent && (\n <div className=\"pl-8 pointer-events-none\">\n {additionalContent}\n </div>\n )}\n\n {/* Spacer pushes content above to align at the top across grid siblings */}\n <div className=\"grow\"/>\n\n </div>\n\n </Card>)\n});\n","\nimport type { NavigationEntry, AdminCollection } from \"@rebasepro/admin-types\";\nimport { useNavigate } from \"react-router\";\n;\nimport { IconButton, StarIcon, Tooltip } from \"@rebasepro/ui\";\nimport { NavigationCard } from \"./NavigationCard\";\nimport { SmallNavigationCard } from \"./SmallNavigationCard\";\nimport React from \"react\";\nimport { useRebaseContext, useSlot } from \"@rebasepro/app\";\nimport { IconForView } from \"@rebasepro/app\";\nimport { useUserConfigurationPersistence } from \"@rebasepro/app\";\n\n/**\n * This is the component used in the home page to render a card for each\n * collection or view.\n * @group Components\n * @param view\n * @param path\n * @param collection\n * @param url\n * @param name\n * @param description\n * @param onClick\n\n */\nexport function NavigationCardBinding({\n slug,\n collection,\n view,\n url,\n name,\n description,\n onClick,\n type,\n shrink\n}: NavigationEntry & {\n onClick?: () => void,\n shrink?: boolean // <-- add shrink prop type\n}) {\n\n const userConfigurationPersistence = useUserConfigurationPersistence();\n const collectionIcon = <IconForView collectionOrView={collection ?? view} size={\"small\"}/>;\n\n const navigate = useNavigate();\n const context = useRebaseContext();\n\n const favourite = (userConfigurationPersistence?.favouritePaths ?? []).includes(slug);\n\n const actionsArray: React.ReactNode[] = userConfigurationPersistence\n ? [\n <IconButton\n key={\"favourite\"}\n size={\"small\"}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n if (favourite) {\n userConfigurationPersistence.setFavouritePaths(\n userConfigurationPersistence.favouritePaths.filter(p => p !== slug)\n );\n } else {\n userConfigurationPersistence.setFavouritePaths(\n [...userConfigurationPersistence.favouritePaths, slug]\n );\n }\n }}>\n <StarIcon\n className={favourite ? \"text-secondary\" : \"text-surface-400 dark:text-surface-500\"}/>\n </IconButton>\n ]\n : [];\n\n const pluginCardActions = useSlot(\"home.collection.actions\", {\n slug: slug,\n collection: collection!,\n context\n });\n\n const pluginCardWidgets = useSlot(\"home.card.widget\", {\n slug: slug,\n collection: collection!,\n context\n });\n\n const actions: React.ReactNode | undefined = <>\n {actionsArray}\n {pluginCardActions}\n </>\n\n return <NavigationCard\n icon={collectionIcon}\n name={name}\n description={description}\n actions={actions}\n additionalContent={pluginCardWidgets.length > 0 ? <>{pluginCardWidgets}</> : undefined}\n onClick={() => {\n onClick?.();\n navigate(url);\n if (userConfigurationPersistence) {\n userConfigurationPersistence.setRecentlyVisitedPaths(\n [slug, ...(userConfigurationPersistence.recentlyVisitedPaths ?? []).filter(p => p !== slug)]\n );\n }\n }}\n shrink={shrink}\n />;\n}\n","import type { NavigationEntry } from \"@rebasepro/admin-types\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n Active,\n Over,\n closestCenter,\n closestCorners,\n CollisionDetection,\n DropAnimation,\n getFirstCollision,\n KeyboardSensor,\n MouseSensor,\n pointerWithin,\n rectIntersection,\n TouchSensor,\n UniqueIdentifier,\n useDndMonitor,\n useDroppable,\n useSensor,\n useSensors\n} from \"@dnd-kit/core\";\nimport {\n AnimateLayoutChanges,\n arrayMove,\n defaultAnimateLayoutChanges,\n rectSortingStrategy,\n SortableContext,\n useSortable\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\n\nimport { NavigationCardBinding } from \"./NavigationCardBinding\";\n;\nimport { cls } from \"@rebasepro/ui\";\n\nconst animateLayoutChanges: AnimateLayoutChanges = (args) =>\n defaultAnimateLayoutChanges({\n ...args,\n wasDragging: true\n });\n\nconst dropAnimationConfig: DropAnimation = {};\n\nconst cloneSerializableNavigationEntry = (entry: NavigationEntry): NavigationEntry => {\n const clonedEntry: Partial<NavigationEntry> = {\n id: entry.id,\n slug: entry.slug,\n url: entry.url,\n name: entry.name,\n type: entry.type,\n collection: entry.collection ? { ...entry.collection } : undefined,\n view: entry.view ? { ...entry.view } : undefined,\n ...(entry.group && { group: entry.group }),\n ...(entry.description && { description: entry.description })\n };\n return clonedEntry as NavigationEntry;\n};\n\nconst cloneItemsForDnd = (items: { name: string; entries: NavigationEntry[] }[]) =>\n items.map((g) => ({\n name: g.name,\n entries: g.entries.map(cloneSerializableNavigationEntry)\n }));\n\n/* ─────────────────────────────────────────────────────────── */\n/* Sortable card & group */\n\n/* ─────────────────────────────────────────────────────────── */\nexport function SortableNavigationCard({\n entry,\n onClick\n}: {\n entry: NavigationEntry;\n onClick?: () => void;\n}) {\n const {\n setNodeRef,\n listeners,\n attributes,\n transform,\n transition,\n isDragging\n } =\n useSortable({\n id: entry.url,\n animateLayoutChanges\n });\n\n const style = {\n transform: transform ? CSS.Transform.toString(transform) : undefined,\n transition,\n opacity: isDragging ? 0 : 1\n };\n\n return (\n <div ref={setNodeRef} style={style} {...attributes} {...listeners}>\n <NavigationCardBinding {...entry} onClick={onClick}/>\n </div>\n );\n}\n\nexport function NavigationGroupDroppable({\n id,\n itemIds,\n children,\n isPotentialCardDropTarget = false\n}: {\n id: UniqueIdentifier;\n itemIds: UniqueIdentifier[];\n children: React.ReactNode;\n isPotentialCardDropTarget?: boolean;\n}) {\n const { setNodeRef } = useDroppable({ id });\n\n return (\n <div\n ref={setNodeRef}\n className={cls(\n isPotentialCardDropTarget\n ? \"p-2 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg\"\n : undefined,\n \"transition-all duration-200 ease-in-out\"\n )}\n >\n <SortableContext items={itemIds} strategy={rectSortingStrategy}>\n {children}\n </SortableContext>\n </div>\n );\n}\n\nexport function SortableNavigationGroup({\n groupName,\n children,\n disabled\n}: {\n groupName: string;\n children: React.ReactNode;\n disabled?: boolean;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging\n } =\n useSortable({\n id: groupName,\n animateLayoutChanges,\n disabled\n });\n\n const style = {\n transform: transform ? CSS.Transform.toString(transform) : undefined,\n transition,\n opacity: isDragging ? 0 : 1\n };\n\n return (\n <div ref={setNodeRef} style={style} {...attributes} {...listeners}>\n {children}\n </div>\n );\n}\n\nexport function useHomePageDnd({\n items,\n setItems,\n disabled,\n onCardMovedBetweenGroups,\n onGroupMoved,\n onNewGroupDrop,\n onPersist\n}: {\n items: { name: string; entries: NavigationEntry[] }[];\n setItems: (\n newItemsOrUpdater:\n | { name: string; entries: NavigationEntry[] }[]\n | ((\n currentItems: { name: string; entries: NavigationEntry[] }[]\n ) => { name: string; entries: NavigationEntry[] }[])\n ) => void;\n disabled: boolean;\n onCardMovedBetweenGroups?: (card: NavigationEntry) => void;\n onGroupMoved?: (groupName: string, oldIndex: number, newIndex: number) => void;\n onNewGroupDrop?: () => void;\n onPersist?: (latest: { name: string; entries: NavigationEntry[] }[]) => void;\n}) {\n /* ---------------- local state ---------------- */\n const dndItems = items;\n const setDndItems = setItems;\n\n const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);\n const [activeIsGroup, setActiveIsGroup] = useState(false);\n const [currentDraggingGroupId, setCurrentDraggingGroupId] =\n useState<UniqueIdentifier | null>(null);\n const [dndKitActiveNode, setDndKitActiveNode] = useState<Active | null>(null);\n const [isDraggingCardOnly, setIsDraggingCardOnly] = useState(false);\n const [dialogOpenForGroup, setDialogOpenForGroup] = useState<string | null>(null);\n const [isHoveringNewGroupDropZone, setIsHoveringNewGroupDropZone] =\n useState(false);\n const [pendingNewGroupName, setPendingNewGroupName] = useState<string | null>(null);\n const [stateBeforeNewGroup, setStateBeforeNewGroup] = useState<\n { name: string; entries: NavigationEntry[] }[] | null\n >(null);\n\n /* store the original state before any drag modifications */\n const preDragItemsRef = useRef<\n { name: string; entries: NavigationEntry[] }[] | null\n >(null);\n\n /* store interim state for cross-group moves */\n const interimItemsRef = useRef<\n { name: string; entries: NavigationEntry[] }[] | null\n >(null);\n useEffect(() => {\n interimItemsRef.current = dndItems;\n }, [dndItems]);\n\n /* ---------------- sensors ---------------- */\n const mouseSensor = useSensor(MouseSensor, { activationConstraint: { distance: 10 } });\n const touchSensor = useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5\n }\n });\n const keyboardSensor = useSensor(KeyboardSensor);\n const sensors = useSensors(mouseSensor, touchSensor, keyboardSensor);\n\n /* ---------------- helpers ---------------- */\n const dndContainers = dndItems.map((g) => g.name);\n\n const findDndContainer = useCallback(\n (id: UniqueIdentifier): string | undefined => {\n if (!id) return undefined;\n const group = dndItems.find((g) => g.name === id);\n if (group) return group.name;\n for (const g of dndItems) {\n if (g.entries.some((e) => e.url === id)) return g.name;\n }\n return undefined;\n },\n [dndItems]\n );\n\n /* ---------------- collision detection ---------------- */\n const lastOverId = useRef<UniqueIdentifier | null>(null);\n const recentlyMovedToNewContainer = useRef(false);\n\n const collisionDetection: CollisionDetection = useCallback(\n (args) => {\n if (disabled || !activeId) return [];\n if (activeIsGroup) {\n const groups = args.droppableContainers.filter((c) =>\n dndItems.some((g) => g.name === c.id)\n );\n if (!groups.length) return [];\n return closestCenter({\n ...args,\n droppableContainers: groups\n });\n }\n\n const pointer = pointerWithin(args);\n if (pointer.length) {\n const zone = pointer.find((c) => c.id === \"new-group-drop-zone\");\n if (zone) return [zone];\n\n const container = pointer.find((c) =>\n dndItems.some((g) => g.name === c.id)\n );\n if (container) {\n const itemsIn = dndItems.find((g) => g.name === container.id)\n ?.entries;\n if (itemsIn?.length) {\n const closest = closestCorners({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (c) => itemsIn.some((e) => e.url === c.id)\n )\n });\n if (closest.length) return closest;\n }\n return [container];\n }\n const first = getFirstCollision(pointer, \"id\");\n if (first) return [{ id: first }];\n }\n\n const rects = rectIntersection(args);\n const zoneRect = rects.find((c) => c.id === \"new-group-drop-zone\");\n if (zoneRect) return [zoneRect];\n\n let overId = getFirstCollision(rects, \"id\");\n if (overId != null) {\n const overIsContainer = dndItems.some((g) => g.name === overId);\n if (overIsContainer) {\n const itemsIn = dndItems.find((g) => g.name === overId)\n ?.entries;\n if (itemsIn?.length) {\n const closestItem = closestCorners({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (c) => itemsIn.some((e) => e.url === c.id)\n )\n })[0]?.id;\n if (closestItem) overId = closestItem;\n }\n }\n lastOverId.current = overId;\n return [{ id: overId }];\n }\n\n if (\n recentlyMovedToNewContainer.current &&\n lastOverId.current &&\n !activeIsGroup\n )\n return [{ id: lastOverId.current }];\n\n return [];\n },\n [activeId, dndItems, disabled, activeIsGroup]\n );\n\n /* ---------------- drag handlers ---------------- */\n const handleDragStart = ({ active }: { active: Active }) => {\n setDndKitActiveNode(active);\n if (disabled) return;\n\n // Capture the original state before any drag modifications\n preDragItemsRef.current = cloneItemsForDnd(dndItems);\n\n const isGroup = dndItems.some((g) => g.name === active.id);\n if (!active.data.current) active.data.current = {};\n active.data.current.type = isGroup ? \"group\" : \"item\";\n\n setActiveId(active.id);\n setActiveIsGroup(isGroup);\n setIsDraggingCardOnly(!isGroup);\n if (isGroup) setCurrentDraggingGroupId(active.id);\n recentlyMovedToNewContainer.current = false;\n };\n\n const handleDragOver = ({\n active,\n over\n }: { active: Active; over: Over | null }) => {\n if (disabled || !over) return;\n\n const activeIdNow = active.id;\n const overIdNow = over.id;\n if (activeIdNow === overIdNow) return;\n if (activeIsGroup) return;\n\n const activeCont = findDndContainer(activeIdNow);\n const overCont = findDndContainer(overIdNow);\n if (!activeCont) return;\n\n if (overCont && activeCont !== overCont) {\n recentlyMovedToNewContainer.current = true;\n lastOverId.current = overIdNow;\n\n // Update state for visual feedback during drag\n setDndItems((current) => {\n const newState = cloneItemsForDnd(current);\n const srcIdx = newState.findIndex((g) => g.name === activeCont);\n const tgtIdx = newState.findIndex((g) => g.name === overCont);\n if (srcIdx === -1 || tgtIdx === -1) return current;\n const src = newState[srcIdx];\n const tgt = newState[tgtIdx];\n const idxInSrc = src.entries.findIndex((e) => e.url === activeIdNow);\n if (idxInSrc === -1) return current;\n const [moved] = src.entries.splice(idxInSrc, 1);\n\n // Calculate insertion position - SAME logic as handleDragEnd\n const overIsContainer = overIdNow === overCont;\n if (overIsContainer) {\n tgt.entries.push(moved);\n } else {\n const overIdx = tgt.entries.findIndex((e) => e.url === overIdNow);\n if (overIdx !== -1) {\n tgt.entries.splice(overIdx, 0, moved);\n } else {\n tgt.entries.push(moved);\n }\n }\n\n return newState;\n });\n } else if (activeCont === overCont) {\n recentlyMovedToNewContainer.current = false;\n }\n };\n\n const handleDragEnd = ({\n active,\n over\n }: { active: Active; over: Over | null }) => {\n if (disabled || !over) {\n resetDragState();\n return;\n }\n\n const activeIdNow = active.id;\n const overIdNow = over.id;\n\n /* ─── group reorder ─── */\n if (activeIsGroup) {\n if (\n activeIdNow !== overIdNow &&\n dndItems.some((g) => g.name === overIdNow)\n ) {\n const from = dndItems.findIndex((g) => g.name === activeIdNow);\n const to = dndItems.findIndex((g) => g.name === overIdNow);\n if (from !== -1 && to !== -1) {\n const newState = arrayMove(dndItems, from, to);\n setDndItems(newState);\n onPersist?.(newState);\n onGroupMoved?.(activeIdNow as string, from, to);\n }\n }\n }\n /* ─── card move ─── */\n else {\n // CRITICAL: Find source container from ORIGINAL pre-drag state, not current (potentially stale) dndItems\n const findContainerInState = (id: string, state: { name: string; entries: NavigationEntry[] }[]): string | undefined => {\n const group = state.find((g) => g.name === id);\n if (group) return group.name;\n for (const g of state) {\n if (g.entries.some((e) => e.url === id)) return g.name;\n }\n return undefined;\n };\n\n const sourceState = preDragItemsRef.current || dndItems;\n const activeCont = findContainerInState(activeIdNow as string, sourceState);\n const overCont = findDndContainer(overIdNow);\n\n /* drop on new-group zone */\n if (overIdNow === \"new-group-drop-zone\") {\n if (activeCont) {\n // Save current state before making changes\n setStateBeforeNewGroup(cloneItemsForDnd(dndItems));\n\n const newState = cloneItemsForDnd(dndItems);\n const srcIdx = newState.findIndex((g) => g.name === activeCont);\n if (srcIdx !== -1) {\n const src = newState[srcIdx];\n const idxInSrc = src.entries.findIndex(\n (e) => e.url === activeIdNow\n );\n if (idxInSrc !== -1) {\n const [dragged] = src.entries.splice(idxInSrc, 1);\n if (src.entries.length === 0) newState.splice(srcIdx, 1);\n\n let tentative = \"New Group\";\n let counter = 1;\n while (newState.some((g) => g.name === tentative))\n tentative = `New Group ${counter++}`;\n\n newState.push({\n name: tentative,\n entries: [dragged]\n });\n\n // Update local state but DON'T persist yet\n setDndItems(newState);\n setPendingNewGroupName(tentative);\n setDialogOpenForGroup(tentative);\n onNewGroupDrop?.();\n }\n }\n }\n }\n /* reorder inside same container */\n else {\n const overCont = findDndContainer(overIdNow);\n if (activeCont === overCont) {\n const grpIdx = dndItems.findIndex((g) => g.name === activeCont);\n if (grpIdx !== -1) {\n const group = dndItems[grpIdx];\n const oldIdx = group.entries.findIndex(\n (e) => e.url === activeIdNow\n );\n let newIdx = group.entries.findIndex(\n (e) => e.url === overIdNow\n );\n if (newIdx === -1 && overIdNow === activeCont)\n newIdx = group.entries.length - 1;\n if (\n oldIdx !== -1 &&\n newIdx !== -1 &&\n oldIdx !== newIdx\n ) {\n const reordered = arrayMove(group.entries, oldIdx, newIdx);\n const newState = [...dndItems];\n newState[grpIdx] = {\n ...group,\n entries: reordered\n };\n setDndItems(newState);\n onPersist?.(newState);\n }\n }\n } else if (overCont && activeCont !== overCont) {\n // Card moved between different groups - use CLEAN pre-drag state\n const finalState = cloneItemsForDnd(sourceState);\n\n // Find target container from clean state too\n const finalOverId = lastOverId.current || overIdNow;\n const cleanOverCont = findContainerInState(finalOverId as string, sourceState) || overCont;\n\n const srcIdx = finalState.findIndex((g) => g.name === activeCont);\n const tgtIdx = finalState.findIndex((g) => g.name === cleanOverCont);\n\n if (srcIdx !== -1 && tgtIdx !== -1) {\n const src = finalState[srcIdx];\n const tgt = finalState[tgtIdx];\n const idxInSrc = src.entries.findIndex((e) => e.url === activeIdNow);\n\n if (idxInSrc !== -1) {\n // Remove from source\n const [moved] = src.entries.splice(idxInSrc, 1);\n\n // Calculate insertion position in target\n const overIsContainer = finalOverId === cleanOverCont;\n if (overIsContainer) {\n tgt.entries.push(moved);\n } else {\n const overIdx = tgt.entries.findIndex((e) => e.url === finalOverId);\n if (overIdx !== -1) {\n tgt.entries.splice(overIdx, 0, moved);\n } else {\n tgt.entries.push(moved);\n }\n }\n\n // Remove empty source group if needed\n if (src.entries.length === 0) {\n finalState.splice(srcIdx, 1);\n }\n\n setDndItems(finalState);\n onPersist?.(finalState);\n\n onCardMovedBetweenGroups?.(moved);\n }\n }\n } else if (recentlyMovedToNewContainer.current) {\n // This shouldn't happen but log it for debugging\n console.error(\"Move between containers detected but conditions not met\", {\n activeCont,\n overCont,\n activeIdNow,\n overIdNow\n });\n }\n }\n }\n\n resetDragState();\n };\n\n const resetDragState = () => {\n setDndKitActiveNode(null);\n setActiveId(null);\n setActiveIsGroup(false);\n setCurrentDraggingGroupId(null);\n setIsDraggingCardOnly(false);\n recentlyMovedToNewContainer.current = false;\n };\n\n const handleDragCancel = () => resetDragState();\n\n /* ---------------- group rename ---------------- */\n const handleRenameGroup = (oldName: string, newName: string) => {\n setDndItems((current) => {\n const idx = current.findIndex((g) => g.name === oldName);\n if (idx === -1) return current;\n if (current.some((g) => g.name === newName && g.name !== oldName))\n return current;\n\n const updated = [...current];\n updated[idx] = {\n ...updated[idx],\n name: newName\n };\n\n // Persist after successful rename\n onPersist?.(updated);\n return updated;\n });\n\n // Clear all pending state\n setPendingNewGroupName(null);\n setStateBeforeNewGroup(null);\n setDialogOpenForGroup(null);\n };\n\n /* Handle dialog close without renaming */\n const handleDialogClose = () => {\n // If there's a pending new group that wasn't renamed, restore previous state\n if (pendingNewGroupName && dialogOpenForGroup === pendingNewGroupName && stateBeforeNewGroup) {\n // Restore the state from before the new group was created\n setDndItems(stateBeforeNewGroup);\n }\n\n // Clear all pending state\n setPendingNewGroupName(null);\n setStateBeforeNewGroup(null);\n setDialogOpenForGroup(null);\n };\n\n /* ---------------- public API ---------------- */\n const activeItemForOverlay =\n disabled || !activeId || activeIsGroup\n ? null\n : dndItems.flatMap((g) => g.entries).find((e) => e.url === activeId) || null;\n\n const activeGroupData =\n disabled || !activeId || !activeIsGroup\n ? null\n : dndItems.find((g) => g.name === activeId) || null;\n\n return {\n sensors,\n collisionDetection,\n onDragStart: handleDragStart,\n onDragOver: handleDragOver,\n onDragEnd: handleDragEnd,\n onDragCancel: handleDragCancel,\n dropAnimation: dropAnimationConfig,\n activeItemForOverlay,\n activeGroupData,\n draggingGroupId: currentDraggingGroupId,\n containers: dndContainers,\n dndKitActiveNode,\n isDraggingCardOnly,\n dialogOpenForGroup,\n setDialogOpenForGroup,\n handleRenameGroup,\n handleDialogClose,\n isHoveringNewGroupDropZone,\n setIsHoveringNewGroupDropZone\n };\n}\n\nexport function NewGroupDropZone({\n disabled,\n setIsHovering\n}: {\n disabled: boolean;\n setIsHovering: (v: boolean) => void;\n}) {\n const {\n setNodeRef,\n isOver\n } = useDroppable({\n id: \"new-group-drop-zone\",\n disabled\n });\n const [isVisible, setIsVisible] = useState(false);\n\n useDndMonitor({\n onDragStart({ active }) {\n if (disabled) return;\n const tp = active.data.current?.type;\n setIsVisible(tp === \"item\");\n },\n onDragEnd() {\n setIsVisible(false);\n },\n onDragCancel() {\n setIsVisible(false);\n }\n });\n\n useEffect(() => {\n setIsHovering(isOver && isVisible);\n }, [isOver, isVisible, setIsHovering]);\n\n if (!isVisible || disabled) return null;\n\n return (\n <div\n ref={setNodeRef}\n className={cls(\n \"fixed right-8 top-1/2 -translate-y-1/2 w-[200px] h-[120px] border border-dashed rounded-lg flex items-center justify-center transition-all\",\n isOver\n ? \"bg-surface-accent-100 dark:bg-surface-accent-800 border-surface-300 dark:border-surface-600\"\n : \"bg-surface-50 dark:bg-surface-900 border-surface-200 dark:border-surface-700\"\n )}>\n <div className=\"text-center p-4\">\n <span className=\"block font-medium text-sm\">\n Drop here to create a new group\n </span>\n </div>\n </div>\n );\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { Button, Dialog, DialogActions, DialogContent, DialogTitle, TextField } from \"@rebasepro/ui\";\nimport { useTranslation } from \"@rebasepro/app\";\n\ninterface RenameGroupDialogProps {\n open: boolean;\n initialName: string;\n existingGroupNames: string[]; // Names of other existing groups to check for duplicates\n onClose: () => void;\n onRename: (newName: string) => void;\n}\n\nexport function RenameGroupDialog({\n open,\n initialName,\n existingGroupNames,\n onClose,\n onRename\n}: RenameGroupDialogProps) {\n const { t } = useTranslation();\n const [name, setName] = useState(initialName);\n const [error, setError] = useState<string | null>(null);\n const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement | null>(null); // Create a ref for the input\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setError(null);\n // Focus and select text when dialog opens\n setTimeout(() => { // setTimeout to ensure the input is rendered and focusable\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, 100);\n }\n }, [initialName, open]);\n\n const handleNameChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const newName = event.target.value;\n setName(newName);\n if (!newName.trim()) {\n setError(t(\"group_name_empty_error\"));\n } else if (existingGroupNames.includes(newName.trim())) {\n setError(t(\"group_name_exists_error\"));\n } else {\n setError(null);\n }\n };\n\n const handleSave = () => {\n const trimmedName = name.trim();\n if (!trimmedName) {\n setError(t(\"group_name_empty_error\"));\n return;\n }\n if (existingGroupNames.includes(trimmedName)) {\n setError(t(\"group_name_exists_error\"));\n return;\n }\n if (!error) {\n onRename(trimmedName);\n onClose();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n if (event.key === \"Enter\") {\n event.preventDefault(); // Prevent default form submission behavior\n const trimmedName = name.trim();\n // We need to check the error state directly as well,\n // because the error state might not have updated if the user types and immediately hits enter.\n let currentError = null;\n if (!trimmedName) {\n currentError = t(\"group_name_empty_error\");\n } else if (existingGroupNames.includes(trimmedName)) {\n currentError = t(\"group_name_exists_error\");\n }\n\n if (!currentError && trimmedName) {\n handleSave();\n } else if (currentError) {\n setError(currentError); // Ensure error is displayed if trying to submit with Enter\n }\n }\n };\n\n const handleClose = () => {\n setName(initialName);\n setError(null);\n onClose();\n };\n\n if (!open) return null;\n\n return (\n <Dialog open={open}>\n <DialogTitle>{t(\"rename_group\")}</DialogTitle>\n <DialogContent>\n <TextField\n inputRef={inputRef} // Pass the ref to the TextField\n label={t(\"group_name_label\")}\n value={name}\n onChange={handleNameChange}\n onKeyDown={handleKeyDown} // Added onKeyDown handler\n error={!!error}\n aria-describedby={error ? \"group-name-error\" : undefined}\n />\n {error && <p id=\"group-name-error\" style={{ display: \"none\" }}>{error}</p>}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}\n variant=\"text\">\n {t(\"cancel\")}\n </Button>\n <Button onClick={handleSave}\n disabled={!!error || !name.trim()}>\n {t(\"save\")}\n </Button>\n </DialogActions>\n </Dialog>\n );\n}\n","import type { HomePageSection, NavigationEntry, NavigationGroupMapping, PluginGenericProps } from \"@rebasepro/admin-types\";\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport Fuse from \"fuse.js\";\nimport { Container, SearchBar } from \"@rebasepro/ui\";\nimport { AnalyticsEvent } from \"@rebasepro/admin-types\";\nimport { FavouritesView } from \"./FavouritesView\";\nimport { ErrorBoundary } from \"@rebasepro/ui\";\nimport { NavigationGroup } from \"./NavigationGroup\";\nimport {\n NavigationGroupDroppable,\n NewGroupDropZone,\n SortableNavigationCard,\n SortableNavigationGroup,\n useHomePageDnd\n} from \"./HomePageDnD\";\nimport { DndContext, DragOverlay, MeasuringStrategy } from \"@dnd-kit/core\";\nimport { NavigationCardBinding } from \"./NavigationCardBinding\";\nimport { SortableContext, verticalListSortingStrategy } from \"@dnd-kit/sortable\";\nimport { restrictToVerticalAxis, restrictToWindowEdges } from \"@dnd-kit/modifiers\";\nimport { RenameGroupDialog } from \"./RenameGroupDialog\";\nimport { toArray } from \"@rebasepro/utils\";\nimport { useCollapsedGroups, buildCollapsedDefaults, useCustomizationController, useTranslation, useSlot, useAdminModeController, useRebaseRegistry } from \"@rebasepro/app\";\nimport { useRestoreScroll } from \"@rebasepro/app\";\n\nimport { SchemaDriftBanner } from \"@rebasepro/app\";\nimport { useBreadcrumbsController } from \"../../hooks/useBreadcrumbsController\";\nimport { useAdminContext } from \"../../hooks/useAdminContext\";\n\nexport const DEFAULT_GROUP_NAME = \"Views\";\nexport const ADMIN_GROUP_NAME = \"Admin\";\n\nexport function ContentHomePage({\n additionalActions,\n additionalChildrenStart,\n additionalChildrenEnd,\n sections,\n hiddenGroups\n}: {\n additionalActions?: React.ReactNode;\n additionalChildrenStart?: React.ReactNode;\n additionalChildrenEnd?: React.ReactNode;\n sections?: HomePageSection[];\n hiddenGroups?: string[];\n}) {\n\n const context = useAdminContext();\n const { navigationStateController } = context;\n const customizationController = useCustomizationController();\n const adminModeController = useAdminModeController();\n const registry = useRebaseRegistry();\n\n const { resolvedSlots } = customizationController;\n const breadcrumbs = useBreadcrumbsController();\n const { t } = useTranslation();\n\n useEffect(() => {\n breadcrumbs.set({ breadcrumbs: [] });\n }, [breadcrumbs.set]);\n\n const {\n allowDragAndDrop = false,\n navigationEntries: unFilteredNavigationEntries = [],\n groups: unFilteredGroupOrder = [],\n onNavigationEntriesUpdate = () => {}\n } = navigationStateController.topLevelNavigation || {};\n\n // Build a set of Studio-only dev view slugs so we can distinguish them from\n // admin custom views added via <RebaseAdmin views={...}> or plugins.\n const studioViewSlugs = useMemo(() => {\n const slugs = new Set<string>();\n (registry.studioConfig?.devViews ?? []).forEach(v => slugs.add(v.slug));\n if (registry.studioConfig && registry.cmsConfig?.collectionEditor) slugs.add(\"schema\");\n return slugs;\n }, [registry.studioConfig, registry.cmsConfig?.collectionEditor]);\n\n // Studio mode shows Studio dev views + admin entries (Users/Roles).\n // Content mode shows collections, admin custom views, and admin entries — but not Studio dev views.\n const rawNavigationEntries = useMemo(() => {\n if (adminModeController.mode === \"studio\") {\n return unFilteredNavigationEntries.filter(e => (e.type === \"view\" && studioViewSlugs.has(e.slug)) || e.type === \"admin\");\n }\n return unFilteredNavigationEntries.filter(e => e.type !== \"view\" || !studioViewSlugs.has(e.slug));\n }, [unFilteredNavigationEntries, adminModeController.mode, studioViewSlugs]);\n\n const groupOrderFromNavController = useMemo(() => {\n const entryGroups = new Set(rawNavigationEntries.map(e => e.group).filter(Boolean));\n return unFilteredGroupOrder.filter(g => entryGroups.has(g));\n }, [unFilteredGroupOrder, rawNavigationEntries]);\n\n const fuse = useRef<Fuse<NavigationEntry> | null>(null);\n const [filteredUrls, setFilteredUrls] = useState<string[] | null>(null);\n const performingSearch = Boolean(filteredUrls);\n\n // Memoize filtered navigation entries to prevent unnecessary recalculations\n const filteredNavigationEntries = useMemo(() => {\n return filteredUrls\n ? rawNavigationEntries.filter((e) => filteredUrls.includes(e.url))\n : rawNavigationEntries;\n }, [filteredUrls, rawNavigationEntries]);\n\n useEffect(() => {\n fuse.current = new Fuse(rawNavigationEntries, {\n keys: [\"name\", \"description\", \"group\", \"path\"]\n });\n }, [rawNavigationEntries]);\n\n const updateSearch = useCallback((v?: string) => {\n if (!v?.trim()) {\n setFilteredUrls(null);\n return;\n }\n const results = fuse.current?.search(v.trim());\n setFilteredUrls(results ? results.map((x) => x.item.url) : []);\n }, []);\n\n /* ───────────────────────────────────────────────────────────────\n Build groups (all items) + isolate Admin\n ─────────────────────────────────────────────────────────────── */\n const [items, setItems] = useState<\n { name: string; entries: NavigationEntry[] }[]\n >([]);\n const [adminGroupData, setAdminGroupData] = useState<{\n name: string;\n entries: NavigationEntry[];\n } | null>(null);\n\n // Flag to prevent useEffect from overwriting local DnD state\n const isDndDirtyRef = useRef(false);\n const dndDirtyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Memoize the processed groups to avoid unnecessary recalculations\n const processedGroups = useMemo(() => {\n const src = filteredNavigationEntries;\n const entriesByGroup: Record<string, NavigationEntry[]> = {};\n\n src.forEach((e) => {\n const g =\n e.type === \"admin\"\n ? ADMIN_GROUP_NAME\n : e.group ?? DEFAULT_GROUP_NAME;\n (entriesByGroup[g] ??= []).push(e);\n });\n\n // Check if there are custom additional card components from plugins\n const hasPluginAdditionalCards = customizationController.resolvedSlots.some(s => s.slot === \"home.cards\");\n\n let allProcessed: { name: string; entries: NavigationEntry[] }[];\n\n if (performingSearch) {\n const ordered = [\n ...new Set(src.map((e) => e.group ?? DEFAULT_GROUP_NAME))\n ];\n allProcessed = ordered\n .map((name) => ({\n name,\n entries: entriesByGroup[name] || []\n }))\n .filter((g) => g.entries.length);\n } else {\n allProcessed = groupOrderFromNavController.map((g) => ({\n name: g,\n entries: entriesByGroup[g] || []\n }));\n Object.keys(entriesByGroup).forEach((g) => {\n if (!groupOrderFromNavController.includes(g))\n allProcessed.push({\n name: g,\n entries: entriesByGroup[g]\n });\n });\n\n // Ensure default group exists if there are plugin additional cards but no collections\n if (hasPluginAdditionalCards && !allProcessed.some(g => g.name === DEFAULT_GROUP_NAME)) {\n allProcessed.push({\n name: DEFAULT_GROUP_NAME,\n entries: []\n });\n }\n\n allProcessed = allProcessed.filter(\n (g) =>\n g.entries.length ||\n (g.name === DEFAULT_GROUP_NAME && hasPluginAdditionalCards)\n );\n }\n\n const admin = allProcessed.find((g) => g.name === ADMIN_GROUP_NAME);\n return {\n adminGroupData: admin || null,\n items: allProcessed.filter((g) => g.name !== ADMIN_GROUP_NAME && !hiddenGroups?.includes(g.name))\n };\n }, [filteredNavigationEntries, performingSearch, groupOrderFromNavController, customizationController.resolvedSlots, hiddenGroups]);\n\n // Update state only when processedGroups actually changes\n // Skip update if DnD just made a local change (dirty flag is set)\n useEffect(() => {\n if (isDndDirtyRef.current) {\n // DnD just updated the state, skip this sync\n return;\n }\n setAdminGroupData(processedGroups.adminGroupData);\n setItems(processedGroups.items);\n }, [processedGroups]);\n\n /* ───────────────────────────────────────────────────────────────\n Local update vs. persistence helpers\n ─────────────────────────────────────────────────────────────── */\n const updateItems = (\n updater:\n | { name: string; entries: NavigationEntry[] }[]\n | ((\n prev: { name: string; entries: NavigationEntry[] }[]\n ) => { name: string; entries: NavigationEntry[] }[])\n ) => {\n setItems(updater); // local only\n };\n\n const persistNavigationGroups = (\n latest: { name: string; entries: NavigationEntry[] }[]\n ) => {\n // Set dirty flag to prevent useEffect from overwriting local state\n isDndDirtyRef.current = true;\n\n // Clear any existing timeout\n if (dndDirtyTimeoutRef.current) {\n clearTimeout(dndDirtyTimeoutRef.current);\n }\n\n // Clear dirty flag after a delay to allow navigation to update\n dndDirtyTimeoutRef.current = setTimeout(() => {\n isDndDirtyRef.current = false;\n }, 1000);\n\n // Map ALL groups including \"Views\"\n const draggable: NavigationGroupMapping[] = latest.map((g) => ({\n name: g.name,\n entries: g.entries.map((e) => e.slug)\n }));\n\n const all: NavigationGroupMapping[] = adminGroupData\n ? [\n ...draggable,\n {\n name: adminGroupData.name,\n entries: adminGroupData.entries.map((e) => e.slug)\n }\n ]\n : draggable;\n\n onNavigationEntriesUpdate(all);\n };\n\n // Use custom hook for collapsed groups with localStorage persistence\n const groupNames = useMemo(() => [\n ...items.map(item => item.name),\n ...(adminGroupData ? [adminGroupData.name] : [])\n ], [items, adminGroupData]);\n\n const collapsedDefaults = useMemo(\n () => buildCollapsedDefaults(registry.cmsConfig?.navigationGroupMappings, \"home\"),\n [registry.cmsConfig?.navigationGroupMappings]\n );\n const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupNames, \"home\", collapsedDefaults);\n\n const {\n sensors,\n collisionDetection,\n onDragStart,\n onDragOver,\n onDragEnd,\n dropAnimation,\n activeItemForOverlay,\n activeGroupData,\n draggingGroupId,\n containers,\n dndKitActiveNode,\n onDragCancel,\n isDraggingCardOnly,\n dialogOpenForGroup,\n setDialogOpenForGroup,\n handleRenameGroup,\n handleDialogClose,\n isHoveringNewGroupDropZone,\n setIsHoveringNewGroupDropZone\n } = useHomePageDnd({\n items,\n setItems: updateItems,\n disabled: !allowDragAndDrop || performingSearch,\n onPersist: persistNavigationGroups,\n onGroupMoved: (g) =>\n context.analyticsController?.onAnalyticsEvent?.(\"home_move_group\", {\n name: g\n }),\n onCardMovedBetweenGroups: (card) =>\n context.analyticsController?.onAnalyticsEvent?.(\"home_move_card\", {\n id: card.id\n }),\n onNewGroupDrop: () =>\n context.analyticsController?.onAnalyticsEvent?.(\n \"home_drop_new_group\"\n )\n });\n\n const {\n containerRef,\n direction\n } = useRestoreScroll();\n\n const dndDisabled = !allowDragAndDrop || performingSearch;\n\n const dndModifiers = dndKitActiveNode?.data.current?.type === \"group\"\n ? [restrictToVerticalAxis, restrictToWindowEdges]\n : [restrictToWindowEdges];\n\n const sectionProps: PluginGenericProps = { context };\n const additionalPluginChildrenStart = useSlot(\"home.children.start\", sectionProps);\n const additionalPluginChildrenEnd = useSlot(\"home.children.end\", sectionProps);\n const additionalPluginActions = useSlot(\"home.actions\", sectionProps);\n\n // Pre-compute home.cards slot contributions (cannot call useSlot inside .map loop)\n const homeCardContributions = useMemo(() => {\n return resolvedSlots\n .filter(s => s.slot === \"home.cards\")\n .sort((a, b) => (a.order ?? 50) - (b.order ?? 50));\n }, [resolvedSlots]);\n\n /* ───────────────────────────────────────────────────────────────\n Render\n ─────────────────────────────────────────────────────────────── */\n return (\n <div ref={containerRef} className=\"py-2 overflow-auto h-full w-full bg-surface-50 dark:bg-surface-800\">\n <Container maxWidth=\"6xl\">\n <div className=\"mb-4 flex flex-col gap-2\">\n <SchemaDriftBanner />\n </div>\n {/* search & actions */}\n <div\n className=\"w-full sticky py-4 transition-all duration-400 ease-in-out top-0 z-10 flex flex-row gap-4\"\n style={{ top: direction === \"down\" ? -84 : 0 }}\n >\n <SearchBar\n onTextSearch={updateSearch}\n placeholder={t(\"search_collections\")}\n autoFocus\n size=\"small\"\n innerClassName=\"w-full\"\n className=\"w-full grow\"\n />\n {additionalActions}\n {additionalPluginActions}\n </div>\n\n <FavouritesView hidden={performingSearch}/>\n\n {additionalChildrenStart}\n {additionalPluginChildrenStart}\n\n {/* ─────── DND context ─────── */}\n <DndContext\n sensors={sensors}\n collisionDetection={collisionDetection}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always,\n frequency: 500\n }\n }}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDragCancel={onDragCancel}\n modifiers={dndModifiers}\n >\n <SortableContext\n key={containers.join(\",\")}\n items={containers}\n strategy={verticalListSortingStrategy}\n >\n {items.map((groupData, groupIndex) => {\n const groupKey = groupData.name;\n const entriesInGroup = groupData.entries;\n\n const homeCardsProps = {\n group:\n groupKey === DEFAULT_GROUP_NAME\n ? undefined\n : groupKey,\n context\n };\n // Render home.cards contributions inline (no hook call inside loop)\n const additionalCards = homeCardContributions.map((s, i) => (\n <ErrorBoundary key={`home_cards_${groupKey}_${i}`}>\n <s.Component {...homeCardsProps} {...(s.props ?? {})}/>\n </ErrorBoundary>\n ));\n\n if (\n entriesInGroup.length === 0 &&\n (additionalCards.length === 0 || performingSearch)\n )\n return null;\n\n return (\n <SortableNavigationGroup\n key={`group-${groupIndex}`}\n groupName={groupKey}\n disabled={dndDisabled}\n >\n <NavigationGroup\n group={\n groupKey === DEFAULT_GROUP_NAME\n ? undefined\n : groupKey\n }\n minimised={\n draggingGroupId === groupKey &&\n !isDraggingCardOnly\n }\n isPotentialCardDropTarget={\n isDraggingCardOnly\n }\n dndDisabled={dndDisabled}\n onEditGroup={() => {\n if (dndDisabled) return;\n setDialogOpenForGroup(groupKey);\n }}\n collapsed={isGroupCollapsed(groupKey)}\n onToggleCollapsed={() => toggleGroupCollapsed(groupKey)}\n >\n <NavigationGroupDroppable\n id={groupKey}\n itemIds={entriesInGroup.map(\n (e) => e.url\n )}\n isPotentialCardDropTarget={\n isDraggingCardOnly\n }\n >\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 \">\n {entriesInGroup.map(\n (entry) => (\n <SortableNavigationCard\n key={entry.url}\n entry={entry}\n onClick={() => {\n let event: AnalyticsEvent =\n \"unmapped_event\";\n if (\n entry.type ===\n \"collection\"\n )\n event =\n \"home_navigate_to_collection\";\n else if (\n entry.type ===\n \"view\"\n )\n event =\n \"home_navigate_to_view\";\n else if (\n entry.type ===\n \"admin\"\n )\n event =\n \"home_navigate_to_admin_view\";\n\n context.analyticsController?.onAnalyticsEvent?.(\n event,\n {\n path: entry.slug\n }\n );\n }}\n />\n )\n )}\n {!performingSearch &&\n groupKey.toLowerCase() !==\n ADMIN_GROUP_NAME.toLowerCase() &&\n additionalCards}\n </div>\n </NavigationGroupDroppable>\n </NavigationGroup>\n </SortableNavigationGroup>\n );\n })}\n </SortableContext>\n\n <NewGroupDropZone\n disabled={dndDisabled}\n setIsHovering={setIsHoveringNewGroupDropZone}\n />\n\n <DragOverlay adjustScale={false} dropAnimation={dropAnimation}>\n {activeGroupData &&\n draggingGroupId === activeGroupData.name ? (\n <div\n className=\"rounded-lg bg-transparent\"\n style={{\n padding: 0,\n margin: 0\n }}\n >\n <NavigationGroup\n group={\n activeGroupData.name ===\n DEFAULT_GROUP_NAME\n ? undefined\n : activeGroupData.name\n }\n isPreview={false}\n minimised\n />\n </div>\n ) : activeItemForOverlay ? (\n <NavigationCardBinding\n {...activeItemForOverlay}\n shrink={isHoveringNewGroupDropZone}\n />\n ) : null}\n </DragOverlay>\n </DndContext>\n\n {!performingSearch && adminGroupData && (\n <NavigationGroup\n group={adminGroupData.name}\n collapsed={isGroupCollapsed(adminGroupData.name)}\n onToggleCollapsed={() => toggleGroupCollapsed(adminGroupData.name)}\n >\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 \">\n {adminGroupData.entries.map((entry) => (\n <NavigationCardBinding\n key={entry.url}\n {...entry}\n onClick={() => {\n let event: AnalyticsEvent =\n \"unmapped_event\";\n if (entry.type === \"collection\")\n event =\n \"home_navigate_to_collection\";\n else if (entry.type === \"view\")\n event = \"home_navigate_to_view\";\n else if (entry.type === \"admin\")\n event =\n \"home_navigate_to_admin_view\";\n\n context.analyticsController?.onAnalyticsEvent?.(\n event,\n { path: entry.slug }\n );\n }}\n />\n ))}\n </div>\n </NavigationGroup>\n )}\n\n {sections && sections.map((section) => (\n <NavigationGroup\n key={section.key}\n group={section.title}\n >\n {section.children}\n </NavigationGroup>\n ))}\n\n {additionalPluginChildrenEnd}\n {additionalChildrenEnd}\n </Container>\n\n {dialogOpenForGroup && (\n <RenameGroupDialog\n open\n initialName={dialogOpenForGroup}\n existingGroupNames={items\n .map((g) => g.name)\n .filter((n) => n !== dialogOpenForGroup)}\n onClose={handleDialogClose}\n onRename={(newName) => {\n handleRenameGroup(dialogOpenForGroup, newName);\n }}\n />\n )}\n </div>\n );\n}\n","import React, { Suspense } from \"react\";\nimport { lazyChunk } from \"@rebasepro/ui\";\nimport { useCollectionEditorDialogsState } from \"../collection_editor/CollectionEditorDialogsContext\";\n\n// Dynamic imports targeting the separate collection_editor_ui entry point.\n// This ensures the heavy editor UI lands in its own chunk and is only fetched\n// when a dialog is actually opened.\nconst CollectionEditorDialog = lazyChunk(() =>\n import(\"../collection_editor/ui/collection_editor/CollectionEditorDialog\")\n .then(m => ({ default: m.CollectionEditorDialog }))\n);\n\nconst PropertyFormDialog = lazyChunk(() =>\n import(\"../collection_editor/ui/collection_editor/PropertyEditView\")\n .then(m => ({ default: m.PropertyFormDialog }))\n);\n\n/**\n * Renders the CollectionEditorDialog and PropertyFormDialog inside\n * the RebaseShell tree where admin-internal contexts\n * (CollectionRegistryContext, NavigationStateContext, UrlContext)\n * are available.\n *\n * Both dialog components are loaded dynamically via React.lazy so that\n * production admin bundles that never open the collection editor don't pay\n * the download/parse cost up-front.\n *\n * The dialog state (open/close, props) is managed by ConfigControllerProvider\n * (a root-scope plugin provider that wraps the shell) and exposed via\n * CollectionEditorDialogsContext.\n */\nexport function CollectionEditorDialogs() {\n const state = useCollectionEditorDialogsState();\n\n if (!state) return null;\n\n const { collectionDialogProps, propertyDialogProps } = state;\n\n // Don't even mount the Suspense boundary until a dialog is actually open.\n const hasOpenDialog =\n collectionDialogProps?.open || propertyDialogProps?.open;\n\n if (!hasOpenDialog) return null;\n\n return (\n <Suspense fallback={null}>\n {collectionDialogProps?.open && (\n <CollectionEditorDialog\n open={false}\n isNewCollection={false}\n configController={undefined!}\n handleClose={() => {}}\n {...collectionDialogProps}\n />\n )}\n {propertyDialogProps?.open && (\n <PropertyFormDialog\n open={false}\n existingProperty={false}\n autoOpenTypeSelect={false}\n inArray={false}\n allowDataInference={false}\n propertyConfigs={{}}\n {...propertyDialogProps}\n />\n )}\n </Suspense>\n );\n}\n","import React, { lazy, Suspense, useMemo } from \"react\";\nimport { Route } from \"react-router\";\nimport {\n useRebaseRegistry,\n RebaseRoutes,\n UserSettingsView,\n UIReferenceView,\n NotFoundPage,\n useComponentOverride\n} from \"@rebasepro/app\";\nimport { CircularProgressCenter } from \"@rebasepro/ui\";\n\nimport { ContentHomePage as DefaultHomePage } from \"./HomePage/ContentHomePage\";\n\nimport { RebaseRoute } from \"../routes/RebaseRoute\";\nimport { CustomViewRoute } from \"../routes/CustomViewRoute\";\nimport { useNavigationStateController } from \"../hooks/navigation/contexts/NavigationStateContext\";\nimport { CollectionEditorDialogs } from \"./CollectionEditorDialogs\";\nimport { useEffect } from \"react\";\nimport { useTranslation } from \"@rebasepro/app\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\n\nfunction SettingsView() {\n const { t } = useTranslation();\n const breadcrumbs = useBreadcrumbsController();\n useEffect(() => {\n breadcrumbs.set({\n breadcrumbs: [{ title: t(\"account_settings\"),\nurl: \"/settings\" }]\n });\n\n }, []);\n return <UserSettingsView/>;\n}\n\nexport interface RebaseRouteDefsProps {\n /** User-provided custom routes to include. */\n children?: React.ReactNode;\n /**\n * Wrap function — receives the route tree and lets you wrap it in a layout.\n * If provided, the routes are rendered inside this wrapper.\n * If not provided, routes are rendered directly inside <RebaseRoutes>.\n */\n layout?: React.ReactElement;\n}\n\n/**\n * Route definitions for the admin.\n *\n * Defines all standard routes: home, studio home, collection view,\n * settings, debug, custom views, and a catch-all 404.\n *\n * **Independently usable**: Use this when you want Rebase routes\n * inside your own layout/navigation setup.\n *\n * @example\n * ```tsx\n * <RebaseNavigation>\n * <RebaseRouteDefs layout={<MyCustomLayout />}>\n * <Route path=\"/my-custom\" element={<MyView />} />\n * </RebaseRouteDefs>\n * </RebaseNavigation>\n * ```\n */\nexport function RebaseRouteDefs({ children, layout }: RebaseRouteDefsProps) {\n const registry = useRebaseRegistry();\n const navigationStateController = useNavigationStateController();\n\n const ResolvedHomePage = useComponentOverride(\"HomePage\", DefaultHomePage);\n const cmsHomePage = registry.cmsConfig?.homePage ?? <Suspense fallback={<CircularProgressCenter/>}><ResolvedHomePage/></Suspense>;\n const studioHomePage = registry.studioConfig?.homePage;\n\n const combinedViews = useMemo(() => [\n ...(navigationStateController.views ?? []),\n ...(navigationStateController.adminViews ?? [])\n ], [navigationStateController.views, navigationStateController.adminViews]);\n\n const routeContents = (\n <>\n {/* Core admin Routes */}\n <Route path={\"/\"} element={cmsHomePage}/>\n {registry.studioConfig && (\n <Route path={\"/s\"} element={studioHomePage}/>\n )}\n\n <Route path={\"/c/*\"} element={<RebaseRoute/>}/>\n <Route path={\"/settings\"} element={<SettingsView/>}/>\n\n\n {/* Hidden debug route */}\n <Route path={\"/debug/ui\"} element={<UIReferenceView/>}/>\n\n {/* Custom Registered Views */}\n {combinedViews.map(view => {\n const slugs = Array.isArray(view.slug) ? view.slug : [view.slug];\n return slugs.flatMap(slug => {\n const routes = [\n <Route key={slug} path={slug} element={<CustomViewRoute view={view}/>}/>\n ];\n if (view.nestedRoutes) {\n routes.push(\n <Route key={slug + \"/*\"} path={slug + \"/*\"} element={<CustomViewRoute view={view}/>}/>\n );\n }\n return routes;\n });\n })}\n\n {/* User Provided Custom Routes */}\n {children}\n\n <Route path={\"*\"} element={navigationStateController.loading ? <CircularProgressCenter/> : <NotFoundPage/>}/>\n </>\n );\n\n return (\n <>\n <RebaseRoutes>\n {layout\n ? <Route element={layout}>{routeContents}</Route>\n : <Route element={<>{routeContents}</>}>{routeContents}</Route>\n }\n </RebaseRoutes>\n <CollectionEditorDialogs/>\n </>\n );\n}\n","import React, { useMemo } from \"react\";\nimport {\n useRebaseRegistry\n} from \"@rebasepro/app\";\nimport { ErrorBoundary } from \"@rebasepro/ui\";\n\nimport { RebaseAuthGate } from \"./RebaseAuthGate\";\nimport { RebaseNavigation } from \"./RebaseNavigation\";\nimport { RebaseLayout } from \"./RebaseLayout\";\nimport { RebaseRouteDefs } from \"./RebaseRouteDefs\";\n\nexport interface RebaseShellProps {\n title?: string;\n /** Top bar. Only rendered if provided — pass `<AppBar/>` for the default one. */\n appBar?: React.ReactNode;\n drawer?: React.ReactNode;\n /** Expand the drawer while the pointer is over it. On by default; pass `false` to opt out. Not a load-time default — that is `defaultDrawerOpen`. */\n autoOpenDrawer?: boolean;\n /** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */\n defaultDrawerOpen?: boolean;\n /** Path to the logo shown in the drawer and top bar. Falls back to the Rebase mark. */\n logo?: string;\n children?: React.ReactNode;\n}\n\n/**\n * Convenience component that composes all four admin layers:\n *\n * ```\n * <RebaseAuthGate>\n * <RebaseNavigation>\n * <RebaseRouteDefs layout={<RebaseLayout>}>\n * {children}\n * </RebaseRouteDefs>\n * </RebaseNavigation>\n * </RebaseAuthGate>\n * ```\n *\n * Each layer is independently usable — see their individual docs.\n * RebaseShell is sugar that composes them all with sensible defaults.\n */\nexport function RebaseShell(props: RebaseShellProps) {\n const {\n title = \"Rebase\",\n appBar,\n drawer,\n autoOpenDrawer = true,\n defaultDrawerOpen = false,\n logo,\n children\n } = props;\n\n const registry = useRebaseRegistry();\n\n // Compute devViews for the layout's AdminModeSyncer\n const devViews = useMemo(() => {\n return registry.studioConfig?.devViews ?? [];\n }, [registry.studioConfig?.devViews]);\n\n return (\n <RebaseAuthGate>\n <RebaseNavigation>\n <ErrorBoundary fullPage>\n <RebaseRouteDefs\n layout={\n <RebaseLayout\n title={title}\n appBar={appBar}\n drawer={drawer}\n autoOpenDrawer={autoOpenDrawer}\n defaultDrawerOpen={defaultDrawerOpen}\n logo={logo}\n devViews={devViews}\n />\n }\n >\n {children}\n </RebaseRouteDefs>\n </ErrorBoundary>\n </RebaseNavigation>\n </RebaseAuthGate>\n );\n}\n","\nimport type { ViewMode, AdminCollection } from \"@rebasepro/admin-types\";\nimport React, { useMemo } from \"react\";\nimport { CollectionViewBinding } from \"./CollectionViewBinding/CollectionViewBinding\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { Typography } from \"@rebasepro/ui\";\nimport { useComponentOverride, CollectionScopeProvider } from \"@rebasepro/app\";\n\n/**\n * Props for the {@link CollectionPanel} component.\n *\n * This is a high-level, consumer-friendly wrapper around {@link CollectionViewBinding}\n * designed for embedding collection views inside custom pages (home pages,\n * dashboards, entity detail views, etc.).\n *\n * At minimum, provide the `path` (collection slug). All other props are optional\n * overrides that take precedence over the collection's default configuration.\n *\n * @group Components\n */\nexport type CollectionPanelProps = {\n /**\n * The collection slug / path to display (e.g. \"tasks\", \"clients\").\n * The collection must be registered in the Rebase context.\n */\n path: string;\n\n /**\n * Optional title displayed above the collection.\n * Set to `false` to hide the title entirely.\n * Defaults to the collection's `name`.\n */\n title?: string | false;\n\n /**\n * Force a specific view mode, overriding the collection's default.\n */\n viewMode?: ViewMode;\n\n /**\n * Override the sort field.\n */\n sort?: [string, \"asc\" | \"desc\"];\n\n /**\n * Maximum number of entities to display.\n */\n limit?: number;\n\n /**\n * Whether to sync filter/sort state with URL query params.\n * Defaults to `false` (embedded panels shouldn't hijack the URL).\n */\n updateUrl?: boolean;\n\n /**\n * Override the entity open mode when clicking a entity.\n */\n openEntityMode?: \"side_panel\" | \"full_screen\" | \"split\" | \"dialog\";\n\n /**\n * Additional CSS class name for the container.\n */\n className?: string;\n\n /**\n * Any additional collection-level overrides (e.g. `previewProperties`,\n * `enabledViews`, `entityActions`, `defaultFilter`, etc.).\n */\n collectionOverrides?: Partial<AdminCollection>;\n};\n\n/**\n * A high-level, reusable wrapper for embedding a Rebase collection view\n * inside custom pages (dashboards, home pages, entity detail views, etc.).\n *\n * Usage:\n * ```tsx\n * import { CollectionPanel } from \"@rebasepro/admin\";\n *\n * function MyDashboard() {\n * return (\n * <div>\n * <CollectionPanel path=\"tasks\" title=\"Pending Tasks\" />\n * <CollectionPanel\n * path=\"clients\"\n * viewMode=\"table\"\n * collectionOverrides={{\n * defaultFilter: { status: [\"!=\", \"completed\"] }\n * }}\n * />\n * </div>\n * );\n * }\n * ```\n *\n * @group Components\n */\nfunction CollectionPanelInner({\n mergedCollection,\n path,\n title,\n updateUrl,\n className\n}: CollectionPanelProps & { mergedCollection: AdminCollection }) {\n const ResolvedCollectionView = useComponentOverride(\"Collection.View\", CollectionViewBinding);\n\n return (\n <div className={className}>\n {title !== false && (\n <Typography\n variant=\"subtitle2\"\n className=\"font-bold mb-2 text-surface-700 dark:text-surface-300\"\n >\n {title ?? mergedCollection.name}\n </Typography>\n )}\n <ResolvedCollectionView\n {...mergedCollection}\n path={path}\n updateUrl={updateUrl}\n />\n </div>\n );\n}\n\nexport function CollectionPanel(props: CollectionPanelProps) {\n const {\n path,\n viewMode,\n sort,\n limit,\n openEntityMode,\n className,\n collectionOverrides\n } = props;\n const collectionRegistry = useCollectionRegistryController();\n const registeredCollection = collectionRegistry.getCollection(path);\n\n const mergedCollection = useMemo(() => {\n if (!registeredCollection) return undefined;\n\n // Build overrides object from shorthand props + explicit overrides\n const propOverrides: Record<string, unknown> = {};\n if (viewMode) propOverrides.defaultViewMode = viewMode;\n if (sort) propOverrides.sort = sort;\n if (limit) propOverrides.pagination = limit;\n if (openEntityMode) propOverrides.openEntityMode = openEntityMode;\n\n return {\n ...registeredCollection,\n ...(collectionOverrides ?? {}),\n ...propOverrides\n } as AdminCollection;\n }, [registeredCollection, collectionOverrides, viewMode, sort, limit, openEntityMode]);\n\n if (!mergedCollection) {\n return (\n <div className={className}>\n <Typography variant=\"body2\" color=\"secondary\">\n Collection "{path}" not found.\n </Typography>\n </div>\n );\n }\n\n const content = (\n <CollectionPanelInner\n {...props}\n mergedCollection={mergedCollection}\n />\n );\n\n return (\n <CollectionScopeProvider collection={mergedCollection}>\n {content}\n </CollectionScopeProvider>\n );\n}\n","/**\n * Maps a Rebase `Property` (from @rebasepro/types) to a `CollectionPropertyConfig`\n * (from @rebasepro/ui), stripping all entity-specific fields and keeping only\n * the UI-relevant subset.\n *\n * This is the bridge between the entity-aware and headless layers.\n */\n\nimport type { Property, Properties, EnumValues, EnumValueConfig } from \"@rebasepro/types\";\nimport type { CollectionPropertyConfig, CollectionEnumValueConfig } from \"@rebasepro/ui\";\n\n/**\n * Map Rebase property types to headless-supported types.\n * `vector` and `binary` are not directly renderable, so we fall back to `string`.\n */\nconst TYPE_MAP: Record<string, CollectionPropertyConfig[\"type\"]> = {\n string: \"string\",\n number: \"number\",\n boolean: \"boolean\",\n date: \"date\",\n geopoint: \"geopoint\",\n reference: \"reference\",\n relation: \"relation\",\n array: \"array\",\n map: \"map\",\n vector: \"string\", // vectors display as text\n binary: \"string\", // binary displays as text\n};\n\n/**\n * Convert a single Property to a CollectionPropertyConfig.\n */\nexport function mapPropertyToConfig(property: Property): CollectionPropertyConfig {\n const base: CollectionPropertyConfig = {\n type: TYPE_MAP[property.type] ?? \"string\",\n name: property.name,\n description: property.description,\n columnWidth: property.admin?.columnWidth,\n hideFromCollection: property.admin?.hideFromCollection,\n };\n\n // String-specific\n if (property.type === \"string\") {\n if (property.enum) {\n base.enum = mapEnumValues(property.enum);\n }\n if (property.admin?.multiline) base.multiline = true;\n if (property.admin?.previewAsTag) base.previewAsTag = true;\n if (property.admin?.urlPreview) base.url = property.admin.urlPreview;\n if (property.admin?.markdown) base.markdown = true;\n if (property.storage) base.storage = true;\n if (property.email) base.email = true;\n }\n\n // Number-specific\n if (property.type === \"number\" && property.enum) {\n base.enum = mapEnumValues(property.enum);\n }\n\n // Array-specific\n if (property.type === \"array\" && property.of && !Array.isArray(property.of)) {\n base.of = mapPropertyToConfig(property.of);\n }\n\n // Map-specific\n if (property.type === \"map\" && property.properties) {\n base.properties = mapPropertiesToConfigs(property.properties);\n if (property.propertiesOrder) {\n base.propertiesOrder = property.propertiesOrder;\n }\n }\n\n // Date-specific\n if (property.type === \"date\" && property.mode) {\n base.mode = property.mode;\n }\n\n // Custom preview component\n if (property.admin?.Preview) {\n // The connected wrapper will handle this by injecting via cellRenderer override\n // We don't copy it here because Preview may reference entity-aware components\n }\n\n return base;\n}\n\n/**\n * Convert a Properties record to a CollectionPropertyConfig record.\n */\nexport function mapPropertiesToConfigs(\n properties: Properties\n): Record<string, CollectionPropertyConfig> {\n const result: Record<string, CollectionPropertyConfig> = {};\n for (const [key, property] of Object.entries(properties)) {\n result[key] = mapPropertyToConfig(property);\n }\n return result;\n}\n\n/**\n * Convert Rebase EnumValues to CollectionEnumValueConfig format.\n * Handles both array form (EnumValueConfig[]) and record form.\n */\nfunction mapEnumValues(\n enumValues: EnumValues | undefined\n): Record<string, CollectionEnumValueConfig> | Map<string | number, CollectionEnumValueConfig> | undefined {\n if (!enumValues) return undefined;\n\n // Array form: EnumValueConfig[]\n if (Array.isArray(enumValues)) {\n const result: Record<string, CollectionEnumValueConfig> = {};\n for (const item of enumValues) {\n result[String(item.id)] = normalizeEnumValueConfig(item);\n }\n return result;\n }\n\n // Record form: Record<string | number, string | EnumValueConfig>\n const result: Record<string, CollectionEnumValueConfig> = {};\n for (const [key, value] of Object.entries(enumValues)) {\n result[key] = typeof value === \"string\"\n ? value\n : normalizeEnumValueConfig(value);\n }\n return result;\n}\n\nfunction normalizeEnumValueConfig(config: EnumValueConfig): CollectionEnumValueConfig {\n return {\n label: config.label,\n color: typeof config.color === \"string\" ? config.color : undefined,\n disabled: config.disabled,\n };\n}\n","/**\n * Adapts an `EntityTableController<M>` (from @rebasepro/types) to a\n * `CollectionDataController<T>` (from @rebasepro/ui), bridging the\n * entity-aware data layer to the headless collection view.\n */\n\nimport { useMemo } from \"react\";\nimport type { Entity } from \"@rebasepro/types\";\nimport type { EntityTableController } from \"@rebasepro/admin-types\";\nimport type { CollectionDataController } from \"@rebasepro/ui\";\n\n/**\n * Unwrap `Entity<M>` objects to flat rows for the headless view.\n * The entity system uses `{ id, path, values: M }`; `values` is already the\n * flat row `M` carrying its real primary key, so unwrapping is just `.values` —\n * no `id`/`path` merge (those are view-model metadata, not row columns).\n */\nfunction flattenEntities<M extends Record<string, unknown>>(\n entities: Entity<M>[]\n): M[] {\n return entities.map(entity => entity.values);\n}\n\n/**\n * React hook that adapts a EntityTableController to a CollectionDataController.\n *\n * Usage:\n * ```tsx\n * const tableController = useDataTableController({ path, collection });\n * const dataController = useCollectionDataController(tableController);\n *\n * <CollectionView dataController={dataController} ... />\n * ```\n */\nexport function useCollectionDataController<M extends Record<string, unknown>>(\n tableController: EntityTableController<M>\n): CollectionDataController<M> {\n const flatData = useMemo(\n () => flattenEntities(tableController.data),\n [tableController.data]\n );\n\n return useMemo((): CollectionDataController<M> => ({\n data: flatData,\n loading: tableController.dataLoading,\n noMoreToLoad: tableController.noMoreToLoad,\n error: tableController.dataLoadingError,\n\n filterValues: tableController.filterValues as Record<string, [string, unknown]> | undefined,\n setFilterValues: tableController.setFilterValues as\n ((values: Record<string, [string, unknown]> | undefined) => void) | undefined,\n\n sortBy: tableController.sortBy,\n setSortBy: tableController.setSortBy,\n\n searchString: tableController.searchString,\n setSearchString: tableController.setSearchString,\n\n clearFilter: tableController.clearFilter,\n\n initialScroll: tableController.initialScroll,\n onScroll: tableController.onScroll,\n\n paginationEnabled: tableController.paginationEnabled,\n pageSize: tableController.pageSize,\n itemCount: tableController.itemCount,\n setItemCount: tableController.setItemCount,\n }), [flatData, tableController]);\n}\n\n/**\n * Non-hook version for cases where you already have the data\n * and just need to build a static controller.\n */\nexport function createStaticDataController<T extends Record<string, unknown>>(\n data: T[],\n options?: {\n loading?: boolean;\n error?: Error;\n }\n): CollectionDataController<T> {\n return {\n data,\n loading: options?.loading ?? false,\n noMoreToLoad: true,\n error: options?.error,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { EngineProperties, Property } from \"@rebasepro/types\";\nimport type { NavigationGroupMapping, AdminCollection } from \"@rebasepro/admin-types\";\nimport type {\n CollectionsConfigController,\n SaveCollectionParams,\n UpdateCollectionParams,\n DeleteCollectionParams,\n SavePropertyParams,\n DeletePropertyParams,\n UpdatePropertiesOrderParams,\n UpdateKanbanColumnsOrderParams,\n} from \"./types/config_controller\";\nimport type { JsonCollectionStore, SerializableCollectionConfig } from \"./serializable_types\";\nimport { toSerializableCollectionConfig, toSerializableProperty, fromSerializableCollectionConfigs } from \"./serializable_utils\";\n\nexport interface UseJsonCollectionsConfigControllerOptions {\n /**\n * The store adapter for persisting/loading collections.\n */\n store: JsonCollectionStore;\n\n /**\n * If true, the configuration cannot be modified.\n */\n readOnly?: boolean;\n\n /**\n * If true, collections will be loaded from the store on mount.\n * Defaults to true.\n */\n autoLoad?: boolean;\n}\n\n/**\n * A `CollectionsConfigController` implementation that persists collection\n * configurations as JSON via a pluggable `JsonCollectionStore` adapter.\n *\n * Use this when you want to store collection schemas in a database, API,\n * localStorage, or any other JSON-compatible backend — as opposed to the\n * default code-based persistence.\n *\n * @example\n * ```tsx\n * const store: JsonCollectionStore = {\n * load: async () => { const res = await fetch('/api/schemas'); return res.json(); },\n * save: async (slug, data) => { await fetch(`/api/schemas/${slug}`, { method: 'PUT', body: JSON.stringify(data) }); },\n * delete: async (slug) => { await fetch(`/api/schemas/${slug}`, { method: 'DELETE' }); },\n * };\n *\n * const configController = useJsonCollectionsConfigController({ store });\n * ```\n */\nexport function useJsonCollectionsConfigController({\n store,\n readOnly = false,\n autoLoad = true,\n}: UseJsonCollectionsConfigControllerOptions): CollectionsConfigController {\n const [collections, setCollections] = useState<AdminCollection[]>([]);\n const [loading, setLoading] = useState(autoLoad);\n const [navigationEntries, setNavigationEntries] = useState<NavigationGroupMapping[]>([]);\n\n // Keep store ref stable to avoid stale closures in callbacks\n const storeRef = useRef(store);\n storeRef.current = store;\n\n /**\n * The current collections, readable outside a state updater.\n *\n * Three mutators used to compute their new value inside\n * `setCollections(prev => …)` and persist from in there, which cost them\n * both halves of a save: the promise they returned resolved before the\n * store had answered, so a failed write reached the caller as a success,\n * and a `setState` updater must be pure — under `StrictMode` React invokes\n * it twice, so every one of those saves wrote to the store twice in\n * development. Reading `prev` from a ref lets them do what\n * `updatePropertiesOrder` already did: compute, set, then await.\n */\n const collectionsRef = useRef<AdminCollection[]>([]);\n const applyCollections = useCallback((next: AdminCollection[]) => {\n collectionsRef.current = next;\n setCollections(next);\n }, []);\n\n // ── Load on mount ─────────────────────────────────────────────────\n useEffect(() => {\n if (!autoLoad) return;\n let cancelled = false;\n\n (async () => {\n try {\n const [serialized, navEntries] = await Promise.all([\n storeRef.current.load(),\n storeRef.current.loadNavigationEntries?.() ?? Promise.resolve([]),\n ]);\n if (cancelled) return;\n // Deserialized as a set: a relation's target is a slug, and a slug only\n // resolves against the other collections it arrived with.\n applyCollections(fromSerializableCollectionConfigs(serialized));\n setNavigationEntries(navEntries);\n } catch (e) {\n console.error(\"useJsonCollectionsConfigController: failed to load collections\", e);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n\n return () => { cancelled = true; };\n // `applyCollections` is `useCallback(…, [])`, so naming it here cannot\n // re-run the mount effect — it is listed because a stable identity is a\n // fact about today's code, not a reason to leave a dependency out.\n }, [autoLoad, applyCollections]);\n\n // ── Helpers ────────────────────────────────────────────────────────\n\n /**\n * Update local state and persist a collection to the store.\n */\n const persistCollection = useCallback(async (collection: AdminCollection) => {\n const serializable = toSerializableCollectionConfig(collection);\n await storeRef.current.save(collection.slug, serializable);\n }, []);\n\n /**\n * Find collection by id (slug).\n */\n const getCollection = useCallback((id: string): AdminCollection => {\n const found = collections.find(c => c.slug === id);\n if (found) return found;\n throw new Error(`Collection \"${id}\" not found`);\n }, [collections]);\n\n // ── CRUD operations ───────────────────────────────────────────────\n\n const saveCollection = useCallback(async <M extends Record<string, unknown>>(\n { id, collectionData }: SaveCollectionParams<M>\n ) => {\n const collection = collectionData as AdminCollection;\n await persistCollection(collection);\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === id);\n if (idx >= 0) {\n const next = [...prev];\n next[idx] = collection;\n applyCollections(next);\n } else {\n applyCollections([...prev, collection]);\n }\n }, [persistCollection, applyCollections]);\n\n const updateCollection = useCallback(async <M extends Record<string, unknown>>(\n { id, collectionData, previousId }: UpdateCollectionParams<M>\n ) => {\n const prev = collectionsRef.current;\n const lookupId = previousId ?? id;\n const idx = prev.findIndex(c => c.slug === lookupId);\n if (idx < 0) return;\n\n const merged = { ...prev[idx], ...collectionData } as AdminCollection;\n const next = [...prev];\n next[idx] = merged;\n applyCollections(next);\n\n await persistCollection(merged);\n\n // If the slug changed, clean up the old entry in the store. After the\n // save, not beside it: dropping the old key first and then failing to\n // write the new one loses the collection outright.\n if (previousId && previousId !== id) {\n await storeRef.current.delete(previousId);\n }\n }, [persistCollection, applyCollections]);\n\n const deleteCollection = useCallback(async ({ id }: DeleteCollectionParams) => {\n await storeRef.current.delete(id);\n applyCollections(collectionsRef.current.filter(c => c.slug !== id));\n }, [applyCollections]);\n\n const saveProperty = useCallback(async ({\n path,\n propertyKey,\n property,\n newPropertiesOrder,\n }: SavePropertyParams) => {\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === path);\n if (idx < 0) return;\n\n const collection = { ...prev[idx] };\n collection.properties = {\n ...collection.properties,\n [propertyKey]: property,\n } as EngineProperties;\n if (newPropertiesOrder) {\n collection.propertiesOrder = newPropertiesOrder as typeof collection.propertiesOrder;\n }\n\n const next = [...prev];\n next[idx] = collection as AdminCollection;\n applyCollections(next);\n\n await persistCollection(next[idx]);\n }, [persistCollection, applyCollections]);\n\n const deleteProperty = useCallback(async ({\n path,\n propertyKey,\n newPropertiesOrder,\n }: DeletePropertyParams) => {\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === path);\n if (idx < 0) return;\n\n const collection = { ...prev[idx] };\n const { [propertyKey]: _removed, ...remaining } = collection.properties;\n collection.properties = remaining;\n if (newPropertiesOrder) {\n collection.propertiesOrder = newPropertiesOrder as typeof collection.propertiesOrder;\n }\n\n const next = [...prev];\n next[idx] = collection as AdminCollection;\n applyCollections(next);\n\n await persistCollection(next[idx]);\n }, [persistCollection, applyCollections]);\n\n const updatePropertiesOrder = useCallback(async ({\n collection,\n newPropertiesOrder,\n }: UpdatePropertiesOrderParams) => {\n const updated = {\n ...collection,\n propertiesOrder: newPropertiesOrder,\n } as AdminCollection;\n\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === collection.slug);\n if (idx >= 0) {\n const next = [...prev];\n next[idx] = updated;\n applyCollections(next);\n }\n\n await persistCollection(updated);\n }, [persistCollection, applyCollections]);\n\n const updateKanbanColumnsOrder = useCallback(async ({\n collection,\n kanbanColumnProperty,\n newColumnsOrder,\n }: UpdateKanbanColumnsOrderParams) => {\n // Kanban column order is stored in the enum order of the column property.\n // For JSON persistence, we store it as-is — the view layer reads enum order.\n // This is a no-op for now; the kanban order is determined by the enum\n // definition on the property itself.\n }, []);\n\n const saveNavigationEntriesHandler = useCallback(async (entries: NavigationGroupMapping[]) => {\n setNavigationEntries(entries);\n if (storeRef.current.saveNavigationEntries) {\n await storeRef.current.saveNavigationEntries(entries);\n }\n }, []);\n\n // ── Return controller ─────────────────────────────────────────────\n return useMemo<CollectionsConfigController>(() => ({\n loading,\n readOnly,\n readOnlyReason: readOnly ? \"Configuration is read-only.\" : undefined,\n collections,\n getCollection,\n saveCollection,\n updateCollection,\n deleteCollection,\n saveProperty,\n deleteProperty,\n updatePropertiesOrder,\n updateKanbanColumnsOrder,\n navigationEntries,\n saveNavigationEntries: saveNavigationEntriesHandler,\n }), [\n loading,\n readOnly,\n collections,\n getCollection,\n saveCollection,\n updateCollection,\n deleteCollection,\n saveProperty,\n deleteProperty,\n updatePropertiesOrder,\n updateKanbanColumnsOrder,\n navigationEntries,\n saveNavigationEntriesHandler,\n ]);\n}\n","import { useCollectionRegistryController } from \"../_cms_internals\";\nimport { ErrorView, useTranslation } from \"@rebasepro/app\";\nimport { useCollectionEditorController } from \"../useCollectionEditorController\";\nimport { Button } from \"@rebasepro/ui\";\nimport { prettifyIdentifier } from \"@rebasepro/utils\";\nimport { getLastSegment } from \"@rebasepro/app\";\n\nexport function MissingReferenceWidget({ path: pathProp }: {\n path: string\n}) {\n const registry = useCollectionRegistryController();\n const path = getLastSegment(pathProp);\n const parentCollectionSlugs = registry.getParentCollectionSlugs(pathProp);\n const parentEntityIds = registry.getParentEntityIds(pathProp);\n const collectionEditor = useCollectionEditorController();\n const { t } = useTranslation();\n return <div className={\"p-1 flex flex-col items-center\"}>\n <ErrorView error={t(\"studio_missing_reference_error\", { path })}/>\n <Button className={\"mx-2\"}\n size={\"small\"}\n onClick={() => {\n collectionEditor.createCollection({\n initialValues: { path,\nname: prettifyIdentifier(path) },\n parentCollectionSlugs,\nparentEntityIds,\n redirect: false,\n sourceClick: \"missing_reference\"\n });\n }}>\n {t(\"studio_missing_reference_create\")}\n </Button>\n </div>;\n}\n\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/routes/CustomViewRoute.tsx","../src/routes/RebaseRoute.tsx","../src/components/ReferenceWidget.tsx","../src/hooks/useBuildSideDialogsController.tsx","../src/components/SidePanelProvider.tsx","../src/components/AdminModeSyncer.tsx","../src/components/app/useApp.tsx","../src/components/DefaultAppBar.tsx","../src/components/app/AppBar.tsx","../src/components/DrawerNavigationItem.tsx","../src/components/DrawerNavigationGroup.tsx","../src/components/DefaultDrawer.tsx","../src/components/app/Drawer.tsx","../src/components/app/Scaffold.tsx","../src/components/RebaseAdmin.tsx","../src/components/RebaseAuthGate.tsx","../src/collection_editor/useLocalCollectionsConfigController.tsx","../src/components/RebaseNavigation.tsx","../src/components/RebaseLayout.tsx","../src/components/HomePage/FavouritesView.tsx","../src/components/HomePage/NavigationGroup.tsx","../src/components/HomePage/NavigationCard.tsx","../src/components/HomePage/NavigationCardBinding.tsx","../src/components/HomePage/HomePageDnD.tsx","../src/components/HomePage/RenameGroupDialog.tsx","../src/components/HomePage/ContentHomePage.tsx","../src/components/CollectionEditorDialogs.tsx","../src/components/RebaseRouteDefs.tsx","../src/components/RebaseShell.tsx","../src/components/CollectionPanel.tsx","../src/util/propertyConfigMapper.ts","../src/util/dataControllerAdapter.ts","../src/collection_editor/useJsonCollectionsConfigController.tsx","../src/collection_editor/ui/MissingReferenceWidget.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport type { AppView } from \"@rebasepro/admin-types\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\n\nexport function CustomViewRoute({ view }: {\n view: AppView\n}) {\n\n const breadcrumbs = useBreadcrumbsController();\n const urlController = useUrlController();\n\n // Use a ref to avoid breadcrumbs identity in the dep array —\n // breadcrumbs.set() creates a new context value each call, which would\n // re-trigger this effect and cause an infinite render loop.\n const breadcrumbsRef = useRef(breadcrumbs);\n breadcrumbsRef.current = breadcrumbs;\n\n useEffect(() => {\n breadcrumbsRef.current.set({\n breadcrumbs: [{\n title: view.name,\n url: urlController.buildAppUrlPath(view.slug)\n }]\n });\n }, [view.slug, urlController]);\n\n if (typeof view.view === 'function') {\n const ViewComponent = view.view;\n return <ViewComponent />;\n }\n return <>{view.view}</>;\n}\n","\nimport type { ViewMode, AdminCollection } from \"@rebasepro/admin-types\";\nimport { useLocation } from \"react-router\";\nimport { EditViewBinding } from \"../components/EditViewBinding\";\nimport { DetailViewBinding } from \"../components/DetailViewBinding\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { useNavigate } from \"react-router\";\nimport { CollectionViewBinding } from \"../components/CollectionViewBinding/CollectionViewBinding\";\nimport { ErrorView, NotFoundPage, useUserConfigurationPersistence, useComponentOverride, useNavigationBlocker } from \"@rebasepro/app\";\nimport { resolveOpenEntityMode, resolveViewMode } from \"../util/view_mode\";\nimport { UnsavedChangesDialog } from \"@rebasepro/app\";\nimport { CenteredView, CircularProgressCenter } from \"@rebasepro/ui\";\nimport { NavigationViewCollectionInternal, NavigationViewEntityCustomInternal, NavigationViewInternal } from \"@rebasepro/app\";\nimport { getNavigationEntriesFromPath } from \"@rebasepro/app\";\nimport { toArray } from \"@rebasepro/utils\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\n\nexport function RebaseRoute() {\n\n const location = useLocation();\n const collectionRegistry = useCollectionRegistryController();\n const urlController = useUrlController();\n const breadcrumbs = useBreadcrumbsController();\n const userConfigPersistence = useUserConfigurationPersistence();\n const ResolvedCollectionView = useComponentOverride(\"Collection.View\", CollectionViewBinding);\n\n const hash = location.hash;\n const isSidePanel = hash.includes(\"#side\");\n const isNew = hash.includes(\"#new\") || hash.includes(\"#new_side\");\n const isCopy = hash.includes(\"#copy\");\n const isFullScreen = hash.includes(\"#full\");\n\n const pathname = location.pathname;\n const navigationPath = urlController.urlPathToDataPath(pathname);\n\n const navigationEntries = getNavigationEntriesFromPath({\n path: navigationPath,\n collections: collectionRegistry.collections ?? []\n });\n\n useEffect(() => {\n breadcrumbs.set({\n breadcrumbs: navigationEntries.map((entry) => {\n\n if (entry.type === \"entity\") {\n return ({\n title: String(entry.entityId),\n url: urlController.buildUrlCollectionPath(entry.path)\n });\n } else if (entry.type === \"custom_view\") {\n return ({\n title: String(entry.view.name ?? entry.view.key),\n url: urlController.buildUrlCollectionPath(entry.path)\n });\n } else if (entry.type === \"collection\") {\n return ({\n title: entry.collection.name,\n url: urlController.buildUrlCollectionPath(entry.path),\n id: entry.path\n });\n } else {\n throw new Error(\"Unexpected navigation entry type\");\n }\n })\n });\n }, [navigationEntries.map(entry => entry.path).join(\",\")]);\n\n if (isNew) {\n // New entities always use full-screen mode, even for split-layout collections\n return <EntityFullScreenRoute\n pathname={pathname}\n navigationEntries={navigationEntries}\n isNew={true}\n isCopy={false}\n />;\n }\n\n if (navigationEntries.length === 1 && navigationEntries[0].type === \"collection\") {\n let collection: AdminCollection<any> | undefined;\n collection = collectionRegistry.getCollection(navigationEntries[0].id);\n if (!collection)\n collection = collectionRegistry.getCollection(navigationEntries[0].slug);\n if (!collection) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n return <UnresolvedCollectionView path={navigationEntries[0].slug}/>;\n }\n return <ResolvedCollectionView\n key={`collection_view_${collection.slug}`}\n {...collection}\n parentCollectionSlugs={[]} parentEntityIds={[]}\n path={collection.slug}\n updateUrl={true}\n Actions={toArray(collection.Actions)}/>\n }\n\n if (isSidePanel) {\n const lastCollectionEntry = [...navigationEntries].reverse().find((entry) => entry.type === \"collection\");\n if (lastCollectionEntry) {\n let collection: AdminCollection<any> | undefined;\n const firstEntry = navigationEntries[0] as NavigationViewCollectionInternal<any>;\n collection = collectionRegistry.getCollection(firstEntry.id);\n if (!collection)\n collection = collectionRegistry.getCollection(firstEntry.slug);\n if (!collection) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n return <UnresolvedCollectionView path={firstEntry.slug}/>;\n }\n return <ResolvedCollectionView\n key={`collection_view_${collection.slug}`}\n {...collection}\n parentCollectionSlugs={[]} parentEntityIds={[]}\n path={collection.slug}\n updateUrl={true}\n Actions={toArray(collection.Actions)}/>;\n }\n }\n\n // Check if this is a simple entity route (collection + entity) for a split-layout collection.\n // If so, render the collection view with the entity shown in the split detail panel\n // instead of the full-screen editor. This keeps the master-detail UX with clean URLs.\n //\n // Also handles subcollection tabs: /c/customers/39/orders produces 3 entries\n // (collection→entity→subcollection). We extract the subcollection slug as selectedTab.\n const lastEntityEntry = navigationEntries.find((entry) => entry.type === \"entity\");\n const firstCollectionEntry = navigationEntries[0];\n if (\n !isFullScreen &&\n !isCopy &&\n firstCollectionEntry?.type === \"collection\" &&\n lastEntityEntry?.type === \"entity\" &&\n (navigationEntries.length === 2 || navigationEntries.length === 3)\n ) {\n let collection: AdminCollection<any> | undefined;\n collection = collectionRegistry.getCollection(firstCollectionEntry.id);\n if (!collection)\n collection = collectionRegistry.getCollection(firstCollectionEntry.slug);\n\n const effectiveOpenMode = collection\n ? resolveOpenEntityMode({\n collection,\n viewMode: resolveViewMode({\n collection,\n search: location.search,\n savedViewMode: userConfigPersistence?.getCollectionConfig(collection.slug)?.defaultViewMode as ViewMode | undefined\n })\n })\n : undefined;\n if (collection && effectiveOpenMode === \"split\") {\n // Extract subcollection tab from the 3rd entry if present\n let selectedTab: string | undefined;\n if (navigationEntries.length === 3) {\n const thirdEntry = navigationEntries[2];\n if (thirdEntry.type === \"collection\") {\n selectedTab = thirdEntry.collection.slug;\n } else if (thirdEntry.type === \"custom_view\") {\n selectedTab = thirdEntry.view.key;\n }\n }\n // Fallback: check for unregistered tabs (e.g. __json, __rebase_history)\n // that aren't parsed as navigation entries\n if (!selectedTab && (navigationEntries.length === 2) && lastEntityEntry) {\n const entityIdStr = String(lastEntityEntry.entityId);\n const entityIdIdx = pathname.lastIndexOf(`/${entityIdStr}`);\n if (entityIdIdx >= 0) {\n const afterEntity = pathname.substring(entityIdIdx + 1 + entityIdStr.length);\n const trailingSegment = afterEntity.startsWith(\"/\") ? afterEntity.substring(1) : afterEntity;\n if (trailingSegment.length > 0) {\n selectedTab = trailingSegment;\n }\n }\n }\n return <ResolvedCollectionView\n key={`collection_view_${collection.slug}`}\n {...collection}\n parentCollectionSlugs={[]} parentEntityIds={[]}\n path={collection.slug}\n updateUrl={true}\n selectedEntityId={lastEntityEntry.entityId}\n selectedTab={selectedTab}\n Actions={toArray(collection.Actions)}/>;\n }\n }\n\n return <EntityFullScreenRoute\n pathname={pathname}\n navigationEntries={navigationEntries}\n isNew={isNew}\n isCopy={isCopy}\n />;\n\n}\n\nfunction getSelectedTabFromUrl(isNew: boolean, lastCustomView: NavigationViewCollectionInternal<any> | NavigationViewEntityCustomInternal<any> | undefined) {\n if (isNew) {\n return undefined;\n } else if (lastCustomView) {\n if (lastCustomView.type === \"custom_view\") {\n return lastCustomView.view.key;\n } else if (lastCustomView.type === \"collection\") {\n return lastCustomView.id ?? lastCustomView.slug;\n }\n }\n return undefined;\n}\n\nfunction EntityFullScreenRoute({\n pathname,\n navigationEntries,\n isNew,\n isCopy\n}: {\n pathname: string;\n navigationEntries: NavigationViewInternal[],\n isNew: boolean,\n isCopy: boolean\n}) {\n\n const collectionRegistry = useCollectionRegistryController();\n const urlController = useUrlController();\n const navigate = useNavigate();\n const location = useLocation();\n const userConfigPersistence = useUserConfigurationPersistence();\n\n // defaultValues may be carried via location.state when openNewDocument() is called\n // for full-screen mode. We read it once on mount — after that, the form owns its state.\n const defaultValues = (location.state as { defaultValues?: Record<string, unknown> } | null)?.defaultValues;\n\n // Preserve the current hash (e.g. #full) across tab/save navigations\n const hash = location.hash;\n\n const navigationPath = urlController.urlPathToDataPath(pathname);\n\n // is navigating away blocked\n const blocked = useRef(false);\n\n const lastEntityEntry = [...navigationEntries].reverse().find((entry) => entry.type === \"entity\");\n const navigationEntriesAfterEntity = lastEntityEntry ? navigationEntries.slice(navigationEntries.indexOf(lastEntityEntry) + 1) : [];\n\n const lastCustomView = [...navigationEntriesAfterEntity].reverse().find(\n (entry) => entry.type === \"custom_view\" || entry.type === \"collection\"\n ) as NavigationViewCollectionInternal<any> | NavigationViewEntityCustomInternal<any> | undefined;\n\n const entityId = lastEntityEntry && \"entityId\" in lastEntityEntry ? lastEntityEntry.entityId : undefined;\n\n // Derive tab from navigation entries (works for registered custom views)\n let urlTab = getSelectedTabFromUrl(isNew, lastCustomView);\n\n // Fallback: internal tabs like __json or __rebase_history aren't registered as\n // entity views, so the navigation parser ignores them. Check the raw pathname\n // for a trailing segment after the entity ID to catch those cases.\n if (!urlTab && entityId && !isNew) {\n const entityIdStr = String(entityId);\n const entityIdIdx = pathname.lastIndexOf(`/${entityIdStr}`);\n if (entityIdIdx >= 0) {\n const afterEntity = pathname.substring(entityIdIdx + 1 + entityIdStr.length);\n const trailingSegment = afterEntity.startsWith(\"/\") ? afterEntity.substring(1) : afterEntity;\n if (trailingSegment.length > 0 && trailingSegment !== \"edit\") {\n urlTab = trailingSegment;\n }\n }\n }\n\n const [selectedTab, setSelectedTab] = useState<string | undefined>(urlTab);\n\n const parentCollectionSlugs = collectionRegistry.getParentCollectionSlugs(navigationPath);\n const parentEntityIds = collectionRegistry.getParentEntityIds(navigationPath);\n useEffect(() => {\n if (urlTab !== selectedTab) {\n setSelectedTab(urlTab);\n }\n }, [urlTab]);\n\n const basePath = !entityId || isNew\n ? pathname\n : pathname.substring(0, pathname.lastIndexOf(`/${entityId}`));\n\n const entityPath = basePath + `/${entityId}`;\n\n const blocker = useNavigationBlocker(useCallback(({\n currentLocation,\n nextLocation\n }) => {\n if (nextLocation.pathname.startsWith(entityPath))\n return false;\n\n // Side panel overlay navigations preserve the underlying form via\n // base_location in router state — no data is lost in either direction.\n\n // Opening a side panel (e.g. clicking a relation arrow)\n const nextHash = nextLocation.hash;\n if (nextHash === \"#side\" || nextHash === \"#new_side\")\n return false;\n\n // Closing a side panel (navigate(-1) back to the form's own path)\n const currentHash = currentLocation.hash;\n if ((currentHash === \"#side\" || currentHash === \"#new_side\") &&\n (nextLocation.pathname === basePath ||\n nextLocation.pathname.startsWith(entityPath)))\n return false;\n\n return blocked.current;\n }, [entityPath, basePath]));\n\n const lastCollectionEntry = [...navigationEntries].reverse().find((entry) => entry.type === \"collection\");\n\n if (isNew && !lastCollectionEntry) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n throw new Error(\"INTERNAL: No collection found in the navigation\");\n }\n\n if (!isNew && !lastEntityEntry) {\n if (!collectionRegistry.initialised) {\n return <CircularProgressCenter/>;\n }\n return <NotFoundPage/>;\n }\n\n const rawCollection = isNew\n ? (lastCollectionEntry && \"collection\" in lastCollectionEntry ? lastCollectionEntry.collection : undefined)!\n : (lastEntityEntry && \"parentCollection\" in lastEntityEntry ? lastEntityEntry.parentCollection : undefined)!;\n const collection = collectionRegistry.getCollection(rawCollection.slug) || rawCollection;\n const fullIdPath = isNew ? lastCollectionEntry!.slug : lastEntityEntry!.slug;\n const collectionPath = urlController.resolveDatabasePathsFrom(fullIdPath);\n const isEditRoute = pathname.endsWith(\"/edit\") || pathname.split(\"/\").pop() === \"edit\";\n // Determine if this is a detail-view-first collection showing the view page\n const isDetailMode = collection.defaultEntityAction === \"view\" && !isNew && !isCopy && entityId && !isEditRoute;\n\n // A record is full screen either because its collection has no list to show\n // beside it, or because the user folded that list away. Only the second is\n // reversible, and it is reversible by dropping `#full` alone: this is the\n // same URL the split route reads, so the same conditions decide it.\n const splitListAvailable = !isNew && !isCopy && entityId !== undefined &&\n navigationEntries[0]?.type === \"collection\" &&\n (navigationEntries.length === 2 || navigationEntries.length === 3) &&\n resolveOpenEntityMode({\n collection,\n viewMode: resolveViewMode({\n collection,\n search: location.search,\n savedViewMode: userConfigPersistence?.getCollectionConfig(collection.slug)?.defaultViewMode as ViewMode | undefined\n })\n }) === \"split\";\n\n const showList = splitListAvailable\n ? () => navigate({\n pathname,\n search: location.search,\n hash: \"\"\n })\n : undefined;\n\n if (isDetailMode) {\n return <>\n <DetailViewBinding\n key={collection.slug + \"_view_\" + entityId}\n entityId={entityId}\n collection={collection}\n layout={\"full_screen\"}\n path={collectionPath}\n selectedTab={selectedTab ?? undefined}\n onShowList={showList}\n onEditClick={() => {\n const editUrl = urlController.buildUrlCollectionPath(`${collectionPath}/${entityId}`) + \"/edit\";\n navigate(editUrl + hash);\n }}\n onTabChange={(params) => {\n setSelectedTab(params.selectedTab);\n const newSelectedTab = params.selectedTab;\n if (newSelectedTab) {\n navigate(`${basePath}/${entityId}/${newSelectedTab}${hash}`, { replace: true });\n } else {\n navigate(`${basePath}/${entityId}${hash}`, { replace: true });\n }\n }}\n parentCollectionSlugs={parentCollectionSlugs}\n parentEntityIds={parentEntityIds}\n />\n </>;\n }\n\n return <>\n <EditViewBinding\n key={collection.slug + \"_\" + (isNew ? \"new\" : (isCopy ? entityId + \"_copy\" : entityId))}\n entityId={isNew ? undefined : entityId}\n collection={collection}\n layout={\"full_screen\"}\n path={collectionPath}\n copy={isCopy}\n selectedTab={selectedTab ?? undefined}\n onShowList={showList}\n defaultValues={isNew ? defaultValues : undefined}\n onValuesModified={(modified) => blocked.current = modified}\n navigateBack={() => {\n const detailUrl = urlController.buildUrlCollectionPath(`${collectionPath}/${entityId}`);\n navigate(detailUrl + hash);\n }}\n onSaved={(params) => {\n const newSelectedTab = params.selectedTab;\n const newEntityId = params.entityId;\n const savedHash = isNew ? \"\" : hash;\n if (newSelectedTab) {\n navigate(`${basePath}/${newEntityId}/${newSelectedTab}${savedHash}`, { replace: true });\n } else {\n navigate(`${basePath}/${newEntityId}${savedHash}`, { replace: true });\n }\n }}\n onTabChange={(params) => {\n setSelectedTab(params.selectedTab);\n if (isNew) {\n return;\n }\n const newSelectedTab = params.selectedTab;\n if (newSelectedTab) {\n navigate(`${basePath}/${entityId}/${newSelectedTab}${hash}`, { replace: true });\n } else {\n navigate(`${basePath}/${entityId}${hash}`, { replace: true });\n }\n }}\n parentCollectionSlugs={parentCollectionSlugs} parentEntityIds={parentEntityIds}\n />\n\n <UnsavedChangesDialog\n open={blocker?.state === \"blocked\"}\n handleOk={() => blocker?.proceed?.()}\n handleCancel={() => blocker?.reset?.()}\n body={\"You have unsaved changes in this entity.\"}/>\n </>;\n}\n\n/**\n * Shown when a URL names a collection the registry cannot resolve.\n *\n * This used to be `return null`, which renders an empty pane inside the app\n * chrome: the sidebar, the nav highlight and the breadcrumb all still work,\n * because those read the collections array directly, while the view itself is\n * blank. Nothing is thrown, and the only trace is a `console.debug` — so the\n * panel looks like it lost its data rather than like it failed to find the\n * collection, and there is no string to search for.\n *\n * A slug containing slashes went unresolvable this way and cost an afternoon to\n * find. The lookup is fixed; this is the part that made it expensive.\n */\nfunction UnresolvedCollectionView({ path }: { path: string }) {\n // Warn, not debug: this is a route that renders nothing useful, and it\n // should be visible at the console's default level.\n useEffect(() => {\n console.warn(\n `[rebase] No collection is registered for \"${path}\", so this route has nothing to render. ` +\n \"Check that the collection is in the collections array and that its slug matches the URL.\"\n );\n }, [path]);\n\n return <CenteredView>\n <ErrorView\n title={\"Collection not found\"}\n error={`Nothing is registered for \"${path}\".`}\n tooltip={\"The URL names a collection the panel does not know about. It may have been renamed or removed from the collections array, or the slug may not match the path.\"}/>\n </CenteredView>;\n}\n","import { useSelectionDialog } from \"../hooks/useSelectionDialog\";\n\nimport React, { useCallback, useMemo } from \"react\";\n\nimport { Entity, EntityReference, FilterValues } from \"@rebasepro/types\";\nimport type { PreviewSize } from \"../types/components/PropertyPreviewProps\";\nimport { getReferenceFrom } from \"@rebasepro/common\";\nimport { ReferencePreview } from \"../preview\";\nimport { Button, cls } from \"@rebasepro/ui\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport type ReferenceWidgetProps<M extends Record<string, unknown>> = {\n name?: string,\n multiselect?: boolean,\n value: EntityReference | EntityReference[] | null,\n onReferenceSelected?: (params: {\n reference: EntityReference | null,\n entity: Entity<M> | null\n }) => void,\n onMultipleReferenceSelected?: (params: {\n references: EntityReference[] | null,\n entities: Entity<M>[] | null\n }) => void,\n path: string,\n disabled?: boolean,\n previewProperties?: string[];\n /**\n * Allow selection of entities that pass the given filter only.\n */\n fixedFilter?: FilterValues<string>;\n size: PreviewSize;\n className?: string;\n includeId?: boolean;\n includeEntityLink?: boolean;\n};\n\n/**\n * This field allows selecting reference/s.\n */\nexport function ReferenceWidget<M extends Record<string, unknown>>({\n name,\n multiselect = false,\n path,\n disabled,\n value,\n onReferenceSelected,\n onMultipleReferenceSelected,\n previewProperties,\n fixedFilter,\n size,\n className,\n includeId,\n includeEntityLink\n}: ReferenceWidgetProps<M>) {\n\n const collectionRegistryController = useCollectionRegistryController();\n\n const collection: AdminCollection | undefined = useMemo(() => {\n return collectionRegistryController.getCollection(path);\n }, [path, collectionRegistryController.getCollection]);\n\n const onSingleEntitySelected = useCallback((entity: Entity<M> | null) => {\n if (disabled)\n return;\n if (onReferenceSelected) {\n const reference = entity ? getReferenceFrom(entity) : null;\n onReferenceSelected?.({\n reference,\n entity\n });\n }\n }, [disabled, onReferenceSelected]);\n\n const onMultipleEntitiesSelected = useCallback((entities: Entity<M>[]) => {\n if (disabled)\n return;\n if (onMultipleReferenceSelected) {\n const references = entities ? entities.map(e => getReferenceFrom(e)) : null;\n onMultipleReferenceSelected({\n references,\n entities\n });\n }\n }, [disabled, onReferenceSelected]);\n\n const referenceDialogController = useSelectionDialog({\n multiselect,\n path,\n collection,\n onSingleEntitySelected,\n onMultipleEntitiesSelected,\n fixedFilter\n }\n );\n\n const clearValue = useCallback((e: React.MouseEvent) => {\n e.stopPropagation();\n if (multiselect) {\n onMultipleEntitiesSelected([]);\n } else {\n onSingleEntitySelected(null);\n }\n }, [onReferenceSelected]);\n\n let child: React.ReactNode;\n\n const onEntryClick = () => {\n if (disabled)\n return;\n referenceDialogController.open();\n };\n\n if (Array.isArray(value)) {\n child = <div className={\"flex flex-col gap-4\"}>\n {value.map((ref, index) => {\n return <ReferencePreview\n key={`reference_preview_${index}`}\n onClick={onEntryClick}\n reference={ref}\n disabled={disabled}\n previewProperties={previewProperties}\n size={size}\n includeId={includeId}\n includeEntityLink={includeEntityLink}/>\n })}\n </div>\n } else if (value?.isEntityReference && value?.isEntityReference()) {\n child = <ReferencePreview\n reference={value}\n onClick={onEntryClick}\n disabled={disabled}\n previewProperties={previewProperties}\n size={size}\n includeId={includeId}\n includeEntityLink={includeEntityLink}/>\n\n }\n return <div className={cls(\"text-sm font-medium\",\n \"min-w-80 flex flex-col gap-4\",\n \"relative transition-colors duration-200 ease-in rounded-xs font-medium\",\n disabled ? \"bg-opacity-50\" : \"hover:bg-opacity-75\",\n \"dark:text-white/50 text-text-primary/50 dark:text-text-primary-dark/50 dark:text-white/50\",\n className\n )}>\n\n {child}\n {!value && <div className=\"justify-center text-left\">\n <Button disabled={disabled}\n onClick={onEntryClick}>\n Edit {name}\n </Button>\n </div>}\n\n </div>;\n}\n","import type { SideDialogPanelProps, SideDialogsController } from \"../hooks/useSideDialogsController\";\nimport { useCallback, useEffect, useRef, useState, useMemo } from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\n;\nimport { deepEqual as equal } from \"fast-equals\"\nimport { Location } from \"react-router\";\n\ninterface SideDialogLocationState {\n base_location?: Location;\n panels?: string[];\n}\n\nexport function useBuildSideDialogsController(): SideDialogsController {\n\n const location = useLocation();\n const navigate = useNavigate();\n\n const locationRef = useRef(location);\n locationRef.current = location;\n\n const [sidePanels, setSidePanels] = useState<SideDialogPanelProps[]>([]);\n const sidePanelsRef = useRef<SideDialogPanelProps[]>(sidePanels);\n\n const routesStore = useRef<Record<string, SideDialogPanelProps>>({});\n const routesCount = useRef<number>(0);\n\n const updateSidePanels = useCallback((newPanels: SideDialogPanelProps[]) => {\n sidePanelsRef.current = newPanels;\n setSidePanels(newPanels);\n }, []);\n\n useEffect(() => {\n const state = location.state as SideDialogLocationState | null;\n const panelKeys: string[] = state?.panels ?? [];\n const newPanels = panelKeys\n .map(key => routesStore.current[key])\n .filter(p => Boolean(p)) as SideDialogPanelProps[];\n if (!equal(sidePanelsRef.current.map(p => p.key), newPanels.map(p => p.key))) {\n updateSidePanels(newPanels);\n // If all panels were cleared via explicit navigation (full-screen expand),\n // reset routesCount so close() doesn't fire navigate(-1)\n if (newPanels.length === 0) {\n routesCount.current = 0;\n }\n }\n }, [location]);\n\n const close = useCallback(() => {\n\n const currentPanels = sidePanelsRef.current;\n if (currentPanels.length === 0)\n return;\n\n const lastSidePanel = currentPanels[currentPanels.length - 1];\n const updatedPanels = [...currentPanels.slice(0, -1)];\n updateSidePanels(updatedPanels);\n\n if (routesCount.current > 0) {\n if (lastSidePanel.urlPath) // if it has a url path, we need to navigate back, don't remove this code\n navigate(-1);\n routesCount.current--;\n } else if (lastSidePanel.parentUrlPath) {\n const baseLocation = (locationRef.current.state as SideDialogLocationState | null)?.base_location ?? locationRef.current;\n navigate(\n lastSidePanel.parentUrlPath,\n {\n replace: true,\n state: {\n base_location: baseLocation,\n panels: updatedPanels.map(p => p.key)\n }\n }\n );\n }\n }, [navigate]);\n\n const open = useCallback((panelProps: SideDialogPanelProps | SideDialogPanelProps[]) => {\n\n const newPanels: SideDialogPanelProps[] = Array.isArray(panelProps) ? panelProps : [panelProps];\n\n newPanels.forEach((panel) => {\n routesStore.current[panel.key] = panel;\n });\n routesCount.current = routesCount.current + newPanels.length;\n\n const baseLocation = (locationRef.current.state as SideDialogLocationState | null)?.base_location ?? locationRef.current;\n\n const currentPanels = sidePanelsRef.current;\n const updatedPanels = [...currentPanels, ...newPanels];\n updateSidePanels(updatedPanels);\n\n newPanels.forEach((panel) => {\n if (panel.urlPath) {\n navigate(\n panel.urlPath,\n {\n state: {\n base_location: baseLocation,\n panels: updatedPanels.map(p => p.key)\n }\n }\n );\n }\n });\n\n }, [navigate]);\n\n const replace = useCallback((panelProps: SideDialogPanelProps | SideDialogPanelProps[]) => {\n\n const newPanels: SideDialogPanelProps[] = Array.isArray(panelProps) ? panelProps : [panelProps];\n newPanels.forEach((panel) => {\n routesStore.current[panel.key] = panel;\n });\n\n const baseLocation = (locationRef.current.state as SideDialogLocationState | null)?.base_location ?? locationRef.current;\n\n const currentPanels = sidePanelsRef.current;\n const updatedPanels = [...currentPanels.slice(0, -newPanels.length), ...newPanels];\n updateSidePanels(updatedPanels);\n\n newPanels.forEach((panel) => {\n if (panel.urlPath) {\n navigate(\n panel.urlPath,\n {\n replace: true,\n state: {\n base_location: baseLocation,\n panels: updatedPanels.map(p => p.key)\n }\n }\n );\n }\n });\n\n }, [navigate]);\n\n return useMemo(() => ({\n sidePanels,\n setSidePanels: updateSidePanels,\n close,\n open,\n replace\n }), [sidePanels, updateSidePanels, close, open, replace]);\n}\n","import type { SidePanelController } from \"@rebasepro/admin-types\";\nimport React from \"react\";\nimport { useBuildSidePanel } from \"../hooks/useBuildSidePanel\";\nimport { useBuildSideDialogsController } from \"../hooks/useBuildSideDialogsController\";\nimport { SidePanelControllerContext } from \"../hooks/useSidePanel\";\nimport { SideDialogsControllerContext } from \"../contexts/SideDialogsControllerContext\";\nimport { BreadcrumbsProvider } from \"../contexts/BreacrumbsContext\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useNavigationStateController } from \"../hooks/navigation/contexts/NavigationStateContext\";\nimport { useAuthController, useBridgeRegistration, NavigationBlockerProvider } from \"@rebasepro/app\";\n\n/**\n * Provider that builds the SidePanelController and makes it available\n * via the SidePanelControllerContext from @rebasepro/app.\n *\n * After the admin extraction refactor, `useBuildSidePanel` lives\n * in the admin package while the context it feeds into lives in core.\n * This provider bridges the two: place it inside the `<Rebase>` tree and\n * above any component that calls `useSidePanel()`.\n *\n * Also auto-registers the side entity controller and breadcrumbs into the\n * self-assembling Studio bridge (when a StudioBridgeRegistryProvider is\n * mounted above in the tree).\n *\n * @example\n * ```tsx\n * <Rebase ...>\n * {({ loading }) => (\n * <SidePanelProvider>\n * <RebaseRoutes>\n * ...\n * </RebaseRoutes>\n * </SidePanelProvider>\n * )}\n * </Rebase>\n * ```\n *\n * @group Components\n */\nexport function SidePanelProvider({ children }: { children: React.ReactNode }) {\n const collectionRegistryController = useCollectionRegistryController();\n const urlController = useUrlController();\n const navigationStateController = useNavigationStateController();\n const sideDialogsController = useBuildSideDialogsController();\n const authController = useAuthController();\n\n const sidePanelController = useBuildSidePanel(\n collectionRegistryController,\n urlController,\n navigationStateController,\n sideDialogsController,\n authController\n );\n\n return (\n <NavigationBlockerProvider>\n <BreadcrumbsProvider>\n <SideDialogsControllerContext.Provider value={sideDialogsController}>\n <SidePanelControllerContext.Provider value={sidePanelController}>\n <BridgeAutoRegistrar sidePanelController={sidePanelController}/>\n {children}\n </SidePanelControllerContext.Provider>\n </SideDialogsControllerContext.Provider>\n </BreadcrumbsProvider>\n </NavigationBlockerProvider>\n );\n}\n\n/**\n * Internal component that auto-registers side entity and breadcrumbs\n * into the Studio bridge. Must be a child of BreadcrumbsProvider.\n */\nfunction BridgeAutoRegistrar({ sidePanelController }: { sidePanelController: SidePanelController }) {\n const breadcrumbs = useBreadcrumbsController();\n useBridgeRegistration(\"sidePanelController\", sidePanelController);\n useBridgeRegistration(\"breadcrumbs\", breadcrumbs);\n return null;\n}\n","import type { AppView } from \"@rebasepro/admin-types\";\nimport React, { useEffect } from \"react\";\nimport { useLocation } from \"react-router\";\n;\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useAdminModeController } from \"@rebasepro/app\";\nexport interface AdminModeSyncerProps {\n /**\n * Map of views designated as 'Studio' views.\n * Navigating to any of these views will automatically flag the admin mode as \"studio\".\n */\n devViews?: AppView[];\n}\n\n/**\n * A highly customizable utility component that observes react-router routes and\n * actively shifts the internal Rebase `adminModeController` context to match\n * the user's active window segment (e.g., Content vs Studio mode).\n *\n * Placing this anywhere safely inside the Rebase layout automatically triggers\n * UI mode synchronization.\n */\nexport function AdminModeSyncer({ devViews }: AdminModeSyncerProps) {\n const location = useLocation();\n const urlController = useUrlController();\n const adminModeController = useAdminModeController();\n\n // Keep track of the current mode using a ref to avoid adding it to the dependency array\n const currentModeRef = React.useRef(adminModeController.mode);\n currentModeRef.current = adminModeController.mode;\n\n // Stable ref for setMode so it doesn't trigger the effect\n const setModeRef = React.useRef(adminModeController.setMode);\n setModeRef.current = adminModeController.setMode;\n\n useEffect(() => {\n const path = location.pathname;\n const isContentRoute = urlController.isUrlCollectionPath(path) || path === urlController.basePath;\n\n // Check both devViews slugs AND the studio home path (/s or basePath/s)\n const studioHomePath = urlController.basePath === \"/\" ? \"/s\" : `${urlController.basePath}/s`;\n const isStudioRoute = path === studioHomePath || path.startsWith(studioHomePath + \"/\") || devViews?.some(view => {\n const viewPath = urlController.buildAppUrlPath(view.slug);\n return path.startsWith(`${viewPath}/`) || path === viewPath;\n });\n\n if (isStudioRoute && currentModeRef.current !== \"studio\") {\n setModeRef.current(\"studio\");\n } else if (isContentRoute && currentModeRef.current !== \"content\") {\n setModeRef.current(\"content\");\n }\n }, [location.pathname, urlController, devViews]);\n\n return null;\n}\n\n","import React from \"react\";\n\n/**\n * This context represents the state of the app in terms of layout.\n * @group Core\n */\nexport type AppState = {\n hasDrawer: boolean,\n drawerHovered: boolean,\n drawerOpen: boolean,\n openDrawer: () => void,\n closeDrawer: () => void,\n closeHover: () => void,\n autoOpenDrawer?: boolean,\n logo?: string\n}\n\nexport const AppContext = React.createContext<AppState>({\n hasDrawer: false,\n drawerHovered: false,\n drawerOpen: false,\n openDrawer: () => {\n throw new Error(\"openDrawer not implemented\");\n },\n closeDrawer: () => {\n throw new Error(\"closeDrawer not implemented\");\n },\n closeHover: () => {\n throw new Error(\"closeHover not implemented\");\n },\n autoOpenDrawer: false\n});\n\nexport function useApp() {\n return React.useContext(AppContext);\n}\n","\nimport React from \"react\";\n\nimport { Link, useNavigate } from \"react-router\";\nimport { RebaseLogo, LanguageToggle } from \"@rebasepro/app\";\nimport { ErrorBoundary, iconSize } from \"@rebasepro/ui\";\nimport {\n Avatar,\n cls,\n IconButton,\n LogOutIcon,\n Menu,\n MenuItem,\n MoonIcon,\n SettingsIcon,\n Skeleton,\n SunIcon,\n SunMoonIcon,\n Typography\n} from \"@rebasepro/ui\";\nimport { useAuthController, useLargeLayout, useModeController, useAdminModeController, useTranslation } from \"@rebasepro/app\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { User } from \"@rebasepro/types\";\nimport { useApp } from \"./app/useApp\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\nimport { UserSettingsView } from \"@rebasepro/app\";\n\nexport type DefaultAppBarProps<ADDITIONAL_PROPS = object> = {\n\n /**\n * The content of the app bar, usually a title or logo. This includes a link to the home page.\n */\n title?: React.ReactNode;\n\n /**\n * A component that gets rendered on the upper side to the end of the main toolbar\n */\n endAdornment?: React.ReactNode;\n\n /**\n * A component that gets rendered on the upper side to the start of the main toolbar\n */\n startAdornment?: React.ReactNode;\n\n dropDownActions?: React.ReactNode;\n\n /**\n * Whether to render the dark/light/system mode toggle in the app bar.\n * Set to `false` when the drawer owns this action.\n * @default true\n */\n includeModeToggle?: boolean;\n\n /**\n * Whether to render the language switcher in the app bar.\n * Set to `false` when the drawer owns this action.\n * @default true\n */\n includeLanguageToggle?: boolean;\n\n /**\n * Whether to render the user avatar / menu in the app bar.\n * Set to `false` when the drawer owns this action.\n * @default true\n */\n includeUserMenu?: boolean;\n\n className?: string;\n\n style?: React.CSSProperties;\n\n logo?: string;\n\n user?: User;\n} & ADDITIONAL_PROPS;\n\n/**\n * This component renders the main app bar of Rebase.\n * You will likely not need to use this component directly.\n *\n\n */\nexport const DefaultAppBar = function DefaultAppBar({\n title,\n endAdornment,\n startAdornment,\n dropDownActions,\n includeModeToggle = true,\n includeLanguageToggle = true,\n includeUserMenu = true,\n className,\n style,\n user: userProp,\n logo: logoProp\n}: DefaultAppBarProps) {\n\n const {\n hasDrawer,\n drawerOpen,\n logo: appLogo\n } = useApp();\n\n const logo = logoProp ?? appLogo;\n\n const navigation = useUrlController();\n\n const breadcrumbs = useBreadcrumbsController();\n\n const authController = useAuthController();\n const adminModeController = useAdminModeController();\n const {\n mode,\n setMode\n } = useModeController();\n\n const navigate = useNavigate();\n\n const largeLayout = useLargeLayout();\n\n const user = userProp ?? authController.user;\n const { t } = useTranslation();\n\n let avatarComponent: React.ReactElement | null;\n\n if (user) {\n const initial = user?.displayName\n ? user.displayName[0].toUpperCase()\n : (user?.email ? user.email[0].toUpperCase() : \"A\");\n avatarComponent = <Avatar src={user.photoURL ?? undefined}>\n {initial}\n </Avatar>;\n } else if (user === undefined || authController.initialLoading) {\n avatarComponent = <div className={\"p-1 flex justify-center\"}>\n <Skeleton className={\"w-10 h-10 rounded-full\"}/>\n </div>;\n } else {\n avatarComponent = null;\n }\n\n\n return (\n <div\n style={style}\n role=\"banner\"\n className={cls(\"w-full h-14 transition-all ease-in duration-75 absolute top-0 max-w-full overflow-x-auto no-scrollbar\",\n \"flex flex-row gap-2 px-4 items-center\",\n \"backdrop-blur-sm bg-surface-50/95 dark:bg-surface-900/80\",\n {\n \"pl-[19rem]\": drawerOpen && largeLayout,\n \"pl-24\": hasDrawer && !(drawerOpen && largeLayout),\n \"z-10\": largeLayout,\n \"duration-100\": drawerOpen && largeLayout\n },\n className)}>\n\n {navigation && (!hasDrawer || title) && <div className=\"mr-2 hidden lg:block\">\n <Link\n className=\"visited:text-inherit dark:visited:text-inherit block\"\n to={navigation?.basePath ?? \"/\"}\n >\n <div className={\"flex flex-row gap-4\"}>\n {!hasDrawer && (logo\n ? <img src={logo}\n alt=\"Logo\"\n className={cls(\"w-[32px] h-[32px] object-contain\")}/>\n : <RebaseLogo width={\"32px\"} height={\"32px\"}/>)}\n\n {typeof title === \"string\"\n ? <Typography variant=\"subtitle1\"\n noWrap>\n {title}\n </Typography>\n : title}\n </div>\n </Link>\n </div>}\n\n <div className=\"mr-8 hidden lg:block\">\n <nav aria-label=\"Breadcrumb\">\n <div className={\"flex flex-row gap-2 items-center\"}>\n {breadcrumbs.breadcrumbs.map((breadcrumb, index) => {\n return <React.Fragment key={breadcrumb.url + \"_\" + index}>\n {index > 0 && (\n <Typography variant={\"caption\"} color={\"secondary\"}>\n /\n </Typography>\n )}\n <Link\n key={index}\n className=\"visited:text-inherit dark:visited:text-inherit block\"\n to={breadcrumb.url}\n >\n <div className=\"flex flex-row items-center gap-2 whitespace-nowrap\">\n <Typography variant={\"body2\"}>\n {breadcrumb.title}\n </Typography>\n </div>\n </Link>\n </React.Fragment>;\n })}\n </div>\n </nav>\n </div>\n {startAdornment}\n\n <div className={\"grow\"}/>\n\n {endAdornment &&\n <ErrorBoundary>\n {endAdornment}\n </ErrorBoundary>}\n\n {includeLanguageToggle && <LanguageToggle/>}\n\n {includeModeToggle &&\n <Menu\n trigger={<IconButton\n color=\"inherit\"\n aria-label=\"Toggle theme\"\n>\n {mode === \"dark\"\n ? <MoonIcon size={iconSize.small}/>\n : <SunIcon size={iconSize.small}/>}\n </IconButton>}>\n <MenuItem onClick={() => setMode(\"dark\")}><MoonIcon size={iconSize.smallest}/> {t(\"dark_mode\")}</MenuItem>\n <MenuItem onClick={() => setMode(\"light\")}><SunIcon size={iconSize.smallest}/> {t(\"light_mode\")} </MenuItem>\n <MenuItem onClick={() => setMode(\"system\")}> <SunMoonIcon\n size={iconSize.smallest}/>{t(\"system_mode\")}</MenuItem>\n </Menu>}\n\n\n {includeUserMenu &&\n <Menu trigger={<div aria-label=\"User menu\" role=\"button\">{avatarComponent}</div>}>\n {user && <div className={\"px-4 py-2 mb-2\"}>\n {user.displayName && <Typography variant={\"body1\"} color={\"secondary\"}>\n {user.displayName}\n </Typography>}\n {user.email && <Typography variant={\"body2\"} color={\"secondary\"}>\n {user.email}\n </Typography>}\n </div>}\n\n {dropDownActions}\n\n {!dropDownActions && <>\n <MenuItem onClick={() => navigate(\"/settings\")}>\n <SettingsIcon/>\n {t(\"account_settings\")}\n </MenuItem>\n <MenuItem onClick={async () => {\n await authController.signOut();\n // replace current route with home\n navigate(\"/\");\n }}>\n <LogOutIcon/>\n {t(\"log_out\")}\n </MenuItem>\n </>}\n\n </Menu>}\n\n </div>\n );\n}\n","import { DefaultAppBar, DefaultAppBarProps } from \"../DefaultAppBar\";\n/**\n * This component renders the main app bar of Rebase.\n */\nexport function AppBar({\n children,\n ...props\n}: {\n children?: React.ReactNode,\n className?: string,\n style?: React.CSSProperties\n} & DefaultAppBarProps) {\n const usedChildren = children ?? <DefaultAppBar {...props}/>;\n return <>{usedChildren}</>;\n}\n\nAppBar.componentType = \"AppBar\";\n","import React from \"react\";\n\nimport { NavLink } from \"react-router\";\nimport { cls, Tooltip } from \"@rebasepro/ui\";\n\n/**\n * Props of a drawer navigation row, named so an app overriding\n * `Shell.DrawerNavigationItem` can type its wrapper against them.\n */\nexport type DrawerNavigationItemProps = {\n icon: React.ReactElement,\n name: string,\n /** @deprecated No longer read: the tooltip is uncontrolled. */\n tooltipsOpen?: boolean,\n drawerOpen: boolean,\n /** @deprecated No longer read: the tooltip is uncontrolled. */\n adminMenuOpen?: boolean,\n url: string,\n onClick?: () => void,\n /**\n * Drop the row's icon and indent the label into the space it occupied, so the\n * row reads as a child of the group header above it.\n *\n * Nothing in the framework sets this: the stock drawer always passes `false`,\n * and an app that wants the categorised look opts into it by overriding\n * `Shell.DrawerNavigationItem` and deciding for itself which rows get it.\n */\n indented?: boolean,\n};\n\nexport function DrawerNavigationItem({\n name,\n icon,\n drawerOpen,\n url,\n onClick,\n indented = false\n}: DrawerNavigationItemProps) {\n\n // Indented rows give up the icon rather than keeping it *and* indenting: a\n // per-row icon repeated down a group is what flattens the hierarchy, since\n // every row then reads at the weight of the category above it. The indent is\n // the same 44px the icon occupied, so labels stay on the original grid and the\n // rail width does not change.\n const iconWrap = indented\n ? <div className={\"shrink-0 w-[44px] h-[30px]\"} aria-hidden={true}/>\n : <div\n className={\"shrink-0 flex items-center justify-center w-[44px] h-[30px] text-surface-500 dark:text-text-secondary-dark [&>svg]:size-4 group-hover/nav:text-primary transition-colors duration-150\"}>\n {icon}\n </div>;\n\n const [wantsTooltip, setWantsTooltip] = React.useState(false);\n\n // Radix will not report a close it never noticed: while the tooltip is masked\n // the pointer can leave the row without `onOpenChange(false)` ever firing. So\n // the stale `true` is dropped on the way *into* the masked state — otherwise\n // it surfaces the moment the mask lifts, as a tooltip hanging over a rail the\n // pointer left long ago.\n if (drawerOpen && wantsTooltip) setWantsTooltip(false);\n\n const listItem = <div>\n <NavLink\n onClick={onClick}\n // The label below is `hidden` (display:none) while the rail is\n // collapsed, which takes it out of the accessibility tree along with\n // the row's only text — a collapsed rail was a column of links with no\n // accessible name at all. The tooltip does not cover this: Radix wires\n // a trigger to its content with `aria-describedby`, which is a\n // description rather than a name, and only while the tooltip is open —\n // and this one is masked shut whenever the drawer is open.\n //\n // Named unconditionally rather than only when collapsed: expanded, this\n // is the same string the row already displays, so the accessible name\n // stays stable across the transition instead of appearing with it.\n aria-label={name}\n style={{\n width: \"100%\",\n transition: drawerOpen ? \"width 150ms ease-in\" : undefined\n }}\n className={({ isActive }: { isActive: boolean }) => cls(\"rounded-lg truncate group/nav\",\n \"hover:bg-primary/5 dark:hover:bg-primary/5 text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white\",\n \"flex flex-row items-center\",\n drawerOpen ? \"pr-4 h-[30px]\" : \"h-[30px]\",\n \"font-medium text-[13px]\",\n isActive ? \"bg-primary/8 dark:bg-primary/10 text-primary dark:text-primary [&_div]:text-primary\" : \"\"\n )}\n to={url}\n >\n\n {iconWrap}\n\n <div\n className={cls(\n \"text-text-primary dark:text-surface-200\",\n drawerOpen ? \"opacity-100\" : \"opacity-0 hidden\",\n \"font-inherit truncate space-x-2\"\n )}>\n {name}\n </div>\n </NavLink>\n </div>;\n\n // Per row, and always controlled. The old shared flag could only say \"every\n // tooltip\" or \"none\", and the state it needed was unreachable, so no entry\n // tooltip ever opened — leaving a bare rail of unlabelled icons. Radix decides\n // when this one wants to be open, from the pointer and from focus; the drawer\n // only masks it once the label says the same thing.\n //\n // Masked rather than withheld: dropping `open`, or the title, would move the\n // tooltip between controlled and uncontrolled as the drawer opens, which\n // strands the old state — a tooltip left up over a pointer nowhere near it.\n return <Tooltip\n open={!drawerOpen && wantsTooltip}\n onOpenChange={setWantsTooltip}\n side=\"right\"\n title={name}>\n {listItem}\n </Tooltip>;\n}\n","import type { NavigationEntry } from \"@rebasepro/admin-types\";\nimport React from \"react\";\nimport { ChevronDownIcon, cls, iconSize, Typography } from \"@rebasepro/ui\";\n\nimport { IconForView, getIcon } from \"@rebasepro/app\";\nimport { DrawerNavigationItem } from \"./DrawerNavigationItem\";\nimport { useTranslation, useComponentOverride } from \"@rebasepro/app\";\n\nexport interface DrawerNavigationGroupProps {\n /**\n * Group name to display in header\n */\n group: string;\n /**\n * Navigation entries in this group\n */\n entries: NavigationEntry[];\n /**\n * Whether the group is collapsed\n */\n collapsed: boolean;\n /**\n * Callback when collapse state should toggle\n */\n onToggleCollapsed: () => void;\n /**\n * Whether the drawer is in open (expanded) state\n */\n drawerOpen: boolean;\n /**\n * @deprecated No longer read. Entry tooltips are uncontrolled — they follow the\n * pointer and focus, and are suppressed wherever the label is already visible.\n */\n tooltipsOpen?: boolean;\n /**\n * @deprecated No longer read. See {@link tooltipsOpen}.\n */\n adminMenuOpen?: boolean;\n /**\n * Optional actions to render in the group header (e.g., \"Add collection\" button)\n */\n headerActions?: React.ReactNode;\n /**\n * Optional callback when a navigation item is clicked\n */\n onItemClick?: (entry: NavigationEntry) => void;\n /**\n * Hide the group header (title and expandable panel)\n */\n hideHeader?: boolean;\n /**\n * Lucide icon name for the group header, from `NavigationGroupMapping.icon`.\n *\n * It decorates the header and nothing else: the entries below are untouched and\n * keep their own icons. An app that wants the categorised look — rows giving up\n * their icons to indent under the group — builds it in its own drawer, by\n * overriding `Shell.DrawerNavigationItem` and passing `indented`.\n */\n icon?: string;\n}\n\n/**\n * Shared drawer navigation group component used by both DefaultDrawer and RebaseCloudDrawer.\n * Renders a collapsible group with header and navigation items.\n */\nexport function DrawerNavigationGroup({\n group,\n entries,\n collapsed,\n onToggleCollapsed,\n drawerOpen,\n headerActions,\n onItemClick,\n hideHeader,\n icon\n}: DrawerNavigationGroupProps) {\n const { t } = useTranslation();\n const ResolvedDrawerNavigationItem = useComponentOverride(\"Shell.DrawerNavigationItem\", DrawerNavigationItem);\n\n // The icon decorates the header, and stops there. It used to also strip the\n // entries of theirs and indent them, which made a per-app styling choice into\n // framework behaviour: every project that labelled a group with an icon lost the\n // icons on its rows, with nothing to turn it off. An app that wants that look\n // now opts into it in its own drawer — see `indented` on\n // {@link DrawerNavigationItem}.\n const groupIcon = !hideHeader && drawerOpen ? getIcon(icon, undefined, undefined, \"small\") : undefined;\n return (\n <div\n className={\"my-2 mx-2 flex flex-col\"}\n key={`drawer_group_${group}`}\n >\n {/* Group Header */}\n {!hideHeader && (\n <div\n className={cls(\"pl-3 pr-2 py-0.5 flex flex-row items-center transition-colors\",\n drawerOpen ? \"cursor-pointer hover:bg-surface-100 dark:hover:bg-surface-800/40 rounded-lg\" : \"opacity-0 invisible pointer-events-none\"\n )}\n onClick={drawerOpen ? onToggleCollapsed : undefined}\n >\n <ChevronDownIcon\n size={iconSize.small}\n className={cls(\n \"text-surface-400 dark:text-surface-400 transition-transform duration-200 mr-1\",\n collapsed ? \"-rotate-90\" : \"rotate-0\"\n )}\n />\n {groupIcon && (\n <span className=\"shrink-0 mr-2 flex items-center text-surface-600 dark:text-surface-300 [&>svg]:size-4\">\n {groupIcon}\n </span>\n )}\n <Typography\n variant={\"caption\"}\n color={\"secondary\"}\n className=\"font-semibold text-[11px] uppercase tracking-wider flex-grow line-clamp-1 text-surface-400 dark:text-surface-400\"\n >\n {(group || t(\"views_group\"))}\n </Typography>\n {headerActions && (\n <div onClick={(e) => e.stopPropagation()}>\n {headerActions}\n </div>\n )}\n </div>\n )}\n\n {/* Collapsible Content */}\n <div\n className={cls(\n \"transition-all duration-200 ease-in-out\",\n \"overflow-hidden\",\n !hideHeader && \"dark:bg-transparent\",\n \"rounded-lg\",\n (!hideHeader && collapsed) ? \"max-h-0 opacity-0\" : \"max-h-[2000px] opacity-100\"\n )}\n >\n {entries.map((entry) => (\n <ResolvedDrawerNavigationItem\n key={entry.id}\n icon={<IconForView collectionOrView={entry.collection ?? entry.view} size={\"small\"}/>}\n drawerOpen={drawerOpen}\n onClick={() => onItemClick?.(entry)}\n url={entry.url}\n name={entry.name}\n />\n ))}\n </div>\n </div>\n );\n}\n","import type { NavigationEntry, NavigationResult } from \"@rebasepro/admin-types\";\nimport React, { useMemo } from \"react\";\n\nimport { useCollapsedGroups, buildCollapsedDefaults, useLargeLayout, useAdminModeController, useAuthController, useModeController, useTranslation, useSlot, useRebaseContext, useAnalyticsController, useRebaseRegistry, useComponentOverride } from \"@rebasepro/app\";\nimport { useUrlController } from \"../hooks/navigation/contexts/UrlContext\";\nimport { useNavigationStateController } from \"../hooks/navigation/contexts/NavigationStateContext\";\n\n\nimport { Link, useNavigate } from \"react-router\";\nimport { AnalyticsEvent } from \"@rebasepro/admin-types\";\nimport {\n Avatar,\n ChevronsLeftIcon,\n ChevronsRightIcon,\n cls,\n iconSize,\n IconButton,\n LanguagesIcon,\n LogOutIcon,\n Menu,\n MenuItem,\n MoonIcon,\n Separator,\n SettingsIcon,\n Skeleton,\n SunIcon,\n SunMoonIcon,\n Tooltip,\n Typography\n} from \"@rebasepro/ui\";\nimport { DrawerNavigationGroup } from \"./DrawerNavigationGroup\";\nimport { LanguageToggle, RebaseLogo } from \"@rebasepro/app\";\nimport { useApp } from \"./app/useApp\";\n\n/**\n * Default drawer used in the admin.\n *\n * When no `children` are provided, renders the full admin navigation\n * (collection groups, mode switch, plugin slots).\n *\n * When `children` **are** provided, renders the shared drawer shell\n * (logo, scrollable area, footer actions, collapse toggle) with the\n * custom content injected in the scrollable area. This lets consumers\n * like the SaaS dashboard reuse the identical structural layout while\n * supplying their own navigation items.\n *\n * @group Core\n */\nexport function DefaultDrawer({\n title,\n logo,\n logoDestination,\n children,\n footerActions,\n className,\n style\n}: {\n title?: React.ReactNode;\n logo?: string;\n logoDestination?: string;\n /**\n * Custom navigation content for the drawer.\n * When provided, replaces the default admin navigation (collection groups,\n * mode switch, slots). The shared shell (logo, scroll area, footer\n * actions, collapse toggle) is still rendered around it.\n */\n children?: React.ReactNode;\n /**\n * Custom content for the drawer footer actions area (language, theme, user menu).\n * - `undefined` — renders the default `DrawerFooterActions`.\n * - `null` — renders nothing (hides the footer actions).\n * - `ReactNode` — renders the provided custom content.\n */\n footerActions?: React.ReactNode | null;\n className?: string;\n style?: React.CSSProperties;\n}) {\n\n const {\n drawerHovered,\n drawerOpen,\n openDrawer,\n closeDrawer,\n logo: appLogo\n } = useApp();\n\n const resolvedLogo = logo ?? appLogo;\n\n const scrollRef = React.useRef<HTMLDivElement>(null);\n const [scrolled, setScrolled] = React.useState(false);\n\n const handleScroll = () => {\n if (scrollRef.current) {\n setScrolled(scrollRef.current.scrollTop > 0);\n }\n };\n\n return (\n <div role=\"navigation\" aria-label=\"Main navigation\" className={cls(\"flex flex-col h-full relative grow w-full\", className)} style={style}>\n\n <DrawerLogo\n logo={resolvedLogo}\n title={title}\n logoDestination={logoDestination}\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n />\n\n <div\n ref={scrollRef}\n onScroll={handleScroll}\n className={\"flex-grow min-h-0 overflow-y-auto overflow-x-hidden no-scrollbar px-2\"}\n style={{\n maskImage: scrolled\n ? \"linear-gradient(to bottom, transparent 0, black 20px, black calc(100% - 20px), transparent 100%)\"\n : \"linear-gradient(to bottom, black 0, black calc(100% - 20px), transparent 100%)\"\n }}>\n {children ?? <AdminNavigationContent />}\n </div>\n\n {footerActions !== null && (\n footerActions !== undefined\n ? footerActions\n : <DrawerFooterActions\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n />\n )}\n\n <DrawerToggle\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n openDrawer={openDrawer}\n closeDrawer={closeDrawer}\n />\n </div>\n );\n}\n\n/**\n * Default admin navigation content — rendered inside DefaultDrawer when no\n * custom `children` are provided. Contains the mode switch, navigation\n * groups, and header / footer plugin slots.\n */\nfunction AdminNavigationContent() {\n\n const {\n drawerHovered,\n drawerOpen,\n closeDrawer,\n closeHover\n } = useApp();\n\n const analyticsController = useAnalyticsController();\n const navigationState = useNavigationStateController();\n const context = useRebaseContext();\n\n const largeLayout = useLargeLayout();\n const adminModeController = useAdminModeController();\n const registry = useRebaseRegistry();\n const ResolvedDrawerNavigationGroup = useComponentOverride(\"Shell.DrawerNavigationGroup\", DrawerNavigationGroup);\n\n const allNavigationEntries = navigationState.topLevelNavigation?.navigationEntries ?? [];\n\n // Build a set of Studio-only dev view slugs so we can distinguish them from\n // admin custom views added via <RebaseAdmin views={...}> or plugins.\n const studioViewSlugs = useMemo(() => {\n const slugs = new Set<string>();\n (registry.studioConfig?.devViews ?? []).forEach(v => slugs.add(v.slug));\n // The schema view is also a Studio dev view (auto-injected when collectionEditor is enabled)\n if (registry.studioConfig && registry.cmsConfig?.collectionEditor) slugs.add(\"schema\");\n return slugs;\n }, [registry.studioConfig, registry.cmsConfig?.collectionEditor]);\n\n // Studio mode shows Studio dev views + admin entries (Users/Roles).\n // Content mode shows collections, admin custom views, and admin entries — but not Studio dev views.\n const filteredEntries = adminModeController.mode === \"studio\"\n ? allNavigationEntries.filter(e => (e.type === \"view\" && studioViewSlugs.has(e.slug)) || e.type === \"admin\")\n : allNavigationEntries.filter(e => e.type !== \"view\" || !studioViewSlugs.has(e.slug));\n\n // Derive groups from the filtered entries, preserving the order from topLevelNavigation.groups\n const entryGroups = new Set(filteredEntries.map(e => e.group).filter(Boolean));\n const orderedGroups = navigationState.topLevelNavigation?.groups ?? [];\n const groupsToRender = [\n ...orderedGroups.filter(g => entryGroups.has(g)),\n ...[...entryGroups].filter(g => !orderedGroups.includes(g))\n ];\n\n // Group header icons, declared on `navigationGroupMappings`. Keyed by name\n // because that is what a navigation entry's `group` holds.\n const groupIcons = useMemo(() => {\n const icons = new Map<string, string>();\n (registry.cmsConfig?.navigationGroupMappings ?? []).forEach(mapping => {\n if (mapping.icon) icons.set(mapping.name, mapping.icon);\n });\n return icons;\n }, [registry.cmsConfig?.navigationGroupMappings]);\n\n // Collapsible groups state - using \"drawer\" namespace for independent state from home page\n const collapsedDefaults = useMemo(\n () => buildCollapsedDefaults(registry.cmsConfig?.navigationGroupMappings, \"drawer\"),\n [registry.cmsConfig?.navigationGroupMappings]\n );\n const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupsToRender, \"drawer\", collapsedDefaults);\n\n const headerSlot = useSlot(\"navigation.header\", { drawerOpen,\ndrawerHovered,\ncontext });\n const footerSlot = useSlot(\"navigation.footer\", { drawerOpen,\ndrawerHovered,\ncontext });\n\n if (!navigationState.topLevelNavigation)\n return null;\n\n const onItemClick = (view: NavigationEntry) => {\n const eventName: AnalyticsEvent = view.type === \"collection\"\n ? \"drawer_navigate_to_collection\"\n : (view.type === \"view\" ? \"drawer_navigate_to_view\" : \"unmapped_event\");\n analyticsController.onAnalyticsEvent?.(eventName, { url: view.url });\n if (!largeLayout) {\n closeDrawer();\n } else if (!drawerOpen) {\n closeHover();\n }\n };\n\n const drawerVisuallyOpen = drawerOpen || drawerHovered;\n\n return (\n <>\n {registry.studioConfig && (\n <DrawerModeSwitch\n drawerOpen={drawerOpen}\n drawerHovered={drawerHovered}\n />\n )}\n\n {headerSlot}\n\n {groupsToRender.map((group) => {\n const entriesInGroup = filteredEntries.filter(e => e.group === group);\n return (\n <ResolvedDrawerNavigationGroup\n key={`drawer_group_${group}`}\n group={group}\n entries={entriesInGroup}\n collapsed={isGroupCollapsed(group)}\n onToggleCollapsed={() => toggleGroupCollapsed(group)}\n drawerOpen={drawerVisuallyOpen}\n onItemClick={onItemClick}\n icon={groupIcons.get(group)}\n />\n );\n })}\n\n {footerSlot}\n </>\n );\n}\n\nexport function DrawerLogo({\n logo,\n title,\n logoDestination = \"/\",\n drawerOpen,\n drawerHovered\n}: {\n logo?: string;\n title?: React.ReactNode;\n logoDestination?: string;\n drawerOpen: boolean;\n drawerHovered: boolean;\n}) {\n\n const showFullContent = drawerOpen || drawerHovered;\n const { t } = useTranslation();\n\n return (\n <div className=\"flex flex-row items-center shrink-0 pt-4 pb-0 px-2\">\n {/* Logo — always visible */}\n {/* Named explicitly because neither branch below carries text: the\n stock `RebaseLogo` is a bare <svg> with no <title>, and a custom\n `logo` only ever gets the generic alt \"Logo\", which names the image\n rather than saying where the link goes. The title link beside it is\n no help either — it renders only when a `title` is set. */}\n <Link\n className=\"shrink-0 flex items-center justify-center w-[56px] h-[40px]\"\n to={logoDestination}\n aria-label={t(\"home\") || \"Home\"}\n >\n {logo\n ? <img src={logo} alt=\"Logo\" className=\"w-[28px] h-[28px] object-contain\"/>\n : <RebaseLogo width=\"28px\" height=\"28px\"/>\n }\n </Link>\n\n {/* Title (fades in when expanded or hovered) */}\n <div\n className={cls(\n \"flex flex-row items-center overflow-hidden transition-all duration-200 ease-in-out\",\n showFullContent ? \"opacity-100 w-full ml-1\" : \"opacity-0 w-0 ml-0\"\n )}\n >\n {title && (\n <Link\n className=\"visited:text-inherit dark:visited:text-inherit block truncate\"\n to={logoDestination}\n >\n {typeof title === \"string\"\n ? <Typography variant=\"subtitle1\" noWrap className=\"truncate\">{title}</Typography>\n : title\n }\n </Link>\n )}\n </div>\n </div>\n );\n}\n\n/**\n * Toggle button at the bottom of the drawer.\n * Uses double-chevron icons to indicate collapse/expand direction.\n */\nexport function DrawerToggle({\n drawerOpen,\n drawerHovered,\n openDrawer,\n closeDrawer\n}: {\n drawerOpen: boolean;\n drawerHovered: boolean;\n openDrawer: () => void;\n closeDrawer: () => void;\n}) {\n const isExpanded = drawerOpen;\n const isHovered = drawerHovered && !drawerOpen;\n const showFullContent = isExpanded || isHovered;\n\n const [wantsTooltip, setWantsTooltip] = React.useState(false);\n // See {@link DrawerNavigationItem}: a masked tooltip never hears the pointer\n // leave, so the stale state is dropped as the mask goes on.\n if (showFullContent && wantsTooltip) setWantsTooltip(false);\n\n const { t } = useTranslation();\n\n return (\n <div className=\"shrink-0 mt-auto px-4 pt-0.5 pb-2\">\n <Tooltip\n title={isExpanded ? t(\"collapse\") : t(\"expand\")}\n // The row spells out \"Collapse\"/\"Expand\" itself whenever it is wide\n // enough to show the label — expanded, or floating open under the\n // pointer. A tooltip repeating that word is noise; it earns its\n // place only on a bare rail, where the chevron stands alone.\n //\n // Masked, not withheld: see {@link DrawerNavigationItem} for why\n // this stays controlled in both states.\n open={!showFullContent && wantsTooltip}\n onOpenChange={setWantsTooltip}\n side=\"right\"\n sideOffset={12}\n asChild={true}\n >\n <button\n type=\"button\"\n className={cls(\n \"flex flex-row items-center rounded-lg cursor-pointer w-full\",\n \"hover:bg-surface-accent-100 dark:hover:bg-surface-800\",\n \"transition-colors duration-150\",\n \"py-2\"\n )}\n aria-expanded={isExpanded}\n aria-label={isExpanded ? t(\"collapse\") : t(\"expand\")}\n onClick={() => isExpanded ? closeDrawer() : openDrawer()}\n >\n <div className=\"shrink-0 flex items-center justify-center w-[44px] h-[24px] text-surface-500 dark:text-surface-400\">\n {isExpanded\n ? <ChevronsLeftIcon size={iconSize.small}/>\n : <ChevronsRightIcon size={iconSize.small}/>\n }\n </div>\n <div className={cls(\n \"overflow-hidden transition-all duration-200 ease-in-out\",\n showFullContent ? \"opacity-100 w-auto\" : \"opacity-0 w-0\"\n )}>\n <Typography\n variant=\"body2\"\n className=\"text-surface-500 dark:text-surface-400 select-none whitespace-nowrap\"\n >\n {isExpanded ? t(\"collapse\") : t(\"expand\")}\n </Typography>\n </div>\n </button>\n </Tooltip>\n </div>\n );\n}\n\n/**\n * Segmented Content / Studio switch rendered inside the drawer.\n * Animates in/out with the drawer open state via opacity + max-height.\n */\nfunction DrawerModeSwitch({\n drawerOpen,\n drawerHovered\n}: {\n drawerOpen: boolean;\n drawerHovered: boolean;\n}) {\n const adminModeController = useAdminModeController();\n const urlController = useUrlController();\n const navigate = useNavigate();\n const showSwitch = drawerOpen || drawerHovered;\n\n return (\n <div\n className={cls(\n \"shrink-0 overflow-hidden transition-all duration-200 ease-in-out px-3\",\n showSwitch ? \"opacity-100 h-7 mt-2 mb-0\" : \"opacity-0 pointer-events-none h-7 mt-2 mb-0\"\n )}\n >\n <div role=\"group\" aria-label=\"Content mode\" className=\"flex bg-surface-100 dark:bg-surface-900 rounded-lg p-0.5 border border-surface-200 dark:border-surface-700/60\">\n <button\n onClick={() => {\n adminModeController.setMode(\"content\");\n navigate(urlController.basePath ?? \"/\");\n }}\n aria-pressed={adminModeController.mode === \"content\"}\n className={cls(\n \"flex-1 px-3 py-0.5 text-xs font-semibold rounded-md transition-all text-center\",\n adminModeController.mode === \"content\"\n ? \"bg-white dark:bg-surface-800 shadow-sm text-primary dark:text-primary-400\"\n : \"text-surface-500 hover:text-surface-900 dark:hover:text-white\"\n )}\n >\n Content\n </button>\n <button\n onClick={() => {\n adminModeController.setMode(\"studio\");\n navigate(urlController.basePath === \"/\" ? \"/s\" : `${urlController.basePath ?? \"\"}/s`);\n }}\n aria-pressed={adminModeController.mode === \"studio\"}\n className={cls(\n \"flex-1 px-3 py-0.5 text-xs font-semibold rounded-md transition-all text-center\",\n adminModeController.mode === \"studio\"\n ? \"bg-white dark:bg-surface-800 shadow-sm text-primary dark:text-primary-400\"\n : \"text-surface-500 hover:text-surface-900 dark:hover:text-white\"\n )}\n >\n Studio\n </button>\n </div>\n </div>\n );\n}\n\n/**\n * Footer actions rendered at the bottom of the drawer, above the collapse/expand toggle.\n * Replaces the app bar icons (language, theme, user avatar) with a drawer-native layout\n * that adapts between collapsed (icons only) and expanded (full labels + user bar) states.\n *\n * @group Core\n */\nexport function DrawerFooterActions({\n drawerOpen,\n drawerHovered,\n /**\n * Custom content to render inside the user dropdown menu.\n * When provided, these items are appended after the user info header\n * and before the default Sign Out item.\n */\n dropDownActions,\n /**\n * Override the user object displayed in the footer.\n * When omitted, falls back to `authController.user`.\n */\n user: userProp\n}: {\n drawerOpen: boolean;\n drawerHovered: boolean;\n dropDownActions?: React.ReactNode;\n user?: import(\"@rebasepro/types\").User;\n}) {\n const authController = useAuthController();\n const {\n mode,\n setMode\n } = useModeController();\n const navigate = useNavigate();\n const { t } = useTranslation();\n\n const user = userProp ?? authController.user;\n const showFullContent = drawerOpen || drawerHovered;\n const isFloating = drawerHovered && !drawerOpen;\n const portalRef = React.useRef<HTMLDivElement>(null);\n\n // User avatar\n let avatarComponent: React.ReactElement | null;\n if (user) {\n const initial = user?.displayName\n ? user.displayName[0].toUpperCase()\n : (user?.email ? user.email[0].toUpperCase() : \"A\");\n avatarComponent = <Avatar src={user.photoURL ?? undefined} className=\"w-8 h-8 text-xs\">\n {initial}\n </Avatar>;\n } else if (user === undefined || authController.initialLoading) {\n avatarComponent = <Skeleton className=\"w-8 h-8 rounded-full\"/>;\n } else {\n avatarComponent = null;\n }\n\n return (\n <div className=\"shrink-0 pt-2 pb-0\" ref={portalRef}>\n {avatarComponent && (\n <div className=\"flex items-center px-[16px] py-1\">\n <Menu\n trigger={\n <div\n className={cls(\n \"shrink-0 flex items-center justify-center w-[44px] cursor-pointer\",\n \"rounded-md py-1\",\n \"hover:bg-surface-accent-100 dark:hover:bg-surface-800\",\n \"transition-colors duration-150\"\n )}\n role=\"button\"\n tabIndex={0}\n aria-label={t(\"user_menu\") || \"User menu\"}\n >\n {avatarComponent}\n </div>\n }\n side=\"top\"\n align=\"start\"\n >\n {user && <div className=\"px-4 py-2 mb-1\">\n {user.displayName && <Typography variant=\"body1\" color=\"secondary\">\n {user.displayName}\n </Typography>}\n {user.email && <Typography variant=\"body2\" color=\"secondary\">\n {user.email}\n </Typography>}\n </div>}\n\n {dropDownActions}\n\n {!dropDownActions && <>\n <MenuItem onClick={() => navigate(\"/settings\")}>\n <SettingsIcon/>\n {t(\"account_settings\")}\n </MenuItem>\n <MenuItem onClick={async () => {\n await authController.signOut();\n navigate(\"/\");\n }}>\n <LogOutIcon/>\n {t(\"log_out\")}\n </MenuItem>\n </>}\n </Menu>\n\n {/* Language + Theme — only when expanded */}\n {showFullContent && (\n <div className=\"flex items-center gap-0\">\n <LanguageToggle/>\n <Menu\n trigger={\n <IconButton\n color=\"inherit\"\n aria-label={t(\"toggle_theme\") || \"Toggle theme\"}\n className=\"text-surface-500 dark:text-surface-400\"\n >\n {mode === \"dark\"\n ? <MoonIcon size={iconSize.small}/>\n : mode === \"light\"\n ? <SunIcon size={iconSize.small}/>\n : <SunMoonIcon size={iconSize.small}/>}\n </IconButton>\n }\n portalContainer={portalRef.current}\n side=\"top\"\n >\n <MenuItem onClick={() => setMode(\"dark\")}><MoonIcon size={iconSize.smallest}/> {t(\"dark_mode\")}</MenuItem>\n <MenuItem onClick={() => setMode(\"light\")}><SunIcon size={iconSize.smallest}/> {t(\"light_mode\")}</MenuItem>\n <MenuItem onClick={() => setMode(\"system\")}><SunMoonIcon size={iconSize.smallest}/> {t(\"system_mode\")}</MenuItem>\n </Menu>\n </div>\n )}\n </div>\n )}\n </div>\n );\n}\n","import { DefaultDrawer } from \"../DefaultDrawer\";\n\n/**\n * This component is in charge of rendering the drawer.\n * If you add this component under your {@link Scaffold}, it will be rendered\n * as a drawer, and the open and close functionality will be handled automatically.\n * If you want to customise the drawer, you can create your own component and pass it as a child.\n * For custom drawers, you can use the {@link useApp} to open and close the drawer.\n *\n */\nexport function Drawer({\n children,\n title,\n logo,\n logoDestination,\n footerActions,\n className,\n style\n }: {\n children?: React.ReactNode,\n title?: React.ReactNode,\n logo?: string,\n logoDestination?: string,\n /**\n * Custom content for the drawer footer actions area (language, theme, user menu).\n * - `undefined` — renders the default `DrawerFooterActions`.\n * - `null` — renders nothing (hides the footer actions).\n * - `ReactNode` — renders the provided custom content.\n */\n footerActions?: React.ReactNode | null,\n className?: string,\n style?: React.CSSProperties\n}) {\n const usedChildren = children ?? <DefaultDrawer title={title} logo={logo} logoDestination={logoDestination} footerActions={footerActions} className={className} style={style}/>;\n return <>{usedChildren}</>;\n}\n\nDrawer.componentType = \"Drawer\";\n","import React, { PropsWithChildren, useCallback, useMemo } from \"react\";\nimport { cls, defaultBorderMixin, IconButton, Sheet, Tooltip } from \"@rebasepro/ui\";\nimport { ChevronLeftIcon, ErrorBoundary, MenuIcon } from \"@rebasepro/ui\";\nimport { deepEqual as equal } from \"fast-equals\"\n\nimport { useLargeLayout, useAdminModeController, useTranslation } from \"@rebasepro/app\";\nimport { useUrlController } from \"../../hooks/navigation/contexts/UrlContext\";\nimport { AppContext } from \"./useApp\";\n\nexport const DRAWER_WIDTH = 280;\n\n/**\n * Namespaced by base path: two admins served from one origin are two different\n * navigations, and a single key would have them overwrite each other's drawer.\n */\nexport function drawerOpenStorageKey(basePath: string | undefined) {\n return `rebase-drawer-open:${basePath || \"/\"}`;\n}\n\n/** `null` when the user has never toggled the drawer, or storage is unavailable. */\nfunction readStoredDrawerOpen(key: string): boolean | null {\n if (typeof window === \"undefined\") return null;\n try {\n const stored = window.localStorage.getItem(key);\n return stored === null ? null : stored === \"true\";\n } catch (e) {\n // Storage can be blocked: private mode, sandboxed iframe, cookie policy.\n return null;\n }\n}\n\nfunction writeStoredDrawerOpen(key: string, open: boolean) {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(key, String(open));\n } catch (e) {\n // Same as above: a drawer that forgets is better than a crash.\n }\n}\n\n/**\n * @group Core\n */\nexport interface ScaffoldProps {\n\n /**\n * Expand the collapsed drawer while the pointer is over it. On by default —\n * pass `false` to keep the rail a rail until the user clicks the toggle.\n */\n autoOpenDrawer?: boolean;\n\n /**\n * Start with the drawer expanded rather than collapsed to icons.\n *\n * Distinct from {@link autoOpenDrawer}, which is a hover behaviour: this one\n * only seeds the very first visit. Once the user toggles the drawer, that\n * choice is stored in `localStorage` and wins over this prop on every load.\n *\n * Ignored on small layouts, where an expanded drawer covers the content it is\n * meant to navigate.\n */\n defaultDrawerOpen?: boolean;\n\n /**\n * Logo to be displayed in the top bar and drawer.\n * Note that this has no effect if you are using a custom AppBar or Drawer.\n */\n logo?: string;\n\n /**\n * If true, the main content will be padded in large layouts. Defaults to true.\n */\n padding?: boolean;\n\n className?: string;\n\n style?: React.CSSProperties;\n}\n\n/**\n * This view acts as a scaffold for Rebase.\n *\n * It is in charge of displaying the navigation drawer, top bar and main\n * collection views.\n * This component needs a parent {@link Rebase}\n *\n * @param props\n\n * @group Core\n */\nexport const Scaffold = React.memo<PropsWithChildren<ScaffoldProps>>(\n function Scaffold(props: PropsWithChildren<ScaffoldProps>) {\n\n const {\n children,\n autoOpenDrawer = true,\n defaultDrawerOpen = false,\n logo,\n className,\n style,\n padding = true\n } = props;\n\n const drawerChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === \"Drawer\");\n if (drawerChildren.length > 1) {\n throw Error(\"Only one Drawer component is allowed in Scaffold\");\n }\n const appBarChildren = React.Children.toArray(children).filter((child: any) => child.type.componentType === \"AppBar\");\n if (appBarChildren.length > 1) {\n throw Error(\"Only one AppBar component is allowed in Scaffold\");\n }\n const otherChildren = React.Children.toArray(children)\n .filter((child: any) => child.type.componentType !== \"Drawer\" && child.type.componentType !== \"AppBar\");\n const includeDrawer = drawerChildren.length > 0;\n const largeLayout = useLargeLayout();\n\n const storageKey = drawerOpenStorageKey(useUrlController().basePath);\n\n // Seeded once, deliberately: a `useEffect` syncing this to the prop would\n // re-expand the drawer under a user who had just collapsed it.\n const [drawerOpen, setDrawerOpenState] = React.useState(defaultDrawerOpen && largeLayout);\n const [onHover, setOnHover] = React.useState(false);\n\n // The stored choice is a client-only fact, so it is applied after the first\n // render rather than seeded into it: reading storage while rendering would\n // make the client disagree with server-rendered HTML. A layout effect runs\n // before paint, so the drawer still arrives in its remembered state.\n // `defaultDrawerOpen` seeds the very first visit and is ignored after that.\n React.useLayoutEffect(() => {\n const stored = readStoredDrawerOpen(storageKey);\n if (stored === null) return;\n setDrawerOpenState(stored && largeLayout);\n // Deliberately not re-run on `largeLayout`: crossing the breakpoint is\n // the effect below, and re-running here would undo a user's toggle.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [storageKey]);\n\n // One piece of state drives two different things: the expanded rail on\n // large layouts, and the modal sheet on small ones. Carrying an expanded\n // rail across the breakpoint would drop that sheet, overlay and all, over\n // the content — so the crossing resets it, and widening again restores\n // whatever the user last chose.\n const wasLargeLayout = React.useRef(largeLayout);\n React.useEffect(() => {\n if (wasLargeLayout.current === largeLayout) return;\n wasLargeLayout.current = largeLayout;\n setDrawerOpenState(largeLayout ? (readStoredDrawerOpen(storageKey) ?? defaultDrawerOpen) : false);\n }, [largeLayout, defaultDrawerOpen, storageKey]);\n\n const setDrawerOpen = useCallback((open: boolean) => {\n setDrawerOpenState(open);\n // Small layouts render the drawer as a modal sheet. Remembering that\n // one would greet the next load with an overlay over the content.\n if (!largeLayout) return;\n writeStoredDrawerOpen(storageKey, open);\n }, [largeLayout, storageKey]);\n\n // The pointer has left, but a popover the drawer opened is still up, so the\n // collapse is owed rather than cancelled. See `setOnHoverFalse`.\n const collapseWhenPopoverCloses = React.useRef(false);\n\n const setOnHoverTrue = useCallback(() => {\n // Hover expansion is the default; `autoOpenDrawer={false}` opts out for\n // admins that want the rail to stay a rail until the toggle is clicked.\n if (!autoOpenDrawer) return;\n collapseWhenPopoverCloses.current = false;\n setOnHover(true);\n }, [autoOpenDrawer]);\n const setOnHoverFalse = useCallback(() => {\n // Don't collapse the drawer out from under an open popover/dropdown —\n // its content is portalled outside the drawer, so reaching for it reads\n // as a mouseleave. The collapse is owed until that popover closes.\n if (document.querySelector(\"[data-radix-popper-content-wrapper]\")) {\n collapseWhenPopoverCloses.current = true;\n return;\n }\n collapseWhenPopoverCloses.current = false;\n setOnHover(false);\n }, []);\n\n // Nothing fires a second mouseleave when the popover finally closes, so the\n // owed collapse has to be noticed rather than waited for. Only mounted\n // while the drawer is actually floating open.\n React.useEffect(() => {\n if (!onHover) return;\n const collapseIfOwed = () => {\n if (!collapseWhenPopoverCloses.current) return;\n if (document.querySelector(\"[data-radix-popper-content-wrapper]\")) return;\n collapseWhenPopoverCloses.current = false;\n setOnHover(false);\n };\n const observer = new MutationObserver(collapseIfOwed);\n observer.observe(document.body, {\n childList: true,\n subtree: true\n });\n return () => observer.disconnect();\n }, [onHover]);\n\n const handleDrawerOpen = useCallback(() => {\n setDrawerOpen(true);\n }, [setDrawerOpen]);\n\n const handleDrawerClose = useCallback(() => {\n setDrawerOpen(false);\n }, [setDrawerOpen]);\n\n const computedDrawerOpen: boolean = drawerOpen;\n const computedDrawerHovered = Boolean(largeLayout && onHover);\n\n const adminModeController = useAdminModeController();\n const isStudioDark = adminModeController.mode === \"studio\";\n\n\n const hasAppBar = Boolean(appBarChildren.length > 0);\n const appContextValue = useMemo(() => ({\n hasDrawer: Boolean(includeDrawer),\n drawerOpen: computedDrawerOpen,\n drawerHovered: computedDrawerHovered,\n openDrawer: handleDrawerOpen,\n closeDrawer: handleDrawerClose,\n closeHover: setOnHoverFalse,\n logo\n }), [includeDrawer, computedDrawerOpen, computedDrawerHovered, handleDrawerOpen, handleDrawerClose, setOnHoverFalse, logo]);\n\n return (\n <AppContext.Provider value={appContextValue}>\n <div\n className={cls(\"flex h-screen w-screen overflow-hidden\",\n \"bg-surface-50 dark:bg-surface-900\",\n \"text-surface-900 dark:text-white\", className)}\n style={{\n paddingTop: \"env(safe-area-inset-top)\",\n paddingLeft: \"env(safe-area-inset-left)\",\n paddingRight: \"env(safe-area-inset-right)\",\n paddingBottom: \"env(safe-area-inset-bottom)\",\n height: \"100dvh\",\n ...style\n }}>\n {appBarChildren}\n\n <DrawerWrapper\n displayed={includeDrawer}\n onMouseEnter={setOnHoverTrue}\n onMouseMove={setOnHoverTrue}\n onMouseLeave={setOnHoverFalse}\n open={drawerOpen}\n hovered={onHover}\n isStudioDark={isStudioDark}\n setDrawerOpen={setDrawerOpen}>\n {includeDrawer && drawerChildren}\n </DrawerWrapper>\n\n <main\n className=\"flex flex-col grow overflow-auto\">\n\n {hasAppBar && <DrawerHeader/>}\n\n <div\n className={cls(defaultBorderMixin, \"bg-surface-50 dark:bg-surface-800\", \"grow overflow-auto m-0\", {\n \"mt-1 lg:m-0 lg:mx-2 lg:mb-2 lg:rounded-lg lg:border-t lg:border-x lg:border-solid\": padding,\n // No app bar means no DrawerHeader spacer above, so inset the\n // panel by the same amount as its sides and bottom.\n // Must come after the padding classes, which reset lg margins.\n \"lg:mt-2\": !hasAppBar && padding,\n \"lg:mt-4\": !hasAppBar && !padding,\n \"border-t\": hasAppBar && !padding\n })}>\n\n <ErrorBoundary>\n {otherChildren}\n </ErrorBoundary>\n\n </div>\n </main>\n </div>\n </AppContext.Provider>\n );\n },\n equal\n)\n\nconst DrawerHeader = () => {\n return (\n <div className=\"flex flex-col min-h-14\"></div>\n );\n};\n\nfunction DrawerWrapper(props: {\n children: React.ReactNode,\n displayed: boolean,\n open: boolean,\n logo?: string,\n hovered: boolean,\n isStudioDark: boolean,\n setDrawerOpen: (open: boolean) => void,\n onMouseEnter: () => void,\n onMouseMove: () => void,\n onMouseLeave: () => void\n}) {\n\n const layoutWidth = !props.displayed ? 0 : (props.open ? DRAWER_WIDTH : 72);\n const visualWidth = !props.displayed ? 0 : ((props.open || props.hovered) ? DRAWER_WIDTH : 72);\n\n const isFloating = props.hovered && !props.open;\n const darkBg = \"dark:bg-surface-900\";\n const darkBgFloating = \"dark:bg-surface-900\";\n const { t } = useTranslation();\n\n const innerDrawer = <div\n className={cls(\"h-full overflow-hidden\", defaultBorderMixin,\n isFloating ? `absolute top-0 left-0 bottom-0 z-50 bg-surface-50 ${darkBgFloating} shadow-lg border-r` : `relative bg-surface-50 ${darkBg}`)}\n style={{\n width: visualWidth,\n 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\"\n }}\n >\n\n <div className={\"flex flex-col h-full\"}>\n {props.children}\n </div>\n\n </div>;\n\n const largeLayout = useLargeLayout();\n if (!largeLayout) {\n if (!props.displayed)\n return null;\n return <>\n <IconButton\n color=\"inherit\"\n aria-label={t(\"open_menu\")}\n onClick={() => props.setDrawerOpen(true)}\n className=\"absolute sm:top-2 sm:left-4 top-1 left-2\"\n >\n <MenuIcon/>\n </IconButton>\n <Sheet side={\"left\"}\n transparent={true}\n open={props.open}\n onOpenChange={props.setDrawerOpen}\n title={t(\"navigation_drawer\")}\n overlayClassName={\"bg-white/80 dark:bg-surface-900/80\"}\n >\n {innerDrawer}\n </Sheet>\n </>;\n }\n\n return (\n <div\n className=\"z-20 relative flex-shrink-0 overflow-visible\"\n onMouseEnter={props.onMouseEnter}\n onMouseMove={props.onMouseMove}\n onMouseLeave={props.onMouseLeave}\n style={{\n width: layoutWidth,\n minWidth: layoutWidth,\n 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\"\n }}>\n\n {innerDrawer}\n\n </div>\n );\n}\n","import React, { useLayoutEffect } from \"react\";\nimport { useRebaseRegistryDispatch } from \"@rebasepro/app\";\nimport type { RebaseAdminConfig } from \"@rebasepro/admin-types\";\n\n/**\n * Declarative component to configure the admin in Rebase.\n * Renders nothing — purely registers config into the RebaseRegistry.\n *\n * When `collectionEditor` is provided, the built-in visual schema editor\n * is auto-wired as a native feature (slots, provider, Studio view) without\n * needing any external plugin.\n */\nexport function RebaseAdmin({ collections, views, homePage, entityViews, collectionViews, entityActions, collectionEditor, navigationGroupMappings, basePath }: RebaseAdminConfig) {\n const dispatch = useRebaseRegistryDispatch();\n\n useLayoutEffect(() => {\n dispatch.registerAdmin({ collections,\nviews,\nhomePage,\nentityViews,\ncollectionViews,\nentityActions,\ncollectionEditor,\nnavigationGroupMappings,\nbasePath });\n return () => dispatch.unregisterAdmin();\n }, [dispatch, collections, views, homePage, entityViews, collectionViews, entityActions, collectionEditor, navigationGroupMappings, basePath]);\n\n return null;\n}\n","import React from \"react\";\nimport {\n useRebaseRegistry,\n useAuthController\n} from \"@rebasepro/app\";\nimport { CircularProgressCenter } from \"@rebasepro/ui\";\nimport { LoginView } from \"@rebasepro/app\";\nimport type { AuthControllerExtended } from \"@rebasepro/admin-types\";\n\n/**\n * Auth gate component that handles the authentication flow.\n *\n * - Shows a loading spinner while `authController.initialLoading` is true.\n * - Shows the login view when no user is authenticated.\n * - Renders `children` when a user is authenticated.\n *\n * **Independently usable**: Use this alone when you want auth gating\n * without the full admin layout or navigation.\n *\n * @example\n * ```tsx\n * <RebaseAuthGate>\n * <MyCustomApp />\n * </RebaseAuthGate>\n * ```\n */\nexport function RebaseAuthGate({ children }: { children: React.ReactNode }) {\n const registry = useRebaseRegistry();\n const authController = useAuthController();\n\n\n if (authController?.initialLoading) {\n return <CircularProgressCenter size={\"large\"}/>;\n }\n\n if (!authController?.user) {\n const ActiveLoginView = registry.authConfig?.loginView ?? (\n <LoginView authController={authController as AuthControllerExtended}/>\n );\n return <>{ActiveLoginView}</>;\n }\n\n return <>{children}</>;\n}\n","import { CollectionsConfigController, SaveCollectionParams, UpdateCollectionParams, DeleteCollectionParams, SavePropertyParams, DeletePropertyParams, UpdatePropertiesOrderParams } from \"./types/config_controller\";\nimport { Properties } from \"@rebasepro/types\";\nimport { getSubcollections } from \"@rebasepro/common\";\n\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\nimport { DEFAULT_API_PATH } from \"@rebasepro/app\";\n\n/**\n * What the backend said about its schema editor, and how sure we are.\n *\n * `unknown` covers both \"still asking\" and \"could not ask\" — a backend too old\n * to have the endpoint, or one that is unreachable. Those fall back to the\n * build-mode guess below rather than locking the editor for someone whose\n * editor used to work.\n */\ntype SchemaEditorAvailability =\n | { state: \"unknown\" }\n | { state: \"known\", enabled: boolean, reason?: string };\n\n/**\n * The guess this hook used to make on its own.\n *\n * `process.env.NODE_ENV` here is the *frontend bundle's* build mode. Whether\n * the schema editor exists is decided by a different process entirely — the\n * server's own `NODE_ENV`, its `collectionsDir`, whether its collections were\n * introspected, whether `ts-morph` is installed. The two disagree in every\n * ordinary setup: a dev frontend against a deployed API, a `baas` project, a\n * hosted console. When they did, the editor offered itself and every save came\n * back `404 Not Found`. It is kept only as the answer for a backend too old to\n * be asked.\n */\nconst buildModeGuess = (): boolean => process.env.NODE_ENV === \"production\";\n\nexport function useLocalCollectionsConfigController(\n clientOrUrl: any,\n baseCollections: AdminCollection[] = [],\n options?: {\n readOnly?: boolean;\n getAuthToken?: () => Promise<string | null>;\n /**\n * Identity of the signed-in user, if any.\n *\n * Only used to re-ask the backend when it changes: whether the editor\n * will accept a write depends on who is asking, and the answer to an\n * anonymous probe does not survive a sign-in.\n */\n authKey?: string | null;\n }\n): CollectionsConfigController {\n\n const parsedCollections = baseCollections;\n\n // Store latest options in a ref to prevent stale closures in the `request` function\n // due to useMemo caching the saveCollection function.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n // `/api` only by default — a backend configured with another `basePath`\n // mounts the schema editor under that instead.\n const clientBaseUrl = typeof clientOrUrl === \"string\"\n ? clientOrUrl\n : (clientOrUrl?.baseUrl ?? \"\");\n const clientApiPath = (typeof clientOrUrl === \"object\" && clientOrUrl !== null && clientOrUrl.apiPath)\n || DEFAULT_API_PATH;\n const editorUrl = `${String(clientBaseUrl).replace(/\\/$/, \"\")}${clientApiPath}/schema-editor`;\n\n const resolveToken = async (): Promise<string | null> => {\n let token = optionsRef.current?.getAuthToken ? await optionsRef.current.getAuthToken() : null;\n if (!token && typeof clientOrUrl === \"object\" && clientOrUrl !== null && clientOrUrl.resolveToken) {\n token = await clientOrUrl.resolveToken();\n }\n return token ?? null;\n };\n\n const request = async (endpoint: string, payload: Record<string, unknown>) => {\n try {\n const token = await resolveToken();\n\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (token) {\n headers[\"Authorization\"] = `Bearer ${token}`;\n }\n\n const response = await fetch(`${editorUrl}${endpoint}`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload)\n });\n if (!response.ok) {\n const text = await response.text();\n let err: Record<string, unknown> = {};\n try {\n err = JSON.parse(text);\n } catch (e) {\n // ignore json parse error\n }\n\n if (Object.keys(err).length === 0) {\n err = { message: text };\n }\n console.error(\"dev server error payload:\", err);\n const errObj = err.error as Record<string, unknown> | string | undefined;\n const errMessage = typeof errObj === \"object\" && errObj !== null\n ? (errObj.message as string)\n : (typeof errObj === \"string\" ? errObj : (err.message as string | undefined));\n throw new Error(errMessage || \"Error communicating with local dev server\");\n }\n } catch (e) {\n console.error(\"fetch request failed\", e);\n throw e;\n }\n };\n\n // ── Ask the backend whether it will accept an edit ────────────────\n const forcedReadOnly = options?.readOnly;\n const authKey = options?.authKey ?? null;\n const [availability, setAvailability] = useState<SchemaEditorAvailability>({ state: \"unknown\" });\n\n useEffect(() => {\n // Nothing to ask about: the caller has already decided.\n if (forcedReadOnly === true) return;\n\n let cancelled = false;\n (async () => {\n try {\n const token = await resolveToken();\n const response = await fetch(`${editorUrl}/status`, {\n headers: token ? { Authorization: `Bearer ${token}` } : {}\n });\n if (cancelled) return;\n\n // A backend from before the endpoint existed. Guessing from the\n // bundle's build mode is wrong, but it is what that backend's\n // admin panel has always done, and locking the editor for\n // someone whose editor works would be worse.\n if (response.status === 404) {\n setAvailability({ state: \"unknown\" });\n return;\n }\n\n const body = await response.json().catch(() => ({})) as {\n enabled?: boolean,\n reason?: string,\n error?: { message?: string }\n };\n if (cancelled) return;\n\n if (response.ok) {\n setAvailability({\n state: \"known\",\n enabled: body.enabled === true,\n reason: body.reason\n });\n } else {\n // 401/403 (not an admin) or 501 (no auth configured at all)\n // — all of them mean this session cannot edit collections,\n // and the body says why better than we could.\n setAvailability({\n state: \"known\",\n enabled: false,\n reason: body.error?.message\n ?? `The backend refused to say whether collections are editable (HTTP ${response.status}).`\n });\n }\n } catch {\n if (!cancelled) setAvailability({ state: \"unknown\" });\n }\n })();\n\n return () => { cancelled = true; };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [editorUrl, forcedReadOnly, authKey]);\n\n const readOnly = forcedReadOnly\n ?? (availability.state === \"known\" ? !availability.enabled : buildModeGuess());\n\n const readOnlyReason = availability.state === \"known\" && availability.reason\n ? availability.reason\n : \"Collections can only be edited against a backend running the schema editor, which is off in production.\";\n\n return useMemo(() => ({\n loading: false,\n readOnly,\n readOnlyReason,\n collections: parsedCollections,\n getCollection: (id: string) => {\n const found = parsedCollections.find(c => (c as AdminCollection & { id?: string }).id === id || c.slug === id);\n if (found) return found;\n throw Error(`Collection ${id} not found in local mode`);\n },\n\n saveCollection: async ({ id, collectionData }: SaveCollectionParams) => {\n await request(\"/collection/save\", { collectionId: id,\ncollectionData });\n },\n updateCollection: async ({ id, collectionData }: UpdateCollectionParams) => {\n await request(\"/collection/save\", { collectionId: id,\ncollectionData });\n },\n deleteCollection: async ({ id }: DeleteCollectionParams) => {\n await request(\"/collection/delete\", { collectionId: id });\n },\n\n // The follow-up write carries exactly one key, and `partial` is what says\n // so. Read as a whole-collection save it deletes everything it does not\n // mention — `securityRules` first, which then falls back to the\n // directory default and widens who can read the collection.\n saveProperty: async ({ path, propertyKey, property, newPropertiesOrder }: SavePropertyParams) => {\n await request(\"/property/save\", { collectionId: path,\npropertyKey,\npropertyConfig: property });\n if (newPropertiesOrder) {\n await request(\"/collection/save\", { collectionId: path,\ncollectionData: { propertiesOrder: newPropertiesOrder },\npartial: true });\n }\n },\n deleteProperty: async ({ path, propertyKey, newPropertiesOrder }: DeletePropertyParams) => {\n await request(\"/property/delete\", { collectionId: path,\npropertyKey });\n if (newPropertiesOrder) {\n await request(\"/collection/save\", { collectionId: path,\ncollectionData: { propertiesOrder: newPropertiesOrder },\npartial: true });\n }\n },\n\n updatePropertiesOrder: async ({ collection, fullPath, newPropertiesOrder }: UpdatePropertiesOrderParams) => {\n const collectionId = (collection as AdminCollection & { id?: string }).id || fullPath.split(\"/\").pop();\n await request(\"/collection/save\", { collectionId,\ncollectionData: { propertiesOrder: newPropertiesOrder },\npartial: true });\n },\n updateKanbanColumnsOrder: async () => {\n // Kanban order mapping logic can be added later if needed natively.\n },\n\n navigationEntries: [],\n saveNavigationEntries: async () => { }\n }), [clientOrUrl, parsedCollections, readOnly, readOnlyReason, options?.getAuthToken]);\n}\n","import React, { useMemo, useRef, useEffect, useCallback, useContext, Suspense } from \"react\";\nimport {\n useRebaseRegistry,\n useRebaseContext,\n useAuthController,\n useCustomizationController,\n useAdminModeController,\n useBuildLocalConfigurationPersistence,\n useRebaseClient,\n useData,\n useDataSources,\n CollectionResolverRegistrationContext,\n StudioBridgeRegistryProvider,\n useBridgeRegistration,\n CustomizationControllerContext,\n RebaseDataContext\n} from \"@rebasepro/app\";\nimport { buildRoutedRebaseData, resolveDataSource } from \"@rebasepro/common\";\nimport { CircularProgressCenter, lazyChunk } from \"@rebasepro/ui\";\n\nimport type { AppView, CollectionCustomView, CollectionEditorOptions, EntityCustomView, EntityAction, RebasePlugin, AdminCollection } from \"@rebasepro/admin-types\";\nimport type { CollectionRegistryController } from \"@rebasepro/types\";\nimport type { UrlController, NavigationStateController } from \"@rebasepro/admin-types\";\n\nconst EMPTY_PLUGINS: RebasePlugin[] = [];\nconst EMPTY_COLLECTIONS: AdminCollection[] = [];\n\nimport { useBuildNavigationStateController } from \"../hooks/navigation/useBuildNavigationStateController\";\nimport { useBuildUrlController } from \"../hooks/navigation/useBuildUrlController\";\nimport { useBuildCollectionRegistryController } from \"../hooks/navigation/useBuildCollectionRegistryController\";\n\nimport { CollectionRegistryContext } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { UrlContext } from \"../hooks/navigation/contexts/UrlContext\";\nimport { NavigationStateContext } from \"../hooks/navigation/contexts/NavigationStateContext\";\n\nimport { SidePanelProvider } from \"./SidePanelProvider\";\n\n// Collection editor internals — used when collectionEditor is enabled\nimport { useLocalCollectionsConfigController } from \"../collection_editor/useLocalCollectionsConfigController\";\nimport { ConfigControllerProvider } from \"../collection_editor/ConfigControllerProvider\";\nimport { useCollectionsConfigController } from \"../collection_editor/useCollectionsConfigController\";\n\n// Lazy-load the schema view — only fetched when studio schema tool is active\nconst CollectionsStudioView = lazyChunk(() =>\n import(\"../collection_editor/ui/collection_editor/RouterCollectionsStudioView\")\n .then(m => ({ default: m.RouterCollectionsStudioView }))\n);\n\nexport interface RebaseNavigationProps {\n children: React.ReactNode;\n}\n\n/**\n * Navigation layer — builds and provides all admin navigation controllers:\n * collection registry, URL controller, navigation state, side entity,\n * and the self-assembling Studio bridge.\n *\n * Also handles the collection editor config controller when enabled.\n *\n * **Independently usable**: Use this when you need admin navigation\n * (entity tables, side panels) in a custom layout.\n *\n * @example\n * ```tsx\n * <RebaseNavigation>\n * <MyCustomLayout>\n * <CollectionViewBinding ... />\n * </MyCustomLayout>\n * </RebaseNavigation>\n * ```\n */\nexport function RebaseNavigation({ children }: RebaseNavigationProps) {\n const registry = useRebaseRegistry();\n const context = useRebaseContext();\n const adminModeController = useAdminModeController();\n const userConfigPersistence = useBuildLocalConfigurationPersistence();\n\n // ── Collection Editor resolution ──────────────────────────────────\n // The collection editor is ALWAYS enabled when Studio is registered.\n // The `collectionEditor` admin config is for fine-tuning (readOnly, auth, etc.),\n // not for opting-in. When omitted, the editor defaults to enabled\n // (read-only in production).\n const collectionEditorConfig = registry.cmsConfig?.collectionEditor;\n const collectionEditorEnabled = Boolean(collectionEditorConfig) || Boolean(registry.studioConfig);\n const collectionEditorOptions: CollectionEditorOptions | undefined = useMemo(() => {\n if (collectionEditorConfig === true || !collectionEditorConfig) return {};\n return collectionEditorConfig;\n }, [collectionEditorConfig]);\n\n // ── Combine admin and Studio Configs ────────────────────────────────\n const cmsCollections = registry.cmsConfig?.collections ?? EMPTY_COLLECTIONS;\n\n // ── Build the navigation controllers ──────────────────────────────\n const collectionsBuilder = useMemo(() => Array.isArray(cmsCollections) ? () => [...cmsCollections] : cmsCollections, [cmsCollections]);\n\n const dataSources = useDataSources();\n const collectionRegistryController = useBuildCollectionRegistryController({ userConfigPersistence, dataSources: dataSources.registry });\n\n // ── Multi-data-source routing ─────────────────────────────────────\n // Combine the default data source (server transport) with the registered\n // direct/custom sources from <Rebase> and route each collection by its\n // resolved data-source key, looked up by path against the collection\n // registry. A stable resolver ref keeps the routed data instance\n // referentially stable across registry rebuilds, so data-effect\n // dependencies don't thrash.\n const defaultData = useData();\n const getCollectionRef = useRef(collectionRegistryController.getCollection);\n getCollectionRef.current = collectionRegistryController.getCollection;\n\n // Hand the data layer a way to read this registry. It was built by <Rebase>,\n // above us, and needs a collection's primary keys to give its rows an\n // address — rows themselves carry only columns.\n //\n // Registered during render, not in an effect: the views that fetch rows are\n // below us, and their effects run before ours, so an effect here would bind\n // after the first page had already been converted. The call only assigns a\n // ref, so repeating it per render is free.\n const registerCollectionResolver = useContext(CollectionResolverRegistrationContext);\n const resolveCollection = useCallback(\n (slug: string) => getCollectionRef.current(slug),\n []);\n registerCollectionResolver(resolveCollection);\n const routedData = useMemo(() => buildRoutedRebaseData({\n defaultData,\n sources: dataSources.sources,\n resolveKey: (slugOrPath) => resolveDataSource(getCollectionRef.current(slugOrPath), dataSources.registry).key\n }), [defaultData, dataSources]);\n\n // Normalize the configured mount prefix to a leading-slash, no-trailing-slash\n // form (e.g. \"admin\" or \"/admin/\" -> \"/admin\"); empty/\"/\" stays \"/\".\n const basePath = useMemo(() => {\n const raw = registry.cmsConfig?.basePath;\n if (!raw || raw === \"/\") return \"/\";\n const trimmed = raw.replace(/^\\/+/, \"\").replace(/\\/+$/, \"\");\n return trimmed ? `/${trimmed}` : \"/\";\n }, [registry.cmsConfig?.basePath]);\n\n const urlController = useBuildUrlController({\n basePath,\n baseCollectionPath: \"/c\",\n collectionRegistryController\n });\n\n // ── Build config controller internally when collection editor is enabled ──\n const rebaseClient = useRebaseClient();\n const authController = useAuthController();\n const resolvedCollections = useMemo(\n () => Array.isArray(cmsCollections) ? cmsCollections : [],\n [cmsCollections]\n );\n\n // ── Dev-only data-source sanity check ─────────────────────────────\n // Warn about data sources declared with a direct/custom transport that\n // have no client-side driver — these silently fall back to the default\n // (server) source, a common source of misrouting. Unambiguous: it never\n // false-positives on server-mediated sources (which intentionally have\n // no client driver).\n useEffect(() => {\n if (process.env.NODE_ENV === \"production\") return;\n const { registry, sources } = dataSources;\n const missing = Object.values(registry)\n .filter((d) => (d.transport === \"direct\" || d.transport === \"custom\") && !sources[d.key])\n .map((d) => d.key);\n if (missing.length > 0) {\n console.warn(\n `[Rebase] These data source(s) declare a direct/custom transport but have no client-side driver and will fall back to the default data source: ${missing.map(k => `\"${k}\"`).join(\", \")}. ` +\n `Provide a \\`driver\\` for them in \\`dataSources\\` on <Rebase>.`\n );\n }\n }, [dataSources]);\n\n // `readOnly` is left undefined unless the developer set it: the controller\n // asks the backend whether its schema editor will accept a write, which is\n // the only process that knows. Deciding it here from `process.env.NODE_ENV`\n // — the *frontend bundle's* build mode — is what made the editor offer\n // itself against production backends, `baas` projects and servers without\n // `ts-morph`, and turned every save into a bare 404.\n const internalConfigController = useLocalCollectionsConfigController(\n rebaseClient,\n resolvedCollections,\n collectionEditorEnabled ? {\n readOnly: collectionEditorOptions?.readOnly,\n getAuthToken: collectionEditorOptions?.getAuthToken ?? authController?.getAuthToken,\n authKey: authController?.user?.uid ?? null\n } : { readOnly: true }\n );\n\n // ── Auto-inject schema view into Studio devViews ──────────────────\n const schemaView: AppView | undefined = useMemo(() => {\n if (!collectionEditorEnabled) return undefined;\n // Only inject when Studio is registered and includes \"schema\" tool (or all tools)\n const studioTools = registry.studioConfig?.tools ?? [\"sql\", \"js\", \"rls\", \"schema\", \"storage\"];\n if (!registry.studioConfig || !studioTools.includes(\"schema\")) return undefined;\n return {\n slug: \"schema\",\n name: \"Edit collections\",\n group: \"Database\",\n icon: \"LayoutList\",\n nestedRoutes: true,\n // Reads the controller from context at render time rather than\n // capturing it here. A view is a React *element*, and the\n // navigation state controller resolves the view list once and holds\n // on to the elements it resolved — so a controller passed as a prop\n // is frozen at whatever it was on the first render, forever. That\n // hid every later change: the editor stayed writable after the\n // backend said it was read-only, and the collection list never\n // refreshed. Everything else in the editor already reads this from\n // `ConfigControllerProvider`, which wraps this subtree.\n view: (\n <Suspense fallback={<CircularProgressCenter/>}>\n <CollectionsStudioViewFromContext/>\n </Suspense>\n )\n };\n }, [collectionEditorEnabled, registry.studioConfig]);\n\n const devViews = useMemo(() => {\n const base = registry.studioConfig?.devViews ?? [];\n if (schemaView) return [...base, schemaView];\n return base;\n }, [registry.studioConfig?.devViews, schemaView]);\n\n // Merge admin-registered views with Studio dev views.\n // Order: admin views (developer's primary content) → Studio dev views (tooling).\n // Plugin views are merged later inside resolveAppViews.\n const cmsViews = registry.cmsConfig?.views;\n const mergedViews = useMemo(() => {\n if (!cmsViews) return devViews;\n if (Array.isArray(cmsViews) && cmsViews.length === 0) return devViews;\n // When cmsViews is a builder function, wrap it to append devViews after resolution\n if (typeof cmsViews === \"function\") {\n return async (params: Parameters<typeof cmsViews>[0]) => {\n const resolved = await cmsViews(params) ?? [];\n return [...resolved, ...devViews];\n };\n }\n return [...cmsViews, ...devViews];\n }, [cmsViews, devViews]);\n\n const parentCustomizationController = useCustomizationController();\n\n const navigationStateController = useBuildNavigationStateController({\n plugins: parentCustomizationController.plugins ?? EMPTY_PLUGINS,\n collections: collectionsBuilder,\n views: mergedViews,\n navigationGroupMappings: registry.cmsConfig?.navigationGroupMappings,\n authController: context.authController!,\n data: routedData,\n collectionRegistryController,\n urlController,\n adminMode: adminModeController?.mode\n });\n\n // ── Merge admin-registered entityViews/entityActions into the customization controller ──\n // The <Rebase> component builds the customizationController from its own props,\n // but entity views passed to <RebaseAdmin> are stored in the registry and not\n // automatically merged. We re-provide an enriched controller here so that\n // downstream consumers (EditViewBinding, side panels, etc.) can resolve\n // string-keyed entity views like \"blog_preview\".\n const enrichedCustomizationController = useMemo(() => {\n const cmsEntityViews = (registry.cmsConfig?.entityViews ?? []) as EntityCustomView[];\n const cmsEntityActions = (registry.cmsConfig?.entityActions ?? []) as EntityAction[];\n // Collection view modes ride the same channel, for the same reason:\n // `admin.customViews: [\"map\"]` has to find the component somewhere.\n const cmsCollectionViews = (registry.cmsConfig?.collectionViews ?? []) as CollectionCustomView[];\n if (cmsEntityViews.length === 0 && cmsEntityActions.length === 0 && cmsCollectionViews.length === 0) {\n return parentCustomizationController;\n }\n return {\n ...parentCustomizationController,\n entityViews: [\n ...(parentCustomizationController.entityViews ?? []),\n ...cmsEntityViews.filter(v => !(parentCustomizationController.entityViews ?? []).some(ev => ev.key === v.key))\n ],\n entityActions: [\n ...(parentCustomizationController.entityActions ?? []),\n ...cmsEntityActions.filter(a => !(parentCustomizationController.entityActions ?? []).some(ea => ea.key === a.key))\n ],\n collectionViews: [\n ...(parentCustomizationController.collectionViews ?? []),\n ...cmsCollectionViews.filter(v => !(parentCustomizationController.collectionViews ?? []).some(cv => cv.key === v.key))\n ]\n };\n }, [parentCustomizationController, registry.cmsConfig?.entityViews, registry.cmsConfig?.entityActions, registry.cmsConfig?.collectionViews]);\n\n // ── Inner content with all context providers ──────────────────────\n // Re-provide RebaseDataContext with the routed data so that every admin\n // consumer (list/entity views, references, board, import/export, and\n // `context.data`) is routed to the correct driver by collection path.\n const navigationContent = (\n <RebaseDataContext.Provider value={routedData}>\n <CustomizationControllerContext.Provider value={enrichedCustomizationController}>\n <StudioBridgeRegistryProvider>\n <CollectionRegistryContext.Provider value={collectionRegistryController}>\n <UrlContext.Provider value={urlController}>\n <NavigationStateContext.Provider value={navigationStateController}>\n <SidePanelProvider>\n <BridgeAutoRegistrar\n collectionRegistryController={collectionRegistryController}\n urlController={urlController}\n navigationStateController={navigationStateController}\n canWriteToCodebase={!internalConfigController.readOnly}\n />\n {children}\n </SidePanelProvider>\n </NavigationStateContext.Provider>\n </UrlContext.Provider>\n </CollectionRegistryContext.Provider>\n </StudioBridgeRegistryProvider>\n </CustomizationControllerContext.Provider>\n </RebaseDataContext.Provider>\n );\n\n // ── Wrap with ConfigControllerProvider when collection editor is enabled ──\n if (collectionEditorEnabled) {\n return (\n <ConfigControllerProvider\n collectionConfigController={internalConfigController}\n pathSuggestions={collectionEditorOptions?.pathSuggestions}\n >\n {navigationContent}\n </ConfigControllerProvider>\n );\n }\n\n return navigationContent;\n}\n\n/**\n * The injected \"Edit collections\" view, bound to the live config controller.\n *\n * Exists so the element stored in the navigation state does not close over a\n * controller instance — see the comment at its construction site.\n */\nfunction CollectionsStudioViewFromContext() {\n const configController = useCollectionsConfigController();\n return <CollectionsStudioView configController={configController}/>;\n}\n\n/**\n * Internal component that auto-registers admin controllers into the\n * self-assembling Studio bridge. Must be rendered inside both the\n * navigation contexts and the StudioBridgeRegistryProvider.\n */\nfunction BridgeAutoRegistrar({\n collectionRegistryController,\n urlController,\n navigationStateController,\n canWriteToCodebase\n}: {\n collectionRegistryController: CollectionRegistryController;\n urlController: UrlController;\n navigationStateController: NavigationStateController;\n canWriteToCodebase: boolean;\n}) {\n useBridgeRegistration(\"collectionRegistry\", collectionRegistryController);\n useBridgeRegistration(\"urlController\", urlController);\n useBridgeRegistration(\"navigationState\", navigationStateController);\n\n // Studio tools that would write into the project's collection source — the\n // RLS editor's policy save for a mapped table, its \"Import to codebase\" —\n // ask the bridge whether that write can land. The default is `true`, which\n // is what an admin panel sitting next to its own `collectionsDir` assumes;\n // it is wrong for exactly the same backends that make the collection editor\n // read-only, so the two now answer from one source.\n const capabilities = useMemo(() => ({ codebase: canWriteToCodebase }), [canWriteToCodebase]);\n useBridgeRegistration(\"capabilities\", capabilities);\n return null;\n}\n","import React from \"react\";\nimport { Outlet } from \"react-router\";\nimport {\n useAdminModeController,\n useComponentOverride,\n useRebaseRegistry\n} from \"@rebasepro/app\";\n\nimport { Scaffold } from \"./app/Scaffold\";\nimport { Drawer } from \"./app/Drawer\";\nimport { SideDialogs } from \"./SideDialogs\";\nimport { AdminModeSyncer } from \"./AdminModeSyncer\";\nimport type { AppView } from \"@rebasepro/admin-types\";\n\nexport interface RebaseLayoutProps {\n /** Title shown in the drawer. */\n title?: string;\n /** Top bar. Only rendered if provided — pass `<AppBar/>` for the default one. */\n appBar?: React.ReactNode;\n /** Custom Drawer to override the default. */\n drawer?: React.ReactNode;\n /** Expand the drawer while the pointer is over it. On by default; pass `false` to opt out. Not a load-time default — that is `defaultDrawerOpen`. */\n autoOpenDrawer?: boolean;\n /** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */\n defaultDrawerOpen?: boolean;\n /** Path to the logo shown in the drawer and top bar. Falls back to the Rebase mark. */\n logo?: string;\n /** Dev views passed to AdminModeSyncer (resolved from RebaseNavigation). */\n devViews?: AppView[];\n}\n\n/**\n * Layout layer — provides the Scaffold, Drawer, and SideDialogs.\n *\n * Wraps the route outlet with the standard Rebase admin layout.\n * Override the drawer via props; pass `appBar` to add a top bar (there is\n * none by default — the drawer owns navigation and user actions).\n *\n * **Independently usable**: Use this when you want the Rebase layout\n * without its default route definitions.\n *\n * @example\n * ```tsx\n * <RebaseLayout title=\"My Admin\" appBar={<AppBar/>}>\n * <Route path=\"/\" element={<MyHomePage />} />\n * <Route path=\"/custom\" element={<CustomView />} />\n * </RebaseLayout>\n * ```\n */\nexport function RebaseLayout(props: RebaseLayoutProps) {\n const {\n title = \"Rebase\",\n appBar,\n drawer,\n autoOpenDrawer = true,\n defaultDrawerOpen = false,\n logo,\n devViews = []\n } = props;\n\n const adminModeController = useAdminModeController();\n const ResolvedDrawer = useComponentOverride(\"Shell.Drawer\", Drawer);\n\n const ActiveDrawer = drawer ?? (\n <ResolvedDrawer\n title={title}\n logoDestination={adminModeController.mode === \"studio\" ? \"/s\" : \"/\"}\n />\n );\n\n return (\n <Scaffold autoOpenDrawer={autoOpenDrawer} defaultDrawerOpen={defaultDrawerOpen} logo={logo}>\n <AdminModeSyncer devViews={devViews}/>\n {appBar}\n {ActiveDrawer}\n <Outlet/>\n <SideDialogs/>\n </Scaffold>\n );\n}\n","import type { NavigationEntry } from \"@rebasepro/admin-types\";\nimport { useNavigate } from \"react-router\";\n;\nimport { Chip, Collapse, StarIcon } from \"@rebasepro/ui\";\nimport { useUserConfigurationPersistence } from \"@rebasepro/app\";\nimport { useNavigationStateController } from \"../../hooks/navigation/contexts/NavigationStateContext\";\n\nfunction NavigationChip({ entry }: { entry: NavigationEntry }) {\n\n const navigate = useNavigate();\n const userConfigurationPersistence = useUserConfigurationPersistence();\n\n if (!userConfigurationPersistence)\n return null;\n\n const favourite = userConfigurationPersistence.favouritePaths.includes(entry.slug);\n const onIconClick = (e: React.SyntheticEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (favourite) {\n userConfigurationPersistence.setFavouritePaths(\n userConfigurationPersistence.favouritePaths.filter(p => p !== entry.slug)\n );\n } else {\n userConfigurationPersistence.setFavouritePaths(\n [...userConfigurationPersistence.favouritePaths, entry.slug]\n );\n }\n };\n return <Chip\n key={entry.slug}\n onClick={() => navigate(entry.url)}\n icon={<StarIcon\n onClick={onIconClick}\n size={\"small\"}\n className={favourite ? \"text-secondary\" : \"text-surface-400 dark:text-surface-500\"}/>\n }>\n {entry.name}\n </Chip>;\n}\n\nexport function FavouritesView({ hidden }: { hidden: boolean }) {\n\n const navigationStateController = useNavigationStateController();\n const userConfigurationPersistence = useUserConfigurationPersistence();\n\n if (!userConfigurationPersistence)\n return null;\n\n const favouriteCollections = (userConfigurationPersistence?.favouritePaths ?? [])\n .map((path) => navigationStateController.topLevelNavigation?.navigationEntries.find((entry) => entry.slug === path))\n .filter(Boolean) as NavigationEntry[];\n\n return <Collapse in={favouriteCollections.length > 0}>\n <div className=\"flex flex-row flex-wrap gap-2 pb-2 min-h-[32px]\">\n {favouriteCollections.map((entry) => <NavigationChip key={entry.slug}\n entry={entry}/>)}\n </div>\n </Collapse>;\n}\n","import React, { PropsWithChildren, useState } from \"react\";\nimport { cls, ExpandablePanel, IconButton, iconSize, PencilIcon, Typography } from \"@rebasepro/ui\";\nimport { useTranslation } from \"@rebasepro/app\";\n\nexport function NavigationGroup({\n children,\n group,\n minimised,\n isPreview,\n isPotentialCardDropTarget,\n onEditGroup,\n dndDisabled,\n collapsed,\n onToggleCollapsed\n}: PropsWithChildren<{\n group: string | undefined,\n minimised?: boolean,\n isPreview?: boolean,\n isPotentialCardDropTarget?: boolean,\n onEditGroup?: (groupName: string) => void;\n dndDisabled?: boolean;\n collapsed?: boolean;\n onToggleCollapsed?: () => void;\n}>) {\n\n const { t } = useTranslation();\n const [isHovered, setIsHovered] = useState(false);\n const currentGroupName = group ?? t(\"views_group\");\n\n // Show caret only when not in preview and there is a toggle handler\n const showCaret = !isPreview && !!onToggleCollapsed;\n\n // Helper for the title content (left side)\n const TitleContent = (\n <div className={cls(\"flex items-center\", isPreview ? \"px-1 py-0.5\" : \"\")}\n >\n <Typography\n variant={isPreview ? \"body2\" : \"caption\"}\n component={\"h2\"}\n color=\"secondary\"\n className={cls(\n \"px-4 py-1 rounded\",\n \"font-medium text-[10px] uppercase tracking-[0.08em] text-primary/50 dark:text-primary/70\"\n )}\n >\n {currentGroupName}\n </Typography>\n {!isPreview && onEditGroup && !dndDisabled && (\n <IconButton\n size=\"smallest\"\n onClick={(e) => {\n e.stopPropagation(); // Prevent toggle on click\n onEditGroup(currentGroupName);\n }}\n className={cls(\"ml-2 \", isHovered ? \"opacity-100\" : \"opacity-0\", \"transition-opacity duration-100\")}\n >\n <PencilIcon size={iconSize.smallest}/>\n </IconButton>\n )}\n </div>\n );\n\n return (\n <div className={cls(\n !isPotentialCardDropTarget ? \"my-10\" : \"my-6\",\n \"transition-all duration-200 ease-in-out\"\n )}\n >\n {/* Preview: static header + content (no caret / no collapse) */}\n {isPreview && (\n <>\n <div\n className={cls(\n \"flex items-center justify-between w-full\",\n \"p-4 py-2\"\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {TitleContent}\n </div>\n {children}\n </>\n )}\n\n {/* Interactive collapsible version when a toggle handler is provided */}\n {!isPreview && showCaret && (\n <ExpandablePanel\n invisible\n expanded={!collapsed}\n onExpandedChange={(open) => {\n if (open !== !collapsed) {\n onToggleCollapsed?.();\n }\n }}\n className={cls(\"mt-6\")}\n titleClassName={cls(\n \"min-h-0 p-0 border-none\",\n \"rounded flex items-center justify-between w-full\",\n \"hover:bg-transparent\",\n \"cursor-pointer select-none\",\n collapsed && \"bg-surface-100 dark:bg-surface-900/50\"\n )}\n innerClassName={cls(\"mt-4\", !minimised ? \"pt-0\" : \"\")}\n title={\n <div\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n className=\"flex items-center\"\n >\n {TitleContent}\n </div>\n }\n >\n {minimised ? (\n <div className={cls(\"mt-4 p-8 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg\")}\n style={{ minHeight: \"50px\" }}>\n </div>\n ) : (\n <div className={cls(\"mt-4\", !minimised ? \"pt-0\" : \"\")}>\n {children}\n </div>\n )}\n </ExpandablePanel>\n )}\n\n {/* Non-collapsible (no caret) runtime, keep old behavior */}\n {!isPreview && !showCaret && (\n <>\n <div\n className={cls(\n \"flex items-center justify-between w-full\",\n \"mt-6\"\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {TitleContent}\n </div>\n\n {!collapsed && (\n minimised ? (\n <div className={cls(\"mt-4 p-8 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg\")}\n style={{ minHeight: \"50px\" }}>\n </div>\n ) : (\n <div className={cls(\"mt-4\", !minimised ? \"pt-0\" : \"\")}>\n {children}\n </div>\n )\n )}\n </>\n )}\n </div>\n );\n}\n","import { ArrowRightIcon, Card, cls, iconSize, Markdown, Typography } from \"@rebasepro/ui\";\nimport React from \"react\";\n\nexport type NavigationCardProps = {\n name: string,\n description?: string;\n actions: React.ReactNode;\n icon: React.ReactNode;\n additionalContent?: React.ReactNode;\n onClick?: () => void,\n shrink?: boolean\n};\n\n// Wrap the component with React.memo\nexport const NavigationCard = React.memo(function NavigationCard({\n name,\n description,\n icon,\n actions,\n additionalContent,\n onClick,\n shrink\n}: NavigationCardProps) {\n\n return (\n <Card\n className={cls(\n \"group h-full p-4 cursor-pointer transition-colors duration-150 ease-in-out\",\n \"hover:bg-primary/5 dark:hover:bg-primary/5\",\n shrink && \"w-full max-w-full min-h-0 scale-75\"\n )}\n onClick={() => {\n onClick?.();\n }}\n >\n\n <div className=\"flex flex-col h-full\">\n {/* Header: title + icon left, actions right */}\n <div className=\"flex items-center w-full justify-between mb-1\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex items-center justify-center w-5 h-5 text-surface-400 dark:text-surface-500 transition-colors duration-150 group-hover:text-primary dark:group-hover:text-primary\">\n {icon}\n </div>\n <Typography variant=\"subtitle1\"\n component=\"h2\">\n {name}\n </Typography>\n </div>\n\n <div\n className=\"flex items-center gap-0.5\"\n onClick={(event: React.MouseEvent) => {\n event.preventDefault();\n event.stopPropagation();\n }}>\n {actions}\n </div>\n </div>\n\n {/* Description */}\n <div className=\"pl-8\">\n {description && <Typography variant=\"caption\"\n color=\"secondary\"\n component=\"div\">\n <Markdown source={description} size={\"small\"}/>\n </Typography>}\n </div>\n\n {additionalContent && (\n <div className=\"pl-8 pointer-events-none\">\n {additionalContent}\n </div>\n )}\n\n {/* Spacer pushes content above to align at the top across grid siblings */}\n <div className=\"grow\"/>\n\n </div>\n\n </Card>)\n});\n","\nimport type { NavigationEntry, AdminCollection } from \"@rebasepro/admin-types\";\nimport { useNavigate } from \"react-router\";\n;\nimport { IconButton, StarIcon, Tooltip } from \"@rebasepro/ui\";\nimport { NavigationCard } from \"./NavigationCard\";\nimport { SmallNavigationCard } from \"./SmallNavigationCard\";\nimport React from \"react\";\nimport { useRebaseContext, useSlot } from \"@rebasepro/app\";\nimport { IconForView } from \"@rebasepro/app\";\nimport { useUserConfigurationPersistence } from \"@rebasepro/app\";\n\n/**\n * This is the component used in the home page to render a card for each\n * collection or view.\n * @group Components\n * @param view\n * @param path\n * @param collection\n * @param url\n * @param name\n * @param description\n * @param onClick\n\n */\nexport function NavigationCardBinding({\n slug,\n collection,\n view,\n url,\n name,\n description,\n onClick,\n type,\n shrink\n}: NavigationEntry & {\n onClick?: () => void,\n shrink?: boolean // <-- add shrink prop type\n}) {\n\n const userConfigurationPersistence = useUserConfigurationPersistence();\n const collectionIcon = <IconForView collectionOrView={collection ?? view} size={\"small\"}/>;\n\n const navigate = useNavigate();\n const context = useRebaseContext();\n\n const favourite = (userConfigurationPersistence?.favouritePaths ?? []).includes(slug);\n\n const actionsArray: React.ReactNode[] = userConfigurationPersistence\n ? [\n <IconButton\n key={\"favourite\"}\n size={\"small\"}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n if (favourite) {\n userConfigurationPersistence.setFavouritePaths(\n userConfigurationPersistence.favouritePaths.filter(p => p !== slug)\n );\n } else {\n userConfigurationPersistence.setFavouritePaths(\n [...userConfigurationPersistence.favouritePaths, slug]\n );\n }\n }}>\n <StarIcon\n className={favourite ? \"text-secondary\" : \"text-surface-400 dark:text-surface-500\"}/>\n </IconButton>\n ]\n : [];\n\n const pluginCardActions = useSlot(\"home.collection.actions\", {\n slug: slug,\n collection: collection!,\n context\n });\n\n const pluginCardWidgets = useSlot(\"home.card.widget\", {\n slug: slug,\n collection: collection!,\n context\n });\n\n const actions: React.ReactNode | undefined = <>\n {actionsArray}\n {pluginCardActions}\n </>\n\n return <NavigationCard\n icon={collectionIcon}\n name={name}\n description={description}\n actions={actions}\n additionalContent={pluginCardWidgets.length > 0 ? <>{pluginCardWidgets}</> : undefined}\n onClick={() => {\n onClick?.();\n navigate(url);\n if (userConfigurationPersistence) {\n userConfigurationPersistence.setRecentlyVisitedPaths(\n [slug, ...(userConfigurationPersistence.recentlyVisitedPaths ?? []).filter(p => p !== slug)]\n );\n }\n }}\n shrink={shrink}\n />;\n}\n","import type { NavigationEntry } from \"@rebasepro/admin-types\";\nimport React, { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n Active,\n Over,\n closestCenter,\n closestCorners,\n CollisionDetection,\n DropAnimation,\n getFirstCollision,\n KeyboardSensor,\n MouseSensor,\n pointerWithin,\n rectIntersection,\n TouchSensor,\n UniqueIdentifier,\n useDndMonitor,\n useDroppable,\n useSensor,\n useSensors\n} from \"@dnd-kit/core\";\nimport {\n AnimateLayoutChanges,\n arrayMove,\n defaultAnimateLayoutChanges,\n rectSortingStrategy,\n SortableContext,\n useSortable\n} from \"@dnd-kit/sortable\";\nimport { CSS } from \"@dnd-kit/utilities\";\n\nimport { NavigationCardBinding } from \"./NavigationCardBinding\";\n;\nimport { cls } from \"@rebasepro/ui\";\n\nconst animateLayoutChanges: AnimateLayoutChanges = (args) =>\n defaultAnimateLayoutChanges({\n ...args,\n wasDragging: true\n });\n\nconst dropAnimationConfig: DropAnimation = {};\n\nconst cloneSerializableNavigationEntry = (entry: NavigationEntry): NavigationEntry => {\n const clonedEntry: Partial<NavigationEntry> = {\n id: entry.id,\n slug: entry.slug,\n url: entry.url,\n name: entry.name,\n type: entry.type,\n collection: entry.collection ? { ...entry.collection } : undefined,\n view: entry.view ? { ...entry.view } : undefined,\n ...(entry.group && { group: entry.group }),\n ...(entry.description && { description: entry.description })\n };\n return clonedEntry as NavigationEntry;\n};\n\nconst cloneItemsForDnd = (items: { name: string; entries: NavigationEntry[] }[]) =>\n items.map((g) => ({\n name: g.name,\n entries: g.entries.map(cloneSerializableNavigationEntry)\n }));\n\n/* ─────────────────────────────────────────────────────────── */\n/* Sortable card & group */\n\n/* ─────────────────────────────────────────────────────────── */\nexport function SortableNavigationCard({\n entry,\n onClick\n}: {\n entry: NavigationEntry;\n onClick?: () => void;\n}) {\n const {\n setNodeRef,\n listeners,\n attributes,\n transform,\n transition,\n isDragging\n } =\n useSortable({\n id: entry.url,\n animateLayoutChanges\n });\n\n const style = {\n transform: transform ? CSS.Transform.toString(transform) : undefined,\n transition,\n opacity: isDragging ? 0 : 1\n };\n\n return (\n <div ref={setNodeRef} style={style} {...attributes} {...listeners}>\n <NavigationCardBinding {...entry} onClick={onClick}/>\n </div>\n );\n}\n\nexport function NavigationGroupDroppable({\n id,\n itemIds,\n children,\n isPotentialCardDropTarget = false\n}: {\n id: UniqueIdentifier;\n itemIds: UniqueIdentifier[];\n children: React.ReactNode;\n isPotentialCardDropTarget?: boolean;\n}) {\n const { setNodeRef } = useDroppable({ id });\n\n return (\n <div\n ref={setNodeRef}\n className={cls(\n isPotentialCardDropTarget\n ? \"p-2 bg-surface-accent-200 dark:bg-surface-accent-800 rounded-lg\"\n : undefined,\n \"transition-all duration-200 ease-in-out\"\n )}\n >\n <SortableContext items={itemIds} strategy={rectSortingStrategy}>\n {children}\n </SortableContext>\n </div>\n );\n}\n\nexport function SortableNavigationGroup({\n groupName,\n children,\n disabled\n}: {\n groupName: string;\n children: React.ReactNode;\n disabled?: boolean;\n}) {\n const {\n attributes,\n listeners,\n setNodeRef,\n transform,\n transition,\n isDragging\n } =\n useSortable({\n id: groupName,\n animateLayoutChanges,\n disabled\n });\n\n const style = {\n transform: transform ? CSS.Transform.toString(transform) : undefined,\n transition,\n opacity: isDragging ? 0 : 1\n };\n\n return (\n <div ref={setNodeRef} style={style} {...attributes} {...listeners}>\n {children}\n </div>\n );\n}\n\nexport function useHomePageDnd({\n items,\n setItems,\n disabled,\n onCardMovedBetweenGroups,\n onGroupMoved,\n onNewGroupDrop,\n onPersist\n}: {\n items: { name: string; entries: NavigationEntry[] }[];\n setItems: (\n newItemsOrUpdater:\n | { name: string; entries: NavigationEntry[] }[]\n | ((\n currentItems: { name: string; entries: NavigationEntry[] }[]\n ) => { name: string; entries: NavigationEntry[] }[])\n ) => void;\n disabled: boolean;\n onCardMovedBetweenGroups?: (card: NavigationEntry) => void;\n onGroupMoved?: (groupName: string, oldIndex: number, newIndex: number) => void;\n onNewGroupDrop?: () => void;\n onPersist?: (latest: { name: string; entries: NavigationEntry[] }[]) => void;\n}) {\n /* ---------------- local state ---------------- */\n const dndItems = items;\n const setDndItems = setItems;\n\n const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);\n const [activeIsGroup, setActiveIsGroup] = useState(false);\n const [currentDraggingGroupId, setCurrentDraggingGroupId] =\n useState<UniqueIdentifier | null>(null);\n const [dndKitActiveNode, setDndKitActiveNode] = useState<Active | null>(null);\n const [isDraggingCardOnly, setIsDraggingCardOnly] = useState(false);\n const [dialogOpenForGroup, setDialogOpenForGroup] = useState<string | null>(null);\n const [isHoveringNewGroupDropZone, setIsHoveringNewGroupDropZone] =\n useState(false);\n const [pendingNewGroupName, setPendingNewGroupName] = useState<string | null>(null);\n const [stateBeforeNewGroup, setStateBeforeNewGroup] = useState<\n { name: string; entries: NavigationEntry[] }[] | null\n >(null);\n\n /* store the original state before any drag modifications */\n const preDragItemsRef = useRef<\n { name: string; entries: NavigationEntry[] }[] | null\n >(null);\n\n /* store interim state for cross-group moves */\n const interimItemsRef = useRef<\n { name: string; entries: NavigationEntry[] }[] | null\n >(null);\n useEffect(() => {\n interimItemsRef.current = dndItems;\n }, [dndItems]);\n\n /* ---------------- sensors ---------------- */\n const mouseSensor = useSensor(MouseSensor, { activationConstraint: { distance: 10 } });\n const touchSensor = useSensor(TouchSensor, {\n activationConstraint: {\n delay: 150,\n tolerance: 5\n }\n });\n const keyboardSensor = useSensor(KeyboardSensor);\n const sensors = useSensors(mouseSensor, touchSensor, keyboardSensor);\n\n /* ---------------- helpers ---------------- */\n const dndContainers = dndItems.map((g) => g.name);\n\n const findDndContainer = useCallback(\n (id: UniqueIdentifier): string | undefined => {\n if (!id) return undefined;\n const group = dndItems.find((g) => g.name === id);\n if (group) return group.name;\n for (const g of dndItems) {\n if (g.entries.some((e) => e.url === id)) return g.name;\n }\n return undefined;\n },\n [dndItems]\n );\n\n /* ---------------- collision detection ---------------- */\n const lastOverId = useRef<UniqueIdentifier | null>(null);\n const recentlyMovedToNewContainer = useRef(false);\n\n const collisionDetection: CollisionDetection = useCallback(\n (args) => {\n if (disabled || !activeId) return [];\n if (activeIsGroup) {\n const groups = args.droppableContainers.filter((c) =>\n dndItems.some((g) => g.name === c.id)\n );\n if (!groups.length) return [];\n return closestCenter({\n ...args,\n droppableContainers: groups\n });\n }\n\n const pointer = pointerWithin(args);\n if (pointer.length) {\n const zone = pointer.find((c) => c.id === \"new-group-drop-zone\");\n if (zone) return [zone];\n\n const container = pointer.find((c) =>\n dndItems.some((g) => g.name === c.id)\n );\n if (container) {\n const itemsIn = dndItems.find((g) => g.name === container.id)\n ?.entries;\n if (itemsIn?.length) {\n const closest = closestCorners({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (c) => itemsIn.some((e) => e.url === c.id)\n )\n });\n if (closest.length) return closest;\n }\n return [container];\n }\n const first = getFirstCollision(pointer, \"id\");\n if (first) return [{ id: first }];\n }\n\n const rects = rectIntersection(args);\n const zoneRect = rects.find((c) => c.id === \"new-group-drop-zone\");\n if (zoneRect) return [zoneRect];\n\n let overId = getFirstCollision(rects, \"id\");\n if (overId != null) {\n const overIsContainer = dndItems.some((g) => g.name === overId);\n if (overIsContainer) {\n const itemsIn = dndItems.find((g) => g.name === overId)\n ?.entries;\n if (itemsIn?.length) {\n const closestItem = closestCorners({\n ...args,\n droppableContainers: args.droppableContainers.filter(\n (c) => itemsIn.some((e) => e.url === c.id)\n )\n })[0]?.id;\n if (closestItem) overId = closestItem;\n }\n }\n lastOverId.current = overId;\n return [{ id: overId }];\n }\n\n if (\n recentlyMovedToNewContainer.current &&\n lastOverId.current &&\n !activeIsGroup\n )\n return [{ id: lastOverId.current }];\n\n return [];\n },\n [activeId, dndItems, disabled, activeIsGroup]\n );\n\n /* ---------------- drag handlers ---------------- */\n const handleDragStart = ({ active }: { active: Active }) => {\n setDndKitActiveNode(active);\n if (disabled) return;\n\n // Capture the original state before any drag modifications\n preDragItemsRef.current = cloneItemsForDnd(dndItems);\n\n const isGroup = dndItems.some((g) => g.name === active.id);\n if (!active.data.current) active.data.current = {};\n active.data.current.type = isGroup ? \"group\" : \"item\";\n\n setActiveId(active.id);\n setActiveIsGroup(isGroup);\n setIsDraggingCardOnly(!isGroup);\n if (isGroup) setCurrentDraggingGroupId(active.id);\n recentlyMovedToNewContainer.current = false;\n };\n\n const handleDragOver = ({\n active,\n over\n }: { active: Active; over: Over | null }) => {\n if (disabled || !over) return;\n\n const activeIdNow = active.id;\n const overIdNow = over.id;\n if (activeIdNow === overIdNow) return;\n if (activeIsGroup) return;\n\n const activeCont = findDndContainer(activeIdNow);\n const overCont = findDndContainer(overIdNow);\n if (!activeCont) return;\n\n if (overCont && activeCont !== overCont) {\n recentlyMovedToNewContainer.current = true;\n lastOverId.current = overIdNow;\n\n // Update state for visual feedback during drag\n setDndItems((current) => {\n const newState = cloneItemsForDnd(current);\n const srcIdx = newState.findIndex((g) => g.name === activeCont);\n const tgtIdx = newState.findIndex((g) => g.name === overCont);\n if (srcIdx === -1 || tgtIdx === -1) return current;\n const src = newState[srcIdx];\n const tgt = newState[tgtIdx];\n const idxInSrc = src.entries.findIndex((e) => e.url === activeIdNow);\n if (idxInSrc === -1) return current;\n const [moved] = src.entries.splice(idxInSrc, 1);\n\n // Calculate insertion position - SAME logic as handleDragEnd\n const overIsContainer = overIdNow === overCont;\n if (overIsContainer) {\n tgt.entries.push(moved);\n } else {\n const overIdx = tgt.entries.findIndex((e) => e.url === overIdNow);\n if (overIdx !== -1) {\n tgt.entries.splice(overIdx, 0, moved);\n } else {\n tgt.entries.push(moved);\n }\n }\n\n return newState;\n });\n } else if (activeCont === overCont) {\n recentlyMovedToNewContainer.current = false;\n }\n };\n\n const handleDragEnd = ({\n active,\n over\n }: { active: Active; over: Over | null }) => {\n if (disabled || !over) {\n resetDragState();\n return;\n }\n\n const activeIdNow = active.id;\n const overIdNow = over.id;\n\n /* ─── group reorder ─── */\n if (activeIsGroup) {\n if (\n activeIdNow !== overIdNow &&\n dndItems.some((g) => g.name === overIdNow)\n ) {\n const from = dndItems.findIndex((g) => g.name === activeIdNow);\n const to = dndItems.findIndex((g) => g.name === overIdNow);\n if (from !== -1 && to !== -1) {\n const newState = arrayMove(dndItems, from, to);\n setDndItems(newState);\n onPersist?.(newState);\n onGroupMoved?.(activeIdNow as string, from, to);\n }\n }\n }\n /* ─── card move ─── */\n else {\n // CRITICAL: Find source container from ORIGINAL pre-drag state, not current (potentially stale) dndItems\n const findContainerInState = (id: string, state: { name: string; entries: NavigationEntry[] }[]): string | undefined => {\n const group = state.find((g) => g.name === id);\n if (group) return group.name;\n for (const g of state) {\n if (g.entries.some((e) => e.url === id)) return g.name;\n }\n return undefined;\n };\n\n const sourceState = preDragItemsRef.current || dndItems;\n const activeCont = findContainerInState(activeIdNow as string, sourceState);\n const overCont = findDndContainer(overIdNow);\n\n /* drop on new-group zone */\n if (overIdNow === \"new-group-drop-zone\") {\n if (activeCont) {\n // Save current state before making changes\n setStateBeforeNewGroup(cloneItemsForDnd(dndItems));\n\n const newState = cloneItemsForDnd(dndItems);\n const srcIdx = newState.findIndex((g) => g.name === activeCont);\n if (srcIdx !== -1) {\n const src = newState[srcIdx];\n const idxInSrc = src.entries.findIndex(\n (e) => e.url === activeIdNow\n );\n if (idxInSrc !== -1) {\n const [dragged] = src.entries.splice(idxInSrc, 1);\n if (src.entries.length === 0) newState.splice(srcIdx, 1);\n\n let tentative = \"New Group\";\n let counter = 1;\n while (newState.some((g) => g.name === tentative))\n tentative = `New Group ${counter++}`;\n\n newState.push({\n name: tentative,\n entries: [dragged]\n });\n\n // Update local state but DON'T persist yet\n setDndItems(newState);\n setPendingNewGroupName(tentative);\n setDialogOpenForGroup(tentative);\n onNewGroupDrop?.();\n }\n }\n }\n }\n /* reorder inside same container */\n else {\n const overCont = findDndContainer(overIdNow);\n if (activeCont === overCont) {\n const grpIdx = dndItems.findIndex((g) => g.name === activeCont);\n if (grpIdx !== -1) {\n const group = dndItems[grpIdx];\n const oldIdx = group.entries.findIndex(\n (e) => e.url === activeIdNow\n );\n let newIdx = group.entries.findIndex(\n (e) => e.url === overIdNow\n );\n if (newIdx === -1 && overIdNow === activeCont)\n newIdx = group.entries.length - 1;\n if (\n oldIdx !== -1 &&\n newIdx !== -1 &&\n oldIdx !== newIdx\n ) {\n const reordered = arrayMove(group.entries, oldIdx, newIdx);\n const newState = [...dndItems];\n newState[grpIdx] = {\n ...group,\n entries: reordered\n };\n setDndItems(newState);\n onPersist?.(newState);\n }\n }\n } else if (overCont && activeCont !== overCont) {\n // Card moved between different groups - use CLEAN pre-drag state\n const finalState = cloneItemsForDnd(sourceState);\n\n // Find target container from clean state too\n const finalOverId = lastOverId.current || overIdNow;\n const cleanOverCont = findContainerInState(finalOverId as string, sourceState) || overCont;\n\n const srcIdx = finalState.findIndex((g) => g.name === activeCont);\n const tgtIdx = finalState.findIndex((g) => g.name === cleanOverCont);\n\n if (srcIdx !== -1 && tgtIdx !== -1) {\n const src = finalState[srcIdx];\n const tgt = finalState[tgtIdx];\n const idxInSrc = src.entries.findIndex((e) => e.url === activeIdNow);\n\n if (idxInSrc !== -1) {\n // Remove from source\n const [moved] = src.entries.splice(idxInSrc, 1);\n\n // Calculate insertion position in target\n const overIsContainer = finalOverId === cleanOverCont;\n if (overIsContainer) {\n tgt.entries.push(moved);\n } else {\n const overIdx = tgt.entries.findIndex((e) => e.url === finalOverId);\n if (overIdx !== -1) {\n tgt.entries.splice(overIdx, 0, moved);\n } else {\n tgt.entries.push(moved);\n }\n }\n\n // Remove empty source group if needed\n if (src.entries.length === 0) {\n finalState.splice(srcIdx, 1);\n }\n\n setDndItems(finalState);\n onPersist?.(finalState);\n\n onCardMovedBetweenGroups?.(moved);\n }\n }\n } else if (recentlyMovedToNewContainer.current) {\n // This shouldn't happen but log it for debugging\n console.error(\"Move between containers detected but conditions not met\", {\n activeCont,\n overCont,\n activeIdNow,\n overIdNow\n });\n }\n }\n }\n\n resetDragState();\n };\n\n const resetDragState = () => {\n setDndKitActiveNode(null);\n setActiveId(null);\n setActiveIsGroup(false);\n setCurrentDraggingGroupId(null);\n setIsDraggingCardOnly(false);\n recentlyMovedToNewContainer.current = false;\n };\n\n const handleDragCancel = () => resetDragState();\n\n /* ---------------- group rename ---------------- */\n const handleRenameGroup = (oldName: string, newName: string) => {\n setDndItems((current) => {\n const idx = current.findIndex((g) => g.name === oldName);\n if (idx === -1) return current;\n if (current.some((g) => g.name === newName && g.name !== oldName))\n return current;\n\n const updated = [...current];\n updated[idx] = {\n ...updated[idx],\n name: newName\n };\n\n // Persist after successful rename\n onPersist?.(updated);\n return updated;\n });\n\n // Clear all pending state\n setPendingNewGroupName(null);\n setStateBeforeNewGroup(null);\n setDialogOpenForGroup(null);\n };\n\n /* Handle dialog close without renaming */\n const handleDialogClose = () => {\n // If there's a pending new group that wasn't renamed, restore previous state\n if (pendingNewGroupName && dialogOpenForGroup === pendingNewGroupName && stateBeforeNewGroup) {\n // Restore the state from before the new group was created\n setDndItems(stateBeforeNewGroup);\n }\n\n // Clear all pending state\n setPendingNewGroupName(null);\n setStateBeforeNewGroup(null);\n setDialogOpenForGroup(null);\n };\n\n /* ---------------- public API ---------------- */\n const activeItemForOverlay =\n disabled || !activeId || activeIsGroup\n ? null\n : dndItems.flatMap((g) => g.entries).find((e) => e.url === activeId) || null;\n\n const activeGroupData =\n disabled || !activeId || !activeIsGroup\n ? null\n : dndItems.find((g) => g.name === activeId) || null;\n\n return {\n sensors,\n collisionDetection,\n onDragStart: handleDragStart,\n onDragOver: handleDragOver,\n onDragEnd: handleDragEnd,\n onDragCancel: handleDragCancel,\n dropAnimation: dropAnimationConfig,\n activeItemForOverlay,\n activeGroupData,\n draggingGroupId: currentDraggingGroupId,\n containers: dndContainers,\n dndKitActiveNode,\n isDraggingCardOnly,\n dialogOpenForGroup,\n setDialogOpenForGroup,\n handleRenameGroup,\n handleDialogClose,\n isHoveringNewGroupDropZone,\n setIsHoveringNewGroupDropZone\n };\n}\n\nexport function NewGroupDropZone({\n disabled,\n setIsHovering\n}: {\n disabled: boolean;\n setIsHovering: (v: boolean) => void;\n}) {\n const {\n setNodeRef,\n isOver\n } = useDroppable({\n id: \"new-group-drop-zone\",\n disabled\n });\n const [isVisible, setIsVisible] = useState(false);\n\n useDndMonitor({\n onDragStart({ active }) {\n if (disabled) return;\n const tp = active.data.current?.type;\n setIsVisible(tp === \"item\");\n },\n onDragEnd() {\n setIsVisible(false);\n },\n onDragCancel() {\n setIsVisible(false);\n }\n });\n\n useEffect(() => {\n setIsHovering(isOver && isVisible);\n }, [isOver, isVisible, setIsHovering]);\n\n if (!isVisible || disabled) return null;\n\n return (\n <div\n ref={setNodeRef}\n className={cls(\n \"fixed right-8 top-1/2 -translate-y-1/2 w-[200px] h-[120px] border border-dashed rounded-lg flex items-center justify-center transition-all\",\n isOver\n ? \"bg-surface-accent-100 dark:bg-surface-accent-800 border-surface-300 dark:border-surface-600\"\n : \"bg-surface-50 dark:bg-surface-900 border-surface-200 dark:border-surface-700\"\n )}>\n <div className=\"text-center p-4\">\n <span className=\"block font-medium text-sm\">\n Drop here to create a new group\n </span>\n </div>\n </div>\n );\n}\n","import React, { useEffect, useRef, useState } from \"react\";\nimport { Button, Dialog, DialogActions, DialogContent, DialogTitle, TextField } from \"@rebasepro/ui\";\nimport { useTranslation } from \"@rebasepro/app\";\n\ninterface RenameGroupDialogProps {\n open: boolean;\n initialName: string;\n existingGroupNames: string[]; // Names of other existing groups to check for duplicates\n onClose: () => void;\n onRename: (newName: string) => void;\n}\n\nexport function RenameGroupDialog({\n open,\n initialName,\n existingGroupNames,\n onClose,\n onRename\n}: RenameGroupDialogProps) {\n const { t } = useTranslation();\n const [name, setName] = useState(initialName);\n const [error, setError] = useState<string | null>(null);\n const inputRef = useRef<HTMLInputElement | HTMLTextAreaElement | null>(null); // Create a ref for the input\n\n useEffect(() => {\n if (open) {\n setName(initialName);\n setError(null);\n // Focus and select text when dialog opens\n setTimeout(() => { // setTimeout to ensure the input is rendered and focusable\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, 100);\n }\n }, [initialName, open]);\n\n const handleNameChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n const newName = event.target.value;\n setName(newName);\n if (!newName.trim()) {\n setError(t(\"group_name_empty_error\"));\n } else if (existingGroupNames.includes(newName.trim())) {\n setError(t(\"group_name_exists_error\"));\n } else {\n setError(null);\n }\n };\n\n const handleSave = () => {\n const trimmedName = name.trim();\n if (!trimmedName) {\n setError(t(\"group_name_empty_error\"));\n return;\n }\n if (existingGroupNames.includes(trimmedName)) {\n setError(t(\"group_name_exists_error\"));\n return;\n }\n if (!error) {\n onRename(trimmedName);\n onClose();\n }\n };\n\n const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n if (event.key === \"Enter\") {\n event.preventDefault(); // Prevent default form submission behavior\n const trimmedName = name.trim();\n // We need to check the error state directly as well,\n // because the error state might not have updated if the user types and immediately hits enter.\n let currentError = null;\n if (!trimmedName) {\n currentError = t(\"group_name_empty_error\");\n } else if (existingGroupNames.includes(trimmedName)) {\n currentError = t(\"group_name_exists_error\");\n }\n\n if (!currentError && trimmedName) {\n handleSave();\n } else if (currentError) {\n setError(currentError); // Ensure error is displayed if trying to submit with Enter\n }\n }\n };\n\n const handleClose = () => {\n setName(initialName);\n setError(null);\n onClose();\n };\n\n if (!open) return null;\n\n return (\n <Dialog open={open}>\n <DialogTitle>{t(\"rename_group\")}</DialogTitle>\n <DialogContent>\n <TextField\n inputRef={inputRef} // Pass the ref to the TextField\n label={t(\"group_name_label\")}\n value={name}\n onChange={handleNameChange}\n onKeyDown={handleKeyDown} // Added onKeyDown handler\n error={!!error}\n aria-describedby={error ? \"group-name-error\" : undefined}\n />\n {error && <p id=\"group-name-error\" style={{ display: \"none\" }}>{error}</p>}\n </DialogContent>\n <DialogActions>\n <Button onClick={onClose}\n variant=\"text\">\n {t(\"cancel\")}\n </Button>\n <Button onClick={handleSave}\n disabled={!!error || !name.trim()}>\n {t(\"save\")}\n </Button>\n </DialogActions>\n </Dialog>\n );\n}\n","import type { HomePageSection, NavigationEntry, NavigationGroupMapping, PluginGenericProps } from \"@rebasepro/admin-types\";\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport Fuse from \"fuse.js\";\nimport { Container, SearchBar } from \"@rebasepro/ui\";\nimport { AnalyticsEvent } from \"@rebasepro/admin-types\";\nimport { FavouritesView } from \"./FavouritesView\";\nimport { ErrorBoundary } from \"@rebasepro/ui\";\nimport { NavigationGroup } from \"./NavigationGroup\";\nimport {\n NavigationGroupDroppable,\n NewGroupDropZone,\n SortableNavigationCard,\n SortableNavigationGroup,\n useHomePageDnd\n} from \"./HomePageDnD\";\nimport { DndContext, DragOverlay, MeasuringStrategy } from \"@dnd-kit/core\";\nimport { NavigationCardBinding } from \"./NavigationCardBinding\";\nimport { SortableContext, verticalListSortingStrategy } from \"@dnd-kit/sortable\";\nimport { restrictToVerticalAxis, restrictToWindowEdges } from \"@dnd-kit/modifiers\";\nimport { RenameGroupDialog } from \"./RenameGroupDialog\";\nimport { toArray } from \"@rebasepro/utils\";\nimport { useCollapsedGroups, buildCollapsedDefaults, useCustomizationController, useTranslation, useSlot, useAdminModeController, useRebaseRegistry } from \"@rebasepro/app\";\nimport { useRestoreScroll } from \"@rebasepro/app\";\n\nimport { SchemaDriftBanner } from \"@rebasepro/app\";\nimport { useBreadcrumbsController } from \"../../hooks/useBreadcrumbsController\";\nimport { useAdminContext } from \"../../hooks/useAdminContext\";\n\nexport const DEFAULT_GROUP_NAME = \"Views\";\nexport const ADMIN_GROUP_NAME = \"Admin\";\n\nexport function ContentHomePage({\n additionalActions,\n additionalChildrenStart,\n additionalChildrenEnd,\n sections,\n hiddenGroups\n}: {\n additionalActions?: React.ReactNode;\n additionalChildrenStart?: React.ReactNode;\n additionalChildrenEnd?: React.ReactNode;\n sections?: HomePageSection[];\n hiddenGroups?: string[];\n}) {\n\n const context = useAdminContext();\n const { navigationStateController } = context;\n const customizationController = useCustomizationController();\n const adminModeController = useAdminModeController();\n const registry = useRebaseRegistry();\n\n const { resolvedSlots } = customizationController;\n const breadcrumbs = useBreadcrumbsController();\n const { t } = useTranslation();\n\n useEffect(() => {\n breadcrumbs.set({ breadcrumbs: [] });\n }, [breadcrumbs.set]);\n\n const {\n allowDragAndDrop = false,\n navigationEntries: unFilteredNavigationEntries = [],\n groups: unFilteredGroupOrder = [],\n onNavigationEntriesUpdate = () => {}\n } = navigationStateController.topLevelNavigation || {};\n\n // Build a set of Studio-only dev view slugs so we can distinguish them from\n // admin custom views added via <RebaseAdmin views={...}> or plugins.\n const studioViewSlugs = useMemo(() => {\n const slugs = new Set<string>();\n (registry.studioConfig?.devViews ?? []).forEach(v => slugs.add(v.slug));\n if (registry.studioConfig && registry.cmsConfig?.collectionEditor) slugs.add(\"schema\");\n return slugs;\n }, [registry.studioConfig, registry.cmsConfig?.collectionEditor]);\n\n // Studio mode shows Studio dev views + admin entries (Users/Roles).\n // Content mode shows collections, admin custom views, and admin entries — but not Studio dev views.\n const rawNavigationEntries = useMemo(() => {\n if (adminModeController.mode === \"studio\") {\n return unFilteredNavigationEntries.filter(e => (e.type === \"view\" && studioViewSlugs.has(e.slug)) || e.type === \"admin\");\n }\n return unFilteredNavigationEntries.filter(e => e.type !== \"view\" || !studioViewSlugs.has(e.slug));\n }, [unFilteredNavigationEntries, adminModeController.mode, studioViewSlugs]);\n\n const groupOrderFromNavController = useMemo(() => {\n const entryGroups = new Set(rawNavigationEntries.map(e => e.group).filter(Boolean));\n return unFilteredGroupOrder.filter(g => entryGroups.has(g));\n }, [unFilteredGroupOrder, rawNavigationEntries]);\n\n const fuse = useRef<Fuse<NavigationEntry> | null>(null);\n const [filteredUrls, setFilteredUrls] = useState<string[] | null>(null);\n const performingSearch = Boolean(filteredUrls);\n\n // Memoize filtered navigation entries to prevent unnecessary recalculations\n const filteredNavigationEntries = useMemo(() => {\n return filteredUrls\n ? rawNavigationEntries.filter((e) => filteredUrls.includes(e.url))\n : rawNavigationEntries;\n }, [filteredUrls, rawNavigationEntries]);\n\n useEffect(() => {\n fuse.current = new Fuse(rawNavigationEntries, {\n keys: [\"name\", \"description\", \"group\", \"path\"]\n });\n }, [rawNavigationEntries]);\n\n const updateSearch = useCallback((v?: string) => {\n if (!v?.trim()) {\n setFilteredUrls(null);\n return;\n }\n const results = fuse.current?.search(v.trim());\n setFilteredUrls(results ? results.map((x) => x.item.url) : []);\n }, []);\n\n /* ───────────────────────────────────────────────────────────────\n Build groups (all items) + isolate Admin\n ─────────────────────────────────────────────────────────────── */\n const [items, setItems] = useState<\n { name: string; entries: NavigationEntry[] }[]\n >([]);\n const [adminGroupData, setAdminGroupData] = useState<{\n name: string;\n entries: NavigationEntry[];\n } | null>(null);\n\n // Flag to prevent useEffect from overwriting local DnD state\n const isDndDirtyRef = useRef(false);\n const dndDirtyTimeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n // Memoize the processed groups to avoid unnecessary recalculations\n const processedGroups = useMemo(() => {\n const src = filteredNavigationEntries;\n const entriesByGroup: Record<string, NavigationEntry[]> = {};\n\n src.forEach((e) => {\n const g =\n e.type === \"admin\"\n ? ADMIN_GROUP_NAME\n : e.group ?? DEFAULT_GROUP_NAME;\n (entriesByGroup[g] ??= []).push(e);\n });\n\n // Check if there are custom additional card components from plugins\n const hasPluginAdditionalCards = customizationController.resolvedSlots.some(s => s.slot === \"home.cards\");\n\n let allProcessed: { name: string; entries: NavigationEntry[] }[];\n\n if (performingSearch) {\n const ordered = [\n ...new Set(src.map((e) => e.group ?? DEFAULT_GROUP_NAME))\n ];\n allProcessed = ordered\n .map((name) => ({\n name,\n entries: entriesByGroup[name] || []\n }))\n .filter((g) => g.entries.length);\n } else {\n allProcessed = groupOrderFromNavController.map((g) => ({\n name: g,\n entries: entriesByGroup[g] || []\n }));\n Object.keys(entriesByGroup).forEach((g) => {\n if (!groupOrderFromNavController.includes(g))\n allProcessed.push({\n name: g,\n entries: entriesByGroup[g]\n });\n });\n\n // Ensure default group exists if there are plugin additional cards but no collections\n if (hasPluginAdditionalCards && !allProcessed.some(g => g.name === DEFAULT_GROUP_NAME)) {\n allProcessed.push({\n name: DEFAULT_GROUP_NAME,\n entries: []\n });\n }\n\n allProcessed = allProcessed.filter(\n (g) =>\n g.entries.length ||\n (g.name === DEFAULT_GROUP_NAME && hasPluginAdditionalCards)\n );\n }\n\n const admin = allProcessed.find((g) => g.name === ADMIN_GROUP_NAME);\n return {\n adminGroupData: admin || null,\n items: allProcessed.filter((g) => g.name !== ADMIN_GROUP_NAME && !hiddenGroups?.includes(g.name))\n };\n }, [filteredNavigationEntries, performingSearch, groupOrderFromNavController, customizationController.resolvedSlots, hiddenGroups]);\n\n // Update state only when processedGroups actually changes\n // Skip update if DnD just made a local change (dirty flag is set)\n useEffect(() => {\n if (isDndDirtyRef.current) {\n // DnD just updated the state, skip this sync\n return;\n }\n setAdminGroupData(processedGroups.adminGroupData);\n setItems(processedGroups.items);\n }, [processedGroups]);\n\n /* ───────────────────────────────────────────────────────────────\n Local update vs. persistence helpers\n ─────────────────────────────────────────────────────────────── */\n const updateItems = (\n updater:\n | { name: string; entries: NavigationEntry[] }[]\n | ((\n prev: { name: string; entries: NavigationEntry[] }[]\n ) => { name: string; entries: NavigationEntry[] }[])\n ) => {\n setItems(updater); // local only\n };\n\n const persistNavigationGroups = (\n latest: { name: string; entries: NavigationEntry[] }[]\n ) => {\n // Set dirty flag to prevent useEffect from overwriting local state\n isDndDirtyRef.current = true;\n\n // Clear any existing timeout\n if (dndDirtyTimeoutRef.current) {\n clearTimeout(dndDirtyTimeoutRef.current);\n }\n\n // Clear dirty flag after a delay to allow navigation to update\n dndDirtyTimeoutRef.current = setTimeout(() => {\n isDndDirtyRef.current = false;\n }, 1000);\n\n // Map ALL groups including \"Views\"\n const draggable: NavigationGroupMapping[] = latest.map((g) => ({\n name: g.name,\n entries: g.entries.map((e) => e.slug)\n }));\n\n const all: NavigationGroupMapping[] = adminGroupData\n ? [\n ...draggable,\n {\n name: adminGroupData.name,\n entries: adminGroupData.entries.map((e) => e.slug)\n }\n ]\n : draggable;\n\n onNavigationEntriesUpdate(all);\n };\n\n // Use custom hook for collapsed groups with localStorage persistence\n const groupNames = useMemo(() => [\n ...items.map(item => item.name),\n ...(adminGroupData ? [adminGroupData.name] : [])\n ], [items, adminGroupData]);\n\n const collapsedDefaults = useMemo(\n () => buildCollapsedDefaults(registry.cmsConfig?.navigationGroupMappings, \"home\"),\n [registry.cmsConfig?.navigationGroupMappings]\n );\n const { isGroupCollapsed, toggleGroupCollapsed } = useCollapsedGroups(groupNames, \"home\", collapsedDefaults);\n\n const {\n sensors,\n collisionDetection,\n onDragStart,\n onDragOver,\n onDragEnd,\n dropAnimation,\n activeItemForOverlay,\n activeGroupData,\n draggingGroupId,\n containers,\n dndKitActiveNode,\n onDragCancel,\n isDraggingCardOnly,\n dialogOpenForGroup,\n setDialogOpenForGroup,\n handleRenameGroup,\n handleDialogClose,\n isHoveringNewGroupDropZone,\n setIsHoveringNewGroupDropZone\n } = useHomePageDnd({\n items,\n setItems: updateItems,\n disabled: !allowDragAndDrop || performingSearch,\n onPersist: persistNavigationGroups,\n onGroupMoved: (g) =>\n context.analyticsController?.onAnalyticsEvent?.(\"home_move_group\", {\n name: g\n }),\n onCardMovedBetweenGroups: (card) =>\n context.analyticsController?.onAnalyticsEvent?.(\"home_move_card\", {\n id: card.id\n }),\n onNewGroupDrop: () =>\n context.analyticsController?.onAnalyticsEvent?.(\n \"home_drop_new_group\"\n )\n });\n\n const {\n containerRef,\n direction\n } = useRestoreScroll();\n\n const dndDisabled = !allowDragAndDrop || performingSearch;\n\n const dndModifiers = dndKitActiveNode?.data.current?.type === \"group\"\n ? [restrictToVerticalAxis, restrictToWindowEdges]\n : [restrictToWindowEdges];\n\n const sectionProps: PluginGenericProps = { context };\n const additionalPluginChildrenStart = useSlot(\"home.children.start\", sectionProps);\n const additionalPluginChildrenEnd = useSlot(\"home.children.end\", sectionProps);\n const additionalPluginActions = useSlot(\"home.actions\", sectionProps);\n\n // Pre-compute home.cards slot contributions (cannot call useSlot inside .map loop)\n const homeCardContributions = useMemo(() => {\n return resolvedSlots\n .filter(s => s.slot === \"home.cards\")\n .sort((a, b) => (a.order ?? 50) - (b.order ?? 50));\n }, [resolvedSlots]);\n\n /* ───────────────────────────────────────────────────────────────\n Render\n ─────────────────────────────────────────────────────────────── */\n return (\n <div ref={containerRef} className=\"py-2 overflow-auto h-full w-full bg-surface-50 dark:bg-surface-800\">\n <Container maxWidth=\"6xl\">\n <div className=\"mb-4 flex flex-col gap-2\">\n <SchemaDriftBanner />\n </div>\n {/* search & actions */}\n <div\n className=\"w-full sticky py-4 transition-all duration-400 ease-in-out top-0 z-10 flex flex-row gap-4\"\n style={{ top: direction === \"down\" ? -84 : 0 }}\n >\n <SearchBar\n onTextSearch={updateSearch}\n placeholder={t(\"search_collections\")}\n autoFocus\n size=\"small\"\n innerClassName=\"w-full\"\n className=\"w-full grow\"\n />\n {additionalActions}\n {additionalPluginActions}\n </div>\n\n <FavouritesView hidden={performingSearch}/>\n\n {additionalChildrenStart}\n {additionalPluginChildrenStart}\n\n {/* ─────── DND context ─────── */}\n <DndContext\n sensors={sensors}\n collisionDetection={collisionDetection}\n measuring={{\n droppable: {\n strategy: MeasuringStrategy.Always,\n frequency: 500\n }\n }}\n onDragStart={onDragStart}\n onDragOver={onDragOver}\n onDragEnd={onDragEnd}\n onDragCancel={onDragCancel}\n modifiers={dndModifiers}\n >\n <SortableContext\n key={containers.join(\",\")}\n items={containers}\n strategy={verticalListSortingStrategy}\n >\n {items.map((groupData, groupIndex) => {\n const groupKey = groupData.name;\n const entriesInGroup = groupData.entries;\n\n const homeCardsProps = {\n group:\n groupKey === DEFAULT_GROUP_NAME\n ? undefined\n : groupKey,\n context\n };\n // Render home.cards contributions inline (no hook call inside loop)\n const additionalCards = homeCardContributions.map((s, i) => (\n <ErrorBoundary key={`home_cards_${groupKey}_${i}`}>\n <s.Component {...homeCardsProps} {...(s.props ?? {})}/>\n </ErrorBoundary>\n ));\n\n if (\n entriesInGroup.length === 0 &&\n (additionalCards.length === 0 || performingSearch)\n )\n return null;\n\n return (\n <SortableNavigationGroup\n key={`group-${groupIndex}`}\n groupName={groupKey}\n disabled={dndDisabled}\n >\n <NavigationGroup\n group={\n groupKey === DEFAULT_GROUP_NAME\n ? undefined\n : groupKey\n }\n minimised={\n draggingGroupId === groupKey &&\n !isDraggingCardOnly\n }\n isPotentialCardDropTarget={\n isDraggingCardOnly\n }\n dndDisabled={dndDisabled}\n onEditGroup={() => {\n if (dndDisabled) return;\n setDialogOpenForGroup(groupKey);\n }}\n collapsed={isGroupCollapsed(groupKey)}\n onToggleCollapsed={() => toggleGroupCollapsed(groupKey)}\n >\n <NavigationGroupDroppable\n id={groupKey}\n itemIds={entriesInGroup.map(\n (e) => e.url\n )}\n isPotentialCardDropTarget={\n isDraggingCardOnly\n }\n >\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 \">\n {entriesInGroup.map(\n (entry) => (\n <SortableNavigationCard\n key={entry.url}\n entry={entry}\n onClick={() => {\n let event: AnalyticsEvent =\n \"unmapped_event\";\n if (\n entry.type ===\n \"collection\"\n )\n event =\n \"home_navigate_to_collection\";\n else if (\n entry.type ===\n \"view\"\n )\n event =\n \"home_navigate_to_view\";\n else if (\n entry.type ===\n \"admin\"\n )\n event =\n \"home_navigate_to_admin_view\";\n\n context.analyticsController?.onAnalyticsEvent?.(\n event,\n {\n path: entry.slug\n }\n );\n }}\n />\n )\n )}\n {!performingSearch &&\n groupKey.toLowerCase() !==\n ADMIN_GROUP_NAME.toLowerCase() &&\n additionalCards}\n </div>\n </NavigationGroupDroppable>\n </NavigationGroup>\n </SortableNavigationGroup>\n );\n })}\n </SortableContext>\n\n <NewGroupDropZone\n disabled={dndDisabled}\n setIsHovering={setIsHoveringNewGroupDropZone}\n />\n\n <DragOverlay adjustScale={false} dropAnimation={dropAnimation}>\n {activeGroupData &&\n draggingGroupId === activeGroupData.name ? (\n <div\n className=\"rounded-lg bg-transparent\"\n style={{\n padding: 0,\n margin: 0\n }}\n >\n <NavigationGroup\n group={\n activeGroupData.name ===\n DEFAULT_GROUP_NAME\n ? undefined\n : activeGroupData.name\n }\n isPreview={false}\n minimised\n />\n </div>\n ) : activeItemForOverlay ? (\n <NavigationCardBinding\n {...activeItemForOverlay}\n shrink={isHoveringNewGroupDropZone}\n />\n ) : null}\n </DragOverlay>\n </DndContext>\n\n {!performingSearch && adminGroupData && (\n <NavigationGroup\n group={adminGroupData.name}\n collapsed={isGroupCollapsed(adminGroupData.name)}\n onToggleCollapsed={() => toggleGroupCollapsed(adminGroupData.name)}\n >\n <div className=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 \">\n {adminGroupData.entries.map((entry) => (\n <NavigationCardBinding\n key={entry.url}\n {...entry}\n onClick={() => {\n let event: AnalyticsEvent =\n \"unmapped_event\";\n if (entry.type === \"collection\")\n event =\n \"home_navigate_to_collection\";\n else if (entry.type === \"view\")\n event = \"home_navigate_to_view\";\n else if (entry.type === \"admin\")\n event =\n \"home_navigate_to_admin_view\";\n\n context.analyticsController?.onAnalyticsEvent?.(\n event,\n { path: entry.slug }\n );\n }}\n />\n ))}\n </div>\n </NavigationGroup>\n )}\n\n {sections && sections.map((section) => (\n <NavigationGroup\n key={section.key}\n group={section.title}\n >\n {section.children}\n </NavigationGroup>\n ))}\n\n {additionalPluginChildrenEnd}\n {additionalChildrenEnd}\n </Container>\n\n {dialogOpenForGroup && (\n <RenameGroupDialog\n open\n initialName={dialogOpenForGroup}\n existingGroupNames={items\n .map((g) => g.name)\n .filter((n) => n !== dialogOpenForGroup)}\n onClose={handleDialogClose}\n onRename={(newName) => {\n handleRenameGroup(dialogOpenForGroup, newName);\n }}\n />\n )}\n </div>\n );\n}\n","import React, { Suspense } from \"react\";\nimport { lazyChunk } from \"@rebasepro/ui\";\nimport { useCollectionEditorDialogsState } from \"../collection_editor/CollectionEditorDialogsContext\";\n\n// Dynamic imports targeting the separate collection_editor_ui entry point.\n// This ensures the heavy editor UI lands in its own chunk and is only fetched\n// when a dialog is actually opened.\nconst CollectionEditorDialog = lazyChunk(() =>\n import(\"../collection_editor/ui/collection_editor/CollectionEditorDialog\")\n .then(m => ({ default: m.CollectionEditorDialog }))\n);\n\nconst PropertyFormDialog = lazyChunk(() =>\n import(\"../collection_editor/ui/collection_editor/PropertyEditView\")\n .then(m => ({ default: m.PropertyFormDialog }))\n);\n\n/**\n * Renders the CollectionEditorDialog and PropertyFormDialog inside\n * the RebaseShell tree where admin-internal contexts\n * (CollectionRegistryContext, NavigationStateContext, UrlContext)\n * are available.\n *\n * Both dialog components are loaded dynamically via React.lazy so that\n * production admin bundles that never open the collection editor don't pay\n * the download/parse cost up-front.\n *\n * The dialog state (open/close, props) is managed by ConfigControllerProvider\n * (a root-scope plugin provider that wraps the shell) and exposed via\n * CollectionEditorDialogsContext.\n */\nexport function CollectionEditorDialogs() {\n const state = useCollectionEditorDialogsState();\n\n if (!state) return null;\n\n const { collectionDialogProps, propertyDialogProps } = state;\n\n // Don't even mount the Suspense boundary until a dialog is actually open.\n const hasOpenDialog =\n collectionDialogProps?.open || propertyDialogProps?.open;\n\n if (!hasOpenDialog) return null;\n\n return (\n <Suspense fallback={null}>\n {collectionDialogProps?.open && (\n <CollectionEditorDialog\n open={false}\n isNewCollection={false}\n configController={undefined!}\n handleClose={() => {}}\n {...collectionDialogProps}\n />\n )}\n {propertyDialogProps?.open && (\n <PropertyFormDialog\n open={false}\n existingProperty={false}\n autoOpenTypeSelect={false}\n inArray={false}\n allowDataInference={false}\n propertyConfigs={{}}\n {...propertyDialogProps}\n />\n )}\n </Suspense>\n );\n}\n","import React, { lazy, Suspense, useMemo } from \"react\";\nimport { Route } from \"react-router\";\nimport {\n useRebaseRegistry,\n RebaseRoutes,\n UserSettingsView,\n UIReferenceView,\n NotFoundPage,\n useComponentOverride\n} from \"@rebasepro/app\";\nimport { CircularProgressCenter } from \"@rebasepro/ui\";\n\nimport { ContentHomePage as DefaultHomePage } from \"./HomePage/ContentHomePage\";\n\nimport { RebaseRoute } from \"../routes/RebaseRoute\";\nimport { CustomViewRoute } from \"../routes/CustomViewRoute\";\nimport { useNavigationStateController } from \"../hooks/navigation/contexts/NavigationStateContext\";\nimport { CollectionEditorDialogs } from \"./CollectionEditorDialogs\";\nimport { useEffect } from \"react\";\nimport { useTranslation } from \"@rebasepro/app\";\nimport { useBreadcrumbsController } from \"../hooks/useBreadcrumbsController\";\n\nfunction SettingsView() {\n const { t } = useTranslation();\n const breadcrumbs = useBreadcrumbsController();\n useEffect(() => {\n breadcrumbs.set({\n breadcrumbs: [{ title: t(\"account_settings\"),\nurl: \"/settings\" }]\n });\n\n }, []);\n return <UserSettingsView/>;\n}\n\nexport interface RebaseRouteDefsProps {\n /** User-provided custom routes to include. */\n children?: React.ReactNode;\n /**\n * Wrap function — receives the route tree and lets you wrap it in a layout.\n * If provided, the routes are rendered inside this wrapper.\n * If not provided, routes are rendered directly inside <RebaseRoutes>.\n */\n layout?: React.ReactElement;\n}\n\n/**\n * Route definitions for the admin.\n *\n * Defines all standard routes: home, studio home, collection view,\n * settings, debug, custom views, and a catch-all 404.\n *\n * **Independently usable**: Use this when you want Rebase routes\n * inside your own layout/navigation setup.\n *\n * @example\n * ```tsx\n * <RebaseNavigation>\n * <RebaseRouteDefs layout={<MyCustomLayout />}>\n * <Route path=\"/my-custom\" element={<MyView />} />\n * </RebaseRouteDefs>\n * </RebaseNavigation>\n * ```\n */\nexport function RebaseRouteDefs({ children, layout }: RebaseRouteDefsProps) {\n const registry = useRebaseRegistry();\n const navigationStateController = useNavigationStateController();\n\n const ResolvedHomePage = useComponentOverride(\"HomePage\", DefaultHomePage);\n const cmsHomePage = registry.cmsConfig?.homePage ?? <Suspense fallback={<CircularProgressCenter/>}><ResolvedHomePage/></Suspense>;\n const studioHomePage = registry.studioConfig?.homePage;\n\n const combinedViews = useMemo(() => [\n ...(navigationStateController.views ?? []),\n ...(navigationStateController.adminViews ?? [])\n ], [navigationStateController.views, navigationStateController.adminViews]);\n\n const routeContents = (\n <>\n {/* Core admin Routes */}\n <Route path={\"/\"} element={cmsHomePage}/>\n {registry.studioConfig && (\n <Route path={\"/s\"} element={studioHomePage}/>\n )}\n\n <Route path={\"/c/*\"} element={<RebaseRoute/>}/>\n <Route path={\"/settings\"} element={<SettingsView/>}/>\n\n\n {/* Hidden debug route */}\n <Route path={\"/debug/ui\"} element={<UIReferenceView/>}/>\n\n {/* Custom Registered Views */}\n {combinedViews.map(view => {\n const slugs = Array.isArray(view.slug) ? view.slug : [view.slug];\n return slugs.flatMap(slug => {\n const routes = [\n <Route key={slug} path={slug} element={<CustomViewRoute view={view}/>}/>\n ];\n if (view.nestedRoutes) {\n routes.push(\n <Route key={slug + \"/*\"} path={slug + \"/*\"} element={<CustomViewRoute view={view}/>}/>\n );\n }\n return routes;\n });\n })}\n\n {/* User Provided Custom Routes */}\n {children}\n\n <Route path={\"*\"} element={navigationStateController.loading ? <CircularProgressCenter/> : <NotFoundPage/>}/>\n </>\n );\n\n return (\n <>\n <RebaseRoutes>\n {layout\n ? <Route element={layout}>{routeContents}</Route>\n : <Route element={<>{routeContents}</>}>{routeContents}</Route>\n }\n </RebaseRoutes>\n <CollectionEditorDialogs/>\n </>\n );\n}\n","import React, { useMemo } from \"react\";\nimport {\n useRebaseRegistry\n} from \"@rebasepro/app\";\nimport { ErrorBoundary } from \"@rebasepro/ui\";\n\nimport { RebaseAuthGate } from \"./RebaseAuthGate\";\nimport { RebaseNavigation } from \"./RebaseNavigation\";\nimport { RebaseLayout } from \"./RebaseLayout\";\nimport { RebaseRouteDefs } from \"./RebaseRouteDefs\";\n\nexport interface RebaseShellProps {\n title?: string;\n /** Top bar. Only rendered if provided — pass `<AppBar/>` for the default one. */\n appBar?: React.ReactNode;\n drawer?: React.ReactNode;\n /** Expand the drawer while the pointer is over it. On by default; pass `false` to opt out. Not a load-time default — that is `defaultDrawerOpen`. */\n autoOpenDrawer?: boolean;\n /** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */\n defaultDrawerOpen?: boolean;\n /** Path to the logo shown in the drawer and top bar. Falls back to the Rebase mark. */\n logo?: string;\n children?: React.ReactNode;\n}\n\n/**\n * Convenience component that composes all four admin layers:\n *\n * ```\n * <RebaseAuthGate>\n * <RebaseNavigation>\n * <RebaseRouteDefs layout={<RebaseLayout>}>\n * {children}\n * </RebaseRouteDefs>\n * </RebaseNavigation>\n * </RebaseAuthGate>\n * ```\n *\n * Each layer is independently usable — see their individual docs.\n * RebaseShell is sugar that composes them all with sensible defaults.\n */\nexport function RebaseShell(props: RebaseShellProps) {\n const {\n title = \"Rebase\",\n appBar,\n drawer,\n autoOpenDrawer = true,\n defaultDrawerOpen = false,\n logo,\n children\n } = props;\n\n const registry = useRebaseRegistry();\n\n // Compute devViews for the layout's AdminModeSyncer\n const devViews = useMemo(() => {\n return registry.studioConfig?.devViews ?? [];\n }, [registry.studioConfig?.devViews]);\n\n return (\n <RebaseAuthGate>\n <RebaseNavigation>\n <ErrorBoundary fullPage>\n <RebaseRouteDefs\n layout={\n <RebaseLayout\n title={title}\n appBar={appBar}\n drawer={drawer}\n autoOpenDrawer={autoOpenDrawer}\n defaultDrawerOpen={defaultDrawerOpen}\n logo={logo}\n devViews={devViews}\n />\n }\n >\n {children}\n </RebaseRouteDefs>\n </ErrorBoundary>\n </RebaseNavigation>\n </RebaseAuthGate>\n );\n}\n","\nimport type { ViewMode, AdminCollection } from \"@rebasepro/admin-types\";\nimport React, { useMemo } from \"react\";\nimport { CollectionViewBinding } from \"./CollectionViewBinding/CollectionViewBinding\";\nimport { useCollectionRegistryController } from \"../hooks/navigation/contexts/CollectionRegistryContext\";\nimport { Typography } from \"@rebasepro/ui\";\nimport { useComponentOverride, CollectionScopeProvider } from \"@rebasepro/app\";\n\n/**\n * Props for the {@link CollectionPanel} component.\n *\n * This is a high-level, consumer-friendly wrapper around {@link CollectionViewBinding}\n * designed for embedding collection views inside custom pages (home pages,\n * dashboards, entity detail views, etc.).\n *\n * At minimum, provide the `path` (collection slug). All other props are optional\n * overrides that take precedence over the collection's default configuration.\n *\n * @group Components\n */\nexport type CollectionPanelProps = {\n /**\n * The collection slug / path to display (e.g. \"tasks\", \"clients\").\n * The collection must be registered in the Rebase context.\n */\n path: string;\n\n /**\n * Optional title displayed above the collection.\n * Set to `false` to hide the title entirely.\n * Defaults to the collection's `name`.\n */\n title?: string | false;\n\n /**\n * Force a specific view mode, overriding the collection's default.\n */\n viewMode?: ViewMode;\n\n /**\n * Override the sort field.\n */\n sort?: [string, \"asc\" | \"desc\"];\n\n /**\n * Maximum number of entities to display.\n */\n limit?: number;\n\n /**\n * Whether to sync filter/sort state with URL query params.\n * Defaults to `false` (embedded panels shouldn't hijack the URL).\n */\n updateUrl?: boolean;\n\n /**\n * Override the entity open mode when clicking a entity.\n */\n openEntityMode?: \"side_panel\" | \"full_screen\" | \"split\" | \"dialog\";\n\n /**\n * Additional CSS class name for the container.\n */\n className?: string;\n\n /**\n * Any additional collection-level overrides (e.g. `previewProperties`,\n * `enabledViews`, `entityActions`, `defaultFilter`, etc.).\n */\n collectionOverrides?: Partial<AdminCollection>;\n};\n\n/**\n * A high-level, reusable wrapper for embedding a Rebase collection view\n * inside custom pages (dashboards, home pages, entity detail views, etc.).\n *\n * Usage:\n * ```tsx\n * import { CollectionPanel } from \"@rebasepro/admin\";\n *\n * function MyDashboard() {\n * return (\n * <div>\n * <CollectionPanel path=\"tasks\" title=\"Pending Tasks\" />\n * <CollectionPanel\n * path=\"clients\"\n * viewMode=\"table\"\n * collectionOverrides={{\n * defaultFilter: { status: [\"!=\", \"completed\"] }\n * }}\n * />\n * </div>\n * );\n * }\n * ```\n *\n * @group Components\n */\nfunction CollectionPanelInner({\n mergedCollection,\n path,\n title,\n updateUrl,\n className\n}: CollectionPanelProps & { mergedCollection: AdminCollection }) {\n const ResolvedCollectionView = useComponentOverride(\"Collection.View\", CollectionViewBinding);\n\n return (\n <div className={className}>\n {title !== false && (\n <Typography\n variant=\"subtitle2\"\n className=\"font-semibold mb-2 text-surface-700 dark:text-surface-300\"\n >\n {title ?? mergedCollection.name}\n </Typography>\n )}\n <ResolvedCollectionView\n {...mergedCollection}\n path={path}\n updateUrl={updateUrl}\n />\n </div>\n );\n}\n\nexport function CollectionPanel(props: CollectionPanelProps) {\n const {\n path,\n viewMode,\n sort,\n limit,\n openEntityMode,\n className,\n collectionOverrides\n } = props;\n const collectionRegistry = useCollectionRegistryController();\n const registeredCollection = collectionRegistry.getCollection(path);\n\n const mergedCollection = useMemo(() => {\n if (!registeredCollection) return undefined;\n\n // Build overrides object from shorthand props + explicit overrides\n const propOverrides: Record<string, unknown> = {};\n if (viewMode) propOverrides.defaultViewMode = viewMode;\n if (sort) propOverrides.sort = sort;\n if (limit) propOverrides.pagination = limit;\n if (openEntityMode) propOverrides.openEntityMode = openEntityMode;\n\n return {\n ...registeredCollection,\n ...(collectionOverrides ?? {}),\n ...propOverrides\n } as AdminCollection;\n }, [registeredCollection, collectionOverrides, viewMode, sort, limit, openEntityMode]);\n\n if (!mergedCollection) {\n return (\n <div className={className}>\n <Typography variant=\"body2\" color=\"secondary\">\n Collection "{path}" not found.\n </Typography>\n </div>\n );\n }\n\n const content = (\n <CollectionPanelInner\n {...props}\n mergedCollection={mergedCollection}\n />\n );\n\n return (\n <CollectionScopeProvider collection={mergedCollection}>\n {content}\n </CollectionScopeProvider>\n );\n}\n","/**\n * Maps a Rebase `Property` (from @rebasepro/types) to a `CollectionPropertyConfig`\n * (from @rebasepro/ui), stripping all entity-specific fields and keeping only\n * the UI-relevant subset.\n *\n * This is the bridge between the entity-aware and headless layers.\n */\n\nimport type { Property, Properties, EnumValues, EnumValueConfig } from \"@rebasepro/types\";\nimport type { CollectionPropertyConfig, CollectionEnumValueConfig } from \"@rebasepro/ui\";\n\n/**\n * Map Rebase property types to headless-supported types.\n * `vector` and `binary` are not directly renderable, so we fall back to `string`.\n */\nconst TYPE_MAP: Record<string, CollectionPropertyConfig[\"type\"]> = {\n string: \"string\",\n number: \"number\",\n boolean: \"boolean\",\n date: \"date\",\n geopoint: \"geopoint\",\n reference: \"reference\",\n relation: \"relation\",\n array: \"array\",\n map: \"map\",\n vector: \"string\", // vectors display as text\n binary: \"string\", // binary displays as text\n};\n\n/**\n * Convert a single Property to a CollectionPropertyConfig.\n */\nexport function mapPropertyToConfig(property: Property): CollectionPropertyConfig {\n const base: CollectionPropertyConfig = {\n type: TYPE_MAP[property.type] ?? \"string\",\n name: property.name,\n description: property.description,\n columnWidth: property.admin?.columnWidth,\n hideFromCollection: property.admin?.hideFromCollection,\n };\n\n // String-specific\n if (property.type === \"string\") {\n if (property.enum) {\n base.enum = mapEnumValues(property.enum);\n }\n if (property.admin?.multiline) base.multiline = true;\n if (property.admin?.previewAsTag) base.previewAsTag = true;\n if (property.admin?.urlPreview) base.url = property.admin.urlPreview;\n if (property.admin?.markdown) base.markdown = true;\n if (property.storage) base.storage = true;\n if (property.email) base.email = true;\n }\n\n // Number-specific\n if (property.type === \"number\" && property.enum) {\n base.enum = mapEnumValues(property.enum);\n }\n\n // Array-specific\n if (property.type === \"array\" && property.of && !Array.isArray(property.of)) {\n base.of = mapPropertyToConfig(property.of);\n }\n\n // Map-specific\n if (property.type === \"map\" && property.properties) {\n base.properties = mapPropertiesToConfigs(property.properties);\n if (property.propertiesOrder) {\n base.propertiesOrder = property.propertiesOrder;\n }\n }\n\n // Date-specific\n if (property.type === \"date\" && property.mode) {\n base.mode = property.mode;\n }\n\n // Custom preview component\n if (property.admin?.Preview) {\n // The connected wrapper will handle this by injecting via cellRenderer override\n // We don't copy it here because Preview may reference entity-aware components\n }\n\n return base;\n}\n\n/**\n * Convert a Properties record to a CollectionPropertyConfig record.\n */\nexport function mapPropertiesToConfigs(\n properties: Properties\n): Record<string, CollectionPropertyConfig> {\n const result: Record<string, CollectionPropertyConfig> = {};\n for (const [key, property] of Object.entries(properties)) {\n result[key] = mapPropertyToConfig(property);\n }\n return result;\n}\n\n/**\n * Convert Rebase EnumValues to CollectionEnumValueConfig format.\n * Handles both array form (EnumValueConfig[]) and record form.\n */\nfunction mapEnumValues(\n enumValues: EnumValues | undefined\n): Record<string, CollectionEnumValueConfig> | Map<string | number, CollectionEnumValueConfig> | undefined {\n if (!enumValues) return undefined;\n\n // Array form: EnumValueConfig[]\n if (Array.isArray(enumValues)) {\n const result: Record<string, CollectionEnumValueConfig> = {};\n for (const item of enumValues) {\n result[String(item.id)] = normalizeEnumValueConfig(item);\n }\n return result;\n }\n\n // Record form: Record<string | number, string | EnumValueConfig>\n const result: Record<string, CollectionEnumValueConfig> = {};\n for (const [key, value] of Object.entries(enumValues)) {\n result[key] = typeof value === \"string\"\n ? value\n : normalizeEnumValueConfig(value);\n }\n return result;\n}\n\nfunction normalizeEnumValueConfig(config: EnumValueConfig): CollectionEnumValueConfig {\n return {\n label: config.label,\n color: typeof config.color === \"string\" ? config.color : undefined,\n disabled: config.disabled,\n };\n}\n","/**\n * Adapts an `EntityTableController<M>` (from @rebasepro/types) to a\n * `CollectionDataController<T>` (from @rebasepro/ui), bridging the\n * entity-aware data layer to the headless collection view.\n */\n\nimport { useMemo } from \"react\";\nimport type { Entity } from \"@rebasepro/types\";\nimport type { EntityTableController } from \"@rebasepro/admin-types\";\nimport type { CollectionDataController } from \"@rebasepro/ui\";\n\n/**\n * Unwrap `Entity<M>` objects to flat rows for the headless view.\n * The entity system uses `{ id, path, values: M }`; `values` is already the\n * flat row `M` carrying its real primary key, so unwrapping is just `.values` —\n * no `id`/`path` merge (those are view-model metadata, not row columns).\n */\nfunction flattenEntities<M extends Record<string, unknown>>(\n entities: Entity<M>[]\n): M[] {\n return entities.map(entity => entity.values);\n}\n\n/**\n * React hook that adapts a EntityTableController to a CollectionDataController.\n *\n * Usage:\n * ```tsx\n * const tableController = useDataTableController({ path, collection });\n * const dataController = useCollectionDataController(tableController);\n *\n * <CollectionView dataController={dataController} ... />\n * ```\n */\nexport function useCollectionDataController<M extends Record<string, unknown>>(\n tableController: EntityTableController<M>\n): CollectionDataController<M> {\n const flatData = useMemo(\n () => flattenEntities(tableController.data),\n [tableController.data]\n );\n\n return useMemo((): CollectionDataController<M> => ({\n data: flatData,\n loading: tableController.dataLoading,\n noMoreToLoad: tableController.noMoreToLoad,\n error: tableController.dataLoadingError,\n\n filterValues: tableController.filterValues as Record<string, [string, unknown]> | undefined,\n setFilterValues: tableController.setFilterValues as\n ((values: Record<string, [string, unknown]> | undefined) => void) | undefined,\n\n sortBy: tableController.sortBy,\n setSortBy: tableController.setSortBy,\n\n searchString: tableController.searchString,\n setSearchString: tableController.setSearchString,\n\n clearFilter: tableController.clearFilter,\n\n initialScroll: tableController.initialScroll,\n onScroll: tableController.onScroll,\n\n paginationEnabled: tableController.paginationEnabled,\n pageSize: tableController.pageSize,\n itemCount: tableController.itemCount,\n setItemCount: tableController.setItemCount,\n }), [flatData, tableController]);\n}\n\n/**\n * Non-hook version for cases where you already have the data\n * and just need to build a static controller.\n */\nexport function createStaticDataController<T extends Record<string, unknown>>(\n data: T[],\n options?: {\n loading?: boolean;\n error?: Error;\n }\n): CollectionDataController<T> {\n return {\n data,\n loading: options?.loading ?? false,\n noMoreToLoad: true,\n error: options?.error,\n };\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport type { EngineProperties, Property } from \"@rebasepro/types\";\nimport type { NavigationGroupMapping, AdminCollection } from \"@rebasepro/admin-types\";\nimport type {\n CollectionsConfigController,\n SaveCollectionParams,\n UpdateCollectionParams,\n DeleteCollectionParams,\n SavePropertyParams,\n DeletePropertyParams,\n UpdatePropertiesOrderParams,\n UpdateKanbanColumnsOrderParams,\n} from \"./types/config_controller\";\nimport type { JsonCollectionStore, SerializableCollectionConfig } from \"./serializable_types\";\nimport { toSerializableCollectionConfig, toSerializableProperty, fromSerializableCollectionConfigs } from \"./serializable_utils\";\n\nexport interface UseJsonCollectionsConfigControllerOptions {\n /**\n * The store adapter for persisting/loading collections.\n */\n store: JsonCollectionStore;\n\n /**\n * If true, the configuration cannot be modified.\n */\n readOnly?: boolean;\n\n /**\n * If true, collections will be loaded from the store on mount.\n * Defaults to true.\n */\n autoLoad?: boolean;\n}\n\n/**\n * A `CollectionsConfigController` implementation that persists collection\n * configurations as JSON via a pluggable `JsonCollectionStore` adapter.\n *\n * Use this when you want to store collection schemas in a database, API,\n * localStorage, or any other JSON-compatible backend — as opposed to the\n * default code-based persistence.\n *\n * @example\n * ```tsx\n * const store: JsonCollectionStore = {\n * load: async () => { const res = await fetch('/api/schemas'); return res.json(); },\n * save: async (slug, data) => { await fetch(`/api/schemas/${slug}`, { method: 'PUT', body: JSON.stringify(data) }); },\n * delete: async (slug) => { await fetch(`/api/schemas/${slug}`, { method: 'DELETE' }); },\n * };\n *\n * const configController = useJsonCollectionsConfigController({ store });\n * ```\n */\nexport function useJsonCollectionsConfigController({\n store,\n readOnly = false,\n autoLoad = true,\n}: UseJsonCollectionsConfigControllerOptions): CollectionsConfigController {\n const [collections, setCollections] = useState<AdminCollection[]>([]);\n const [loading, setLoading] = useState(autoLoad);\n const [navigationEntries, setNavigationEntries] = useState<NavigationGroupMapping[]>([]);\n\n // Keep store ref stable to avoid stale closures in callbacks\n const storeRef = useRef(store);\n storeRef.current = store;\n\n /**\n * The current collections, readable outside a state updater.\n *\n * Three mutators used to compute their new value inside\n * `setCollections(prev => …)` and persist from in there, which cost them\n * both halves of a save: the promise they returned resolved before the\n * store had answered, so a failed write reached the caller as a success,\n * and a `setState` updater must be pure — under `StrictMode` React invokes\n * it twice, so every one of those saves wrote to the store twice in\n * development. Reading `prev` from a ref lets them do what\n * `updatePropertiesOrder` already did: compute, set, then await.\n */\n const collectionsRef = useRef<AdminCollection[]>([]);\n const applyCollections = useCallback((next: AdminCollection[]) => {\n collectionsRef.current = next;\n setCollections(next);\n }, []);\n\n // ── Load on mount ─────────────────────────────────────────────────\n useEffect(() => {\n if (!autoLoad) return;\n let cancelled = false;\n\n (async () => {\n try {\n const [serialized, navEntries] = await Promise.all([\n storeRef.current.load(),\n storeRef.current.loadNavigationEntries?.() ?? Promise.resolve([]),\n ]);\n if (cancelled) return;\n // Deserialized as a set: a relation's target is a slug, and a slug only\n // resolves against the other collections it arrived with.\n applyCollections(fromSerializableCollectionConfigs(serialized));\n setNavigationEntries(navEntries);\n } catch (e) {\n console.error(\"useJsonCollectionsConfigController: failed to load collections\", e);\n } finally {\n if (!cancelled) setLoading(false);\n }\n })();\n\n return () => { cancelled = true; };\n // `applyCollections` is `useCallback(…, [])`, so naming it here cannot\n // re-run the mount effect — it is listed because a stable identity is a\n // fact about today's code, not a reason to leave a dependency out.\n }, [autoLoad, applyCollections]);\n\n // ── Helpers ────────────────────────────────────────────────────────\n\n /**\n * Update local state and persist a collection to the store.\n */\n const persistCollection = useCallback(async (collection: AdminCollection) => {\n const serializable = toSerializableCollectionConfig(collection);\n await storeRef.current.save(collection.slug, serializable);\n }, []);\n\n /**\n * Find collection by id (slug).\n */\n const getCollection = useCallback((id: string): AdminCollection => {\n const found = collections.find(c => c.slug === id);\n if (found) return found;\n throw new Error(`Collection \"${id}\" not found`);\n }, [collections]);\n\n // ── CRUD operations ───────────────────────────────────────────────\n\n const saveCollection = useCallback(async <M extends Record<string, unknown>>(\n { id, collectionData }: SaveCollectionParams<M>\n ) => {\n const collection = collectionData as AdminCollection;\n await persistCollection(collection);\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === id);\n if (idx >= 0) {\n const next = [...prev];\n next[idx] = collection;\n applyCollections(next);\n } else {\n applyCollections([...prev, collection]);\n }\n }, [persistCollection, applyCollections]);\n\n const updateCollection = useCallback(async <M extends Record<string, unknown>>(\n { id, collectionData, previousId }: UpdateCollectionParams<M>\n ) => {\n const prev = collectionsRef.current;\n const lookupId = previousId ?? id;\n const idx = prev.findIndex(c => c.slug === lookupId);\n if (idx < 0) return;\n\n const merged = { ...prev[idx], ...collectionData } as AdminCollection;\n const next = [...prev];\n next[idx] = merged;\n applyCollections(next);\n\n await persistCollection(merged);\n\n // If the slug changed, clean up the old entry in the store. After the\n // save, not beside it: dropping the old key first and then failing to\n // write the new one loses the collection outright.\n if (previousId && previousId !== id) {\n await storeRef.current.delete(previousId);\n }\n }, [persistCollection, applyCollections]);\n\n const deleteCollection = useCallback(async ({ id }: DeleteCollectionParams) => {\n await storeRef.current.delete(id);\n applyCollections(collectionsRef.current.filter(c => c.slug !== id));\n }, [applyCollections]);\n\n const saveProperty = useCallback(async ({\n path,\n propertyKey,\n property,\n newPropertiesOrder,\n }: SavePropertyParams) => {\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === path);\n if (idx < 0) return;\n\n const collection = { ...prev[idx] };\n collection.properties = {\n ...collection.properties,\n [propertyKey]: property,\n } as EngineProperties;\n if (newPropertiesOrder) {\n collection.propertiesOrder = newPropertiesOrder as typeof collection.propertiesOrder;\n }\n\n const next = [...prev];\n next[idx] = collection as AdminCollection;\n applyCollections(next);\n\n await persistCollection(next[idx]);\n }, [persistCollection, applyCollections]);\n\n const deleteProperty = useCallback(async ({\n path,\n propertyKey,\n newPropertiesOrder,\n }: DeletePropertyParams) => {\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === path);\n if (idx < 0) return;\n\n const collection = { ...prev[idx] };\n const { [propertyKey]: _removed, ...remaining } = collection.properties;\n collection.properties = remaining;\n if (newPropertiesOrder) {\n collection.propertiesOrder = newPropertiesOrder as typeof collection.propertiesOrder;\n }\n\n const next = [...prev];\n next[idx] = collection as AdminCollection;\n applyCollections(next);\n\n await persistCollection(next[idx]);\n }, [persistCollection, applyCollections]);\n\n const updatePropertiesOrder = useCallback(async ({\n collection,\n newPropertiesOrder,\n }: UpdatePropertiesOrderParams) => {\n const updated = {\n ...collection,\n propertiesOrder: newPropertiesOrder,\n } as AdminCollection;\n\n const prev = collectionsRef.current;\n const idx = prev.findIndex(c => c.slug === collection.slug);\n if (idx >= 0) {\n const next = [...prev];\n next[idx] = updated;\n applyCollections(next);\n }\n\n await persistCollection(updated);\n }, [persistCollection, applyCollections]);\n\n const updateKanbanColumnsOrder = useCallback(async ({\n collection,\n kanbanColumnProperty,\n newColumnsOrder,\n }: UpdateKanbanColumnsOrderParams) => {\n // Kanban column order is stored in the enum order of the column property.\n // For JSON persistence, we store it as-is — the view layer reads enum order.\n // This is a no-op for now; the kanban order is determined by the enum\n // definition on the property itself.\n }, []);\n\n const saveNavigationEntriesHandler = useCallback(async (entries: NavigationGroupMapping[]) => {\n setNavigationEntries(entries);\n if (storeRef.current.saveNavigationEntries) {\n await storeRef.current.saveNavigationEntries(entries);\n }\n }, []);\n\n // ── Return controller ─────────────────────────────────────────────\n return useMemo<CollectionsConfigController>(() => ({\n loading,\n readOnly,\n readOnlyReason: readOnly ? \"Configuration is read-only.\" : undefined,\n collections,\n getCollection,\n saveCollection,\n updateCollection,\n deleteCollection,\n saveProperty,\n deleteProperty,\n updatePropertiesOrder,\n updateKanbanColumnsOrder,\n navigationEntries,\n saveNavigationEntries: saveNavigationEntriesHandler,\n }), [\n loading,\n readOnly,\n collections,\n getCollection,\n saveCollection,\n updateCollection,\n deleteCollection,\n saveProperty,\n deleteProperty,\n updatePropertiesOrder,\n updateKanbanColumnsOrder,\n navigationEntries,\n saveNavigationEntriesHandler,\n ]);\n}\n","import { useCollectionRegistryController } from \"../_cms_internals\";\nimport { ErrorView, useTranslation } from \"@rebasepro/app\";\nimport { useCollectionEditorController } from \"../useCollectionEditorController\";\nimport { Button } from \"@rebasepro/ui\";\nimport { prettifyIdentifier } from \"@rebasepro/utils\";\nimport { getLastSegment } from \"@rebasepro/app\";\n\nexport function MissingReferenceWidget({ path: pathProp }: {\n path: string\n}) {\n const registry = useCollectionRegistryController();\n const path = getLastSegment(pathProp);\n const parentCollectionSlugs = registry.getParentCollectionSlugs(pathProp);\n const parentEntityIds = registry.getParentEntityIds(pathProp);\n const collectionEditor = useCollectionEditorController();\n const { t } = useTranslation();\n return <div className={\"p-1 flex flex-col items-center\"}>\n <ErrorView error={t(\"studio_missing_reference_error\", { path })}/>\n <Button className={\"mx-2\"}\n size={\"small\"}\n onClick={() => {\n collectionEditor.createCollection({\n initialValues: { path,\nname: prettifyIdentifier(path) },\n parentCollectionSlugs,\nparentEntityIds,\n redirect: false,\n sourceClick: \"missing_reference\"\n });\n }}>\n {t(\"studio_missing_reference_create\")}\n </Button>\n </div>;\n}\n\n"],"mappings":"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"}
|