@elytracms/studio 0.0.42 → 0.0.43
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/components/assets/asset-detail.js +1 -1
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/assets-module.js +19 -6
- package/dist/components/assets/assets-module.js.map +1 -1
- package/dist/components/assets/assets-store.d.ts +2 -1
- package/dist/components/assets/assets-store.js +4 -8
- package/dist/components/assets/assets-store.js.map +1 -1
- package/dist/components/assets/assets-view-preference.d.ts +0 -8
- package/dist/components/assets/assets-view-preference.js +12 -13
- package/dist/components/assets/assets-view-preference.js.map +1 -1
- package/dist/components/auth-context.d.ts +2 -1
- package/dist/components/auth-context.js +6 -8
- package/dist/components/auth-context.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +2 -2
- package/dist/components/builder/builder-store.js +4 -8
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/cms/bulk-actions.js +2 -1
- package/dist/components/cms/bulk-actions.js.map +1 -1
- package/dist/components/cms/cell-edit.js +2 -1
- package/dist/components/cms/cell-edit.js.map +1 -1
- package/dist/components/cms/cms-composition-validators.d.ts +25 -0
- package/dist/components/cms/cms-composition-validators.js +75 -0
- package/dist/components/cms/cms-composition-validators.js.map +1 -0
- package/dist/components/cms/cms-labels.d.ts +15 -0
- package/dist/components/cms/cms-labels.js +27 -0
- package/dist/components/cms/cms-labels.js.map +1 -0
- package/dist/components/cms/cms-store.d.ts +23 -10
- package/dist/components/cms/cms-store.js +78 -154
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/collection-table.js +1 -1
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/detail-editor.js +33 -42
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/discard-draft.d.ts +18 -0
- package/dist/components/cms/discard-draft.js +18 -0
- package/dist/components/cms/discard-draft.js.map +1 -1
- package/dist/components/cms/document-editor-context.d.ts +2 -1
- package/dist/components/cms/document-editor-context.js +4 -9
- package/dist/components/cms/document-editor-context.js.map +1 -1
- package/dist/components/cms/document-ref-utils.d.ts +33 -0
- package/dist/components/cms/document-ref-utils.js +47 -0
- package/dist/components/cms/document-ref-utils.js.map +1 -0
- package/dist/components/cms/field-control.js +1 -1
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/components/cms/issues-pane.js +1 -1
- package/dist/components/cms/issues-pane.js.map +1 -1
- package/dist/components/cms/rich-text/block-commands.d.ts +36 -0
- package/dist/components/cms/rich-text/block-commands.js +47 -0
- package/dist/components/cms/rich-text/block-commands.js.map +1 -0
- package/dist/components/cms/rich-text/slash-command.js +25 -8
- package/dist/components/cms/rich-text/slash-command.js.map +1 -1
- package/dist/components/cms/rich-text/toolbar.js +3 -2
- package/dist/components/cms/rich-text/toolbar.js.map +1 -1
- package/dist/components/cms/version-compare.js +1 -1
- package/dist/components/cms/version-compare.js.map +1 -1
- package/dist/components/cms/versions-model.d.ts +31 -0
- package/dist/components/cms/versions-model.js +30 -0
- package/dist/components/cms/versions-model.js.map +1 -1
- package/dist/components/cms/view-bar.js +9 -6
- package/dist/components/cms/view-bar.js.map +1 -1
- package/dist/components/collab/collab-context.d.ts +2 -1
- package/dist/components/collab/collab-context.js +4 -8
- package/dist/components/collab/collab-context.js.map +1 -1
- package/dist/components/collection-view/collection-view-context.d.ts +9 -1
- package/dist/components/collection-view/collection-view-context.js +4 -9
- package/dist/components/collection-view/collection-view-context.js.map +1 -1
- package/dist/components/components/component-detail.js +2 -5
- package/dist/components/components/component-detail.js.map +1 -1
- package/dist/components/components/component-preview.js +8 -4
- package/dist/components/components/component-preview.js.map +1 -1
- package/dist/components/components/registry-browser.js +24 -5
- package/dist/components/components/registry-browser.js.map +1 -1
- package/dist/components/components/transfer-dialog.d.ts +10 -0
- package/dist/components/components/transfer-dialog.js +24 -8
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/delivery-health-banner.d.ts +12 -6
- package/dist/components/delivery-health-banner.js +27 -29
- package/dist/components/delivery-health-banner.js.map +1 -1
- package/dist/components/dev-login-badge.d.ts +0 -2
- package/dist/components/dev-login-badge.js +1 -3
- package/dist/components/dev-login-badge.js.map +1 -1
- package/dist/components/playground-badge.d.ts +0 -2
- package/dist/components/playground-badge.js +0 -2
- package/dist/components/playground-badge.js.map +1 -1
- package/dist/components/project-list.js +2 -6
- package/dist/components/project-list.js.map +1 -1
- package/dist/components/project-session.d.ts +6 -2
- package/dist/components/project-session.js +32 -83
- package/dist/components/project-session.js.map +1 -1
- package/dist/components/project-switcher.js +2 -6
- package/dist/components/project-switcher.js.map +1 -1
- package/dist/components/redirects/redirects-store.d.ts +2 -1
- package/dist/components/redirects/redirects-store.js +4 -8
- package/dist/components/redirects/redirects-store.js.map +1 -1
- package/dist/components/studio-context.d.ts +2 -1
- package/dist/components/studio-context.js +4 -8
- package/dist/components/studio-context.js.map +1 -1
- package/dist/components/studio-shell.js +1 -1
- package/dist/components/studio-shell.js.map +1 -1
- package/dist/components/theme-context.d.ts +2 -1
- package/dist/components/theme-context.js +4 -8
- package/dist/components/theme-context.js.map +1 -1
- package/dist/components/use-hydration-phase.d.ts +65 -0
- package/dist/components/use-hydration-phase.js +64 -0
- package/dist/components/use-hydration-phase.js.map +1 -0
- package/dist/components/users/users-store.d.ts +2 -1
- package/dist/components/users/users-store.js +4 -8
- package/dist/components/users/users-store.js.map +1 -1
- package/dist/components/workspace-projects.d.ts +14 -0
- package/dist/components/workspace-projects.js +21 -0
- package/dist/components/workspace-projects.js.map +1 -1
- package/dist/lib/data/data-store.d.ts +2 -1
- package/dist/lib/data/data-store.js +4 -8
- package/dist/lib/data/data-store.js.map +1 -1
- package/dist/lib/delivery/instant-publish.d.ts +9 -13
- package/dist/lib/delivery/instant-publish.js +0 -7
- package/dist/lib/delivery/instant-publish.js.map +1 -1
- package/dist/lib/diff-view-preference.js +4 -4
- package/dist/lib/diff-view-preference.js.map +1 -1
- package/dist/lib/i18n/messages.en.js +1 -0
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/local-preference.d.ts +37 -0
- package/dist/lib/local-preference.js +36 -0
- package/dist/lib/local-preference.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.d.ts +3 -1
- package/dist/lib/persistence/convex-adapter.js +20 -0
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/rail.js +7 -6
- package/dist/lib/rail.js.map +1 -1
- package/dist/lib/required-context.d.ts +24 -0
- package/dist/lib/required-context.js +28 -0
- package/dist/lib/required-context.js.map +1 -0
- package/dist/lib/theme.js +11 -4
- package/dist/lib/theme.js.map +1 -1
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.js +1 -0
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/segmented-control.d.ts +46 -0
- package/dist/ui/segmented-control.js +13 -0
- package/dist/ui/segmented-control.js.map +1 -0
- package/package.json +2 -2
|
@@ -30,3 +30,21 @@ export declare function discardDraftStatus(input: {
|
|
|
30
30
|
collection: CollectionDef;
|
|
31
31
|
draft: CmsDocument;
|
|
32
32
|
}): DiscardDraftStatus;
|
|
33
|
+
/**
|
|
34
|
+
* EC-325 — the flush-before-restore ordering "Discard changes" must follow,
|
|
35
|
+
* mirroring the IDENTICAL `if (dirty) save()` step the Versions pane's
|
|
36
|
+
* (`versions-pane.tsx`'s `handleRestore`) and the Compare view's
|
|
37
|
+
* (`version-compare.tsx`'s `restore`) own restores already take before theirs.
|
|
38
|
+
* `documents.restore` (`packages/core/src/operations/documents.ts`) snapshots
|
|
39
|
+
* whatever is currently PERSISTED as its own "pre-restore" version — never the
|
|
40
|
+
* client's in-memory draft — so an edit still sitting in the autosave debounce
|
|
41
|
+
* window when Discard fires would otherwise never reach the server and be
|
|
42
|
+
* silently unrecoverable once the draft is reverted. The underlying
|
|
43
|
+
* save/restore commands are serialized by the shared operations queue
|
|
44
|
+
* (EC-225), so the un-awaited `save()` here still lands before `restore` reads
|
|
45
|
+
* the persisted document.
|
|
46
|
+
*/
|
|
47
|
+
export declare function flushDirtyDraft(input: {
|
|
48
|
+
dirty: boolean;
|
|
49
|
+
save: () => void;
|
|
50
|
+
}): void;
|
|
@@ -10,4 +10,22 @@ export function discardDraftStatus(input) {
|
|
|
10
10
|
? 'up-to-date'
|
|
11
11
|
: 'ready';
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* EC-325 — the flush-before-restore ordering "Discard changes" must follow,
|
|
15
|
+
* mirroring the IDENTICAL `if (dirty) save()` step the Versions pane's
|
|
16
|
+
* (`versions-pane.tsx`'s `handleRestore`) and the Compare view's
|
|
17
|
+
* (`version-compare.tsx`'s `restore`) own restores already take before theirs.
|
|
18
|
+
* `documents.restore` (`packages/core/src/operations/documents.ts`) snapshots
|
|
19
|
+
* whatever is currently PERSISTED as its own "pre-restore" version — never the
|
|
20
|
+
* client's in-memory draft — so an edit still sitting in the autosave debounce
|
|
21
|
+
* window when Discard fires would otherwise never reach the server and be
|
|
22
|
+
* silently unrecoverable once the draft is reverted. The underlying
|
|
23
|
+
* save/restore commands are serialized by the shared operations queue
|
|
24
|
+
* (EC-225), so the un-awaited `save()` here still lands before `restore` reads
|
|
25
|
+
* the persisted document.
|
|
26
|
+
*/
|
|
27
|
+
export function flushDirtyDraft(input) {
|
|
28
|
+
if (input.dirty)
|
|
29
|
+
input.save();
|
|
30
|
+
}
|
|
13
31
|
//# sourceMappingURL=discard-draft.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discard-draft.js","sourceRoot":"","sources":["../../../src/components/cms/discard-draft.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAuBhE,MAAM,UAAU,kBAAkB,CAAC,KAWlC;IACC,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,SAAS;QAAE,OAAO,QAAQ,CAAA;IAC1D,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,gBAAgB,CAAA;IAC/C,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC3D,OAAO,sBAAsB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC;QACnF,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,OAAO,CAAA;AACb,CAAC","sourcesContent":["import { documentsSemanticEqual } from '@elytracms/core/content'\nimport type { CmsDocument, CollectionDef } from '@elytracms/core/cms-core'\n\n/**\n * EC-316 — the \"Discard changes\" header action's enablement, as one pure\n * decision. Discarding reverts the draft to exactly the published content (via\n * the EC-298 restore machinery), so it is offered iff there is a published\n * version to revert TO and the draft actually differs from it:\n *\n * - `hidden` — the rail can't discard at all (no publish/versions\n * capability) or the document isn't published: there is no\n * published content to revert to, so no menu item.\n * - `view-read-only`— viewing the Published snapshot (EC-226): the draft isn't\n * the active view, so the item is disabled with a hint.\n * - `loading` — the version history hasn't resolved yet; disabled.\n * - `up-to-date` — the draft SEMANTICALLY equals the published snapshot\n * (`documentsSemanticEqual`, the SAME comparator the\n * Versions pane's publish gate uses, EC-298 — so the two\n * surfaces never contradict); nothing to discard, disabled.\n * - `ready` — a published version exists and the draft differs: enabled.\n */\nexport type DiscardDraftStatus = 'hidden' | 'view-read-only' | 'loading' | 'up-to-date' | 'ready'\n\nexport function discardDraftStatus(input: {\n /** The rail can publish AND has version history (both required to discard). */\n canDiscard: boolean\n /** The document IS published (version pointer set). */\n published: boolean\n /** The editor is viewing the read-only Published snapshot (EC-226). */\n viewReadOnly: boolean\n /** The pinned published version's snapshot; `undefined` while loading / none pinned. */\n publishedSnapshot: CmsDocument | undefined\n collection: CollectionDef\n draft: CmsDocument\n}): DiscardDraftStatus {\n if (!input.canDiscard || !input.published) return 'hidden'\n if (input.viewReadOnly) return 'view-read-only'\n if (input.publishedSnapshot === undefined) return 'loading'\n return documentsSemanticEqual(input.collection, input.publishedSnapshot, input.draft)\n ? 'up-to-date'\n : 'ready'\n}\n"]}
|
|
1
|
+
{"version":3,"file":"discard-draft.js","sourceRoot":"","sources":["../../../src/components/cms/discard-draft.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAA;AAuBhE,MAAM,UAAU,kBAAkB,CAAC,KAWlC;IACC,IAAI,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,KAAK,CAAC,SAAS;QAAE,OAAO,QAAQ,CAAA;IAC1D,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,gBAAgB,CAAA;IAC/C,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IAC3D,OAAO,sBAAsB,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,iBAAiB,EAAE,KAAK,CAAC,KAAK,CAAC;QACnF,CAAC,CAAC,YAAY;QACd,CAAC,CAAC,OAAO,CAAA;AACb,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,KAA2C;IACzE,IAAI,KAAK,CAAC,KAAK;QAAE,KAAK,CAAC,IAAI,EAAE,CAAA;AAC/B,CAAC","sourcesContent":["import { documentsSemanticEqual } from '@elytracms/core/content'\nimport type { CmsDocument, CollectionDef } from '@elytracms/core/cms-core'\n\n/**\n * EC-316 — the \"Discard changes\" header action's enablement, as one pure\n * decision. Discarding reverts the draft to exactly the published content (via\n * the EC-298 restore machinery), so it is offered iff there is a published\n * version to revert TO and the draft actually differs from it:\n *\n * - `hidden` — the rail can't discard at all (no publish/versions\n * capability) or the document isn't published: there is no\n * published content to revert to, so no menu item.\n * - `view-read-only`— viewing the Published snapshot (EC-226): the draft isn't\n * the active view, so the item is disabled with a hint.\n * - `loading` — the version history hasn't resolved yet; disabled.\n * - `up-to-date` — the draft SEMANTICALLY equals the published snapshot\n * (`documentsSemanticEqual`, the SAME comparator the\n * Versions pane's publish gate uses, EC-298 — so the two\n * surfaces never contradict); nothing to discard, disabled.\n * - `ready` — a published version exists and the draft differs: enabled.\n */\nexport type DiscardDraftStatus = 'hidden' | 'view-read-only' | 'loading' | 'up-to-date' | 'ready'\n\nexport function discardDraftStatus(input: {\n /** The rail can publish AND has version history (both required to discard). */\n canDiscard: boolean\n /** The document IS published (version pointer set). */\n published: boolean\n /** The editor is viewing the read-only Published snapshot (EC-226). */\n viewReadOnly: boolean\n /** The pinned published version's snapshot; `undefined` while loading / none pinned. */\n publishedSnapshot: CmsDocument | undefined\n collection: CollectionDef\n draft: CmsDocument\n}): DiscardDraftStatus {\n if (!input.canDiscard || !input.published) return 'hidden'\n if (input.viewReadOnly) return 'view-read-only'\n if (input.publishedSnapshot === undefined) return 'loading'\n return documentsSemanticEqual(input.collection, input.publishedSnapshot, input.draft)\n ? 'up-to-date'\n : 'ready'\n}\n\n/**\n * EC-325 — the flush-before-restore ordering \"Discard changes\" must follow,\n * mirroring the IDENTICAL `if (dirty) save()` step the Versions pane's\n * (`versions-pane.tsx`'s `handleRestore`) and the Compare view's\n * (`version-compare.tsx`'s `restore`) own restores already take before theirs.\n * `documents.restore` (`packages/core/src/operations/documents.ts`) snapshots\n * whatever is currently PERSISTED as its own \"pre-restore\" version — never the\n * client's in-memory draft — so an edit still sitting in the autosave debounce\n * window when Discard fires would otherwise never reach the server and be\n * silently unrecoverable once the draft is reverted. The underlying\n * save/restore commands are serialized by the shared operations queue\n * (EC-225), so the un-awaited `save()` here still lands before `restore` reads\n * the persisted document.\n */\nexport function flushDirtyDraft(input: { dirty: boolean; save: () => void }): void {\n if (input.dirty) input.save()\n}\n"]}
|
|
@@ -60,11 +60,12 @@ export interface DocumentEditorContextValue {
|
|
|
60
60
|
/** Leave compare mode, back to editing. */
|
|
61
61
|
exitCompare: () => void;
|
|
62
62
|
}
|
|
63
|
+
declare const useDocumentEditor: () => DocumentEditorContextValue;
|
|
63
64
|
export declare function DocumentEditorProvider({ value, children, }: {
|
|
64
65
|
value: DocumentEditorContextValue;
|
|
65
66
|
children: ReactNode;
|
|
66
67
|
}): import("react").JSX.Element;
|
|
67
|
-
export
|
|
68
|
+
export { useDocumentEditor };
|
|
68
69
|
/**
|
|
69
70
|
* The open document's editing context, or null when there is none (e.g. a
|
|
70
71
|
* relation picker opened from a table cell rather than the detail editor). Lets a
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import { useContext } from 'react';
|
|
3
|
+
import { createRequiredContext } from '@elytracms/studio/lib/required-context';
|
|
4
|
+
const { Context: DocumentEditorContext, useRequired: useDocumentEditor } = createRequiredContext('DocumentEditor');
|
|
4
5
|
export function DocumentEditorProvider({ value, children, }) {
|
|
5
6
|
return _jsx(DocumentEditorContext.Provider, { value: value, children: children });
|
|
6
7
|
}
|
|
7
|
-
export
|
|
8
|
-
const value = useContext(DocumentEditorContext);
|
|
9
|
-
if (!value) {
|
|
10
|
-
throw new Error('useDocumentEditor must be used within a <DocumentEditorProvider>.');
|
|
11
|
-
}
|
|
12
|
-
return value;
|
|
13
|
-
}
|
|
8
|
+
export { useDocumentEditor };
|
|
14
9
|
/**
|
|
15
10
|
* The open document's editing context, or null when there is none (e.g. a
|
|
16
11
|
* relation picker opened from a table cell rather than the detail editor). Lets a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document-editor-context.js","sourceRoot":"","sources":["../../../src/components/cms/document-editor-context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"document-editor-context.js","sourceRoot":"","sources":["../../../src/components/cms/document-editor-context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAGlC,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAgE9E,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE,WAAW,EAAE,iBAAiB,EAAE,GACtE,qBAAqB,CAA6B,gBAAgB,CAAC,CAAA;AAErE,MAAM,UAAU,sBAAsB,CAAC,EACrC,KAAK,EACL,QAAQ,GAIT;IACC,OAAO,KAAC,qBAAqB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAkC,CAAA;AAClG,CAAC;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAE5B;;;;;GAKG;AACH,MAAM,UAAU,yBAAyB;IACvC,OAAO,UAAU,CAAC,qBAAqB,CAAC,CAAA;AAC1C,CAAC","sourcesContent":["import { useContext } from 'react'\nimport type { ReactNode } from 'react'\nimport type { CmsDocument, CollectionDef, DocumentRef } from '@elytracms/core/cms-core'\nimport { createRequiredContext } from '@elytracms/studio/lib/required-context'\n\n/**\n * EC-224 — the open document's editing context, provided by the detail editor\n * and consumed by document-level inspector panes (the `Versions` pane).\n *\n * It exists because the Versions pane is rendered in two places — directly in\n * the form view's sidebar, and inside the canvas view's own sidebar (deep in the\n * scoped `BuilderProvider` subtree). A context lets the pane reach the open\n * document's ref + live draft + actions from either mount point, without\n * threading props through the canvas field editor.\n */\n/**\n * EC-298 version-compare selection: which two snapshots the compare view diffs.\n * `base` is a recorded version number (the older side); `target` is either\n * another recorded version or the live working draft.\n */\nexport interface CompareState {\n base: number\n target: number | 'draft'\n}\n\nexport interface DocumentEditorContextValue {\n /** The project being edited (undefined in fixture/playground sessions). */\n projectId: string | undefined\n collection: CollectionDef\n docRef: DocumentRef\n /** The editor's live (possibly unsaved) draft buffer. */\n draft: CmsDocument\n /** Does the draft buffer diverge from the saved document? */\n dirty: boolean\n /** Does the draft have error-severity validation issues (blocks publish)? */\n hasErrors: boolean\n /**\n * Is the editor in the read-only Published view (EC-226)? Document-level panes\n * must disable their mutating actions (publish/restore) while it is true.\n */\n viewReadOnly: boolean\n /** Persist the current draft buffer (the editor's Save). */\n save: () => void\n /**\n * Replace the editor's draft buffer — used after a version restore swaps the\n * working draft for an older snapshot, so the open form/canvas reflect it.\n */\n replaceDraft: (doc: CmsDocument) => void\n /**\n * EC-298 — the open version comparison, or null when none. The Compare tab is a\n * sticky content tab: this selection persists while the user tabs between the\n * diff and the real fields, and is cleared only by closing the tab (its ✕).\n */\n compare: CompareState | null\n /** Is the Compare tab the currently VISIBLE view? Drives the Versions pane's\n * base-picker mode — the pane navigates only while the diff is on screen. */\n compareActive: boolean\n /** Open (or refocus) the Compare tab with `base` vs the current draft. */\n startCompare: (base: number) => void\n /** Change which recorded version is the (older) base side. */\n setCompareBase: (base: number) => void\n /** Change what the base is compared against (a version, or the live draft). */\n setCompareTarget: (target: number | 'draft') => void\n /** Leave compare mode, back to editing. */\n exitCompare: () => void\n}\n\nconst { Context: DocumentEditorContext, useRequired: useDocumentEditor } =\n createRequiredContext<DocumentEditorContextValue>('DocumentEditor')\n\nexport function DocumentEditorProvider({\n value,\n children,\n}: {\n value: DocumentEditorContextValue\n children: ReactNode\n}) {\n return <DocumentEditorContext.Provider value={value}>{children}</DocumentEditorContext.Provider>\n}\n\nexport { useDocumentEditor }\n\n/**\n * The open document's editing context, or null when there is none (e.g. a\n * relation picker opened from a table cell rather than the detail editor). Lets a\n * control opt into doc-aware behavior — like the EC-218 parent cycle guard —\n * without requiring the provider.\n */\nexport function useOptionalDocumentEditor(): DocumentEditorContextValue | null {\n return useContext(DocumentEditorContext)\n}\n"]}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { CmsDocument, DocumentRef } from '@elytracms/core/cms-core';
|
|
2
|
+
/**
|
|
3
|
+
* By-ref document array helpers (EC-326) — a shared idiom over
|
|
4
|
+
* `@elytracms/core/cms-core`'s `documentRefEquals`, replacing ~12 hand-inlined
|
|
5
|
+
* `d.collection === x.collection && d.id === x.id` predicates across
|
|
6
|
+
* `cms-store.tsx`, `bulk-actions.ts`, and `cell-edit.ts`.
|
|
7
|
+
*
|
|
8
|
+
* Two real shapes exist over a document array and must stay distinct:
|
|
9
|
+
* - {@link replaceDoc}/{@link removeDoc} are pure, no-op-if-absent (an edit or
|
|
10
|
+
* delete of a document that's already gone from the session is a silent
|
|
11
|
+
* no-op, never an append).
|
|
12
|
+
* - {@link upsertDoc} is replace-or-append — `saveDocument` and
|
|
13
|
+
* `importDocuments` rely on the append branch to create new documents; a
|
|
14
|
+
* naive `replaceDoc` there would silently stop those flows from ever adding
|
|
15
|
+
* a document to the session.
|
|
16
|
+
*/
|
|
17
|
+
/** Does `doc` identify the same document as `ref` (collection + id, EC-017)? */
|
|
18
|
+
export declare function matchesRef(doc: DocumentRef, ref: DocumentRef): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Replace the document matching `next`'s ref with `next`. A no-op (returns
|
|
21
|
+
* `docs` unchanged) if no document with that ref exists — pure map-replace,
|
|
22
|
+
* never appends.
|
|
23
|
+
*/
|
|
24
|
+
export declare function replaceDoc(docs: readonly CmsDocument[], next: CmsDocument): CmsDocument[];
|
|
25
|
+
/** Remove the document identified by `ref`, if present. A no-op otherwise. */
|
|
26
|
+
export declare function removeDoc(docs: readonly CmsDocument[], ref: DocumentRef): CmsDocument[];
|
|
27
|
+
/**
|
|
28
|
+
* Replace the document matching `next`'s ref with `next`, or append it when
|
|
29
|
+
* no match exists (upsert) — the shape `saveDocument` and the accepted-batch
|
|
30
|
+
* fold of `importDocuments` need, so a create/import flow always lands the
|
|
31
|
+
* document even on a session with no prior entry for that ref.
|
|
32
|
+
*/
|
|
33
|
+
export declare function upsertDoc(docs: readonly CmsDocument[], next: CmsDocument): CmsDocument[];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { documentRefEquals } from '@elytracms/core/cms-core';
|
|
2
|
+
/**
|
|
3
|
+
* By-ref document array helpers (EC-326) — a shared idiom over
|
|
4
|
+
* `@elytracms/core/cms-core`'s `documentRefEquals`, replacing ~12 hand-inlined
|
|
5
|
+
* `d.collection === x.collection && d.id === x.id` predicates across
|
|
6
|
+
* `cms-store.tsx`, `bulk-actions.ts`, and `cell-edit.ts`.
|
|
7
|
+
*
|
|
8
|
+
* Two real shapes exist over a document array and must stay distinct:
|
|
9
|
+
* - {@link replaceDoc}/{@link removeDoc} are pure, no-op-if-absent (an edit or
|
|
10
|
+
* delete of a document that's already gone from the session is a silent
|
|
11
|
+
* no-op, never an append).
|
|
12
|
+
* - {@link upsertDoc} is replace-or-append — `saveDocument` and
|
|
13
|
+
* `importDocuments` rely on the append branch to create new documents; a
|
|
14
|
+
* naive `replaceDoc` there would silently stop those flows from ever adding
|
|
15
|
+
* a document to the session.
|
|
16
|
+
*/
|
|
17
|
+
/** Does `doc` identify the same document as `ref` (collection + id, EC-017)? */
|
|
18
|
+
export function matchesRef(doc, ref) {
|
|
19
|
+
return documentRefEquals(doc, ref);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Replace the document matching `next`'s ref with `next`. A no-op (returns
|
|
23
|
+
* `docs` unchanged) if no document with that ref exists — pure map-replace,
|
|
24
|
+
* never appends.
|
|
25
|
+
*/
|
|
26
|
+
export function replaceDoc(docs, next) {
|
|
27
|
+
return docs.map((d) => (matchesRef(d, next) ? next : d));
|
|
28
|
+
}
|
|
29
|
+
/** Remove the document identified by `ref`, if present. A no-op otherwise. */
|
|
30
|
+
export function removeDoc(docs, ref) {
|
|
31
|
+
return docs.filter((d) => !matchesRef(d, ref));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Replace the document matching `next`'s ref with `next`, or append it when
|
|
35
|
+
* no match exists (upsert) — the shape `saveDocument` and the accepted-batch
|
|
36
|
+
* fold of `importDocuments` need, so a create/import flow always lands the
|
|
37
|
+
* document even on a session with no prior entry for that ref.
|
|
38
|
+
*/
|
|
39
|
+
export function upsertDoc(docs, next) {
|
|
40
|
+
const i = docs.findIndex((d) => matchesRef(d, next));
|
|
41
|
+
if (i < 0)
|
|
42
|
+
return [...docs, next];
|
|
43
|
+
const out = [...docs];
|
|
44
|
+
out[i] = next;
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=document-ref-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document-ref-utils.js","sourceRoot":"","sources":["../../../src/components/cms/document-ref-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAG5D;;;;;;;;;;;;;;GAcG;AAEH,gFAAgF;AAChF,MAAM,UAAU,UAAU,CAAC,GAAgB,EAAE,GAAgB;IAC3D,OAAO,iBAAiB,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AACpC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,IAA4B,EAAE,IAAiB;IACxE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAC1D,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,SAAS,CAAC,IAA4B,EAAE,GAAgB;IACtE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAA;AAChD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,IAA4B,EAAE,IAAiB;IACvE,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;IACpD,IAAI,CAAC,GAAG,CAAC;QAAE,OAAO,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAA;IACjC,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,CAAA;IACrB,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;IACb,OAAO,GAAG,CAAA;AACZ,CAAC","sourcesContent":["import { documentRefEquals } from '@elytracms/core/cms-core'\nimport type { CmsDocument, DocumentRef } from '@elytracms/core/cms-core'\n\n/**\n * By-ref document array helpers (EC-326) — a shared idiom over\n * `@elytracms/core/cms-core`'s `documentRefEquals`, replacing ~12 hand-inlined\n * `d.collection === x.collection && d.id === x.id` predicates across\n * `cms-store.tsx`, `bulk-actions.ts`, and `cell-edit.ts`.\n *\n * Two real shapes exist over a document array and must stay distinct:\n * - {@link replaceDoc}/{@link removeDoc} are pure, no-op-if-absent (an edit or\n * delete of a document that's already gone from the session is a silent\n * no-op, never an append).\n * - {@link upsertDoc} is replace-or-append — `saveDocument` and\n * `importDocuments` rely on the append branch to create new documents; a\n * naive `replaceDoc` there would silently stop those flows from ever adding\n * a document to the session.\n */\n\n/** Does `doc` identify the same document as `ref` (collection + id, EC-017)? */\nexport function matchesRef(doc: DocumentRef, ref: DocumentRef): boolean {\n return documentRefEquals(doc, ref)\n}\n\n/**\n * Replace the document matching `next`'s ref with `next`. A no-op (returns\n * `docs` unchanged) if no document with that ref exists — pure map-replace,\n * never appends.\n */\nexport function replaceDoc(docs: readonly CmsDocument[], next: CmsDocument): CmsDocument[] {\n return docs.map((d) => (matchesRef(d, next) ? next : d))\n}\n\n/** Remove the document identified by `ref`, if present. A no-op otherwise. */\nexport function removeDoc(docs: readonly CmsDocument[], ref: DocumentRef): CmsDocument[] {\n return docs.filter((d) => !matchesRef(d, ref))\n}\n\n/**\n * Replace the document matching `next`'s ref with `next`, or append it when\n * no match exists (upsert) — the shape `saveDocument` and the accepted-batch\n * fold of `importDocuments` need, so a create/import flow always lands the\n * document even on a session with no prior entry for that ref.\n */\nexport function upsertDoc(docs: readonly CmsDocument[], next: CmsDocument): CmsDocument[] {\n const i = docs.findIndex((d) => matchesRef(d, next))\n if (i < 0) return [...docs, next]\n const out = [...docs]\n out[i] = next\n return out\n}\n"]}
|
|
@@ -13,7 +13,7 @@ import { useOptionalAssets } from '../assets/assets-store';
|
|
|
13
13
|
import { AssetThumb, FocalCropPreviews, FocalPointPicker, useAssetRecord } from '../assets/asset-thumb';
|
|
14
14
|
import { newlyAddedAssetIds } from '../assets/focal-point';
|
|
15
15
|
import { assetMetaFieldsOf, pruneMeta } from '../assets/asset-metadata';
|
|
16
|
-
import { fieldLabel } from './cms-
|
|
16
|
+
import { fieldLabel } from './cms-labels';
|
|
17
17
|
import { useCollectionView } from '../collection-view/collection-view-context';
|
|
18
18
|
import { useFieldDensity } from './field-density';
|
|
19
19
|
import { useOptionalDocumentEditor } from './document-editor-context';
|