@rebasepro/cms 0.19.1 → 0.19.2-canary.g09316f6
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-BeX4b92r.js → CollectionEditorDialog-DQjLtp1W.js} +75 -70
- package/dist/CollectionEditorDialog-DQjLtp1W.js.map +1 -0
- package/dist/{PropertyEditView-C7thfj4L.js → PropertyEditView-BMCCD2OI.js} +6 -6
- package/dist/PropertyEditView-BMCCD2OI.js.map +1 -0
- package/dist/{RouterCollectionsStudioView-BtjzvB6E.js → RouterCollectionsStudioView-DwsbIAqr.js} +9 -9
- package/dist/RouterCollectionsStudioView-DwsbIAqr.js.map +1 -0
- package/dist/{SchemaChangeDialog-CkqK6KOC.js → SchemaChangeDialog-BeP0A4MJ.js} +3 -3
- package/dist/SchemaChangeDialog-BeP0A4MJ.js.map +1 -0
- package/dist/collection_editor/serializable_types.d.ts +20 -0
- package/dist/collection_editor_ui.js +5 -5
- package/dist/components/CollectionTableBinding/fields/CompactEntityCellField.d.ts +23 -0
- package/dist/components/CollectionTableBinding/fields/TableRelationSelectorField.d.ts +1 -1
- package/dist/components/RelationSelector.d.ts +5 -1
- package/dist/data_import/utils/file_headers.d.ts +28 -4
- package/dist/editor.js +11 -11
- package/dist/editor.js.map +1 -1
- package/dist/{export--arni_VY.js → export-DJoGYb89.js} +2 -2
- package/dist/{export--arni_VY.js.map → export-DJoGYb89.js.map} +1 -1
- package/dist/{history-C2TpoQwi.js → history-BBpsdTrJ.js} +4 -4
- package/dist/history-BBpsdTrJ.js.map +1 -0
- package/dist/{import-DTkXNoBg.js → import-C4VQ0rwO.js} +2 -2
- package/dist/{import-DTkXNoBg.js.map → import-C4VQ0rwO.js.map} +1 -1
- package/dist/index.js +30 -35
- package/dist/index.js.map +1 -1
- package/dist/{markdown-CklalUUk.js → markdown-CCqp8ibf.js} +3 -3
- package/dist/markdown-CCqp8ibf.js.map +1 -0
- package/dist/util/view_constants.d.ts +3 -3
- package/dist/{util-DE1WQW6h.js → util-4oPxPkbp.js} +339 -155
- package/dist/util-4oPxPkbp.js.map +1 -0
- package/dist/{util-CfLFggP7.js → util-DB31IoJE.js} +4 -4
- package/dist/{util-CfLFggP7.js.map → util-DB31IoJE.js.map} +1 -1
- package/package.json +12 -11
- package/dist/CollectionEditorDialog-BeX4b92r.js.map +0 -1
- package/dist/PropertyEditView-C7thfj4L.js.map +0 -1
- package/dist/RouterCollectionsStudioView-BtjzvB6E.js.map +0 -1
- package/dist/SchemaChangeDialog-CkqK6KOC.js.map +0 -1
- package/dist/history-C2TpoQwi.js.map +0 -1
- package/dist/markdown-CklalUUk.js.map +0 -1
- package/dist/util-DE1WQW6h.js.map +0 -1
package/dist/{RouterCollectionsStudioView-BtjzvB6E.js → RouterCollectionsStudioView-DwsbIAqr.js}
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
|
|
2
|
-
import { hn as useUrlController } from "./util-
|
|
3
|
-
import { t as CollectionEditor } from "./CollectionEditorDialog-
|
|
4
|
-
import { s as AIModifiedPathsProvider } from "./PropertyEditView-
|
|
2
|
+
import { hn as useUrlController } from "./util-4oPxPkbp.js";
|
|
3
|
+
import { t as CollectionEditor } from "./CollectionEditorDialog-DQjLtp1W.js";
|
|
4
|
+
import { s as AIModifiedPathsProvider } from "./PropertyEditView-BMCCD2OI.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";
|
|
@@ -22,7 +22,7 @@ function CollectionStudioView({ collectionId, onSave, onCancel, ...props }) {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
return /* @__PURE__ */ jsx("div", {
|
|
25
|
-
className: "flex-grow flex flex-col h-full w-full bg-surface-
|
|
25
|
+
className: "flex-grow flex flex-col h-full w-full bg-surface-sheet",
|
|
26
26
|
children: /* @__PURE__ */ jsxs(AIModifiedPathsProvider, { children: [activeCollectionId ? /* @__PURE__ */ jsx(CollectionEditor, {
|
|
27
27
|
...props,
|
|
28
28
|
fullScreen: true,
|
|
@@ -83,16 +83,16 @@ function CollectionsStudioView({ configController, collections: collectionsProp,
|
|
|
83
83
|
writeStoredString("rebase_collections_editor_sidebar_size", sidebarSize.toString());
|
|
84
84
|
}, [sidebarSize]);
|
|
85
85
|
return /* @__PURE__ */ jsx("div", {
|
|
86
|
-
className: "flex h-full w-full bg-surface-
|
|
86
|
+
className: "flex h-full w-full bg-surface-sheet overflow-hidden text-text-primary dark:text-text-primary-dark",
|
|
87
87
|
children: /* @__PURE__ */ jsx(ResizablePanels, {
|
|
88
88
|
orientation: "horizontal",
|
|
89
89
|
panelSizePercent: sidebarSize,
|
|
90
90
|
onPanelSizeChange: setSidebarSize,
|
|
91
91
|
minPanelSizePx: 220,
|
|
92
92
|
firstPanel: /* @__PURE__ */ jsxs("div", {
|
|
93
|
-
className: cls("flex flex-col h-full w-full bg-surface-
|
|
93
|
+
className: cls("flex flex-col h-full w-full bg-surface-sheet border-r", defaultBorderMixin),
|
|
94
94
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
95
|
-
className: cls("flex items-center justify-between px-3 py-2 border-b
|
|
95
|
+
className: cls("flex items-center justify-between px-3 py-2 border-b min-h-[48px]", defaultBorderMixin),
|
|
96
96
|
children: [/* @__PURE__ */ jsx(Typography, {
|
|
97
97
|
variant: "caption",
|
|
98
98
|
className: "font-semibold text-[11px] uppercase tracking-wider text-surface-400 dark:text-surface-400",
|
|
@@ -121,7 +121,7 @@ function CollectionsStudioView({ configController, collections: collectionsProp,
|
|
|
121
121
|
const isSelected = activeCollectionId === collectionKey;
|
|
122
122
|
return /* @__PURE__ */ jsxs("div", {
|
|
123
123
|
onClick: () => setActiveCollectionId(collectionKey),
|
|
124
|
-
className: cls("flex items-center gap-2.5 px-3 h-[30px] cursor-pointer rounded-lg text-[13px] font-medium transition-colors", isSelected ? "bg-primary/8 text-primary dark:bg-primary/10 dark:text-primary-light font-semibold" : "hover:bg-
|
|
124
|
+
className: cls("flex items-center gap-2.5 px-3 h-[30px] cursor-pointer rounded-lg text-[13px] font-medium transition-colors", isSelected ? "bg-primary/8 text-primary dark:bg-primary/10 dark:text-primary-light font-semibold" : "hover:bg-surface-hover text-surface-700 dark:text-surface-300 hover:text-surface-900 dark:hover:text-white"),
|
|
125
125
|
children: [/* @__PURE__ */ jsx(IconForView, {
|
|
126
126
|
collectionOrView: collection,
|
|
127
127
|
size: "smallest",
|
|
@@ -185,4 +185,4 @@ function RouterCollectionsStudioView(props) {
|
|
|
185
185
|
//#endregion
|
|
186
186
|
export { CollectionStudioView as i, RouterCollectionsStudioView_exports as n, CollectionsStudioView as r, RouterCollectionsStudioView as t };
|
|
187
187
|
|
|
188
|
-
//# sourceMappingURL=RouterCollectionsStudioView-
|
|
188
|
+
//# sourceMappingURL=RouterCollectionsStudioView-DwsbIAqr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RouterCollectionsStudioView-DwsbIAqr.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/cms-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-sheet\">\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/cms-types\";\nimport { readStoredString, writeStoredString } from \"@rebasepro/utils\";\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 // Checked, not just parsed: `parseFloat` answers NaN for anything it cannot\n // read, and a NaN pane size lays the sidebar out to nothing — with the bad\n // value still in storage on reload. `SplitListView.getSavedPanelSize` is the\n // same read, done this way.\n const [sidebarSize, setSidebarSize] = useState(() => {\n const saved = readStoredString(\"rebase_collections_editor_sidebar_size\");\n const parsed = saved === null ? NaN : parseFloat(saved);\n return Number.isFinite(parsed) && parsed > 0 && parsed < 100 ? parsed : 25;\n });\n\n useEffect(() => {\n writeStoredString(\"rebase_collections_editor_sidebar_size\", sidebarSize.toString());\n }, [sidebarSize]);\n\n return (\n <div className=\"flex h-full w-full bg-surface-sheet 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-sheet border-r\", defaultBorderMixin)}>\n <div className={cls(\"flex items-center justify-between px-3 py-2 border-b 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-surface-hover 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":";;;;;;;;;;;AA2BA,SAAgB,qBAAqB,EAAE,cAAc,QAAQ,UAAU,GAAG,SAAoC;CAG1G,MAAM,CAAC,WAAW,gBAAgB,SAAkB,KAAK;CACzD,MAAM,CAAC,iBAAiB,sBAAsB,SAAkB,KAAK;CAErE,MAAM,EAAE,aAAa,kBAAkB,wBACnC,iBACM,aAAa,KAAK,CAC5B;CAEA,MAAM,qBAAqB;CAE3B,MAAM,0BAA0B;EAC5B,IAAI,CAAC,WACD,WAAW;OACR;GACH,mBAAmB,IAAI;GACvB,cAAc;EAClB;CACJ;CAEA,OACI,oBAAC,OAAD;EAAK,WAAU;YACX,qBAAC,yBAAD,EAAA,UAAA,CACK,qBACG,oBAAC,kBAAD;GAEI,GAAI;GACJ,YAAY;GACZ,MAAM;GACN,iBAAiB,uBAAuB;GACxC,oBAAoB,uBAAuB,QAAQ,qBAAqB,KAAA;GACxE,cAAc;GACd,cAAc,oBAAoB;IAC9B,aAAa,KAAK;IAClB,IAAI,iBACA,iBAAiB;KACb,SAAS,eAAe;IAC5B,GAAG,CAAC;GAEZ;GACc;EACjB,GAhBQ,kBAgBR,IAED,qBAAC,OAAD;GAAK,WAAU;aAAf,CACI,oBAAC,YAAD;IAAY,SAAQ;cAAQ;GAEhB,CAAA,GACZ,qBAAC,QAAD;IACI,UAAU,MAAM,kBAAkB;IAClC,eAAe,SAAS;cAF5B,CAII,oBAAC,UAAD,CAAU,CAAA,GAAC,oBAEP;KACP;MAGT,oBAAC,sBAAD;GACI,GAAI;GACJ,gBAAgB;IACZ,YAAY,SAAS;IACrB,IAAI,iBAAiB;KACjB,WAAW;KACX,mBAAmB,KAAK;IAC5B;GACJ;GACA,oBAAoB;IAChB,YAAY,aAAa;IACzB,mBAAmB,KAAK;GAC5B;EACH,CAAA,CACoB,EAAA,CAAA;CACxB,CAAA;AAEb;;;ACvDA,SAAgB,sBAAsB,EAClC,kBACA,aAAa,iBACb,oBAAoB,oBACpB,0BACA,qBACA,qBACA,2BACA,6BACA,aACA,cAC2B;CAK3B,MAAM,CAAC,kBAAkB,uBAAuB,SAA6B,KAAA,CAAS;CACtF,MAAM,eAAe,6BAA6B,KAAA;CAClD,MAAM,qBAAqB,eAAe,qBAAqB;CAE/D,MAAM,yBAAyB,OAA2B;EACtD,IAAI,cACA,2BAA2B,EAAE;OAE7B,oBAAoB,EAAE;CAE9B;CAGA,MAAM,cAAc,mBAAmB,iBAAiB,eAAe,CAAC;CAOxE,MAAM,CAAC,aAAa,kBAAkB,eAAe;EACjD,MAAM,QAAQ,iBAAiB,wCAAwC;EACvE,MAAM,SAAS,UAAU,OAAO,MAAM,WAAW,KAAK;EACtD,OAAO,OAAO,SAAS,MAAM,KAAK,SAAS,KAAK,SAAS,MAAM,SAAS;CAC5E,CAAC;CAED,gBAAgB;EACZ,kBAAkB,0CAA0C,YAAY,SAAS,CAAC;CACtF,GAAG,CAAC,WAAW,CAAC;CAEhB,OACI,oBAAC,OAAD;EAAK,WAAU;YACX,oBAAC,iBAAD;GACI,aAAY;GACZ,kBAAkB;GAClB,mBAAmB;GACnB,gBAAgB;GAChB,YACI,qBAAC,OAAD;IAAK,WAAW,IAAI,yDAAyD,kBAAkB;cAA/F,CACI,qBAAC,OAAD;KAAK,WAAW,IAAI,qEAAqE,kBAAkB;eAA3G,CACI,oBAAC,YAAD;MAAY,SAAQ;MAAU,WAAU;gBAA4F;KAExH,CAAA,GACZ,oBAAC,SAAD;MAAS,OAAO,iBAAiB,WAAW,iBAAiB,kBAAkB,cAAc;gBACzF,oBAAC,OAAD,EAAA,UACI,oBAAC,YAAD;OACI,MAAK;OACL,UAAU,iBAAiB;OAC3B,eAAe,sBAAsB,KAAK;OAC1C,WAAW,uBAAuB,QAAQ,wCAAwC;iBAElF,oBAAC,UAAD,EAAU,MAAM,SAAS,SAAU,CAAA;MAC3B,CAAA,EACX,CAAA;KACA,CAAA,CACR;QAEL,qBAAC,OAAD;KAAK,WAAU;eAAf,CACK,YAAY,WAAW,KACpB,oBAAC,OAAD;MAAK,WAAU;gBACX,oBAAC,YAAD;OAAY,SAAQ;OAAU,WAAU;iBAAyD;MAErF,CAAA;KACX,CAAA,GAER,YAAY,KAAK,eAAe;MAC7B,MAAM,gBAAgB,WAAW;MACjC,MAAM,aAAa,uBAAuB;MAC1C,OACI,qBAAC,OAAD;OAEI,eAAe,sBAAsB,aAAa;OAClD,WAAW,IACP,+GACA,aACM,uFACA,4GACV;iBARJ,CAUI,oBAAC,aAAD;QAAa,kBAAkB;QAAY,MAAM;QAAY,WAAW,IACpE,aACM,yCACA,gDACV;OAAG,CAAA,GACH,oBAAC,QAAD;QAAM,WAAU;kBACX,WAAW,QAAQ,WAAW;OAC7B,CAAA,CACL;SAjBI,aAiBJ;KAEb,CAAC,CACA;MACJ;;GAET,aACI,oBAAC,OAAD;IAAK,WAAU;cAEV,qBACG,oBAAC,sBAAD;KAEsB;KAClB,cAAc;KACd,SAAS,oBAAoB;MAEzB,IAAI,uBAAuB,SAAS,iBAAiB,MACjD,sBAAsB,gBAAgB,IAAI;KAElD;KACA,gBAAgB,sBAAsB,KAAA,CAAS;KAC1B;KACA;KACM;KACE;KAChB;KACD;IACf,GAhBQ,kBAgBR,IAED,qBAAC,OAAD;KAAK,WAAU;eAAf,CACI,oBAAC,YAAD;MAAY,SAAQ;gBAAQ;KAEhB,CAAA,GACZ,qBAAC,QAAD;MACI,UAAU,iBAAiB;MAC3B,eAAe,sBAAsB,KAAK;gBAF9C,CAII,oBAAC,UAAD,CAAU,CAAA,GAAC,oBAEP;OACP;;GAER,CAAA;EAEZ,CAAA;CACA,CAAA;AAEb;;;;ACrLA,SAAgB,4BAA4B,OAAyC;CACjF,MAAM,WAAW,YAAY;CAC7B,MAAM,gBAAgB,iBAAiB;CACvC,MAAM,WAAW,YAAY;CAG7B,MAAM,WAAW,cAAc,gBAAgB,QAAQ;CAEvD,MAAM,qBADe,SAAS,SAAS,QAAQ,UAAU,EAAE,CAAC,CAAC,QAAQ,OAAO,EACjD,CAAA,CAAa,MAAM,GAAG,CAAC,CAAC,MAAM,KAAA;CAEzD,OACI,oBAAC,uBAAD;EACI,GAAI;EACgB;EACpB,2BAA2B,OAAO;GAC9B,IAAI,IACA,SAAS,cAAc,gBAAgB,UAAU,IAAI,CAAC;QAEtD,SAAS,cAAc,gBAAgB,QAAQ,CAAC;EAExD;CACH,CAAA;AAET"}
|
|
@@ -71,7 +71,7 @@ var VERDICT_CHIP = {
|
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
var monospace = "font-mono text-xs leading-relaxed";
|
|
74
|
-
var codeBlock = cls(monospace, "bg-surface-
|
|
74
|
+
var codeBlock = cls(monospace, "bg-surface-raised rounded-md p-3 overflow-x-auto whitespace-pre");
|
|
75
75
|
/** A disclosure that starts closed. The evidence, for the reader who wants it. */
|
|
76
76
|
function Details({ summary, count, children }) {
|
|
77
77
|
const [open, setOpen] = useState(false);
|
|
@@ -145,7 +145,7 @@ function WithheldConstraints({ constraints }) {
|
|
|
145
145
|
className: "text-sm",
|
|
146
146
|
children: [
|
|
147
147
|
/* @__PURE__ */ jsx("code", {
|
|
148
|
-
className: "bg-surface-
|
|
148
|
+
className: "bg-surface-raised px-1 rounded",
|
|
149
149
|
children: constraint.target
|
|
150
150
|
}),
|
|
151
151
|
/* @__PURE__ */ jsx("div", {
|
|
@@ -393,4 +393,4 @@ function SchemaChangeDialog({ open, collectionId, plan, planError, result, apply
|
|
|
393
393
|
//#endregion
|
|
394
394
|
export { SchemaChangeDialog_exports as n, SchemaChangeDialog as t };
|
|
395
395
|
|
|
396
|
-
//# sourceMappingURL=SchemaChangeDialog-
|
|
396
|
+
//# sourceMappingURL=SchemaChangeDialog-BeP0A4MJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaChangeDialog-BeP0A4MJ.js","names":[],"sources":["../src/collection_editor/ui/collection_editor/SchemaChangeDialog.tsx"],"sourcesContent":["/**\n * What a schema change would do, before it does it.\n *\n * The dialog exists because a schema change has three possible verdicts and two\n * of them are refusals. Without a preview, the only way to discover that a\n * change is refused is to press a button on a live database and read what comes\n * back — which is a fine way to learn and a poor way to work.\n *\n * ## What it shows, in the order somebody reads it\n *\n * The verdict first, in a sentence, because it decides whether the rest is\n * worth reading. Then the changes, each with what it does and — when it is\n * refused — what to do instead. Then the things that are easy to skip past and\n * expensive to have skipped: constraints the change asks for that the database\n * will not end up enforcing. The SQL and the file list come last, collapsed,\n * for the reader who wants them; they are the evidence, not the summary.\n *\n * ## Why the button says \"Commit and apply\"\n *\n * Because that is the order, and the order is the feature. The commit lands\n * first, so a failed apply leaves the repository ahead of the database — the\n * ordinary state of every project between an edit and a deploy, which the next\n * boot reconciles. A button labelled \"Save\" would be describing a different,\n * worse thing.\n */\nimport React, { useState } from \"react\";\nimport {\n Alert,\n Button,\n Chip,\n CircularProgress,\n cls,\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Typography\n} from \"@rebasepro/ui\";\n\nimport type { LiveSchemaPlan, LiveSchemaResult, WithheldConstraint } from \"../../liveSchemaClient\";\n\nexport interface SchemaChangeDialogProps {\n open: boolean;\n /** The collection being changed, for the title. */\n collectionId: string;\n /** `undefined` while the plan is still being fetched. */\n plan?: LiveSchemaPlan;\n /** Set when planning itself failed — a network error, a refusal, a 500. */\n planError?: string;\n /** Set once the change has been applied, which turns this into a receipt. */\n result?: LiveSchemaResult;\n applying: boolean;\n /** Set when the apply threw rather than returning a result. */\n applyError?: string;\n onConfirm: () => void;\n /**\n * Ask again, when planning failed.\n *\n * A dropped connection should cost a click, not the whole wizard. The form\n * is already filled in, and making somebody redo it for a transient failure\n * teaches them to distrust the preview rather than the network.\n */\n onRetry?: () => void;\n /**\n * Write the collection source and leave the database alone.\n *\n * Offered only when the change is refused, and it is what keeps the editor\n * usable while it is. Removing a property is the ordinary case: the ensure\n * path has no `DROP COLUMN`, so a removal can never be applied — and\n * refusing the whole save over it would mean a dev could no longer delete a\n * field from a collection they are still designing.\n *\n * This is exactly what the editor did before live editing existed, so it is\n * not a new hazard; the difference is that it now says what it leaves\n * behind instead of reporting success.\n */\n onSourceOnly?: () => void;\n onClose: () => void;\n /**\n * Why this caller may preview but not apply, when that is the case.\n *\n * A person signed in with an API key, most often. Shown next to a disabled\n * button so the refusal arrives while they are deciding rather than after\n * they have decided.\n */\n applyRefusedBecause?: string;\n /**\n * Where a confirmation would land — `owner/repo` and a branch.\n *\n * On screen before the button, not in the receipt after it. A commit is\n * going somewhere, and which branch it is going to is the one fact somebody\n * cannot recover from being wrong about.\n */\n target?: { repository?: string; branch?: string };\n}\n\ntype Verdict = LiveSchemaPlan[\"verdict\"];\n\n/** What the verdict means, in the words the reader needs rather than the enum's. */\n/**\n * What the verdict means, in the words the reader needs rather than the enum's.\n *\n * `safe` is written twice because the two cases are genuinely different, and\n * saying \"can be made against the running database\" when nothing will be run is\n * the kind of small lie that teaches people to stop reading. A document\n * database has no table to alter, and a change that needs no DDL on a\n * relational one is in the same position: the commit *is* the change.\n */\nconst VERDICT_COPY: Record<Verdict, { title: string; body: string; color: \"info\" | \"warning\" | \"error\" }> = {\n safe: {\n title: \"Ready to apply\",\n body: \"Every change here can be made against the running database.\",\n color: \"info\"\n },\n diverges: {\n title: \"This would leave the database out of step\",\n body: \"The change can be written, but the database will not end up matching it. \" +\n \"The details below say which part, and what would make it applicable.\",\n color: \"warning\"\n },\n \"needs-migration\": {\n title: \"This needs a migration\",\n body: \"Some of this cannot be done to a running database at all — it drops or rewrites \" +\n \"something, and that belongs in a migration somebody has read.\",\n color: \"error\"\n }\n};\n\nconst VERDICT_CHIP: Record<Verdict, { label: string; scheme: \"greenLighter\" | \"orangeLighter\" | \"redLighter\" }> = {\n safe: { label: \"safe\", scheme: \"greenLighter\" },\n diverges: { label: \"diverges\", scheme: \"orangeLighter\" },\n \"needs-migration\": { label: \"needs migration\", scheme: \"redLighter\" }\n};\n\nconst monospace = \"font-mono text-xs leading-relaxed\";\nconst codeBlock = cls(\n monospace,\n \"bg-surface-raised rounded-md p-3 overflow-x-auto whitespace-pre\"\n);\n\n/** A disclosure that starts closed. The evidence, for the reader who wants it. */\nfunction Details({ summary, count, children }: {\n summary: string;\n count: number;\n children: React.ReactNode;\n}) {\n const [open, setOpen] = useState(false);\n if (count === 0) return null;\n return (\n <div>\n <button\n type=\"button\"\n onClick={() => setOpen(o => !o)}\n className=\"flex items-center gap-2 text-sm text-text-secondary dark:text-text-secondary-dark hover:underline\"\n >\n <span className={cls(\"transition-transform\", open && \"rotate-90\")}>›</span>\n {summary} ({count})\n </button>\n {open && <div className=\"mt-2\">{children}</div>}\n </div>\n );\n}\n\n/**\n * What still has to happen after this lands.\n *\n * Above the evidence and below the changes, because it is not a refusal and not\n * a detail: the change will apply, and something outside this dialog still has\n * to be done or a later environment will differ from this one.\n */\nfunction FollowUp({ items }: { items: string[] }) {\n if (items.length === 0) return null;\n return (\n <Alert color=\"info\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n {items.length === 1 ? \"One thing to do afterwards\" : \"To do afterwards\"}\n </Typography>\n <ul className=\"space-y-2\">\n {items.map(item => (\n <li key={item} className=\"text-sm\">{item}</li>\n ))}\n </ul>\n </Alert>\n );\n}\n\n/**\n * The destination, short enough to read at a glance.\n *\n * A remote repository already reports itself as `owner/repo`, which is exactly\n * what somebody recognises. A local one reports an absolute path, and the\n * leading directories are the part nobody needs: what matters is which\n * checkout, and its name says that.\n */\nfunction repositoryLabel(repository: string): string {\n if (!repository.startsWith(\"/\")) return repository;\n return repository.split(\"/\").filter(Boolean).pop() ?? repository;\n}\n\nfunction WithheldConstraints({ constraints }: { constraints: WithheldConstraint[] }) {\n if (constraints.length === 0) return null;\n return (\n <Alert color=\"warning\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n {constraints.length === 1\n ? \"One constraint will not be enforced\"\n : `${constraints.length} constraints will not be enforced`}\n </Typography>\n <ul className=\"space-y-2\">\n {constraints.map(constraint => (\n <li key={constraint.target} className=\"text-sm\">\n <code className=\"bg-surface-raised px-1 rounded\">\n {constraint.target}\n </code>\n <div className=\"mt-1\">{constraint.reason}</div>\n <div className=\"mt-1 text-text-secondary dark:text-text-secondary-dark\">\n {constraint.remedy}\n </div>\n </li>\n ))}\n </ul>\n </Alert>\n );\n}\n\n/** The receipt. Shown in place of the plan once the change has been applied. */\nfunction Applied({ result }: { result: LiveSchemaResult }) {\n return (\n <div className=\"flex flex-col gap-4\">\n <Alert color={result.applied ? \"success\" : \"warning\"}>\n <Typography variant=\"body2\">{result.summary}</Typography>\n </Alert>\n\n {!result.applied && result.applyError && (\n // Deliberately not an error state. The commit landed, which is\n // the durable half; the database is now behind the repository,\n // which is where every project sits between an edit and a\n // deploy, and boot reconciles it.\n <Alert color=\"warning\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n The database was not changed\n </Typography>\n <Typography variant=\"body2\">{result.applyError}</Typography>\n <Typography variant=\"body2\" className=\"mt-2\">\n The commit is on <code>{result.committed.branch}</code> either way, so the\n change will be applied on the next boot.\n </Typography>\n </Alert>\n )}\n\n <WithheldConstraints constraints={result.withheldConstraints ?? []}/>\n <FollowUp items={result.followUp ?? []}/>\n\n <div>\n <Typography variant=\"label\" color=\"secondary\">Committed</Typography>\n <div className={cls(codeBlock, \"mt-1\")}>\n {result.committed.sha.slice(0, 9)} on {result.committed.branch}\n {\"\\n\"}\n {result.committed.files.map(file => ` ${file}`).join(\"\\n\")}\n </div>\n </div>\n </div>\n );\n}\n\nexport function SchemaChangeDialog({\n open,\n collectionId,\n plan,\n planError,\n result,\n applying,\n applyError,\n onConfirm,\n onRetry,\n onSourceOnly,\n onClose,\n applyRefusedBecause,\n target\n}: SchemaChangeDialogProps) {\n\n const verdict = plan?.verdict;\n const statements = plan?.statements.length ?? 0;\n\n // \"Commit\" only when we positively know there is nothing to apply: a plan\n // that is going ahead and has no statements. A *refused* plan also has none\n // — because it will not run — and labelling that button \"Commit\" would be\n // describing the change it is refusing to make. Unknown reads as the fuller\n // action, which is the safer way to be wrong about a label.\n const commitOnly = Boolean(plan?.applicable) && statements === 0;\n\n // Described from the plan rather than from an assumption about the engine.\n // A document database runs nothing; so does a relational change that only\n // moves source. Both are a commit, and calling either one \"apply\" would be\n // describing something that does not happen.\n const copy = verdict === \"safe\" && commitOnly\n ? {\n title: \"Ready to commit\",\n body: \"This changes what your project declares. Nothing runs against the database — \" +\n \"there is no schema change to make.\",\n color: \"info\" as const\n }\n : verdict\n ? VERDICT_COPY[verdict]\n : undefined;\n\n return (\n <Dialog open={open} onOpenChange={value => { if (!value) onClose(); }} maxWidth=\"3xl\">\n <DialogTitle className=\"flex items-center gap-2\">\n {result ? \"Schema change applied\" : \"Review schema change\"}\n <code className=\"text-sm font-normal text-text-secondary dark:text-text-secondary-dark\">\n {collectionId}\n </code>\n </DialogTitle>\n\n <DialogContent className=\"flex flex-col gap-4\">\n {planError && (\n <Alert color=\"error\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n The change could not be planned\n </Typography>\n <Typography variant=\"body2\">{planError}</Typography>\n </Alert>\n )}\n\n {!plan && !planError && !result && (\n <div className=\"flex items-center gap-3 py-6\">\n <CircularProgress size=\"small\"/>\n <Typography variant=\"body2\" color=\"secondary\">\n Working out what this change would do…\n </Typography>\n </div>\n )}\n\n {result && <Applied result={result}/>}\n\n {plan && !result && copy && (\n <>\n <Alert color={copy.color}>\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n {copy.title}\n </Typography>\n <Typography variant=\"body2\">{copy.body}</Typography>\n </Alert>\n\n {applyError && (\n <Alert color=\"error\">\n <Typography variant=\"body2\">{applyError}</Typography>\n </Alert>\n )}\n\n {plan.changes.length === 0 && (\n <Typography variant=\"body2\" color=\"secondary\">\n Nothing here changes the shape of your data. The collection source\n is still rewritten and committed.\n </Typography>\n )}\n\n {!plan.applicable && onSourceOnly && (\n <Typography variant=\"body2\" color=\"secondary\">\n You can still write the change to your collection source and leave\n the database as it is — the editor’s behaviour before this preview\n existed. The column stays, holding whatever is in it, and nothing\n serves it.\n </Typography>\n )}\n\n {plan.changes.length > 0 && (\n <ul className=\"flex flex-col gap-3\">\n {plan.changes.map((change, index) => (\n <li\n key={`${change.collection}.${change.property ?? \"\"}.${index}`}\n className=\"flex gap-3\"\n >\n <Chip\n size=\"smallest\"\n colorScheme={VERDICT_CHIP[change.verdict].scheme}\n className=\"shrink-0 mt-0.5\"\n >\n {VERDICT_CHIP[change.verdict].label}\n </Chip>\n <div className=\"min-w-0\">\n <Typography variant=\"body2\">{change.detail}</Typography>\n {change.remedy && (\n <Typography\n variant=\"body2\"\n color=\"secondary\"\n className=\"mt-1\"\n >\n {change.remedy}\n </Typography>\n )}\n </div>\n </li>\n ))}\n </ul>\n )}\n\n <WithheldConstraints constraints={plan.withheldConstraints ?? []}/>\n <FollowUp items={plan.followUp ?? []}/>\n\n {applyRefusedBecause && (\n <Alert color=\"info\">\n <Typography variant=\"body2\" className=\"font-medium mb-1\">\n You can preview this change, but not apply it\n </Typography>\n <Typography variant=\"body2\">{applyRefusedBecause}</Typography>\n </Alert>\n )}\n\n <Details summary=\"Statements that will run\" count={plan.statements.length}>\n <div className={codeBlock}>{plan.statements.join(\"\\n\")}</div>\n </Details>\n\n <Details summary=\"Files that will be committed\" count={plan.files.length}>\n <div className={codeBlock}>{plan.files.join(\"\\n\")}</div>\n </Details>\n\n <Details summary=\"Commit message\" count={plan.message ? 1 : 0}>\n <div className={codeBlock}>{plan.message}</div>\n </Details>\n </>\n )}\n </DialogContent>\n\n <DialogActions>\n {!result && target?.repository && (\n <span className={cls(\n monospace,\n \"mr-auto text-text-secondary dark:text-text-secondary-dark truncate\"\n )}>\n → {repositoryLabel(target.repository)}{target.branch ? ` · ${target.branch}` : \"\"}\n </span>\n )}\n <Button variant=\"text\" onClick={onClose} disabled={applying}>\n {result ? \"Close\" : \"Cancel\"}\n </Button>\n {!result && planError && onRetry && (\n <Button variant=\"outlined\" onClick={onRetry}>\n Try again\n </Button>\n )}\n {!result && plan && !plan.applicable && onSourceOnly && (\n <Button variant=\"outlined\" onClick={onSourceOnly} disabled={applying}>\n Edit source only\n </Button>\n )}\n {!result && (\n <Button\n variant=\"filled\"\n color=\"primary\"\n onClick={onConfirm}\n // `applicable` is the server's word, not a\n // re-derivation from the verdicts on screen:\n // `applySchemaChange` re-checks it before it writes\n // anything, so a button that disagreed would only\n // produce the same refusal one click later. The same\n // goes for the permission — `/apply` checks it too, and\n // this only saves somebody the round trip.\n disabled={!plan?.applicable || applying || Boolean(applyRefusedBecause)}\n >\n {applying\n ? (commitOnly ? \"Committing…\" : \"Applying…\")\n : (commitOnly ? \"Commit\" : \"Commit and apply\")}\n </Button>\n )}\n </DialogActions>\n </Dialog>\n );\n}\n"],"mappings":"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"}
|
|
@@ -149,6 +149,17 @@ export interface SerializableBaseProperty {
|
|
|
149
149
|
* so editing a collection in the panel silently unset it.
|
|
150
150
|
*/
|
|
151
151
|
excludeFromApi?: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Per-field read/write roles. Plain data — two optional string arrays — so
|
|
154
|
+
* it round-trips through this mirror unchanged. Absent from it, the
|
|
155
|
+
* collection editor would silently unset a field's access rules the first
|
|
156
|
+
* time someone opened the collection in the panel and saved, which is the
|
|
157
|
+
* exact failure `excludeFromApi` above had.
|
|
158
|
+
*/
|
|
159
|
+
access?: {
|
|
160
|
+
read?: readonly string[];
|
|
161
|
+
write?: readonly string[];
|
|
162
|
+
};
|
|
152
163
|
validation?: PropertyValidationSchema;
|
|
153
164
|
defaultValue?: unknown;
|
|
154
165
|
/**
|
|
@@ -175,6 +186,11 @@ export interface SerializableStringProperty extends SerializableBaseProperty {
|
|
|
175
186
|
email?: boolean;
|
|
176
187
|
/** The string holds a URL. Feeds the generated OpenAPI contract. */
|
|
177
188
|
url?: boolean;
|
|
189
|
+
/**
|
|
190
|
+
* Stamp the column with the acting user's uid. The `created_by` /
|
|
191
|
+
* `updated_by` twin of {@link SerializableDateProperty.autoValue}.
|
|
192
|
+
*/
|
|
193
|
+
autoValue?: "user_on_create" | "user_on_update";
|
|
178
194
|
reference?: SerializableReferenceProperty;
|
|
179
195
|
}
|
|
180
196
|
/** JSON-serializable `NumberProperty`. */
|
|
@@ -185,6 +201,10 @@ export interface SerializableNumberProperty extends SerializableBaseProperty {
|
|
|
185
201
|
validation?: NumberPropertyValidationSchema;
|
|
186
202
|
isId?: boolean | "manual" | "increment" | string;
|
|
187
203
|
enum?: EnumValues;
|
|
204
|
+
/** Total significant digits for a `numeric` column — `NUMERIC(precision, scale)`. */
|
|
205
|
+
precision?: number;
|
|
206
|
+
/** Digits after the decimal point. Requires `precision`. */
|
|
207
|
+
scale?: number;
|
|
188
208
|
}
|
|
189
209
|
/** JSON-serializable `BooleanProperty`. */
|
|
190
210
|
export interface SerializableBooleanProperty extends SerializableBaseProperty {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { hn as useUrlController } from "./util-
|
|
2
|
-
import { n as CollectionEditorDialog } from "./CollectionEditorDialog-
|
|
3
|
-
import { n as PropertyForm, r as PropertyFormDialog } from "./PropertyEditView-
|
|
4
|
-
import { i as CollectionStudioView, r as CollectionsStudioView, t as RouterCollectionsStudioView } from "./RouterCollectionsStudioView-
|
|
5
|
-
import { t as SchemaChangeDialog } from "./SchemaChangeDialog-
|
|
1
|
+
import { hn as useUrlController } from "./util-4oPxPkbp.js";
|
|
2
|
+
import { n as CollectionEditorDialog } from "./CollectionEditorDialog-DQjLtp1W.js";
|
|
3
|
+
import { n as PropertyForm, r as PropertyFormDialog } from "./PropertyEditView-BMCCD2OI.js";
|
|
4
|
+
import { i as CollectionStudioView, r as CollectionsStudioView, t as RouterCollectionsStudioView } from "./RouterCollectionsStudioView-DwsbIAqr.js";
|
|
5
|
+
import { t as SchemaChangeDialog } from "./SchemaChangeDialog-BeP0A4MJ.js";
|
|
6
6
|
import "react";
|
|
7
7
|
import { useSnackbarController } from "@rebasepro/app";
|
|
8
8
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* The one-line editor a reference or relation cell shows while selected, at
|
|
4
|
+
* the row sizes that carry small previews (`xs`, `s`, `m`).
|
|
5
|
+
*
|
|
6
|
+
* The flow it replaces: at 48px the selected cell swapped its resting inline
|
|
7
|
+
* line for the card editor built for 140px rows, which was clipped to its top
|
|
8
|
+
* third and whose only click opened the picker — there was no way to look at
|
|
9
|
+
* the record. Here the line stays (its title opens the record in the side
|
|
10
|
+
* panel, exactly as it does at rest), a pencil opens the picker and a cross
|
|
11
|
+
* clears the value. Click the name to see it, click the pencil to change it.
|
|
12
|
+
*/
|
|
13
|
+
export declare function CompactEntityCellField({ children, empty, disabled, onEdit, onClear, emptyLabel }: {
|
|
14
|
+
/** The inline previews of the current value or values. */
|
|
15
|
+
children?: React.ReactNode;
|
|
16
|
+
/** No value: the line becomes the select prompt. */
|
|
17
|
+
empty: boolean;
|
|
18
|
+
disabled: boolean;
|
|
19
|
+
onEdit: () => void;
|
|
20
|
+
onClear: () => void;
|
|
21
|
+
/** Shown in place of the previews when empty. Defaults to "Select reference". */
|
|
22
|
+
emptyLabel?: string;
|
|
23
|
+
}): React.JSX.Element;
|
|
@@ -14,7 +14,7 @@ interface RelationSelectorFieldProps {
|
|
|
14
14
|
/** Force filter to be applied to the relation search */
|
|
15
15
|
fixedFilter?: FilterValues<string>;
|
|
16
16
|
/** Collection size for display */
|
|
17
|
-
size?: "small" | "medium";
|
|
17
|
+
size?: "compact" | "small" | "medium";
|
|
18
18
|
}
|
|
19
19
|
/** Thin wrapper around RelationSelector for table cells */
|
|
20
20
|
export declare function TableRelationSelectorField({ disabled, internalValue, updateValue, relation, fixedFilter, size }: RelationSelectorFieldProps): React.JSX.Element;
|
|
@@ -20,9 +20,13 @@ export interface RelationSelectorProps {
|
|
|
20
20
|
* scale, so a relation picker lines up with the text field beside it.
|
|
21
21
|
*
|
|
22
22
|
* `small` and `medium` predate that scale (42 and 56) and are kept as they
|
|
23
|
+
*
|
|
24
|
+
* `compact` is the 32px trigger for a selected table cell in a text row:
|
|
25
|
+
* the chosen records as inline lines (each opens its record), a chevron,
|
|
26
|
+
* nothing else.
|
|
23
27
|
* are because the table cells and the filter row are built around them.
|
|
24
28
|
*/
|
|
25
|
-
size?: "small" | "medium" | "large";
|
|
29
|
+
size?: "compact" | "small" | "medium" | "large";
|
|
26
30
|
useChips?: boolean;
|
|
27
31
|
disabled?: boolean;
|
|
28
32
|
invisible?: boolean;
|
|
@@ -1,6 +1,30 @@
|
|
|
1
|
-
import type { Worksheet } from "exceljs";
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* The header row of a spreadsheet, as a column index → name map.
|
|
3
|
+
*
|
|
4
|
+
* A map rather than an array, and that is the whole point. The ExcelJS version
|
|
5
|
+
* built a *sparse* array keyed by column and then returned
|
|
6
|
+
* `headers.filter(Boolean)`, which compacts it — so a sheet with a blank header
|
|
7
|
+
* in the middle shifted every later name one column to the left, and the import
|
|
8
|
+
* wrote each of those columns' values into its neighbour's field. Silently: the
|
|
9
|
+
* row count was right, the field names were right, and only the values were in
|
|
10
|
+
* the wrong places.
|
|
11
|
+
*
|
|
12
|
+
* Keeping the column index means a blank header can be dropped (which is what
|
|
13
|
+
* `filter(Boolean)` was reaching for) without moving anything else.
|
|
5
14
|
*/
|
|
6
|
-
export
|
|
15
|
+
export interface SheetHeaders {
|
|
16
|
+
/** Column index (0-based) → the field name that column feeds. */
|
|
17
|
+
byColumn: Map<number, string>;
|
|
18
|
+
/** The names in column order — the import's `propertiesOrder`. */
|
|
19
|
+
order: string[];
|
|
20
|
+
}
|
|
21
|
+
/** A cell as `read-excel-file` hands it over: a primitive, or null when empty. */
|
|
22
|
+
export type SheetCell = string | number | boolean | Date | null;
|
|
23
|
+
/**
|
|
24
|
+
* Read the header names out of the first row.
|
|
25
|
+
*
|
|
26
|
+
* A column whose header is blank is left out entirely, so it contributes
|
|
27
|
+
* neither a field nor a value — the same intent as the old `filter(Boolean)`,
|
|
28
|
+
* without the shift.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getWorksheetHeaders(headerRow: readonly SheetCell[]): SheetHeaders;
|
package/dist/editor.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as sanitizeUrl } from "./util-
|
|
2
|
-
import { i as schema, n as parser, r as serializer } from "./markdown-
|
|
1
|
+
import { r as sanitizeUrl } from "./util-DB31IoJE.js";
|
|
2
|
+
import { i as schema, n as parser, r as serializer } from "./markdown-CCqp8ibf.js";
|
|
3
3
|
import React, { createContext, forwardRef, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { BoldIcon, Button, CheckIcon, CheckSquareIcon, Checkbox, ChevronDownIcon, CodeIcon, Heading1Icon, Heading2Icon, Heading3Icon, IconButton, ImageIcon, ItalicIcon, Label, ListIcon, ListOrderedIcon, Popover, QuoteIcon, Separator, Slot, StrikethroughIcon, TableIcon, TextField, TextareaAutosize, Tooltip, Trash2Icon, TypeIcon, UnderlineIcon, Wand2Icon, cls, defaultBorderMixin, focusedDisabled, iconSize, useInjectStyles } from "@rebasepro/ui";
|
|
5
5
|
import { useTranslation } from "@rebasepro/app";
|
|
@@ -918,7 +918,7 @@ var SlashCommandMenu = ({ upload, aiController }) => {
|
|
|
918
918
|
zIndex: 9999,
|
|
919
919
|
visibility: "hidden"
|
|
920
920
|
},
|
|
921
|
-
className: cls("text-surface-900 dark:text-white rounded-md border bg-
|
|
921
|
+
className: cls("text-surface-900 dark:text-white rounded-md border bg-surface-card p-2 shadow transition-none", defaultBorderMixin),
|
|
922
922
|
children: /* @__PURE__ */ jsx(TableGridPicker, {
|
|
923
923
|
hoveredRow: tableGridCoords.r,
|
|
924
924
|
hoveredCol: tableGridCoords.c,
|
|
@@ -949,7 +949,7 @@ var SlashCommandMenu = ({ upload, aiController }) => {
|
|
|
949
949
|
zIndex: 9999,
|
|
950
950
|
visibility: "hidden"
|
|
951
951
|
},
|
|
952
|
-
className: cls("text-surface-900 dark:text-white max-h-[280px] w-72 overflow-y-auto rounded-md border bg-
|
|
952
|
+
className: cls("text-surface-900 dark:text-white max-h-[280px] w-72 overflow-y-auto rounded-md border bg-surface-card px-1 py-2 shadow transition-none", defaultBorderMixin),
|
|
953
953
|
children: filteredItems.map((item, index) => /* @__PURE__ */ jsxs("button", {
|
|
954
954
|
ref: (el) => {
|
|
955
955
|
itemRefs.current[index] = el;
|
|
@@ -962,9 +962,9 @@ var SlashCommandMenu = ({ upload, aiController }) => {
|
|
|
962
962
|
}
|
|
963
963
|
},
|
|
964
964
|
onMouseDown: (e) => e.preventDefault(),
|
|
965
|
-
className: cls("flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-
|
|
965
|
+
className: cls("flex w-full items-center space-x-2 rounded-md px-2 py-1 text-left text-sm hover:bg-surface-hover", index === selectedIndex ? "bg-surface-active" : ""),
|
|
966
966
|
children: [/* @__PURE__ */ jsx("div", {
|
|
967
|
-
className: cls("flex h-10 w-10 shrink-0 items-center justify-center rounded-md border bg-
|
|
967
|
+
className: cls("flex h-10 w-10 shrink-0 items-center justify-center rounded-md border bg-surface-card", defaultBorderMixin),
|
|
968
968
|
children: item.icon
|
|
969
969
|
}), /* @__PURE__ */ jsxs("div", {
|
|
970
970
|
className: "flex flex-col overflow-hidden",
|
|
@@ -1008,7 +1008,7 @@ var TableGridPicker = ({ hoveredRow, hoveredCol, onHover, onSelect }) => {
|
|
|
1008
1008
|
children: Array.from({ length: 5 }).map((_, r) => /* @__PURE__ */ jsx("div", {
|
|
1009
1009
|
className: "flex gap-1",
|
|
1010
1010
|
children: Array.from({ length: 5 }).map((_, c) => /* @__PURE__ */ jsx("div", {
|
|
1011
|
-
className: cls("w-5 h-5 border rounded-sm cursor-pointer transition-colors duration-75", r <= hoveredRow && c <= hoveredCol ? "bg-blue-100 border-blue-400 dark:bg-blue-900 dark:border-blue-500" : "bg-
|
|
1011
|
+
className: cls("w-5 h-5 border rounded-sm cursor-pointer transition-colors duration-75", r <= hoveredRow && c <= hoveredCol ? "bg-blue-100 border-blue-400 dark:bg-blue-900 dark:border-blue-500" : "bg-surface-card border-gray-200 dark:border-gray-700 hover:border-blue-300"),
|
|
1012
1012
|
onMouseEnter: () => onHover(r, c),
|
|
1013
1013
|
onClick: () => onSelect(hoveredRow + 1, hoveredCol + 1)
|
|
1014
1014
|
}, c))
|
|
@@ -1128,7 +1128,7 @@ var ImageBubble = forwardRef(({ options, className }, ref) => {
|
|
|
1128
1128
|
position: "fixed",
|
|
1129
1129
|
zIndex: 50
|
|
1130
1130
|
},
|
|
1131
|
-
className: cls("flex flex-col gap-1.5 p-2 w-56 max-w-[90vw] rounded-lg border bg-
|
|
1131
|
+
className: cls("flex flex-col gap-1.5 p-2 w-56 max-w-[90vw] rounded-lg border bg-surface-card shadow-lg", defaultBorderMixin, className),
|
|
1132
1132
|
onMouseDown: (e) => {
|
|
1133
1133
|
if (e.target === e.currentTarget) e.preventDefault();
|
|
1134
1134
|
},
|
|
@@ -1233,7 +1233,7 @@ var TableBubble = forwardRef(({ options, className }, ref) => {
|
|
|
1233
1233
|
position: "fixed",
|
|
1234
1234
|
zIndex: 50
|
|
1235
1235
|
},
|
|
1236
|
-
className: cls("flex flex-row gap-1 p-1 rounded-lg border bg-
|
|
1236
|
+
className: cls("flex flex-row gap-1 p-1 rounded-lg border bg-surface-card shadow-lg", defaultBorderMixin, className),
|
|
1237
1237
|
onMouseDown: (e) => {
|
|
1238
1238
|
e.preventDefault();
|
|
1239
1239
|
},
|
|
@@ -1729,7 +1729,7 @@ var NodeSelector = ({ open, onOpenChange, portalContainer }) => {
|
|
|
1729
1729
|
view.focus();
|
|
1730
1730
|
onOpenChange(false);
|
|
1731
1731
|
},
|
|
1732
|
-
className: "flex cursor-pointer items-center justify-between rounded px-2 py-1 text-sm hover:bg-
|
|
1732
|
+
className: "flex cursor-pointer items-center justify-between rounded px-2 py-1 text-sm hover:bg-surface-hover text-surface-900 dark:text-white",
|
|
1733
1733
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
1734
1734
|
className: "flex items-center space-x-2",
|
|
1735
1735
|
children: [/* @__PURE__ */ jsx(item.icon, { size: iconSize.smallest }), /* @__PURE__ */ jsx("span", { children: t(item.labelKey) })]
|
|
@@ -2835,7 +2835,7 @@ var RichTextEditor = ({ content, onJsonContentChange, onHtmlContentChange, onMar
|
|
|
2835
2835
|
placement: "top",
|
|
2836
2836
|
offset: 6
|
|
2837
2837
|
},
|
|
2838
|
-
className: cls("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-
|
|
2838
|
+
className: cls("flex w-fit max-w-[90vw] h-10 overflow-hidden rounded border bg-surface-card shadow", defaultBorderMixin),
|
|
2839
2839
|
children: [
|
|
2840
2840
|
/* @__PURE__ */ jsx(NodeSelector, {
|
|
2841
2841
|
portalContainer: editorRef.current,
|