@rebasepro/admin 0.13.0 → 0.13.1-canary.g3660bd5
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-CjXkWZ64.js → CollectionEditorDialog-MODRemil.js} +3 -3
- package/dist/{CollectionEditorDialog-CjXkWZ64.js.map → CollectionEditorDialog-MODRemil.js.map} +1 -1
- package/dist/{PropertyEditView-W8I3YV89.js → PropertyEditView-Bt-VM0zQ.js} +2 -2
- package/dist/{PropertyEditView-W8I3YV89.js.map → PropertyEditView-Bt-VM0zQ.js.map} +1 -1
- package/dist/{RouterCollectionsStudioView-BsLTNoqX.js → RouterCollectionsStudioView-D54P9o8O.js} +4 -4
- package/dist/{RouterCollectionsStudioView-BsLTNoqX.js.map → RouterCollectionsStudioView-D54P9o8O.js.map} +1 -1
- package/dist/collection_editor_ui.js +4 -4
- package/dist/components/AdditionalFieldValue.d.ts +25 -0
- package/dist/components/CollectionViewBinding/CollectionViewBinding.d.ts +16 -0
- package/dist/components/CollectionViewBinding/SlotValue.d.ts +37 -0
- package/dist/components/CollectionViewBinding/SplitListCloseButton.d.ts +5 -3
- package/dist/components/CollectionViewBinding/SplitListShowButton.d.ts +12 -0
- package/dist/components/CollectionViewBinding/usePreviewSlots.d.ts +29 -4
- package/dist/components/DetailViewBinding.d.ts +6 -0
- package/dist/components/DrawerNavigationGroup.d.ts +5 -4
- package/dist/components/DrawerNavigationItem.d.ts +4 -2
- package/dist/components/EditViewBinding.d.ts +7 -1
- package/dist/components/EntityDisplayHeader.d.ts +53 -0
- package/dist/components/EntityIdentityBar.d.ts +20 -1
- package/dist/components/EntityViewBinding.d.ts +60 -6
- package/dist/components/RebaseLayout.d.ts +1 -1
- package/dist/components/RebaseShell.d.ts +1 -1
- package/dist/components/app/Scaffold.d.ts +9 -3
- package/dist/components/index.d.ts +2 -0
- package/dist/{export-J79rMoNj.js → export-Bl1V7lKO.js} +2 -2
- package/dist/{export-J79rMoNj.js.map → export-Bl1V7lKO.js.map} +1 -1
- package/dist/form/components/FieldBlock.d.ts +47 -4
- package/dist/form/components/FormRail.d.ts +13 -0
- package/dist/form/components/FormSections.d.ts +15 -1
- package/dist/form/components/useRailVisible.d.ts +5 -4
- package/dist/{history-D7L_JlLO.js → history-DN_dzFAF.js} +4 -4
- package/dist/{history-D7L_JlLO.js.map → history-DN_dzFAF.js.map} +1 -1
- package/dist/hooks/useEntityDisplay.d.ts +102 -0
- package/dist/hooks/useEntityDisplayTitle.d.ts +18 -9
- package/dist/{import-BvYl--U4.js → import-BJXrHdFv.js} +3 -3
- package/dist/{import-BvYl--U4.js.map → import-BJXrHdFv.js.map} +1 -1
- package/dist/index.js +149 -51
- package/dist/index.js.map +1 -1
- package/dist/preview/compact_text.d.ts +23 -0
- package/dist/preview/components/BooleanPreview.d.ts +3 -1
- package/dist/preview/property_previews/ArrayOfStringsPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayOneOfPreview.d.ts +1 -1
- package/dist/preview/property_previews/ArrayPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/MapPropertyPreview.d.ts +1 -1
- package/dist/preview/property_previews/StringPropertyPreview.d.ts +1 -1
- package/dist/routes/RebaseRoute.d.ts +1 -1
- package/dist/types/components/PropertyPreviewProps.d.ts +19 -0
- package/dist/util/number_format.d.ts +14 -0
- package/dist/util/previews.d.ts +9 -2
- package/dist/{util-GiwPgxnL.js → util-EXfeGzbH.js} +8142 -7353
- package/dist/util-EXfeGzbH.js.map +1 -0
- package/package.json +9 -9
- package/src/components/AdditionalFieldValue.tsx +68 -0
- package/src/components/CollectionTableBinding/CollectionTableBinding.tsx +5 -6
- package/src/components/CollectionViewBinding/BoardCardBinding.tsx +9 -27
- package/src/components/CollectionViewBinding/CollectionListViewBinding.tsx +11 -24
- package/src/components/CollectionViewBinding/CollectionViewBinding.tsx +26 -6
- package/src/components/CollectionViewBinding/EntityCardBinding.tsx +10 -33
- package/src/components/CollectionViewBinding/SlotValue.tsx +60 -0
- package/src/components/CollectionViewBinding/SplitListCloseButton.tsx +7 -5
- package/src/components/CollectionViewBinding/SplitListShowButton.tsx +28 -0
- package/src/components/CollectionViewBinding/SplitListView.tsx +14 -1
- package/src/components/CollectionViewBinding/useBoardDataController.tsx +12 -3
- package/src/components/CollectionViewBinding/usePreviewSlots.ts +115 -48
- package/src/components/DefaultDrawer.tsx +19 -23
- package/src/components/DetailViewBinding.tsx +74 -54
- package/src/components/DrawerNavigationGroup.tsx +4 -7
- package/src/components/DrawerNavigationItem.tsx +23 -4
- package/src/components/EditViewBinding.tsx +54 -33
- package/src/components/EntityDisplayHeader.tsx +170 -0
- package/src/components/EntityIdentityBar.tsx +49 -5
- package/src/components/EntityPreviewBinding.tsx +54 -17
- package/src/components/EntityViewBinding.tsx +341 -41
- package/src/components/InlineEntityPreview.tsx +10 -10
- package/src/components/RebaseLayout.tsx +2 -2
- package/src/components/RebaseShell.tsx +2 -2
- package/src/components/app/Scaffold.tsx +112 -10
- package/src/components/index.ts +3 -0
- package/src/form/EntityForm.tsx +28 -33
- package/src/form/components/FieldBlock.tsx +65 -8
- package/src/form/components/FormRail.tsx +19 -2
- package/src/form/components/FormSections.tsx +32 -5
- package/src/form/components/StorageUploadProgress.tsx +9 -3
- package/src/form/components/useRailVisible.tsx +5 -4
- package/src/form/field_bindings/ReadOnlyFieldBinding.tsx +7 -1
- package/src/hooks/navigation/useBuildCollectionRegistryController.tsx +29 -5
- package/src/hooks/useEntityDisplay.tsx +262 -0
- package/src/hooks/useEntityDisplayTitle.tsx +27 -38
- package/src/preview/PropertyPreview.tsx +18 -2
- package/src/preview/compact_text.ts +68 -0
- package/src/preview/components/BooleanPreview.tsx +5 -2
- package/src/preview/components/StorageThumbnail.tsx +5 -2
- package/src/preview/property_previews/ArrayOfStringsPreview.tsx +26 -1
- package/src/preview/property_previews/ArrayOneOfPreview.tsx +10 -1
- package/src/preview/property_previews/ArrayPropertyPreview.tsx +10 -1
- package/src/preview/property_previews/MapPropertyPreview.tsx +52 -1
- package/src/preview/property_previews/NumberPropertyPreview.tsx +9 -1
- package/src/preview/property_previews/StringPropertyPreview.tsx +8 -5
- package/src/routes/RebaseRoute.tsx +62 -4
- package/src/types/components/PropertyPreviewProps.tsx +21 -0
- package/src/util/number_format.ts +46 -0
- package/src/util/previews.ts +8 -55
- package/dist/util-GiwPgxnL.js.map +0 -1
package/dist/{RouterCollectionsStudioView-BsLTNoqX.js → RouterCollectionsStudioView-D54P9o8O.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { in as useUrlController } from "./util-
|
|
3
|
-
import { s as AIModifiedPathsProvider } from "./PropertyEditView-
|
|
4
|
-
import { t as CollectionEditor } from "./CollectionEditorDialog-
|
|
2
|
+
import { in as useUrlController } from "./util-EXfeGzbH.js";
|
|
3
|
+
import { s as AIModifiedPathsProvider } from "./PropertyEditView-Bt-VM0zQ.js";
|
|
4
|
+
import { t as CollectionEditor } from "./CollectionEditorDialog-MODRemil.js";
|
|
5
5
|
import { useEffect, useState } from "react";
|
|
6
6
|
import { Button, IconButton, PlusIcon, ResizablePanels, Tooltip, Typography, cls, defaultBorderMixin, iconSize } from "@rebasepro/ui";
|
|
7
7
|
import { IconForView, UnsavedChangesDialog, useUnsavedChangesDialog } from "@rebasepro/app";
|
|
@@ -189,4 +189,4 @@ function RouterCollectionsStudioView(props) {
|
|
|
189
189
|
//#endregion
|
|
190
190
|
export { CollectionStudioView as i, RouterCollectionsStudioView_exports as n, CollectionsStudioView as r, RouterCollectionsStudioView as t };
|
|
191
191
|
|
|
192
|
-
//# sourceMappingURL=RouterCollectionsStudioView-
|
|
192
|
+
//# sourceMappingURL=RouterCollectionsStudioView-D54P9o8O.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouterCollectionsStudioView-BsLTNoqX.js","names":[],"sources":["../src/collection_editor/ui/collection_editor/CollectionStudioView.tsx","../src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx","../src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx"],"sourcesContent":["\nimport { useUnsavedChangesDialog, UnsavedChangesDialog } from \"@rebasepro/app\";\nimport * as React from \"react\";\nimport { useState } from \"react\";\nimport { Button, PlusIcon, Typography } from \"@rebasepro/ui\";\nimport { CollectionEditorDialogProps } from \"./CollectionEditorDialog\";\nimport { AIModifiedPathsProvider } from \"./AIModifiedPathsContext\";\nimport { CollectionEditor } from \"./CollectionEditorDialog\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport type CollectionStudioViewProps = Omit<CollectionEditorDialogProps, \"open\" | \"isNewCollection\" | \"editedCollectionId\" | \"handleClose\" | \"handleCancel\"> & {\n collectionId?: string | \"new\";\n\n /**\n * Called after a successful save.\n * Receives the saved collection (or undefined if dismissed without saving).\n * When not provided, save completes silently.\n */\n onSave?: (collection?: AdminCollection) => void;\n\n /**\n * Called when the user cancels editing.\n * When not provided, cancel is a no-op.\n */\n onCancel?: () => void;\n};\n\nexport function CollectionStudioView({ collectionId, onSave, onCancel, ...props }: CollectionStudioViewProps) {\n\n // Form state from the editor\n const [formDirty, setFormDirty] = useState<boolean>(false);\n const [cancelRequested, setCancelRequested] = useState<boolean>(false);\n\n const { dialogProps, triggerDialog } = useUnsavedChangesDialog(\n formDirty,\n () => setFormDirty(false)\n );\n\n const activeCollectionId = collectionId;\n\n const handleCancelClick = () => {\n if (!formDirty) {\n onCancel?.();\n } else {\n setCancelRequested(true);\n triggerDialog();\n }\n };\n\n return (\n <div className=\"flex-grow flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800\">\n <AIModifiedPathsProvider>\n {activeCollectionId ? (\n <CollectionEditor\n key={activeCollectionId}\n {...props}\n fullScreen={true}\n open={true}\n isNewCollection={activeCollectionId === \"new\"}\n editedCollectionId={activeCollectionId !== \"new\" ? activeCollectionId : undefined}\n handleCancel={handleCancelClick}\n handleClose={(savedCollection) => {\n setFormDirty(false);\n if (savedCollection) {\n setTimeout(() => {\n onSave?.(savedCollection);\n }, 0);\n }\n }}\n setFormDirty={setFormDirty}\n />\n ) : (\n <div className=\"flex-grow flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one\n </Typography>\n <Button\n disabled={props.configController?.readOnly}\n onClick={() => onSave?.()}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n\n <UnsavedChangesDialog\n {...dialogProps}\n handleOk={() => {\n dialogProps.handleOk();\n if (cancelRequested) {\n onCancel?.();\n setCancelRequested(false);\n }\n }}\n handleCancel={() => {\n dialogProps.handleCancel();\n setCancelRequested(false);\n }}\n />\n </AIModifiedPathsProvider>\n </div>\n );\n}\n","\nimport { IconForView } from \"@rebasepro/app\";\nimport React, { useState, useEffect } from \"react\";\nimport {\n Button,\n cls,\n defaultBorderMixin,\n IconButton,\n iconSize,\n PlusIcon,\n ResizablePanels,\n Tooltip,\n Typography\n} from \"@rebasepro/ui\";\n\nimport { CollectionsConfigController } from \"../../types/config_controller\";\nimport { CollectionStudioView } from \"./CollectionStudioView\";\nimport type { CollectionEditorExtensionProps } from \"../../extensibility_types\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport interface CollectionsStudioViewProps extends CollectionEditorExtensionProps {\n configController: CollectionsConfigController;\n\n /**\n * Collections to show in the sidebar.\n * When provided, overrides the collections from `configController`.\n * Use this to control exactly which collections the editor displays.\n */\n collections?: AdminCollection[];\n\n /**\n * Controlled active collection ID.\n * When provided together with `onActiveCollectionChange`,\n * navigation is fully external — no internal state is used.\n */\n activeCollectionId?: string;\n\n /**\n * Called when the user clicks a collection, \"new\", or navigates.\n * When provided, the component is fully controlled (no internal state).\n * When not provided, the component manages selection via internal state.\n *\n * Pass `\"new\"` to create a new collection. Pass `undefined` to deselect.\n */\n onActiveCollectionChange?: (collectionId: string | undefined) => void;\n}\n\nexport function CollectionsStudioView({\n configController,\n collections: collectionsProp,\n activeCollectionId: controlledActiveId,\n onActiveCollectionChange,\n propertyTypePresets,\n hiddenPropertyTypes,\n renderExtraPropertyFields,\n renderExtraCollectionFields,\n visibleTabs,\n standalone,\n}: CollectionsStudioViewProps) {\n\n // ── Navigation state ────────────────────────────────────────────────\n // If onActiveCollectionChange is provided, the component is controlled.\n // Otherwise, use internal state.\n const [internalActiveId, setInternalActiveId] = useState<string | undefined>(undefined);\n const isControlled = onActiveCollectionChange !== undefined;\n const activeCollectionId = isControlled ? controlledActiveId : internalActiveId;\n\n const setActiveCollectionId = (id: string | undefined) => {\n if (isControlled) {\n onActiveCollectionChange?.(id);\n } else {\n setInternalActiveId(id);\n }\n };\n\n // ── Collections list ────────────────────────────────────────────────\n const collections = collectionsProp ?? configController.collections ?? [];\n\n // ── Sidebar sizing ──────────────────────────────────────────────────\n const [sidebarSize, setSidebarSize] = useState(() => {\n try {\n const saved = localStorage.getItem(\"rebase_collections_editor_sidebar_size\");\n return saved !== null ? parseFloat(saved) : 25;\n } catch (e) {\n return 25;\n }\n });\n\n useEffect(() => {\n try {\n localStorage.setItem(\"rebase_collections_editor_sidebar_size\", sidebarSize.toString());\n } catch (e) {\n // ignore local storage error\n }\n }, [sidebarSize]);\n\n return (\n <div className=\"flex h-full w-full bg-surface-50 dark:bg-surface-800 overflow-hidden text-text-primary dark:text-text-primary-dark\">\n <ResizablePanels\n orientation=\"horizontal\"\n panelSizePercent={sidebarSize}\n onPanelSizeChange={setSidebarSize}\n minPanelSizePx={220}\n firstPanel={\n <div className={cls(\"flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800 border-r\", defaultBorderMixin)}>\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold text-[11px] uppercase tracking-wider text-surface-400 dark:text-surface-400\">\n Collections\n </Typography>\n <Tooltip title={configController.readOnly ? configController.readOnlyReason || \"Read only\" : \"Add collection\"}>\n <div>\n <IconButton\n size=\"small\"\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n className={activeCollectionId === \"new\" ? \"text-primary dark:text-primary-dark\" : \"text-text-secondary dark:text-text-secondary-dark\"}\n >\n <PlusIcon size={iconSize.smallest}/>\n </IconButton>\n </div>\n </Tooltip>\n </div>\n\n <div className=\"flex-grow overflow-y-auto w-full no-scrollbar p-2 space-y-0.5\">\n {collections.length === 0 && (\n <div className=\"p-4 text-center\">\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark italic\">\n No collections yet.\n </Typography>\n </div>\n )}\n {collections.map((collection) => {\n const collectionKey = collection.slug;\n const isSelected = activeCollectionId === collectionKey;\n return (\n <div\n key={collectionKey}\n onClick={() => setActiveCollectionId(collectionKey)}\n className={cls(\n \"flex items-center gap-2.5 px-3 h-[30px] cursor-pointer rounded-lg text-[13px] font-medium transition-colors\",\n isSelected\n ? \"bg-primary/8 text-primary dark:bg-primary/10 dark:text-primary-light font-semibold\"\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 )}\n >\n <IconForView collectionOrView={collection} size={\"smallest\"} className={cls(\n isSelected\n ? \"text-primary dark:text-primary-light\"\n : \"text-surface-500 dark:text-text-secondary-dark\"\n )}/>\n <span className=\"truncate flex-1\">\n {collection.name || collection.slug}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n }\n secondPanel={\n <div className=\"flex-grow flex flex-col min-w-0 h-full w-full\">\n {/* We use key to force unmount when switching collections, preventing stale state */}\n {activeCollectionId ? (\n <CollectionStudioView\n key={activeCollectionId}\n configController={configController}\n collectionId={activeCollectionId}\n onSave={(savedCollection) => {\n // After creating a new collection, switch to it\n if (activeCollectionId === \"new\" && savedCollection?.slug) {\n setActiveCollectionId(savedCollection.slug);\n }\n }}\n onCancel={() => setActiveCollectionId(undefined)}\n propertyTypePresets={propertyTypePresets}\n hiddenPropertyTypes={hiddenPropertyTypes}\n renderExtraPropertyFields={renderExtraPropertyFields}\n renderExtraCollectionFields={renderExtraCollectionFields}\n visibleTabs={visibleTabs}\n standalone={standalone}\n />\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one to start editing\n </Typography>\n <Button\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n </div>\n }\n />\n </div>\n );\n}\n","/**\n * Router-aware wrapper around CollectionsStudioView.\n *\n * This component provides the react-router-based navigation behavior\n * that Rebase Studio expects: the active collection is derived from the\n * URL, and clicking a collection navigates via react-router.\n *\n * External consumers should use `CollectionsStudioView` directly\n * (which has no react-router dependency).\n */\nimport React from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\nimport { useUrlController } from \"../../_cms_internals\";\nimport { CollectionsStudioView, CollectionsStudioViewProps } from \"./CollectionsStudioView\";\n\nexport type RouterCollectionsStudioViewProps = Omit<CollectionsStudioViewProps, \"activeCollectionId\" | \"onActiveCollectionChange\">;\n\nexport function RouterCollectionsStudioView(props: RouterCollectionsStudioViewProps) {\n const navigate = useNavigate();\n const urlController = useUrlController();\n const location = useLocation();\n\n // Determine the active collection from the URL segment after \"schema/\"\n const basePath = urlController.buildAppUrlPath(\"schema\");\n const relativePath = location.pathname.replace(basePath, \"\").replace(/^\\//, \"\");\n const activeCollectionId = relativePath.split(\"/\")[0] || undefined;\n\n return (\n <CollectionsStudioView\n {...props}\n activeCollectionId={activeCollectionId}\n onActiveCollectionChange={(id) => {\n if (id) {\n navigate(urlController.buildAppUrlPath(`schema/${id}`));\n } else {\n navigate(urlController.buildAppUrlPath(\"schema\"));\n }\n }}\n />\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RouterCollectionsStudioView-D54P9o8O.js","names":[],"sources":["../src/collection_editor/ui/collection_editor/CollectionStudioView.tsx","../src/collection_editor/ui/collection_editor/CollectionsStudioView.tsx","../src/collection_editor/ui/collection_editor/RouterCollectionsStudioView.tsx"],"sourcesContent":["\nimport { useUnsavedChangesDialog, UnsavedChangesDialog } from \"@rebasepro/app\";\nimport * as React from \"react\";\nimport { useState } from \"react\";\nimport { Button, PlusIcon, Typography } from \"@rebasepro/ui\";\nimport { CollectionEditorDialogProps } from \"./CollectionEditorDialog\";\nimport { AIModifiedPathsProvider } from \"./AIModifiedPathsContext\";\nimport { CollectionEditor } from \"./CollectionEditorDialog\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport type CollectionStudioViewProps = Omit<CollectionEditorDialogProps, \"open\" | \"isNewCollection\" | \"editedCollectionId\" | \"handleClose\" | \"handleCancel\"> & {\n collectionId?: string | \"new\";\n\n /**\n * Called after a successful save.\n * Receives the saved collection (or undefined if dismissed without saving).\n * When not provided, save completes silently.\n */\n onSave?: (collection?: AdminCollection) => void;\n\n /**\n * Called when the user cancels editing.\n * When not provided, cancel is a no-op.\n */\n onCancel?: () => void;\n};\n\nexport function CollectionStudioView({ collectionId, onSave, onCancel, ...props }: CollectionStudioViewProps) {\n\n // Form state from the editor\n const [formDirty, setFormDirty] = useState<boolean>(false);\n const [cancelRequested, setCancelRequested] = useState<boolean>(false);\n\n const { dialogProps, triggerDialog } = useUnsavedChangesDialog(\n formDirty,\n () => setFormDirty(false)\n );\n\n const activeCollectionId = collectionId;\n\n const handleCancelClick = () => {\n if (!formDirty) {\n onCancel?.();\n } else {\n setCancelRequested(true);\n triggerDialog();\n }\n };\n\n return (\n <div className=\"flex-grow flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800\">\n <AIModifiedPathsProvider>\n {activeCollectionId ? (\n <CollectionEditor\n key={activeCollectionId}\n {...props}\n fullScreen={true}\n open={true}\n isNewCollection={activeCollectionId === \"new\"}\n editedCollectionId={activeCollectionId !== \"new\" ? activeCollectionId : undefined}\n handleCancel={handleCancelClick}\n handleClose={(savedCollection) => {\n setFormDirty(false);\n if (savedCollection) {\n setTimeout(() => {\n onSave?.(savedCollection);\n }, 0);\n }\n }}\n setFormDirty={setFormDirty}\n />\n ) : (\n <div className=\"flex-grow flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one\n </Typography>\n <Button\n disabled={props.configController?.readOnly}\n onClick={() => onSave?.()}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n\n <UnsavedChangesDialog\n {...dialogProps}\n handleOk={() => {\n dialogProps.handleOk();\n if (cancelRequested) {\n onCancel?.();\n setCancelRequested(false);\n }\n }}\n handleCancel={() => {\n dialogProps.handleCancel();\n setCancelRequested(false);\n }}\n />\n </AIModifiedPathsProvider>\n </div>\n );\n}\n","\nimport { IconForView } from \"@rebasepro/app\";\nimport React, { useState, useEffect } from \"react\";\nimport {\n Button,\n cls,\n defaultBorderMixin,\n IconButton,\n iconSize,\n PlusIcon,\n ResizablePanels,\n Tooltip,\n Typography\n} from \"@rebasepro/ui\";\n\nimport { CollectionsConfigController } from \"../../types/config_controller\";\nimport { CollectionStudioView } from \"./CollectionStudioView\";\nimport type { CollectionEditorExtensionProps } from \"../../extensibility_types\";\nimport type { AdminCollection } from \"@rebasepro/admin-types\";\n\nexport interface CollectionsStudioViewProps extends CollectionEditorExtensionProps {\n configController: CollectionsConfigController;\n\n /**\n * Collections to show in the sidebar.\n * When provided, overrides the collections from `configController`.\n * Use this to control exactly which collections the editor displays.\n */\n collections?: AdminCollection[];\n\n /**\n * Controlled active collection ID.\n * When provided together with `onActiveCollectionChange`,\n * navigation is fully external — no internal state is used.\n */\n activeCollectionId?: string;\n\n /**\n * Called when the user clicks a collection, \"new\", or navigates.\n * When provided, the component is fully controlled (no internal state).\n * When not provided, the component manages selection via internal state.\n *\n * Pass `\"new\"` to create a new collection. Pass `undefined` to deselect.\n */\n onActiveCollectionChange?: (collectionId: string | undefined) => void;\n}\n\nexport function CollectionsStudioView({\n configController,\n collections: collectionsProp,\n activeCollectionId: controlledActiveId,\n onActiveCollectionChange,\n propertyTypePresets,\n hiddenPropertyTypes,\n renderExtraPropertyFields,\n renderExtraCollectionFields,\n visibleTabs,\n standalone,\n}: CollectionsStudioViewProps) {\n\n // ── Navigation state ────────────────────────────────────────────────\n // If onActiveCollectionChange is provided, the component is controlled.\n // Otherwise, use internal state.\n const [internalActiveId, setInternalActiveId] = useState<string | undefined>(undefined);\n const isControlled = onActiveCollectionChange !== undefined;\n const activeCollectionId = isControlled ? controlledActiveId : internalActiveId;\n\n const setActiveCollectionId = (id: string | undefined) => {\n if (isControlled) {\n onActiveCollectionChange?.(id);\n } else {\n setInternalActiveId(id);\n }\n };\n\n // ── Collections list ────────────────────────────────────────────────\n const collections = collectionsProp ?? configController.collections ?? [];\n\n // ── Sidebar sizing ──────────────────────────────────────────────────\n const [sidebarSize, setSidebarSize] = useState(() => {\n try {\n const saved = localStorage.getItem(\"rebase_collections_editor_sidebar_size\");\n return saved !== null ? parseFloat(saved) : 25;\n } catch (e) {\n return 25;\n }\n });\n\n useEffect(() => {\n try {\n localStorage.setItem(\"rebase_collections_editor_sidebar_size\", sidebarSize.toString());\n } catch (e) {\n // ignore local storage error\n }\n }, [sidebarSize]);\n\n return (\n <div className=\"flex h-full w-full bg-surface-50 dark:bg-surface-800 overflow-hidden text-text-primary dark:text-text-primary-dark\">\n <ResizablePanels\n orientation=\"horizontal\"\n panelSizePercent={sidebarSize}\n onPanelSizeChange={setSidebarSize}\n minPanelSizePx={220}\n firstPanel={\n <div className={cls(\"flex flex-col h-full w-full bg-surface-50 dark:bg-surface-800 border-r\", defaultBorderMixin)}>\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b bg-surface-50 dark:bg-surface-900 min-h-[48px]\", defaultBorderMixin)}>\n <Typography variant=\"caption\" className=\"font-semibold text-[11px] uppercase tracking-wider text-surface-400 dark:text-surface-400\">\n Collections\n </Typography>\n <Tooltip title={configController.readOnly ? configController.readOnlyReason || \"Read only\" : \"Add collection\"}>\n <div>\n <IconButton\n size=\"small\"\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n className={activeCollectionId === \"new\" ? \"text-primary dark:text-primary-dark\" : \"text-text-secondary dark:text-text-secondary-dark\"}\n >\n <PlusIcon size={iconSize.smallest}/>\n </IconButton>\n </div>\n </Tooltip>\n </div>\n\n <div className=\"flex-grow overflow-y-auto w-full no-scrollbar p-2 space-y-0.5\">\n {collections.length === 0 && (\n <div className=\"p-4 text-center\">\n <Typography variant=\"caption\" className=\"text-text-disabled dark:text-text-disabled-dark italic\">\n No collections yet.\n </Typography>\n </div>\n )}\n {collections.map((collection) => {\n const collectionKey = collection.slug;\n const isSelected = activeCollectionId === collectionKey;\n return (\n <div\n key={collectionKey}\n onClick={() => setActiveCollectionId(collectionKey)}\n className={cls(\n \"flex items-center gap-2.5 px-3 h-[30px] cursor-pointer rounded-lg text-[13px] font-medium transition-colors\",\n isSelected\n ? \"bg-primary/8 text-primary dark:bg-primary/10 dark:text-primary-light font-semibold\"\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 )}\n >\n <IconForView collectionOrView={collection} size={\"smallest\"} className={cls(\n isSelected\n ? \"text-primary dark:text-primary-light\"\n : \"text-surface-500 dark:text-text-secondary-dark\"\n )}/>\n <span className=\"truncate flex-1\">\n {collection.name || collection.slug}\n </span>\n </div>\n );\n })}\n </div>\n </div>\n }\n secondPanel={\n <div className=\"flex-grow flex flex-col min-w-0 h-full w-full\">\n {/* We use key to force unmount when switching collections, preventing stale state */}\n {activeCollectionId ? (\n <CollectionStudioView\n key={activeCollectionId}\n configController={configController}\n collectionId={activeCollectionId}\n onSave={(savedCollection) => {\n // After creating a new collection, switch to it\n if (activeCollectionId === \"new\" && savedCollection?.slug) {\n setActiveCollectionId(savedCollection.slug);\n }\n }}\n onCancel={() => setActiveCollectionId(undefined)}\n propertyTypePresets={propertyTypePresets}\n hiddenPropertyTypes={hiddenPropertyTypes}\n renderExtraPropertyFields={renderExtraPropertyFields}\n renderExtraCollectionFields={renderExtraCollectionFields}\n visibleTabs={visibleTabs}\n standalone={standalone}\n />\n ) : (\n <div className=\"flex flex-col items-center justify-center h-full gap-4\">\n <Typography variant=\"label\">\n Select a collection or create a new one to start editing\n </Typography>\n <Button\n disabled={configController.readOnly}\n onClick={() => setActiveCollectionId(\"new\")}\n >\n <PlusIcon/>\n Add new collection\n </Button>\n </div>\n )}\n </div>\n }\n />\n </div>\n );\n}\n","/**\n * Router-aware wrapper around CollectionsStudioView.\n *\n * This component provides the react-router-based navigation behavior\n * that Rebase Studio expects: the active collection is derived from the\n * URL, and clicking a collection navigates via react-router.\n *\n * External consumers should use `CollectionsStudioView` directly\n * (which has no react-router dependency).\n */\nimport React from \"react\";\nimport { useLocation, useNavigate } from \"react-router\";\nimport { useUrlController } from \"../../_cms_internals\";\nimport { CollectionsStudioView, CollectionsStudioViewProps } from \"./CollectionsStudioView\";\n\nexport type RouterCollectionsStudioViewProps = Omit<CollectionsStudioViewProps, \"activeCollectionId\" | \"onActiveCollectionChange\">;\n\nexport function RouterCollectionsStudioView(props: RouterCollectionsStudioViewProps) {\n const navigate = useNavigate();\n const urlController = useUrlController();\n const location = useLocation();\n\n // Determine the active collection from the URL segment after \"schema/\"\n const basePath = urlController.buildAppUrlPath(\"schema\");\n const relativePath = location.pathname.replace(basePath, \"\").replace(/^\\//, \"\");\n const activeCollectionId = relativePath.split(\"/\")[0] || undefined;\n\n return (\n <CollectionsStudioView\n {...props}\n activeCollectionId={activeCollectionId}\n onActiveCollectionChange={(id) => {\n if (id) {\n navigate(urlController.buildAppUrlPath(`schema/${id}`));\n } else {\n navigate(urlController.buildAppUrlPath(\"schema\"));\n }\n }}\n />\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { in as useUrlController } from "./util-
|
|
2
|
-
import { n as PropertyForm, r as PropertyFormDialog } from "./PropertyEditView-
|
|
3
|
-
import { n as CollectionEditorDialog } from "./CollectionEditorDialog-
|
|
4
|
-
import { i as CollectionStudioView, r as CollectionsStudioView, t as RouterCollectionsStudioView } from "./RouterCollectionsStudioView-
|
|
1
|
+
import { in as useUrlController } from "./util-EXfeGzbH.js";
|
|
2
|
+
import { n as PropertyForm, r as PropertyFormDialog } from "./PropertyEditView-Bt-VM0zQ.js";
|
|
3
|
+
import { n as CollectionEditorDialog } from "./CollectionEditorDialog-MODRemil.js";
|
|
4
|
+
import { i as CollectionStudioView, r as CollectionsStudioView, t as RouterCollectionsStudioView } from "./RouterCollectionsStudioView-D54P9o8O.js";
|
|
5
5
|
import "react";
|
|
6
6
|
import { useSnackbarController } from "@rebasepro/app";
|
|
7
7
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AdditionalFieldDelegate, RebaseContext } from "@rebasepro/admin-types";
|
|
2
|
+
import type { Entity } from "@rebasepro/types";
|
|
3
|
+
import React from "react";
|
|
4
|
+
export interface AdditionalFieldValueProps<M extends Record<string, unknown>> {
|
|
5
|
+
field: AdditionalFieldDelegate<M>;
|
|
6
|
+
entity: Entity<M>;
|
|
7
|
+
context: RebaseContext;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Renders an `additionalFields` entry that supplies a `value` rather than a
|
|
11
|
+
* `Builder`.
|
|
12
|
+
*
|
|
13
|
+
* `value` is typed `string | number | Promise<string | number>`, and the promise
|
|
14
|
+
* arm has been part of that type from the start — the CSV export awaits it
|
|
15
|
+
* correctly. Every *renderer* called `.toString()` on the result instead, so an
|
|
16
|
+
* async value drew the literal text `[object Promise]` in the cell: a shape the
|
|
17
|
+
* type promised, that worked in one of its two consumers, and failed silently in
|
|
18
|
+
* the other. That is what made the obvious port of a FireCMS column — one that
|
|
19
|
+
* fetches a title from a subcollection — look supported and not be.
|
|
20
|
+
*
|
|
21
|
+
* Three call sites had the same three lines copied between them (the table cell,
|
|
22
|
+
* the form and the read-only record), which is why the bug reached all three.
|
|
23
|
+
* Now there is one.
|
|
24
|
+
*/
|
|
25
|
+
export declare function AdditionalFieldValue<M extends Record<string, unknown>>({ field, entity, context }: AdditionalFieldValueProps<M>): React.JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AdminCollection } from "@rebasepro/admin-types";
|
|
2
|
+
import { FilterValues } from "@rebasepro/types";
|
|
2
3
|
import React from "react";
|
|
3
4
|
/**
|
|
4
5
|
* @group Components
|
|
@@ -39,3 +40,18 @@ export type CollectionViewBindingProps<M extends Record<string, unknown>> = {
|
|
|
39
40
|
selectedTab?: string;
|
|
40
41
|
} & AdminCollection<M>;
|
|
41
42
|
export declare const CollectionViewBinding: React.FunctionComponent<CollectionViewBindingProps<any>>;
|
|
43
|
+
export declare function EntitiesCount({ path, collection, filter, sortBy, searchString, onCountChange }: {
|
|
44
|
+
path: string;
|
|
45
|
+
collection: AdminCollection;
|
|
46
|
+
filter?: FilterValues<any>;
|
|
47
|
+
sortBy?: [string, "asc" | "desc"];
|
|
48
|
+
/**
|
|
49
|
+
* Required, not optional. The term sits in the same scope as the element
|
|
50
|
+
* that mounts this and is passed to the toolbar and the empty state beside
|
|
51
|
+
* it — it was simply not passed here, so a searched list showed the count
|
|
52
|
+
* of the unsearched collection. A required prop is what stops the next
|
|
53
|
+
* caller doing the same; there is no useful "count without the search".
|
|
54
|
+
*/
|
|
55
|
+
searchString: string | undefined;
|
|
56
|
+
onCountChange?: (count: number | null | undefined) => void;
|
|
57
|
+
}): null;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { PreviewSize } from "../../types/components/PropertyPreviewProps";
|
|
3
|
+
import type { PreviewSlot } from "./usePreviewSlots";
|
|
4
|
+
export interface SlotValueProps {
|
|
5
|
+
slot: PreviewSlot | undefined;
|
|
6
|
+
size: PreviewSize;
|
|
7
|
+
/**
|
|
8
|
+
* Relations and references render as one line of linked text rather than as
|
|
9
|
+
* a card. Defaults to true: a slot is a line in a row or a card, and a
|
|
10
|
+
* relation that renders its own bordered card there — with its own id line
|
|
11
|
+
* and its own side-panel button — is a card inside a card.
|
|
12
|
+
*
|
|
13
|
+
* Pass `false` only for a slot with room for one, which in practice is
|
|
14
|
+
* none of them.
|
|
15
|
+
*/
|
|
16
|
+
textOnly?: boolean;
|
|
17
|
+
/** Images only: fill the container rather than fitting inside it. */
|
|
18
|
+
fill?: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* One display slot, rendered.
|
|
22
|
+
*
|
|
23
|
+
* A slot's value arrives one of two ways and they cannot be rendered the same:
|
|
24
|
+
*
|
|
25
|
+
* - **From a property** — render it with that property's own preview, so an
|
|
26
|
+
* enum status keeps its colour, a date keeps its format and a storage path
|
|
27
|
+
* becomes a thumbnail. This is why a declared path beats a resolver whenever
|
|
28
|
+
* the value is actually on the record.
|
|
29
|
+
* - **From a resolver** — there is no property, because the value was computed
|
|
30
|
+
* or fetched. All that can be said about it is that it is text.
|
|
31
|
+
*
|
|
32
|
+
* The branch lives here, once, rather than at each of the fourteen places the
|
|
33
|
+
* list row, the card and the board card render a slot. That count is the reason:
|
|
34
|
+
* the last time a rule like this was inlined per call site, it drifted into
|
|
35
|
+
* seven versions.
|
|
36
|
+
*/
|
|
37
|
+
export declare function SlotValue({ slot, size, textOnly, fill }: SlotValueProps): React.JSX.Element | null;
|
|
@@ -3,8 +3,10 @@ import React from "react";
|
|
|
3
3
|
* Closes the list of a split view, leaving the open record on its own.
|
|
4
4
|
*
|
|
5
5
|
* It leads the record's own app bar, where the breadcrumb starts — this is the
|
|
6
|
-
* entity pane's old "Open full screen" button, moved to that edge and wearing
|
|
7
|
-
*
|
|
8
|
-
*
|
|
6
|
+
* entity pane's old "Open full screen" button, moved to that edge and wearing a
|
|
7
|
+
* double chevron pointing at the list it folds away: closing the list and
|
|
8
|
+
* opening the record full screen are the same thing, so there is one control
|
|
9
|
+
* and one route (`#full`) rather than two. Full screen carries the mirrored
|
|
10
|
+
* chevron to bring the list back.
|
|
9
11
|
*/
|
|
10
12
|
export declare function SplitListCloseButton(): React.JSX.Element | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Brings the list back beside a record that was opened full screen.
|
|
4
|
+
*
|
|
5
|
+
* The mirror of {@link SplitListCloseButton}: the same edge of the same bar,
|
|
6
|
+
* the same double chevron pointing the other way, and the same single route —
|
|
7
|
+
* showing the list is dropping the `#full` hash. It replaces the back arrow
|
|
8
|
+
* where it applies, because the list it unfolds already holds the record.
|
|
9
|
+
*/
|
|
10
|
+
export declare function SplitListShowButton({ onClick }: {
|
|
11
|
+
onClick: () => void;
|
|
12
|
+
}): React.JSX.Element;
|
|
@@ -4,12 +4,18 @@ import type { PropertyConfig, AdminCollection } from "@rebasepro/admin-types";
|
|
|
4
4
|
import type { AuthController } from "@rebasepro/admin-types";
|
|
5
5
|
import { ChipColorScheme } from "@rebasepro/ui";
|
|
6
6
|
/**
|
|
7
|
-
* A resolved "slot"
|
|
8
|
-
*
|
|
7
|
+
* A resolved "slot": what fills one display role for one record.
|
|
8
|
+
*
|
|
9
|
+
* `property` and `propertyKey` are set when the value was read off the record,
|
|
10
|
+
* and absent when a `display` resolver computed it — a computed title has no
|
|
11
|
+
* column behind it, so there is nothing to render it *as*. Renderers must go
|
|
12
|
+
* through {@link SlotValue}, which makes that choice once: a property renders
|
|
13
|
+
* with its own preview (an enum keeps its coloured chip, a date its format), a
|
|
14
|
+
* computed value renders as text.
|
|
9
15
|
*/
|
|
10
16
|
export interface PreviewSlot {
|
|
11
|
-
property
|
|
12
|
-
propertyKey
|
|
17
|
+
property?: Property;
|
|
18
|
+
propertyKey?: string;
|
|
13
19
|
value: unknown;
|
|
14
20
|
}
|
|
15
21
|
/**
|
|
@@ -102,3 +108,22 @@ export declare function useCollectionSlotKeys(collection: AdminCollection<Record
|
|
|
102
108
|
* `React.memo` render functions or loops without violating hook rules.
|
|
103
109
|
*/
|
|
104
110
|
export declare function resolveEntitySlots(entity: Entity<Record<string, unknown>>, collection: AdminCollection<Record<string, unknown>>, slotKeys: CollectionSlotKeys): EntityPreviewSlots;
|
|
111
|
+
/**
|
|
112
|
+
* The slots for one record, with `admin.display` resolvers applied.
|
|
113
|
+
*
|
|
114
|
+
* {@link resolveEntitySlots} answers the question from values already in hand —
|
|
115
|
+
* which is everything a slot filled by a property needs, and nothing a slot
|
|
116
|
+
* filled by a *resolver* can use. A computed title may have to be fetched, so it
|
|
117
|
+
* arrives after the first render; this hook is where the two meet.
|
|
118
|
+
*
|
|
119
|
+
* Until a resolver lands, the derived slot shows. That is deliberate: a list of
|
|
120
|
+
* fifty rows must not blank its titles for a beat while fifty promises settle,
|
|
121
|
+
* and the derived answer — the best-ranked property carrying a readable value —
|
|
122
|
+
* is a reasonable thing to be looking at meanwhile. When the resolved value
|
|
123
|
+
* arrives it replaces the slot outright, property and all, because there is no
|
|
124
|
+
* property behind a computed value (see {@link PreviewSlot}).
|
|
125
|
+
*
|
|
126
|
+
* Every role is hooked unconditionally, so the hook order is fixed regardless of
|
|
127
|
+
* what a given collection declares.
|
|
128
|
+
*/
|
|
129
|
+
export declare function useEntitySlots(entity: Entity<Record<string, unknown>>, collection: AdminCollection<Record<string, unknown>>, slotKeys: CollectionSlotKeys): EntityPreviewSlots;
|
|
@@ -29,5 +29,11 @@ export interface DetailViewBindingProps<M extends Record<string, unknown> = Reco
|
|
|
29
29
|
* of the breadcrumb — the side panel's close button.
|
|
30
30
|
*/
|
|
31
31
|
barActionsStart?: React.ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Full screen only: bring the list back beside this record. Set when the
|
|
34
|
+
* record was opened out of a split collection, so folding the list away is
|
|
35
|
+
* reversible; it takes the place of the back arrow when present.
|
|
36
|
+
*/
|
|
37
|
+
onShowList?: () => void;
|
|
32
38
|
}
|
|
33
39
|
export declare function DetailViewBinding<M extends Record<string, unknown>>({ entityId, ...props }: DetailViewBindingProps<M>): React.JSX.Element;
|
|
@@ -22,11 +22,12 @@ export interface DrawerNavigationGroupProps {
|
|
|
22
22
|
*/
|
|
23
23
|
drawerOpen: boolean;
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* @deprecated No longer read. Entry tooltips are uncontrolled — they follow the
|
|
26
|
+
* pointer and focus, and are suppressed wherever the label is already visible.
|
|
26
27
|
*/
|
|
27
|
-
tooltipsOpen
|
|
28
|
+
tooltipsOpen?: boolean;
|
|
28
29
|
/**
|
|
29
|
-
*
|
|
30
|
+
* @deprecated No longer read. See {@link tooltipsOpen}.
|
|
30
31
|
*/
|
|
31
32
|
adminMenuOpen?: boolean;
|
|
32
33
|
/**
|
|
@@ -53,4 +54,4 @@ export interface DrawerNavigationGroupProps {
|
|
|
53
54
|
* Shared drawer navigation group component used by both DefaultDrawer and RebaseCloudDrawer.
|
|
54
55
|
* Renders a collapsible group with header and navigation items.
|
|
55
56
|
*/
|
|
56
|
-
export declare function DrawerNavigationGroup({ group, entries, collapsed, onToggleCollapsed, drawerOpen,
|
|
57
|
+
export declare function DrawerNavigationGroup({ group, entries, collapsed, onToggleCollapsed, drawerOpen, headerActions, onItemClick, hideHeader, icon }: DrawerNavigationGroupProps): React.JSX.Element;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
export declare function DrawerNavigationItem({ name, icon, drawerOpen,
|
|
2
|
+
export declare function DrawerNavigationItem({ name, icon, drawerOpen, url, onClick, indented }: {
|
|
3
3
|
icon: React.ReactElement;
|
|
4
4
|
name: string;
|
|
5
|
-
|
|
5
|
+
/** @deprecated No longer read: the tooltip is uncontrolled. */
|
|
6
|
+
tooltipsOpen?: boolean;
|
|
6
7
|
drawerOpen: boolean;
|
|
8
|
+
/** @deprecated No longer read: the tooltip is uncontrolled. */
|
|
7
9
|
adminMenuOpen?: boolean;
|
|
8
10
|
url: string;
|
|
9
11
|
onClick?: () => void;
|
|
@@ -40,6 +40,12 @@ export interface EditViewBindingProps<M extends Record<string, unknown> = Record
|
|
|
40
40
|
* of the breadcrumb — the side panel's close button.
|
|
41
41
|
*/
|
|
42
42
|
barActionsStart?: React.ReactNode;
|
|
43
|
+
/**
|
|
44
|
+
* Full screen only: bring the list back beside this record. Set when the
|
|
45
|
+
* record was opened out of a split collection, so folding the list away is
|
|
46
|
+
* reversible; it takes the place of the back arrow when present.
|
|
47
|
+
*/
|
|
48
|
+
onShowList?: () => void;
|
|
43
49
|
formProps?: Partial<EntityFormBindingProps<M>>;
|
|
44
50
|
/**
|
|
45
51
|
* Pre-populate the form with these values when creating a new entity.
|
|
@@ -53,7 +59,7 @@ export interface EditViewBindingProps<M extends Record<string, unknown> = Record
|
|
|
53
59
|
* a record is opened.
|
|
54
60
|
*/
|
|
55
61
|
export declare function EditViewBinding<M extends Record<string, unknown>>({ entityId, ...props }: EditViewBindingProps<M>): React.JSX.Element;
|
|
56
|
-
export declare function EditViewBindingInner<M extends Record<string, unknown>>({ path, entityId, selectedTab: selectedTabProp, collection, parentCollectionSlugs, parentEntityIds, onValuesModified, onSaved, onTabChange, navigateBack, entity, initialDirtyValues, dataLoading, layout, barActions, barActionsStart, status, setStatus, formProps, canEdit }: EditViewBindingProps<M> & {
|
|
62
|
+
export declare function EditViewBindingInner<M extends Record<string, unknown>>({ path, entityId, selectedTab: selectedTabProp, collection, parentCollectionSlugs, parentEntityIds, onValuesModified, onSaved, onTabChange, navigateBack, entity, initialDirtyValues, dataLoading, layout, barActions, barActionsStart, onShowList, status, setStatus, formProps, canEdit }: EditViewBindingProps<M> & {
|
|
57
63
|
entity?: Entity<M>;
|
|
58
64
|
initialDirtyValues?: Partial<M>;
|
|
59
65
|
dataLoading: boolean;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { AdminCollection } from "@rebasepro/admin-types";
|
|
2
|
+
import type { Entity } from "@rebasepro/types";
|
|
3
|
+
import React from "react";
|
|
4
|
+
/**
|
|
5
|
+
* The roles whose property the read-only view takes out of its grid.
|
|
6
|
+
*
|
|
7
|
+
* A role rendered here and left in the grid prints the value twice, so the
|
|
8
|
+
* header's own rendering and this list have to agree — but the list is *not*
|
|
9
|
+
* simply "every role the header draws". Two are deliberately absent:
|
|
10
|
+
*
|
|
11
|
+
* `title`, because the heading above a record and a labelled field are not the
|
|
12
|
+
* same thing. `Order #` is a column with a name, a description and a format that
|
|
13
|
+
* someone reads the record to find; `ORD-2026-0043` sitting in the identity bar
|
|
14
|
+
* beside the breadcrumb is a label for the page. Removing the field because the
|
|
15
|
+
* page is named after it takes a value out of the record on the grounds that its
|
|
16
|
+
* text appears elsewhere, which is not a reason — a value in the database is
|
|
17
|
+
* shown.
|
|
18
|
+
*
|
|
19
|
+
* `date`, because the rail's record block already carries the timestamps, and a
|
|
20
|
+
* collection whose `date` role points at a business date — an order date, a due
|
|
21
|
+
* date — wants that field where it declared it.
|
|
22
|
+
*/
|
|
23
|
+
export declare const HEADER_DISPLAY_ROLES: readonly ["subtitle", "image", "status", "tags"];
|
|
24
|
+
export interface EntityDisplayHeaderProps<M extends Record<string, unknown>> {
|
|
25
|
+
entity: Entity<M>;
|
|
26
|
+
collection: AdminCollection<M>;
|
|
27
|
+
/**
|
|
28
|
+
* Render the title. Off when an identity bar above already shows it — which
|
|
29
|
+
* is every full-page use — and on inside a dialog that has no bar.
|
|
30
|
+
*/
|
|
31
|
+
showTitle?: boolean;
|
|
32
|
+
className?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* What the record *is*, above the fields that say what it holds.
|
|
36
|
+
*
|
|
37
|
+
* A record's picture, name, state and labels are the things you opened the page
|
|
38
|
+
* to see; on the plain grid they were fields like any other, so an order's
|
|
39
|
+
* status sat in the second cell of the first row at the same size and weight as
|
|
40
|
+
* its shipping cost, and its tags were a wrapped list of grey text.
|
|
41
|
+
*
|
|
42
|
+
* Every role here comes from `admin.display` and nothing is derived except the
|
|
43
|
+
* title, which was already derived for the identity bar. A collection that
|
|
44
|
+
* declares no display block therefore gets no header at all rather than a
|
|
45
|
+
* heuristic guess at which of its enums is a "status" — the panel does not know
|
|
46
|
+
* what these records are, and a wrong guess here is louder than no guess.
|
|
47
|
+
*
|
|
48
|
+
* A role filled by a *property* renders through {@link PropertyPreview}, so a
|
|
49
|
+
* status keeps its enum's colour and an image stays a storage thumbnail. A role
|
|
50
|
+
* filled by a resolver has no property behind it and renders as what it
|
|
51
|
+
* returned.
|
|
52
|
+
*/
|
|
53
|
+
export declare function EntityDisplayHeader<M extends Record<string, unknown>>({ entity, collection, showTitle, className }: EntityDisplayHeaderProps<M>): React.JSX.Element | null;
|
|
@@ -4,6 +4,15 @@ import React from "react";
|
|
|
4
4
|
export interface EntityIdentityBarProps {
|
|
5
5
|
/** Plural collection name, shown as the breadcrumb ahead of the title. */
|
|
6
6
|
collection: AdminCollection;
|
|
7
|
+
/**
|
|
8
|
+
* Where the breadcrumb points. Without it the collection name is inert text
|
|
9
|
+
* that still reads as a breadcrumb — worse than no breadcrumb at all, and
|
|
10
|
+
* the only way back once a layout drops its back arrow.
|
|
11
|
+
*
|
|
12
|
+
* Left unset by the overlays (side panel, dialog), where the collection is
|
|
13
|
+
* already underneath and navigating would dismiss the record instead.
|
|
14
|
+
*/
|
|
15
|
+
collectionUrl?: string;
|
|
7
16
|
/** Resolved record title, already guarded against showing a field default. */
|
|
8
17
|
title: string;
|
|
9
18
|
entityId?: string | number;
|
|
@@ -24,6 +33,16 @@ export interface EntityIdentityBarProps {
|
|
|
24
33
|
onInspect?: () => void;
|
|
25
34
|
/** Opens the inspector straight on its history tab. */
|
|
26
35
|
onViewHistory?: () => void;
|
|
36
|
+
/**
|
|
37
|
+
* Where this record appears on the live site, from `entityLinkBuilder`.
|
|
38
|
+
*
|
|
39
|
+
* Here rather than above the record, where it used to be a single unlabelled
|
|
40
|
+
* icon alone on its own right-aligned row — the only thing between the bar
|
|
41
|
+
* and the first field, and the only control in the view that did not say
|
|
42
|
+
* what it was. It is a thing you do *to* a record, so it belongs with the
|
|
43
|
+
* others.
|
|
44
|
+
*/
|
|
45
|
+
externalLink?: string;
|
|
27
46
|
/**
|
|
28
47
|
* Actions performed *on* the record — copy, delete, whatever the collection
|
|
29
48
|
* adds — as menu items under the overflow button. They live here rather
|
|
@@ -50,4 +69,4 @@ export interface EntityIdentityBarProps {
|
|
|
50
69
|
* editing. They live here instead, and the left half of a bar that was
|
|
51
70
|
* previously empty now does the work.
|
|
52
71
|
*/
|
|
53
|
-
export declare function EntityIdentityBar({ collection, title, entityId, status, dirty, saving, onSave, onDiscard, saveDisabled, hasErrors, onSaveAndClose, onBack, onInspect, onViewHistory, recordActions, pluginActions, trailing, leading }: EntityIdentityBarProps): React.JSX.Element;
|
|
72
|
+
export declare function EntityIdentityBar({ collection, collectionUrl, title, entityId, status, dirty, saving, onSave, onDiscard, saveDisabled, hasErrors, onSaveAndClose, onBack, onInspect, onViewHistory, externalLink, recordActions, pluginActions, trailing, leading }: EntityIdentityBarProps): React.JSX.Element;
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
import type { AdminCollection } from "@rebasepro/admin-types";
|
|
2
|
+
import type { FormContext } from "../types/fields";
|
|
2
3
|
import React from "react";
|
|
3
4
|
import { Entity } from "@rebasepro/types";
|
|
5
|
+
/**
|
|
6
|
+
* The fields the read-only view lays out, in render order.
|
|
7
|
+
*
|
|
8
|
+
* The same set the form uses, minus two groups. Both are dropped *before* the
|
|
9
|
+
* layout resolves rather than skipped while rendering, because the resolver has
|
|
10
|
+
* by then given each one a place on the grid — skipping later leaves that place
|
|
11
|
+
* as a hole.
|
|
12
|
+
*
|
|
13
|
+
* - The `additionalFields` when there is no form context to hand them: those
|
|
14
|
+
* entries are arbitrary components, not values, and one rendered against no
|
|
15
|
+
* context is nothing at all.
|
|
16
|
+
* - `headerKeys` — the properties {@link EntityDisplayHeader} has already
|
|
17
|
+
* rendered as the record's picture, subtitle, state and labels. Leaving one in
|
|
18
|
+
* prints its value twice on one screen.
|
|
19
|
+
*
|
|
20
|
+
* The record's **title property is not among them**, deliberately. It names the
|
|
21
|
+
* page in the identity bar, but a heading and a labelled field are different
|
|
22
|
+
* things: `Order #` is a column with a name and a description that someone opens
|
|
23
|
+
* the record to read, and dropping it because its text also appears in the
|
|
24
|
+
* breadcrumb removes a value from the record on the grounds that it is legible
|
|
25
|
+
* somewhere else. See {@link HEADER_DISPLAY_ROLES}.
|
|
26
|
+
*/
|
|
27
|
+
export declare function readOnlyFieldKeys(collection: AdminCollection, hasFormContext: boolean, headerKeys?: ReadonlySet<string>): string[];
|
|
4
28
|
/**
|
|
5
29
|
* @group Components
|
|
6
30
|
*/
|
|
@@ -9,14 +33,44 @@ export interface EntityViewBindingProps<M extends Record<string, unknown>> {
|
|
|
9
33
|
collection: AdminCollection<M>;
|
|
10
34
|
path: string;
|
|
11
35
|
className?: string;
|
|
36
|
+
/**
|
|
37
|
+
* Lay the record out as a page: a centred, scrolling column with the
|
|
38
|
+
* metadata rail beside it, exactly as the form does. Off for the inline
|
|
39
|
+
* uses — the delete dialog renders the record inside a box it already owns.
|
|
40
|
+
*/
|
|
41
|
+
asPage?: boolean;
|
|
42
|
+
/** Padding preset, matching the form's. Only read when `asPage`. */
|
|
43
|
+
openEntityMode?: "side_panel" | "full_screen" | "split" | "dialog";
|
|
44
|
+
/**
|
|
45
|
+
* Needed only to render `additionalFields`, which are arbitrary components
|
|
46
|
+
* that take a form context. Without one those entries are left out rather
|
|
47
|
+
* than rendered against a fake context.
|
|
48
|
+
*/
|
|
49
|
+
formContext?: FormContext<M>;
|
|
12
50
|
}
|
|
13
51
|
/**
|
|
14
52
|
* The read-only rendering of a record's values.
|
|
15
53
|
*
|
|
16
|
-
* This
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
54
|
+
* This is the same layout as {@link EntityForm}: the sections, the grid spans,
|
|
55
|
+
* the labels and the rail all come from the one resolver, so the record does
|
|
56
|
+
* not rearrange itself when you press Edit. Only the controls differ — each
|
|
57
|
+
* field renders its {@link PropertyPreview} instead of an input.
|
|
58
|
+
*
|
|
59
|
+
* It used to be a flat two-column table of every value in the record: no
|
|
60
|
+
* grouping, no widths, a label column sized for short names and a value column
|
|
61
|
+
* that wrapped emails over two lines while the pane beside it stayed empty. A
|
|
62
|
+
* boolean and a markdown body were given the same room.
|
|
63
|
+
*
|
|
64
|
+
* The synthetic `Id` row it used to prepend is gone with the same reasoning the
|
|
65
|
+
* form applies: between that row, the collection's own id property and the
|
|
66
|
+
* `path/id` chip above them, one UUID appeared three times. The id is a
|
|
67
|
+
* copyable chip in the identity bar, and the rail's record block, once each.
|
|
68
|
+
*
|
|
69
|
+
* The labels are the form's labels, icon and all: a field is the same field
|
|
70
|
+
* whether or not you are editing it. What `mode: "read"` drops is the per-field
|
|
71
|
+
* *description*, which is input help rather than part of the label — and what it
|
|
72
|
+
* adds is room. A control is a bordered box that separates itself from the next
|
|
73
|
+
* one; a value is bare text, so the rows and sections are opened up rather than
|
|
74
|
+
* inheriting spacing sized for inputs.
|
|
21
75
|
*/
|
|
22
|
-
export declare function EntityViewBinding<M extends Record<string, unknown>>({ entity, collection,
|
|
76
|
+
export declare function EntityViewBinding<M extends Record<string, unknown>>({ entity, collection, className, asPage, openEntityMode, formContext }: EntityViewBindingProps<M>): React.JSX.Element;
|
|
@@ -7,7 +7,7 @@ export interface RebaseLayoutProps {
|
|
|
7
7
|
appBar?: React.ReactNode;
|
|
8
8
|
/** Custom Drawer to override the default. */
|
|
9
9
|
drawer?: React.ReactNode;
|
|
10
|
-
/** Expand the drawer while the pointer is over it. Not a load-time default — that is `defaultDrawerOpen`. */
|
|
10
|
+
/** 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`. */
|
|
11
11
|
autoOpenDrawer?: boolean;
|
|
12
12
|
/** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */
|
|
13
13
|
defaultDrawerOpen?: boolean;
|
|
@@ -4,7 +4,7 @@ export interface RebaseShellProps {
|
|
|
4
4
|
/** Top bar. Only rendered if provided — pass `<AppBar/>` for the default one. */
|
|
5
5
|
appBar?: React.ReactNode;
|
|
6
6
|
drawer?: React.ReactNode;
|
|
7
|
-
/** Expand the drawer while the pointer is over it. Not a load-time default — that is `defaultDrawerOpen`. */
|
|
7
|
+
/** 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`. */
|
|
8
8
|
autoOpenDrawer?: boolean;
|
|
9
9
|
/** Start with the drawer expanded instead of collapsed to icons. Ignored on small layouts. */
|
|
10
10
|
defaultDrawerOpen?: boolean;
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
export declare const DRAWER_WIDTH = 280;
|
|
3
|
+
/**
|
|
4
|
+
* Namespaced by base path: two admins served from one origin are two different
|
|
5
|
+
* navigations, and a single key would have them overwrite each other's drawer.
|
|
6
|
+
*/
|
|
7
|
+
export declare function drawerOpenStorageKey(basePath: string | undefined): string;
|
|
3
8
|
/**
|
|
4
9
|
* @group Core
|
|
5
10
|
*/
|
|
6
11
|
export interface ScaffoldProps {
|
|
7
12
|
/**
|
|
8
|
-
*
|
|
13
|
+
* Expand the collapsed drawer while the pointer is over it. On by default —
|
|
14
|
+
* pass `false` to keep the rail a rail until the user clicks the toggle.
|
|
9
15
|
*/
|
|
10
16
|
autoOpenDrawer?: boolean;
|
|
11
17
|
/**
|
|
12
18
|
* Start with the drawer expanded rather than collapsed to icons.
|
|
13
19
|
*
|
|
14
20
|
* Distinct from {@link autoOpenDrawer}, which is a hover behaviour: this one
|
|
15
|
-
* only seeds the
|
|
16
|
-
*
|
|
21
|
+
* only seeds the very first visit. Once the user toggles the drawer, that
|
|
22
|
+
* choice is stored in `localStorage` and wins over this prop on every load.
|
|
17
23
|
*
|
|
18
24
|
* Ignored on small layouts, where an expanded drawer covers the content it is
|
|
19
25
|
* meant to navigate.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export type { EntityViewBindingProps } from "./EntityViewBinding";
|
|
2
2
|
export { EntityViewBinding } from "./EntityViewBinding";
|
|
3
|
+
export type { EntityDisplayHeaderProps } from "./EntityDisplayHeader";
|
|
4
|
+
export { EntityDisplayHeader, HEADER_DISPLAY_ROLES } from "./EntityDisplayHeader";
|
|
3
5
|
export * from "./DetailViewBinding";
|
|
4
6
|
export type { SelectionProps } from "./ReferenceTable/SelectionTableBinding";
|
|
5
7
|
export { SelectionTableBinding } from "./ReferenceTable/SelectionTableBinding";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { nn as useAdminContext } from "./util-
|
|
2
|
+
import { nn as useAdminContext } from "./util-EXfeGzbH.js";
|
|
3
3
|
import React, { useCallback } from "react";
|
|
4
4
|
import { Alert, BooleanSwitchWithLabel, Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogTitle, DownloadIcon, IconButton, Label, RadioGroup, RadioGroupItem, Tooltip, iconSize } from "@rebasepro/ui";
|
|
5
5
|
import { getDefaultValuesFor } from "@rebasepro/common";
|
|
@@ -515,4 +515,4 @@ var export_exports = /* @__PURE__ */ __exportAll({
|
|
|
515
515
|
//#endregion
|
|
516
516
|
export { downloadDataAsCsv as a, getEntityJsonExportableData as c, downloadBlob as i, ExportCollectionAction as n, downloadEntitiesExport as o, BasicExportAction as r, getEntityCSVExportableData as s, export_exports as t };
|
|
517
517
|
|
|
518
|
-
//# sourceMappingURL=export-
|
|
518
|
+
//# sourceMappingURL=export-Bl1V7lKO.js.map
|