@elytracms/studio 0.0.92 → 0.0.93
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/convex/asset-alt-migration.test.ts +127 -0
- package/convex/asset-replace.test.ts +168 -0
- package/convex/asset-revalidate.test.ts +6 -6
- package/convex/assets.ts +41 -5
- package/convex/cms.ts +25 -11
- package/convex/contract-parity.test.ts +18 -3
- package/convex/document-revalidate.test.ts +10 -12
- package/convex/orphan-hydration.test.ts +116 -0
- package/convex/rail-write-parity.test.ts +11 -8
- package/convex/schema.ts +6 -0
- package/dist/components/ai/proposal-card.js +2 -1
- package/dist/components/ai/proposal-card.js.map +1 -1
- package/dist/components/ai/translate-document-dialog.js +4 -2
- package/dist/components/ai/translate-document-dialog.js.map +1 -1
- package/dist/components/ai/translate-skipped.d.ts +19 -0
- package/dist/components/ai/translate-skipped.js +46 -0
- package/dist/components/ai/translate-skipped.js.map +1 -0
- package/dist/components/assets/asset-detail.js +18 -8
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/asset-metadata.d.ts +15 -4
- package/dist/components/assets/asset-metadata.js +15 -2
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-search.js +4 -1
- package/dist/components/assets/asset-search.js.map +1 -1
- package/dist/components/assets/asset-selection.d.ts +0 -8
- package/dist/components/assets/asset-selection.js +4 -23
- package/dist/components/assets/asset-selection.js.map +1 -1
- package/dist/components/assets/asset-thumb.js +3 -2
- package/dist/components/assets/asset-thumb.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +3 -3
- package/dist/components/assets/assets-collection-view-source.js +9 -5
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/assets/assets-store.d.ts +14 -0
- package/dist/components/assets/assets-store.js +23 -1
- package/dist/components/assets/assets-store.js.map +1 -1
- package/dist/components/assets/replace-file.d.ts +22 -0
- package/dist/components/assets/replace-file.js +59 -0
- package/dist/components/assets/replace-file.js.map +1 -0
- package/dist/components/builder/blocks-model.d.ts +14 -26
- package/dist/components/builder/blocks-model.js +35 -41
- package/dist/components/builder/blocks-model.js.map +1 -1
- package/dist/components/builder/blocks-panel.d.ts +7 -3
- package/dist/components/builder/blocks-panel.js +6 -5
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +104 -15
- package/dist/components/builder/builder-store.js +156 -31
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-body.d.ts +30 -0
- package/dist/components/builder/canvas-body.js +38 -0
- package/dist/components/builder/canvas-body.js.map +1 -0
- package/dist/components/builder/canvas-chrome-css.js +7 -0
- package/dist/components/builder/canvas-chrome-css.js.map +1 -1
- package/dist/components/builder/canvas-dnd.d.ts +7 -7
- package/dist/components/builder/canvas-dnd.js +5 -5
- package/dist/components/builder/canvas-dnd.js.map +1 -1
- package/dist/components/builder/canvas-render-context.d.ts +27 -19
- package/dist/components/builder/canvas-render-context.js +42 -43
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/canvas-runs.d.ts +45 -0
- package/dist/components/builder/canvas-runs.js +51 -0
- package/dist/components/builder/canvas-runs.js.map +1 -0
- package/dist/components/builder/canvas.js +32 -5
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.d.ts +15 -0
- package/dist/components/builder/clipboard-actions.js +44 -7
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +3 -15
- package/dist/components/builder/composition-field-editor.js +29 -40
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/delete-key.d.ts +5 -0
- package/dist/components/builder/delete-key.js +4 -0
- package/dist/components/builder/delete-key.js.map +1 -1
- package/dist/components/builder/insert-context.d.ts +17 -25
- package/dist/components/builder/insert-context.js +45 -92
- package/dist/components/builder/insert-context.js.map +1 -1
- package/dist/components/builder/page-tree.d.ts +3 -3
- package/dist/components/builder/page-tree.js +3 -3
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/placement-refusal.d.ts +18 -0
- package/dist/components/builder/placement-refusal.js +46 -0
- package/dist/components/builder/placement-refusal.js.map +1 -0
- package/dist/components/builder/property-inspector.js +4 -0
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/reuse-context.js +65 -27
- package/dist/components/builder/reuse-context.js.map +1 -1
- package/dist/components/builder/reuse.d.ts +79 -1
- package/dist/components/builder/reuse.js +69 -2
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/builder/run-inspector.d.ts +11 -0
- package/dist/components/builder/run-inspector.js +33 -0
- package/dist/components/builder/run-inspector.js.map +1 -0
- package/dist/components/cms/asset-field.d.ts +38 -1
- package/dist/components/cms/asset-field.js +182 -58
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/asset-picker-core.d.ts +16 -0
- package/dist/components/cms/asset-picker-core.js +20 -0
- package/dist/components/cms/asset-picker-core.js.map +1 -1
- package/dist/components/cms/asset-picker.js +12 -18
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/bulk-actions.d.ts +3 -19
- package/dist/components/cms/bulk-actions.js +3 -24
- package/dist/components/cms/bulk-actions.js.map +1 -1
- package/dist/components/cms/cell.js.map +1 -1
- package/dist/components/cms/cms-store.d.ts +5 -4
- package/dist/components/cms/cms-store.js +16 -36
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/detail-editor.js +0 -1
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/document-diff-view.d.ts +3 -1
- package/dist/components/cms/document-diff-view.js +12 -7
- package/dist/components/cms/document-diff-view.js.map +1 -1
- package/dist/components/cms/field-anchors.d.ts +7 -4
- package/dist/components/cms/field-anchors.js +9 -7
- package/dist/components/cms/field-anchors.js.map +1 -1
- package/dist/components/cms/field-control-lib.d.ts +15 -1
- package/dist/components/cms/field-control-lib.js +22 -3
- package/dist/components/cms/field-control-lib.js.map +1 -1
- package/dist/components/cms/gate-validation.d.ts +21 -30
- package/dist/components/cms/gate-validation.js +11 -32
- package/dist/components/cms/gate-validation.js.map +1 -1
- package/dist/components/cms/object-array-field.js +4 -4
- package/dist/components/cms/object-array-field.js.map +1 -1
- package/dist/components/cms/prop-fields.d.ts +7 -2
- package/dist/components/cms/prop-fields.js +13 -6
- package/dist/components/cms/prop-fields.js.map +1 -1
- package/dist/components/cms/rich-text/embed-picker.d.ts +1 -1
- package/dist/components/cms/rich-text/embed-picker.js.map +1 -1
- package/dist/components/cms/rich-text/insert.d.ts +20 -9
- package/dist/components/cms/rich-text/insert.js +25 -17
- package/dist/components/cms/rich-text/insert.js.map +1 -1
- package/dist/components/cms/use-publish-controller.d.ts +1 -2
- package/dist/components/cms/use-publish-controller.js +7 -19
- package/dist/components/cms/use-publish-controller.js.map +1 -1
- package/dist/components/cms/versions-pane.js +8 -1
- package/dist/components/cms/versions-pane.js.map +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +3 -1
- package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +2 -1
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/components/transfer.d.ts +10 -10
- package/dist/components/components/transfer.js +13 -12
- package/dist/components/components/transfer.js.map +1 -1
- package/dist/lib/ai/apply-content.js +56 -116
- package/dist/lib/ai/apply-content.js.map +1 -1
- package/dist/lib/ai/chat-context.d.ts +8 -0
- package/dist/lib/ai/chat-context.js +37 -6
- package/dist/lib/ai/chat-context.js.map +1 -1
- package/dist/lib/ai/chat-state.d.ts +6 -0
- package/dist/lib/ai/chat-state.js.map +1 -1
- package/dist/lib/ai/constraints.d.ts +20 -5
- package/dist/lib/ai/constraints.js +125 -33
- package/dist/lib/ai/constraints.js.map +1 -1
- package/dist/lib/ai/fake-provider.d.ts +16 -3
- package/dist/lib/ai/fake-provider.js +22 -6
- package/dist/lib/ai/fake-provider.js.map +1 -1
- package/dist/lib/ai/index.d.ts +2 -0
- package/dist/lib/ai/index.js +2 -0
- package/dist/lib/ai/index.js.map +1 -1
- package/dist/lib/ai/leash.d.ts +34 -0
- package/dist/lib/ai/leash.js +28 -0
- package/dist/lib/ai/leash.js.map +1 -0
- package/dist/lib/ai/rich-text-input.d.ts +8 -8
- package/dist/lib/ai/rich-text-input.js +2 -1
- package/dist/lib/ai/rich-text-input.js.map +1 -1
- package/dist/lib/ai/rich-text-translate.d.ts +27 -4
- package/dist/lib/ai/rich-text-translate.js +28 -10
- package/dist/lib/ai/rich-text-translate.js.map +1 -1
- package/dist/lib/ai/shape.d.ts +13 -13
- package/dist/lib/ai/shape.js +69 -93
- package/dist/lib/ai/shape.js.map +1 -1
- package/dist/lib/ai/tools.d.ts +36 -41
- package/dist/lib/ai/tools.js +83 -87
- package/dist/lib/ai/tools.js.map +1 -1
- package/dist/lib/ai/translate-document.d.ts +32 -4
- package/dist/lib/ai/translate-document.js +144 -46
- package/dist/lib/ai/translate-document.js.map +1 -1
- package/dist/lib/ai/types.d.ts +34 -23
- package/dist/lib/ai/types.js.map +1 -1
- package/dist/lib/ai/update-fields.d.ts +15 -12
- package/dist/lib/ai/update-fields.js +112 -188
- package/dist/lib/ai/update-fields.js.map +1 -1
- package/dist/lib/ai/writer-form.d.ts +116 -0
- package/dist/lib/ai/writer-form.js +429 -0
- package/dist/lib/ai/writer-form.js.map +1 -0
- package/dist/lib/assets/upload.d.ts +31 -2
- package/dist/lib/assets/upload.js +61 -6
- package/dist/lib/assets/upload.js.map +1 -1
- package/dist/lib/clipboard/os-clipboard.d.ts +10 -2
- package/dist/lib/clipboard/os-clipboard.js +8 -4
- package/dist/lib/clipboard/os-clipboard.js.map +1 -1
- package/dist/lib/clipboard/paste-target.d.ts +18 -9
- package/dist/lib/clipboard/paste-target.js +8 -7
- package/dist/lib/clipboard/paste-target.js.map +1 -1
- package/dist/lib/cms/field-patch.d.ts +0 -10
- package/dist/lib/cms/field-patch.js +4 -30
- package/dist/lib/cms/field-patch.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +3 -3
- package/dist/lib/collection-view/collection-view-source.d.ts +7 -3
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/data/collection-content.js +3 -2
- package/dist/lib/data/collection-content.js.map +1 -1
- package/dist/lib/dnd/drop-rules.d.ts +25 -31
- package/dist/lib/dnd/drop-rules.js +53 -59
- package/dist/lib/dnd/drop-rules.js.map +1 -1
- package/dist/lib/engine-version.d.ts +1 -1
- package/dist/lib/engine-version.js +1 -1
- package/dist/lib/engine-version.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +40 -3
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +34 -2
- package/dist/lib/i18n/messages.en.js +43 -3
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/operations/project-runtime-config.d.ts +25 -6
- package/dist/lib/operations/project-runtime-config.js +37 -10
- package/dist/lib/operations/project-runtime-config.js.map +1 -1
- package/dist/lib/operations/publish-with-revision.d.ts +33 -1
- package/dist/lib/operations/publish-with-revision.js +32 -0
- package/dist/lib/operations/publish-with-revision.js.map +1 -1
- package/dist/lib/operations/runtime-validator.d.ts +19 -68
- package/dist/lib/operations/runtime-validator.js +12 -138
- package/dist/lib/operations/runtime-validator.js.map +1 -1
- package/dist/lib/operations/studio-operations.d.ts +9 -2
- package/dist/lib/operations/studio-operations.js +13 -11
- package/dist/lib/operations/studio-operations.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.js +6 -1
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persona/labels.js +3 -1
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/workspace/index.d.ts +8 -11
- package/dist/lib/workspace/index.js +12 -24
- package/dist/lib/workspace/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/cms/cms-composition-validators.d.ts +0 -16
- package/dist/components/cms/cms-composition-validators.js +0 -133
- package/dist/components/cms/cms-composition-validators.js.map +0 -1
- package/dist/components/cms/publish-clean.d.ts +0 -28
- package/dist/components/cms/publish-clean.js +0 -38
- package/dist/components/cms/publish-clean.js.map +0 -1
- package/dist/lib/assets/asset-placements.d.ts +0 -28
- package/dist/lib/assets/asset-placements.js +0 -83
- package/dist/lib/assets/asset-placements.js.map +0 -1
|
@@ -3,29 +3,22 @@ import type { AssetRecord } from '@elytracms/core/persistence';
|
|
|
3
3
|
/** The asset-library oracle the bag carries (EC-588): the record for an id, or `undefined`. */
|
|
4
4
|
export type FindAsset = NonNullable<ValidateDocumentOptions['findAsset']>;
|
|
5
5
|
/**
|
|
6
|
-
* THE option bag (EC-497, AD-497a)
|
|
6
|
+
* THE option bag of the studio SESSION (EC-497, AD-497a) — since EC-582 a caller of the
|
|
7
|
+
* one canonical validator in core (`canonicalValidateOptions`,
|
|
8
|
+
* `@elytracms/core/validation`), which the runtime publish gate, a headless embedder and
|
|
9
|
+
* the CLI build from too. The session passes ITS project's registry — the active one,
|
|
10
|
+
* because the session IS the active project (the runtime gate resolves the OPERATION's
|
|
11
|
+
* project instead, `lib/operations/runtime-validator.ts`).
|
|
7
12
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
* the
|
|
11
|
-
*
|
|
12
|
-
* surface asked, which is a validation system that cannot be reasoned about.
|
|
13
|
+
* The contract, in one line: **surfaces differ in what they DO with the issues, never in
|
|
14
|
+
* what they validated with.** Publish filters by severity, cell edit filters by field +
|
|
15
|
+
* locale, the AI paths take `introducedErrors` (after − before) — all start from the
|
|
16
|
+
* identical list.
|
|
13
17
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* "weaker subsets": a subset is how this defect happened, and the moment one
|
|
19
|
-
* exists someone has to decide per call site which one applies.
|
|
20
|
-
*
|
|
21
|
-
* The one conditionality that remains is the engine's own and is documented on
|
|
22
|
-
* `ValidateDocumentOptions`: `store`-dependent rules (relation/asset existence,
|
|
23
|
-
* hierarchy cycles, `validation.unique`) fire exactly when a store is supplied.
|
|
24
|
-
*
|
|
25
|
-
* **Out of contract by declaration:** the assets and redirects rails. They
|
|
26
|
-
* validate synthetic, non-`cmsDocuments` collections against their own registries
|
|
27
|
-
* with no session store, and their writes go through `operations.assets.*` /
|
|
28
|
-
* `operations.redirects.*` — a different entity, not a weaker check of this one.
|
|
18
|
+
* **Out of contract by declaration:** the assets and redirects rails. They validate
|
|
19
|
+
* synthetic, non-`cmsDocuments` collections against their own registries with no session
|
|
20
|
+
* store, and their writes go through `operations.assets.*` / `operations.redirects.*` — a
|
|
21
|
+
* different entity, not a weaker check of this one.
|
|
29
22
|
*/
|
|
30
23
|
export interface GateValidationInput {
|
|
31
24
|
/** The session document store, with the document under judgement swapped in. */
|
|
@@ -47,15 +40,13 @@ export interface AssetLibraryState {
|
|
|
47
40
|
assets: readonly AssetRecord[];
|
|
48
41
|
}
|
|
49
42
|
/**
|
|
50
|
-
* EC-588 A2 — THE asset-library oracle for the option bag, derived from the
|
|
51
|
-
* store: a record lookup over the loaded library.
|
|
43
|
+
* EC-588 A2 — THE asset-library oracle for the session's option bag, derived from the
|
|
44
|
+
* assets store: a record lookup over the loaded library.
|
|
52
45
|
*
|
|
53
|
-
* Absent — so the validator checks neither existence nor `accept` — when no
|
|
54
|
-
* mounted (a fixture-only session) AND while it is loading or errored
|
|
55
|
-
* is no truthful answer to "which record is this?".
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* while the library is unready is the "validation bound to the operation" question,
|
|
59
|
-
* left to EC-595.
|
|
46
|
+
* Absent — so the display validator checks neither existence nor `accept` — when no
|
|
47
|
+
* library is mounted (a fixture-only session) AND while it is loading or errored: there
|
|
48
|
+
* is no truthful answer to "which record is this?" yet. The PUBLISH gate does not read
|
|
49
|
+
* this: it prefetches through the operation's adapter and refuses visibly when the
|
|
50
|
+
* library cannot be read (EC-595 A2, ruled 1f).
|
|
60
51
|
*/
|
|
61
52
|
export declare function assetLibraryOracle(library: AssetLibraryState | null): FindAsset | undefined;
|
|
@@ -1,42 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { cleanHiddenForPublish } from './publish-clean.js';
|
|
1
|
+
import { getStudioRegistry } from '@elytracms/studio/lib/registry';
|
|
2
|
+
import { canonicalValidateOptions } from '@elytracms/core/validation';
|
|
4
3
|
export function gateValidateOptions(input) {
|
|
5
|
-
return {
|
|
4
|
+
return canonicalValidateOptions({ locales: input.localeConfig }, getStudioRegistry().registry, {
|
|
6
5
|
store: input.store,
|
|
7
|
-
localeConfig: input.localeConfig,
|
|
8
|
-
// EC-188/EC-189: the composition + rich-text-embed leashes, injected so
|
|
9
|
-
// `cms-core` stays free of `project-graph` and `rich-text`. These are what the
|
|
10
|
-
// operations layer could never supply on its own — it has no registry — and
|
|
11
|
-
// the reason the canonical validator is injected downward rather than rebuilt
|
|
12
|
-
// there. Since EC-547 both injected validators unwrap the converged v2 block
|
|
13
|
-
// sequence (`{ version: 2, content }`) and validate its component nodes —
|
|
14
|
-
// top-level and nested in typography — with the same field `allow` leash.
|
|
15
|
-
validateComposition,
|
|
16
|
-
validateRichTextEmbeds,
|
|
17
6
|
isPublished: input.isPublished,
|
|
18
7
|
...(input.findAsset ? { findAsset: input.findAsset } : {}),
|
|
19
|
-
|
|
20
|
-
// — component props through the session's manifests — and judges what publishing
|
|
21
|
-
// would snapshot (the SAME hidden strip `doPublish` / bulk publish apply), so a
|
|
22
|
-
// strict reuse embed of an unpublished target is a blocking error through this one
|
|
23
|
-
// general path (the detail editor's special case is gone) and a hidden relation
|
|
24
|
-
// neither warns nor blocks.
|
|
25
|
-
lookupManifest: studioManifestLookup(),
|
|
26
|
-
publishedForm: (collection, document) => cleanHiddenForPublish(collection, document, undefined, input.localeConfig),
|
|
27
|
-
};
|
|
8
|
+
});
|
|
28
9
|
}
|
|
29
10
|
/**
|
|
30
|
-
* EC-588 A2 — THE asset-library oracle for the option bag, derived from the
|
|
31
|
-
* store: a record lookup over the loaded library.
|
|
11
|
+
* EC-588 A2 — THE asset-library oracle for the session's option bag, derived from the
|
|
12
|
+
* assets store: a record lookup over the loaded library.
|
|
32
13
|
*
|
|
33
|
-
* Absent — so the validator checks neither existence nor `accept` — when no
|
|
34
|
-
* mounted (a fixture-only session) AND while it is loading or errored
|
|
35
|
-
* is no truthful answer to "which record is this?".
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* while the library is unready is the "validation bound to the operation" question,
|
|
39
|
-
* left to EC-595.
|
|
14
|
+
* Absent — so the display validator checks neither existence nor `accept` — when no
|
|
15
|
+
* library is mounted (a fixture-only session) AND while it is loading or errored: there
|
|
16
|
+
* is no truthful answer to "which record is this?" yet. The PUBLISH gate does not read
|
|
17
|
+
* this: it prefetches through the operation's adapter and refuses visibly when the
|
|
18
|
+
* library cannot be read (EC-595 A2, ruled 1f).
|
|
40
19
|
*/
|
|
41
20
|
export function assetLibraryOracle(library) {
|
|
42
21
|
if (!library || library.status !== 'ready')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate-validation.js","sourceRoot":"","sources":["../../../src/components/cms/gate-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"gate-validation.js","sourceRoot":"","sources":["../../../src/components/cms/gate-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAA;AAClE,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAA;AA4CrE,MAAM,UAAU,mBAAmB,CAAC,KAA0B;IAC5D,OAAO,wBAAwB,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,YAAY,EAAE,EAAE,iBAAiB,EAAE,CAAC,QAAQ,EAAE;QAC7F,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3D,CAAC,CAAA;AACJ,CAAC;AAQD;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAiC;IAClE,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO;QAAE,OAAO,SAAS,CAAA;IAC5D,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;IACtE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;AAC7B,CAAC","sourcesContent":["import { getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport { canonicalValidateOptions } from '@elytracms/core/validation'\nimport type {\n DocumentRef,\n DocumentStore,\n LocaleConfig,\n ValidateDocumentOptions,\n} from '@elytracms/core/cms-core'\nimport type { AssetRecord } from '@elytracms/core/persistence'\n\n/** The asset-library oracle the bag carries (EC-588): the record for an id, or `undefined`. */\nexport type FindAsset = NonNullable<ValidateDocumentOptions['findAsset']>\n\n/**\n * THE option bag of the studio SESSION (EC-497, AD-497a) — since EC-582 a caller of the\n * one canonical validator in core (`canonicalValidateOptions`,\n * `@elytracms/core/validation`), which the runtime publish gate, a headless embedder and\n * the CLI build from too. The session passes ITS project's registry — the active one,\n * because the session IS the active project (the runtime gate resolves the OPERATION's\n * project instead, `lib/operations/runtime-validator.ts`).\n *\n * The contract, in one line: **surfaces differ in what they DO with the issues, never in\n * what they validated with.** Publish filters by severity, cell edit filters by field +\n * locale, the AI paths take `introducedErrors` (after − before) — all start from the\n * identical list.\n *\n * **Out of contract by declaration:** the assets and redirects rails. They validate\n * synthetic, non-`cmsDocuments` collections against their own registries with no session\n * store, and their writes go through `operations.assets.*` / `operations.redirects.*` — a\n * different entity, not a weaker check of this one.\n */\nexport interface GateValidationInput {\n /** The session document store, with the document under judgement swapped in. */\n store: DocumentStore\n localeConfig: LocaleConfig\n /** Published-ness from the version POINTER (EC-224) — never a flat state flag. */\n isPublished: (ref: DocumentRef) => boolean\n /**\n * The real asset library oracle (EC-588: returns the record, so the validator checks\n * existence AND the field's `accept`); absent where no library is mounted or ready —\n * see {@link assetLibraryOracle}.\n */\n findAsset?: FindAsset\n}\n\nexport function gateValidateOptions(input: GateValidationInput): ValidateDocumentOptions {\n return canonicalValidateOptions({ locales: input.localeConfig }, getStudioRegistry().registry, {\n store: input.store,\n isPublished: input.isPublished,\n ...(input.findAsset ? { findAsset: input.findAsset } : {}),\n })\n}\n\n/** The slice of the assets store the oracle is derived from (`AssetsStore` satisfies it). */\nexport interface AssetLibraryState {\n status: 'loading' | 'ready' | 'error'\n assets: readonly AssetRecord[]\n}\n\n/**\n * EC-588 A2 — THE asset-library oracle for the session's option bag, derived from the\n * assets store: a record lookup over the loaded library.\n *\n * Absent — so the display validator checks neither existence nor `accept` — when no\n * library is mounted (a fixture-only session) AND while it is loading or errored: there\n * is no truthful answer to \"which record is this?\" yet. The PUBLISH gate does not read\n * this: it prefetches through the operation's adapter and refuses visibly when the\n * library cannot be read (EC-595 A2, ruled 1f).\n */\nexport function assetLibraryOracle(library: AssetLibraryState | null): FindAsset | undefined {\n if (!library || library.status !== 'ready') return undefined\n const byId = new Map(library.assets.map((asset) => [asset.id, asset]))\n return (id) => byId.get(id)\n}\n"]}
|
|
@@ -8,7 +8,7 @@ import { localizedLabel, translate } from '@elytracms/studio/lib/i18n';
|
|
|
8
8
|
import { fieldLabel } from './cms-labels.js';
|
|
9
9
|
import { FieldPathContext, isPathWithin, useFieldFocusRequest, useFieldPath, } from './field-anchors.js';
|
|
10
10
|
import { FieldControl } from './field-control.js';
|
|
11
|
-
import { depthRail, depthTint, isTabularObjectType, objectItemSummary, reorder } from './field-control-lib.js';
|
|
11
|
+
import { depthRail, depthTint, isSubFieldReadOnly, isTabularObjectType, objectItemSummary, reorder, tableColumnsOf, } from './field-control-lib.js';
|
|
12
12
|
/**
|
|
13
13
|
* The object / repeater field controls (EC-253, legibility-rebuilt EC-305) —
|
|
14
14
|
* split from `field-control.tsx` (EC-330). {@link ObjectField} dispatches by
|
|
@@ -109,7 +109,7 @@ export function ObjectItemForm({ fields, value, onChange, readOnly, idPrefix, })
|
|
|
109
109
|
return null;
|
|
110
110
|
const subId = `${idPrefix}-${sub.name}`;
|
|
111
111
|
const subPath = itemPath === null ? undefined : `${itemPath}/${sub.name}`;
|
|
112
|
-
return (_jsx(Field, { htmlFor: subId, fieldPath: subPath, className: cn('transition-shadow', subPath !== undefined && focus?.path === subPath && `${FOCUS_RING_CLASS} p-2`), hint: localizedLabel(sub.form?.description) || undefined, label: _jsxs(Row, { gap: "2", children: [_jsx("span", { children: fieldLabel(sub) }), sub.validation?.required ? _jsx("span", { className: "text-destructive", children: "*" }) : null] }), children: _jsx(FieldPathContext.Provider, { value: subPath ?? null, children: _jsx(FieldControl, { id: subId, field: sub, value: value[sub.name], readOnly: readOnly, onChange: (next) => {
|
|
112
|
+
return (_jsx(Field, { htmlFor: subId, fieldPath: subPath, className: cn('transition-shadow', subPath !== undefined && focus?.path === subPath && `${FOCUS_RING_CLASS} p-2`), hint: localizedLabel(sub.form?.description) || undefined, label: _jsxs(Row, { gap: "2", children: [_jsx("span", { children: fieldLabel(sub) }), sub.validation?.required ? _jsx("span", { className: "text-destructive", children: "*" }) : null] }), children: _jsx(FieldPathContext.Provider, { value: subPath ?? null, children: _jsx(FieldControl, { id: subId, field: sub, value: value[sub.name], readOnly: isSubFieldReadOnly(readOnly, sub), onChange: (next) => {
|
|
113
113
|
const updated = { ...value };
|
|
114
114
|
if (next === undefined)
|
|
115
115
|
delete updated[sub.name];
|
|
@@ -219,7 +219,7 @@ function ObjectTableField({ field, value, onChange, readOnly, id, depth }) {
|
|
|
219
219
|
// cell — `links/3/href` — is always the deepest possible anchor here).
|
|
220
220
|
const parentPath = useFieldPath();
|
|
221
221
|
const focus = useFieldFocusRequest();
|
|
222
|
-
const cols = field
|
|
222
|
+
const cols = tableColumnsOf(field);
|
|
223
223
|
const span = cols.length + (readOnly ? 0 : 2);
|
|
224
224
|
return (_jsxs("div", { className: cn('overflow-hidden rounded-md border border-border border-l-2', depthRail(depth), depthTint(depth)), children: [_jsxs("table", { className: "w-full text-sm", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-border/60 bg-muted/30 text-left", children: [!readOnly ? _jsx("th", { className: "w-7" }) : null, cols.map((c) => (_jsxs("th", { className: "px-2 py-1.5 text-xs font-medium text-muted-foreground", children: [fieldLabel(c), c.validation?.required ? _jsx("span", { className: "text-destructive", children: " *" }) : null] }, c.name))), !readOnly ? _jsx("th", { className: "w-9" }) : null] }) }), _jsx("tbody", { children: items.length === 0 ? (_jsx("tr", { children: _jsx("td", { colSpan: span, className: "px-2 py-2 text-muted-foreground", children: _jsx(Text, { size: "sm", tone: "subtle", children: translate('cms.field.noItems') }) }) })) : (items.map((item, i) => {
|
|
225
225
|
const key = keys[i] ?? i;
|
|
@@ -243,7 +243,7 @@ function ObjectTableField({ field, value, onChange, readOnly, id, depth }) {
|
|
|
243
243
|
const cellPath = itemPath === undefined ? undefined : `${itemPath}/${c.name}`;
|
|
244
244
|
return (_jsx("td", { ...(cellPath !== undefined ? { [FIELD_PATH_ATTR]: cellPath } : {}), className: cn('px-2 py-1', cellPath !== undefined && focus?.path === cellPath
|
|
245
245
|
? 'bg-primary/5 ring-2 ring-inset ring-primary/70'
|
|
246
|
-
: ''), children: _jsx(FieldControl, { id: `${id}-${i}-${c.name}`, field: c, value: record[c.name], readOnly: readOnly, onChange: (next) => {
|
|
246
|
+
: ''), children: _jsx(FieldControl, { id: `${id}-${i}-${c.name}`, field: c, value: record[c.name], readOnly: isSubFieldReadOnly(readOnly, c), onChange: (next) => {
|
|
247
247
|
const updated = { ...record };
|
|
248
248
|
if (next === undefined)
|
|
249
249
|
delete updated[c.name];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"object-array-field.js","sourceRoot":"","sources":["../../../src/components/cms/object-array-field.tsx"],"names":[],"mappings":"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","sourcesContent":["import { ChevronDown, ChevronUp, GripVertical, MoreHorizontal, Plus, Trash2 } from 'lucide-react'\nimport { createContext, useContext, useEffect, useRef, useState } from 'react'\nimport type { FieldDef, ObjectFieldDef } from '@elytracms/core/cms-core'\nimport { isFieldHidden, seedObjectItem } from '@elytracms/core/cms-core'\nimport {\n Button,\n Card,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n FIELD_PATH_ATTR,\n Field,\n Row,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { fieldLabel } from './cms-labels'\nimport {\n FieldPathContext,\n isPathWithin,\n useFieldFocusRequest,\n useFieldPath,\n} from './field-anchors'\nimport { FieldControl } from './field-control'\nimport { depthRail, depthTint, isTabularObjectType, objectItemSummary, reorder } from './field-control-lib'\n\n/**\n * The object / repeater field controls (EC-253, legibility-rebuilt EC-305) —\n * split from `field-control.tsx` (EC-330). {@link ObjectField} dispatches by\n * shape (single card / editable table / card list); {@link ObjectItemForm} is\n * the recursive subfield form the asset-field family reuses for per-use\n * sub-fields and asset metadata. Cells and subfields render through\n * `FieldControl`, so any subfield type — including a nested repeater — works\n * for free.\n *\n * EC-443 path anchors: inside a stamped surface (a non-null `FieldPathContext`,\n * provided by the document form) every item card / table row / subfield row\n * stamps its `FIELD_PATH_ATTR` anchor (`links/3`, `links/3/badge/text` — the\n * ONE convention defined on the attribute in `ui/field.tsx`), a collapsed card\n * auto-expands when the active focus request targets a path within it, and the\n * exact requested control ring-highlights. All decisions come from the pure\n * helpers in `field-anchors.ts`.\n */\n\n/** The EC-443 ring on the exact jump target (mirrors the top-level row ring). */\nconst FOCUS_RING_CLASS = 'rounded-md bg-primary/5 ring-2 ring-primary/70'\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\n// EC-305: nested-array depth, propagated via context so each array level can encode\n// its depth (rail colour + tint) without prop-drilling through FieldControl's many\n// branches. The detail editor renders top-level fields with the default depth 0.\nconst ArrayDepthContext = createContext(0)\nconst useArrayDepth = () => useContext(ArrayDepthContext)\n\n/**\n * Shared array state for an object repeater (EC-253/EC-294/EC-305): the value-only\n * items + a parallel stable-key list kept in lockstep through every structural op\n * (the EC-253 C2 key↔value lock), add/remove/move, and native drag-reorder. Used by\n * both the card list (B) and the table (C) so they behave identically.\n */\nfunction useObjectArray(field: ObjectFieldDef, value: unknown, onChange: (value: unknown) => void) {\n const items = Array.isArray(value) ? (value as Record<string, unknown>[]) : []\n const seq = useRef(0)\n const keysRef = useRef<number[]>([])\n if (keysRef.current.length !== items.length) {\n keysRef.current = items.map((_, i) => keysRef.current[i] ?? seq.current++)\n }\n const keys = keysRef.current\n const commit = (nextItems: Record<string, unknown>[], nextKeys: number[]) => {\n keysRef.current = nextKeys\n onChange(nextItems)\n }\n const move = (from: number, to: number) => commit(reorder(items, from, to), reorder(keys, from, to))\n const removeAt = (i: number) =>\n commit(items.filter((_, j) => j !== i), keys.filter((_, j) => j !== i))\n const addItem = (): number => {\n // EC-581: the one seeding rule (core `seedObjectItem`) — nested defaults included.\n const seed = seedObjectItem(field.fields)\n const key = seq.current++\n commit([...items, seed], [...keys, key])\n return key\n }\n const setItem = (i: number, updated: Record<string, unknown>) => {\n const nextItems = items.slice()\n nextItems[i] = updated\n commit(nextItems, keys)\n }\n const [dragIndex, setDragIndex] = useState<number | null>(null)\n const [overIndex, setOverIndex] = useState<number | null>(null)\n const endDrag = () => {\n setDragIndex(null)\n setOverIndex(null)\n }\n const drop = (to: number) => {\n if (dragIndex !== null && dragIndex !== to) move(dragIndex, to)\n endDrag()\n }\n return { items, keys, move, removeAt, addItem, setItem, dragIndex, overIndex, setDragIndex, setOverIndex, endDrag, drop }\n}\n\n/**\n * (E) Chrome reduction: the per-row move/remove controls collapse into one hover/\n * focus overflow menu, so a row reads as content, not a six-button toolbar. Drag is\n * the primary reorder; the arrows stay here for keyboard/a11y.\n */\nfunction ItemOverflowMenu({\n index,\n count,\n onMove,\n onRemove,\n}: {\n index: number\n count: number\n onMove: (from: number, to: number) => void\n onRemove: () => void\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('cms.field.itemActions')}>\n <MoreHorizontal className=\"size-3.5\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem disabled={index === 0} onClick={() => onMove(index, index - 1)}>\n <ChevronUp /> {translate('cms.field.moveUp')}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={index === count - 1} onClick={() => onMove(index, index + 1)}>\n <ChevronDown /> {translate('cms.field.moveDown')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={onRemove}>\n <Trash2 /> {translate('common.remove')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\n/**\n * The nested subfield form for one object item (EC-253). Reuses {@link FieldControl}\n * recursively, so any subfield type — including a nested object/repeater — works for\n * free. Writing a subfield merges it back into the item and bubbles the new item up.\n * EC-443: each subfield row stamps its path anchor (`<itemPath>/<sub>`), rings when\n * it is the exact focus target, and provides its path down for deeper nesting.\n */\nexport function ObjectItemForm({\n fields,\n value,\n onChange,\n readOnly,\n idPrefix,\n}: {\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChange: (value: Record<string, unknown>) => void\n readOnly: boolean\n idPrefix: string\n}) {\n const itemPath = useFieldPath()\n const focus = useFieldFocusRequest()\n return (\n <Stack gap=\"3\" className=\"mt-2\">\n {fields.map((sub) => {\n // EC-273: a conditionally-hidden subfield (its predicate keys off the item's\n // own sibling values) is omitted — e.g. a discriminated link's `href` shows\n // only when `linkType === 'href'`. Re-evaluated as the item is edited.\n if (isFieldHidden(sub, { values: value })) return null\n const subId = `${idPrefix}-${sub.name}`\n const subPath = itemPath === null ? undefined : `${itemPath}/${sub.name}`\n return (\n <Field\n key={sub.name}\n htmlFor={subId}\n fieldPath={subPath}\n className={cn(\n 'transition-shadow',\n subPath !== undefined && focus?.path === subPath && `${FOCUS_RING_CLASS} p-2`,\n )}\n hint={localizedLabel(sub.form?.description) || undefined}\n label={\n <Row gap=\"2\">\n <span>{fieldLabel(sub)}</span>\n {sub.validation?.required ? <span className=\"text-destructive\">*</span> : null}\n </Row>\n }\n >\n <FieldPathContext.Provider value={subPath ?? null}>\n <FieldControl\n id={subId}\n field={sub}\n value={value[sub.name]}\n readOnly={readOnly}\n onChange={(next) => {\n const updated = { ...value }\n if (next === undefined) delete updated[sub.name]\n else updated[sub.name] = next\n onChange(updated)\n }}\n />\n </FieldPathContext.Provider>\n </Field>\n )\n })}\n </Stack>\n )\n}\n\n/**\n * Object / repeater field control (EC-253), legibility-rebuilt (EC-305). A single\n * object (`multiple: false`) renders a depth-encoded card; an array (`'many'`)\n * dispatches by shape: a **flat** object type (all scalar subfields) → a compact\n * editable TABLE (C); a richer/nested type → a card list with depth encoding (B),\n * summary-first collapse (D), and reduced per-row chrome (E). Editing stays in the\n * shared field form — no canvas escape (unlike `blocks`) — so props and document\n * fields share this control. Depth flows via {@link ArrayDepthContext}.\n */\nexport function ObjectField({\n field,\n value,\n onChange,\n readOnly,\n id,\n}: {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n}) {\n const depth = useArrayDepth()\n if (field.multiple === false) {\n return (\n <Card className={cn('border-l-2 p-3', depthRail(depth), depthTint(depth))}>\n <ArrayDepthContext.Provider value={depth + 1}>\n <ObjectItemForm\n fields={field.fields}\n value={asRecord(value)}\n readOnly={readOnly}\n idPrefix={id}\n onChange={onChange}\n />\n </ArrayDepthContext.Provider>\n </Card>\n )\n }\n const props = { field, value, onChange, readOnly, id, depth }\n return isTabularObjectType(field) ? <ObjectTableField {...props} /> : <ObjectCardList {...props} />\n}\n\ninterface ObjectArrayProps {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n depth: number\n}\n\n/**\n * (B + D + E) The card list for a nested/rich object array: depth-encoded cards\n * (coloured rail + tint), items collapsed by default to a scannable summary outline\n * (D), accordion expansion (open one → collapse siblings), and the per-row controls\n * collapsed into one overflow menu (E). Drag-to-reorder; arrows live in the menu for\n * a11y. Nested arrays render one depth deeper via the context provider.\n */\nfunction ObjectCardList({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n const parentPath = useFieldPath()\n const focus = useFieldFocusRequest()\n // (D) Default COLLAPSED: track which keys are EXPANDED (empty = all collapsed).\n // (B) Accordion: expanding one collapses the siblings.\n const [expandedKeys, setExpandedKeys] = useState<ReadonlySet<number>>(() => new Set())\n const toggle = (key: number) =>\n setExpandedKeys((prev) => {\n if (prev.has(key)) {\n const next = new Set(prev)\n next.delete(key)\n return next\n }\n return new Set([key])\n })\n const allExpanded = items.length > 0 && keys.every((k) => expandedKeys.has(k))\n const onAdd = () => setExpandedKeys(new Set([arr.addItem()]))\n // EC-443: a jump-to-field targeting a path INSIDE one of these items expands\n // that item (accordion semantics, like a manual open) so the deeper anchors can\n // render — nested levels cascade, each level's effect firing once its card\n // mounts. Keyed on the request nonce so re-clicking the same issue re-expands\n // a manually re-collapsed item.\n const focusPath = focus?.path\n const focusNonce = focus?.nonce\n useEffect(() => {\n if (parentPath === null || focusPath === undefined) return\n const index = items.findIndex((_, i) => isPathWithin(`${parentPath}/${i}`, focusPath))\n if (index < 0) return\n const key = keys[index]\n if (key !== undefined) setExpandedKeys(new Set([key]))\n // Deps: keys/items stay in lockstep (the C2 key↔value lock) — `items.length`\n // captures the structure; item-content identity must NOT re-trigger expansion.\n }, [focusNonce, focusPath, parentPath, items.length])\n return (\n <ArrayDepthContext.Provider value={depth + 1}>\n <Stack gap=\"2\">\n {items.length > 1 && !readOnly ? (\n <Row justify=\"end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpandedKeys(allExpanded ? new Set() : new Set(keys))}\n >\n {translate(allExpanded ? 'cms.field.collapseAll' : 'cms.field.expandAll')}\n </Button>\n </Row>\n ) : null}\n {items.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n ) : (\n items.map((item, i) => {\n // keysRef is reconciled to items.length, so keys[i] is always present;\n // `?? i` only satisfies noUncheckedIndexedAccess (never taken at runtime).\n const key = keys[i] ?? i\n const record = asRecord(item)\n const isExpanded = expandedKeys.has(key)\n // EC-443: the item's path anchor — stamped even while collapsed, so a\n // degraded jump can still land (and ring) on the closed card.\n const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`\n return (\n <Card\n key={key}\n {...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {})}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-l-2 p-0',\n depthRail(depth),\n depthTint(depth),\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'border-l-primary ring-1 ring-primary/40'\n : '',\n itemPath !== undefined && focus?.path === itemPath\n ? 'ring-2 ring-primary/70'\n : '',\n )}\n >\n <Row className=\"select-none border-b border-border/60 bg-muted/20 px-2 py-1.5\">\n {!readOnly ? (\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n ) : null}\n <button\n type=\"button\"\n onClick={() => toggle(key)}\n aria-expanded={isExpanded}\n className=\"flex min-w-0 flex-1 items-center gap-1.5 text-left\"\n >\n <ChevronDown\n className={cn(\n 'size-3.5 shrink-0 text-muted-foreground transition-transform',\n isExpanded ? '' : '-rotate-90',\n )}\n aria-hidden\n />\n <Text size=\"sm\" className=\"min-w-0 truncate font-medium\">\n {objectItemSummary(field.fields, record, i)}\n </Text>\n </button>\n {!readOnly ? (\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n ) : null}\n </Row>\n {isExpanded ? (\n <div className=\"px-3 pb-3\">\n <FieldPathContext.Provider value={itemPath ?? null}>\n <ObjectItemForm\n fields={field.fields}\n value={record}\n readOnly={readOnly}\n idPrefix={`${id}-${i}`}\n onChange={(updated) => arr.setItem(i, updated)}\n />\n </FieldPathContext.Provider>\n </div>\n ) : null}\n </Card>\n )\n })\n )}\n {!readOnly ? (\n <Button variant=\"outline\" size=\"sm\" onClick={onAdd}>\n <Plus className=\"size-3\" /> {translate('cms.field.addItem')}\n </Button>\n ) : null}\n </Stack>\n </ArrayDepthContext.Provider>\n )\n}\n\n/**\n * (C) A compact editable table for a FLAT object array — columns are the scalar\n * subfields, one row per item. Kills the card-stack sprawl for the commonest case\n * (option lists, opening hours, social links). Drag-reorder + an overflow menu per\n * row; cells reuse {@link FieldControl} so each subfield keeps its native control.\n */\nfunction ObjectTableField({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n // EC-443: rows/cells stamp path anchors too (a tabular type is flat, so the\n // cell — `links/3/href` — is always the deepest possible anchor here).\n const parentPath = useFieldPath()\n const focus = useFieldFocusRequest()\n const cols = field.fields\n const span = cols.length + (readOnly ? 0 : 2)\n return (\n <div className={cn('overflow-hidden rounded-md border border-border border-l-2', depthRail(depth), depthTint(depth))}>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border/60 bg-muted/30 text-left\">\n {!readOnly ? <th className=\"w-7\" /> : null}\n {cols.map((c) => (\n <th key={c.name} className=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {fieldLabel(c)}\n {c.validation?.required ? <span className=\"text-destructive\"> *</span> : null}\n </th>\n ))}\n {!readOnly ? <th className=\"w-9\" /> : null}\n </tr>\n </thead>\n <tbody>\n {items.length === 0 ? (\n <tr>\n <td colSpan={span} className=\"px-2 py-2 text-muted-foreground\">\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n </td>\n </tr>\n ) : (\n items.map((item, i) => {\n const key = keys[i] ?? i\n const record = asRecord(item)\n const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`\n return (\n <tr\n key={key}\n {...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {})}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-b border-border/40 align-top last:border-0',\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'bg-primary/5'\n : '',\n itemPath !== undefined && focus?.path === itemPath\n ? 'ring-2 ring-inset ring-primary/70'\n : '',\n )}\n >\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"inline-flex cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n </td>\n ) : null}\n {cols.map((c) => {\n const cellPath = itemPath === undefined ? undefined : `${itemPath}/${c.name}`\n return (\n <td\n key={c.name}\n {...(cellPath !== undefined ? { [FIELD_PATH_ATTR]: cellPath } : {})}\n className={cn(\n 'px-2 py-1',\n cellPath !== undefined && focus?.path === cellPath\n ? 'bg-primary/5 ring-2 ring-inset ring-primary/70'\n : '',\n )}\n >\n <FieldControl\n id={`${id}-${i}-${c.name}`}\n field={c}\n value={record[c.name]}\n readOnly={readOnly}\n onChange={(next) => {\n const updated = { ...record }\n if (next === undefined) delete updated[c.name]\n else updated[c.name] = next\n arr.setItem(i, updated)\n }}\n />\n </td>\n )\n })}\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n </td>\n ) : null}\n </tr>\n )\n })\n )}\n </tbody>\n </table>\n {!readOnly ? (\n <div className=\"border-t border-border/60 p-1.5\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => arr.addItem()}>\n <Plus className=\"size-3\" /> {translate('common.add')}\n </Button>\n </div>\n ) : null}\n </div>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"object-array-field.js","sourceRoot":"","sources":["../../../src/components/cms/object-array-field.tsx"],"names":[],"mappings":"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","sourcesContent":["import { ChevronDown, ChevronUp, GripVertical, MoreHorizontal, Plus, Trash2 } from 'lucide-react'\nimport { createContext, useContext, useEffect, useRef, useState } from 'react'\nimport type { FieldDef, ObjectFieldDef } from '@elytracms/core/cms-core'\nimport { isFieldHidden, seedObjectItem } from '@elytracms/core/cms-core'\nimport {\n Button,\n Card,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n FIELD_PATH_ATTR,\n Field,\n Row,\n Stack,\n Text,\n} from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { localizedLabel, translate } from '@elytracms/studio/lib/i18n'\nimport { fieldLabel } from './cms-labels'\nimport {\n FieldPathContext,\n isPathWithin,\n useFieldFocusRequest,\n useFieldPath,\n} from './field-anchors'\nimport { FieldControl } from './field-control'\nimport {\n depthRail,\n depthTint,\n isSubFieldReadOnly,\n isTabularObjectType,\n objectItemSummary,\n reorder,\n tableColumnsOf,\n} from './field-control-lib'\n\n/**\n * The object / repeater field controls (EC-253, legibility-rebuilt EC-305) —\n * split from `field-control.tsx` (EC-330). {@link ObjectField} dispatches by\n * shape (single card / editable table / card list); {@link ObjectItemForm} is\n * the recursive subfield form the asset-field family reuses for per-use\n * sub-fields and asset metadata. Cells and subfields render through\n * `FieldControl`, so any subfield type — including a nested repeater — works\n * for free.\n *\n * EC-443 path anchors: inside a stamped surface (a non-null `FieldPathContext`,\n * provided by the document form) every item card / table row / subfield row\n * stamps its `FIELD_PATH_ATTR` anchor (`links/3`, `links/3/badge/text` — the\n * ONE convention defined on the attribute in `ui/field.tsx`), a collapsed card\n * auto-expands when the active focus request targets a path within it, and the\n * exact requested control ring-highlights. All decisions come from the pure\n * helpers in `field-anchors.ts`.\n */\n\n/** The EC-443 ring on the exact jump target (mirrors the top-level row ring). */\nconst FOCUS_RING_CLASS = 'rounded-md bg-primary/5 ring-2 ring-primary/70'\n\nfunction asRecord(value: unknown): Record<string, unknown> {\n return value !== null && typeof value === 'object' && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {}\n}\n\n// EC-305: nested-array depth, propagated via context so each array level can encode\n// its depth (rail colour + tint) without prop-drilling through FieldControl's many\n// branches. The detail editor renders top-level fields with the default depth 0.\nconst ArrayDepthContext = createContext(0)\nconst useArrayDepth = () => useContext(ArrayDepthContext)\n\n/**\n * Shared array state for an object repeater (EC-253/EC-294/EC-305): the value-only\n * items + a parallel stable-key list kept in lockstep through every structural op\n * (the EC-253 C2 key↔value lock), add/remove/move, and native drag-reorder. Used by\n * both the card list (B) and the table (C) so they behave identically.\n */\nfunction useObjectArray(field: ObjectFieldDef, value: unknown, onChange: (value: unknown) => void) {\n const items = Array.isArray(value) ? (value as Record<string, unknown>[]) : []\n const seq = useRef(0)\n const keysRef = useRef<number[]>([])\n if (keysRef.current.length !== items.length) {\n keysRef.current = items.map((_, i) => keysRef.current[i] ?? seq.current++)\n }\n const keys = keysRef.current\n const commit = (nextItems: Record<string, unknown>[], nextKeys: number[]) => {\n keysRef.current = nextKeys\n onChange(nextItems)\n }\n const move = (from: number, to: number) => commit(reorder(items, from, to), reorder(keys, from, to))\n const removeAt = (i: number) =>\n commit(items.filter((_, j) => j !== i), keys.filter((_, j) => j !== i))\n const addItem = (): number => {\n // EC-581: the one seeding rule (core `seedObjectItem`) — nested defaults included.\n const seed = seedObjectItem(field.fields)\n const key = seq.current++\n commit([...items, seed], [...keys, key])\n return key\n }\n const setItem = (i: number, updated: Record<string, unknown>) => {\n const nextItems = items.slice()\n nextItems[i] = updated\n commit(nextItems, keys)\n }\n const [dragIndex, setDragIndex] = useState<number | null>(null)\n const [overIndex, setOverIndex] = useState<number | null>(null)\n const endDrag = () => {\n setDragIndex(null)\n setOverIndex(null)\n }\n const drop = (to: number) => {\n if (dragIndex !== null && dragIndex !== to) move(dragIndex, to)\n endDrag()\n }\n return { items, keys, move, removeAt, addItem, setItem, dragIndex, overIndex, setDragIndex, setOverIndex, endDrag, drop }\n}\n\n/**\n * (E) Chrome reduction: the per-row move/remove controls collapse into one hover/\n * focus overflow menu, so a row reads as content, not a six-button toolbar. Drag is\n * the primary reorder; the arrows stay here for keyboard/a11y.\n */\nfunction ItemOverflowMenu({\n index,\n count,\n onMove,\n onRemove,\n}: {\n index: number\n count: number\n onMove: (from: number, to: number) => void\n onRemove: () => void\n}) {\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\" aria-label={translate('cms.field.itemActions')}>\n <MoreHorizontal className=\"size-3.5\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem disabled={index === 0} onClick={() => onMove(index, index - 1)}>\n <ChevronUp /> {translate('cms.field.moveUp')}\n </DropdownMenuItem>\n <DropdownMenuItem disabled={index === count - 1} onClick={() => onMove(index, index + 1)}>\n <ChevronDown /> {translate('cms.field.moveDown')}\n </DropdownMenuItem>\n <DropdownMenuItem onClick={onRemove}>\n <Trash2 /> {translate('common.remove')}\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\n/**\n * The nested subfield form for one object item (EC-253). Reuses {@link FieldControl}\n * recursively, so any subfield type — including a nested object/repeater — works for\n * free. Writing a subfield merges it back into the item and bubbles the new item up.\n * EC-443: each subfield row stamps its path anchor (`<itemPath>/<sub>`), rings when\n * it is the exact focus target, and provides its path down for deeper nesting.\n */\nexport function ObjectItemForm({\n fields,\n value,\n onChange,\n readOnly,\n idPrefix,\n}: {\n fields: readonly FieldDef[]\n value: Record<string, unknown>\n onChange: (value: Record<string, unknown>) => void\n readOnly: boolean\n idPrefix: string\n}) {\n const itemPath = useFieldPath()\n const focus = useFieldFocusRequest()\n return (\n <Stack gap=\"3\" className=\"mt-2\">\n {fields.map((sub) => {\n // EC-273: a conditionally-hidden subfield (its predicate keys off the item's\n // own sibling values) is omitted — e.g. a discriminated link's `href` shows\n // only when `linkType === 'href'`. Re-evaluated as the item is edited.\n if (isFieldHidden(sub, { values: value })) return null\n const subId = `${idPrefix}-${sub.name}`\n const subPath = itemPath === null ? undefined : `${itemPath}/${sub.name}`\n return (\n <Field\n key={sub.name}\n htmlFor={subId}\n fieldPath={subPath}\n className={cn(\n 'transition-shadow',\n subPath !== undefined && focus?.path === subPath && `${FOCUS_RING_CLASS} p-2`,\n )}\n hint={localizedLabel(sub.form?.description) || undefined}\n label={\n <Row gap=\"2\">\n <span>{fieldLabel(sub)}</span>\n {sub.validation?.required ? <span className=\"text-destructive\">*</span> : null}\n </Row>\n }\n >\n <FieldPathContext.Provider value={subPath ?? null}>\n <FieldControl\n id={subId}\n field={sub}\n value={value[sub.name]}\n readOnly={isSubFieldReadOnly(readOnly, sub)}\n onChange={(next) => {\n const updated = { ...value }\n if (next === undefined) delete updated[sub.name]\n else updated[sub.name] = next\n onChange(updated)\n }}\n />\n </FieldPathContext.Provider>\n </Field>\n )\n })}\n </Stack>\n )\n}\n\n/**\n * Object / repeater field control (EC-253), legibility-rebuilt (EC-305). A single\n * object (`multiple: false`) renders a depth-encoded card; an array (`'many'`)\n * dispatches by shape: a **flat** object type (all scalar subfields) → a compact\n * editable TABLE (C); a richer/nested type → a card list with depth encoding (B),\n * summary-first collapse (D), and reduced per-row chrome (E). Editing stays in the\n * shared field form — no canvas escape (unlike `blocks`) — so props and document\n * fields share this control. Depth flows via {@link ArrayDepthContext}.\n */\nexport function ObjectField({\n field,\n value,\n onChange,\n readOnly,\n id,\n}: {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n}) {\n const depth = useArrayDepth()\n if (field.multiple === false) {\n return (\n <Card className={cn('border-l-2 p-3', depthRail(depth), depthTint(depth))}>\n <ArrayDepthContext.Provider value={depth + 1}>\n <ObjectItemForm\n fields={field.fields}\n value={asRecord(value)}\n readOnly={readOnly}\n idPrefix={id}\n onChange={onChange}\n />\n </ArrayDepthContext.Provider>\n </Card>\n )\n }\n const props = { field, value, onChange, readOnly, id, depth }\n return isTabularObjectType(field) ? <ObjectTableField {...props} /> : <ObjectCardList {...props} />\n}\n\ninterface ObjectArrayProps {\n field: ObjectFieldDef\n value: unknown\n onChange: (value: unknown) => void\n readOnly: boolean\n id: string\n depth: number\n}\n\n/**\n * (B + D + E) The card list for a nested/rich object array: depth-encoded cards\n * (coloured rail + tint), items collapsed by default to a scannable summary outline\n * (D), accordion expansion (open one → collapse siblings), and the per-row controls\n * collapsed into one overflow menu (E). Drag-to-reorder; arrows live in the menu for\n * a11y. Nested arrays render one depth deeper via the context provider.\n */\nfunction ObjectCardList({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n const parentPath = useFieldPath()\n const focus = useFieldFocusRequest()\n // (D) Default COLLAPSED: track which keys are EXPANDED (empty = all collapsed).\n // (B) Accordion: expanding one collapses the siblings.\n const [expandedKeys, setExpandedKeys] = useState<ReadonlySet<number>>(() => new Set())\n const toggle = (key: number) =>\n setExpandedKeys((prev) => {\n if (prev.has(key)) {\n const next = new Set(prev)\n next.delete(key)\n return next\n }\n return new Set([key])\n })\n const allExpanded = items.length > 0 && keys.every((k) => expandedKeys.has(k))\n const onAdd = () => setExpandedKeys(new Set([arr.addItem()]))\n // EC-443: a jump-to-field targeting a path INSIDE one of these items expands\n // that item (accordion semantics, like a manual open) so the deeper anchors can\n // render — nested levels cascade, each level's effect firing once its card\n // mounts. Keyed on the request nonce so re-clicking the same issue re-expands\n // a manually re-collapsed item.\n const focusPath = focus?.path\n const focusNonce = focus?.nonce\n useEffect(() => {\n if (parentPath === null || focusPath === undefined) return\n const index = items.findIndex((_, i) => isPathWithin(`${parentPath}/${i}`, focusPath))\n if (index < 0) return\n const key = keys[index]\n if (key !== undefined) setExpandedKeys(new Set([key]))\n // Deps: keys/items stay in lockstep (the C2 key↔value lock) — `items.length`\n // captures the structure; item-content identity must NOT re-trigger expansion.\n }, [focusNonce, focusPath, parentPath, items.length])\n return (\n <ArrayDepthContext.Provider value={depth + 1}>\n <Stack gap=\"2\">\n {items.length > 1 && !readOnly ? (\n <Row justify=\"end\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setExpandedKeys(allExpanded ? new Set() : new Set(keys))}\n >\n {translate(allExpanded ? 'cms.field.collapseAll' : 'cms.field.expandAll')}\n </Button>\n </Row>\n ) : null}\n {items.length === 0 ? (\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n ) : (\n items.map((item, i) => {\n // keysRef is reconciled to items.length, so keys[i] is always present;\n // `?? i` only satisfies noUncheckedIndexedAccess (never taken at runtime).\n const key = keys[i] ?? i\n const record = asRecord(item)\n const isExpanded = expandedKeys.has(key)\n // EC-443: the item's path anchor — stamped even while collapsed, so a\n // degraded jump can still land (and ring) on the closed card.\n const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`\n return (\n <Card\n key={key}\n {...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {})}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-l-2 p-0',\n depthRail(depth),\n depthTint(depth),\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'border-l-primary ring-1 ring-primary/40'\n : '',\n itemPath !== undefined && focus?.path === itemPath\n ? 'ring-2 ring-primary/70'\n : '',\n )}\n >\n <Row className=\"select-none border-b border-border/60 bg-muted/20 px-2 py-1.5\">\n {!readOnly ? (\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n ) : null}\n <button\n type=\"button\"\n onClick={() => toggle(key)}\n aria-expanded={isExpanded}\n className=\"flex min-w-0 flex-1 items-center gap-1.5 text-left\"\n >\n <ChevronDown\n className={cn(\n 'size-3.5 shrink-0 text-muted-foreground transition-transform',\n isExpanded ? '' : '-rotate-90',\n )}\n aria-hidden\n />\n <Text size=\"sm\" className=\"min-w-0 truncate font-medium\">\n {objectItemSummary(field.fields, record, i)}\n </Text>\n </button>\n {!readOnly ? (\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n ) : null}\n </Row>\n {isExpanded ? (\n <div className=\"px-3 pb-3\">\n <FieldPathContext.Provider value={itemPath ?? null}>\n <ObjectItemForm\n fields={field.fields}\n value={record}\n readOnly={readOnly}\n idPrefix={`${id}-${i}`}\n onChange={(updated) => arr.setItem(i, updated)}\n />\n </FieldPathContext.Provider>\n </div>\n ) : null}\n </Card>\n )\n })\n )}\n {!readOnly ? (\n <Button variant=\"outline\" size=\"sm\" onClick={onAdd}>\n <Plus className=\"size-3\" /> {translate('cms.field.addItem')}\n </Button>\n ) : null}\n </Stack>\n </ArrayDepthContext.Provider>\n )\n}\n\n/**\n * (C) A compact editable table for a FLAT object array — columns are the scalar\n * subfields, one row per item. Kills the card-stack sprawl for the commonest case\n * (option lists, opening hours, social links). Drag-reorder + an overflow menu per\n * row; cells reuse {@link FieldControl} so each subfield keeps its native control.\n */\nfunction ObjectTableField({ field, value, onChange, readOnly, id, depth }: ObjectArrayProps) {\n const arr = useObjectArray(field, value, onChange)\n const { items, keys } = arr\n // EC-443: rows/cells stamp path anchors too (a tabular type is flat, so the\n // cell — `links/3/href` — is always the deepest possible anchor here).\n const parentPath = useFieldPath()\n const focus = useFieldFocusRequest()\n const cols = tableColumnsOf(field)\n const span = cols.length + (readOnly ? 0 : 2)\n return (\n <div className={cn('overflow-hidden rounded-md border border-border border-l-2', depthRail(depth), depthTint(depth))}>\n <table className=\"w-full text-sm\">\n <thead>\n <tr className=\"border-b border-border/60 bg-muted/30 text-left\">\n {!readOnly ? <th className=\"w-7\" /> : null}\n {cols.map((c) => (\n <th key={c.name} className=\"px-2 py-1.5 text-xs font-medium text-muted-foreground\">\n {fieldLabel(c)}\n {c.validation?.required ? <span className=\"text-destructive\"> *</span> : null}\n </th>\n ))}\n {!readOnly ? <th className=\"w-9\" /> : null}\n </tr>\n </thead>\n <tbody>\n {items.length === 0 ? (\n <tr>\n <td colSpan={span} className=\"px-2 py-2 text-muted-foreground\">\n <Text size=\"sm\" tone=\"subtle\">\n {translate('cms.field.noItems')}\n </Text>\n </td>\n </tr>\n ) : (\n items.map((item, i) => {\n const key = keys[i] ?? i\n const record = asRecord(item)\n const itemPath = parentPath === null ? undefined : `${parentPath}/${i}`\n return (\n <tr\n key={key}\n {...(itemPath !== undefined ? { [FIELD_PATH_ATTR]: itemPath } : {})}\n onDragOver={(e) => {\n if (arr.dragIndex === null) return\n e.preventDefault()\n if (arr.overIndex !== i) arr.setOverIndex(i)\n }}\n onDrop={() => arr.drop(i)}\n className={cn(\n 'border-b border-border/40 align-top last:border-0',\n arr.dragIndex === i ? 'opacity-50' : '',\n arr.overIndex === i && arr.dragIndex !== null && arr.dragIndex !== i\n ? 'bg-primary/5'\n : '',\n itemPath !== undefined && focus?.path === itemPath\n ? 'ring-2 ring-inset ring-primary/70'\n : '',\n )}\n >\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <span\n draggable\n onDragStart={(e) => {\n e.dataTransfer.effectAllowed = 'move'\n e.dataTransfer.setData('text/plain', String(i))\n arr.setDragIndex(i)\n }}\n onDragEnd={arr.endDrag}\n aria-label={translate('cms.field.dragToReorder')}\n className=\"inline-flex cursor-grab text-muted-foreground/50 hover:text-muted-foreground active:cursor-grabbing\"\n >\n <GripVertical className=\"size-3.5\" />\n </span>\n </td>\n ) : null}\n {cols.map((c) => {\n const cellPath = itemPath === undefined ? undefined : `${itemPath}/${c.name}`\n return (\n <td\n key={c.name}\n {...(cellPath !== undefined ? { [FIELD_PATH_ATTR]: cellPath } : {})}\n className={cn(\n 'px-2 py-1',\n cellPath !== undefined && focus?.path === cellPath\n ? 'bg-primary/5 ring-2 ring-inset ring-primary/70'\n : '',\n )}\n >\n <FieldControl\n id={`${id}-${i}-${c.name}`}\n field={c}\n value={record[c.name]}\n readOnly={isSubFieldReadOnly(readOnly, c)}\n onChange={(next) => {\n const updated = { ...record }\n if (next === undefined) delete updated[c.name]\n else updated[c.name] = next\n arr.setItem(i, updated)\n }}\n />\n </td>\n )\n })}\n {!readOnly ? (\n <td className=\"px-1 py-1\">\n <ItemOverflowMenu\n index={i}\n count={items.length}\n onMove={arr.move}\n onRemove={() => arr.removeAt(i)}\n />\n </td>\n ) : null}\n </tr>\n )\n })\n )}\n </tbody>\n </table>\n {!readOnly ? (\n <div className=\"border-t border-border/60 p-1.5\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => arr.addItem()}>\n <Plus className=\"size-3\" /> {translate('common.add')}\n </Button>\n </div>\n ) : null}\n </div>\n )\n}\n"]}
|
|
@@ -19,7 +19,7 @@ import type { PropField } from '@elytracms/core/component-registry';
|
|
|
19
19
|
* vocabulary derives from the field `type` plus the optional `form.control`
|
|
20
20
|
* presentation hint on `text` fields.
|
|
21
21
|
*/
|
|
22
|
-
export type ControlKind = 'text' | 'textarea' | 'number' | 'boolean' | 'select' | 'options' | 'json' | 'color' | 'richtext' | 'asset' | 'object' | 'relation';
|
|
22
|
+
export type ControlKind = 'text' | 'textarea' | 'number' | 'boolean' | 'select' | 'options' | 'json' | 'color' | 'richtext' | 'asset' | 'object' | 'relation' | 'date';
|
|
23
23
|
export declare function controlKind(spec: PropField): ControlKind;
|
|
24
24
|
/**
|
|
25
25
|
* The manifest `default` as the inspector's greyed HINT (EC-591, ratified 2f) — a
|
|
@@ -62,10 +62,15 @@ export interface PropValueControlProps {
|
|
|
62
62
|
* default applies, never the manifest `default` (a hint only).
|
|
63
63
|
*/
|
|
64
64
|
onClear: () => void;
|
|
65
|
+
/**
|
|
66
|
+
* The node's effective prop values (EC-582) — what a `validate` function and a
|
|
67
|
+
* `form.hidden` predicate read. Absent → judged against no siblings.
|
|
68
|
+
*/
|
|
69
|
+
siblings?: Readonly<Record<string, unknown>>;
|
|
65
70
|
}
|
|
66
71
|
/**
|
|
67
72
|
* Render + edit a single manifest prop value. Store-agnostic: emits through
|
|
68
73
|
* `onSet`/`onClear`. Shows a validation issue when the current value fails the
|
|
69
74
|
* prop's field-def validator.
|
|
70
75
|
*/
|
|
71
|
-
export declare function PropValueControl({ id, name, spec, value, onSet, onClear }: PropValueControlProps): import("react").JSX.Element;
|
|
76
|
+
export declare function PropValueControl({ id, name, spec, value, onSet, onClear, siblings }: PropValueControlProps): import("react").JSX.Element;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { isStaticProp } from '@elytracms/core/project-graph';
|
|
4
|
-
import {
|
|
4
|
+
import { fieldValueIssues } from '@elytracms/core/cms-core';
|
|
5
5
|
import { Input, Row, Select, Stack, Text } from '@elytracms/studio/ui';
|
|
6
6
|
import { localizedLabel, translate } from '@elytracms/studio/lib/i18n';
|
|
7
|
+
import { cmsValidationIssueMessage } from '@elytracms/studio/lib/persona/labels';
|
|
7
8
|
import { FieldControl } from './field-control.js';
|
|
8
9
|
import { SegmentedOptions } from './field-control-lib.js';
|
|
9
10
|
import { FieldDensityProvider } from './field-density.js';
|
|
@@ -36,6 +37,10 @@ export function controlKind(spec) {
|
|
|
36
37
|
// CMS relation picker — never a text box that stringifies the ref to "[object Object]".
|
|
37
38
|
case 'relation':
|
|
38
39
|
return 'relation';
|
|
40
|
+
// EC-582 (SHAPES #26): a `date` prop gets the date control a `date` field gets —
|
|
41
|
+
// one per-type dispatch (the document form's `FieldControl`), never a text box.
|
|
42
|
+
case 'date':
|
|
43
|
+
return 'date';
|
|
39
44
|
case 'text': {
|
|
40
45
|
const c = spec.form?.control;
|
|
41
46
|
if (c === 'textarea')
|
|
@@ -95,7 +100,7 @@ export function applyRichTextPropChange(next, handlers) {
|
|
|
95
100
|
* `onSet`/`onClear`. Shows a validation issue when the current value fails the
|
|
96
101
|
* prop's field-def validator.
|
|
97
102
|
*/
|
|
98
|
-
export function PropValueControl({ id, name, spec, value, onSet, onClear }) {
|
|
103
|
+
export function PropValueControl({ id, name, spec, value, onSet, onClear, siblings }) {
|
|
99
104
|
// EC-591 / ratified 2f: an absent prop shows EMPTY — the manifest `default` is a
|
|
100
105
|
// greyed hint (placeholder), never presented as the value. Until EC-591 this read
|
|
101
106
|
// `spec.default` as the current value, so the inspector showed a value the canvas
|
|
@@ -109,8 +114,10 @@ export function PropValueControl({ id, name, spec, value, onSet, onClear }) {
|
|
|
109
114
|
// to a read-only value display instead of throwing "useCollectionView must be
|
|
110
115
|
// used within a <CollectionViewProvider>" (the Konditorei Components-view crash).
|
|
111
116
|
const hasWorkspaceContext = useOptionalCollectionView() != null;
|
|
112
|
-
// EC-
|
|
113
|
-
|
|
117
|
+
// EC-582: THE per-position rule set — what the publish gate runs at this prop
|
|
118
|
+
// (`required` on an absent prop, `validate`, type, constraints, structure) — so the
|
|
119
|
+
// inspector shows the gate's own finding AT the prop, never a weaker local check.
|
|
120
|
+
const propIssues = fieldValueIssues({ ...spec, name }, current, siblings ? { siblings } : {}).filter((issue) => issue.severity === 'error');
|
|
114
121
|
// EC-190: derive the editor control from the field `type` + optional `form.control`.
|
|
115
122
|
const kind = controlKind(spec);
|
|
116
123
|
// Select options live on the `select` field-def.
|
|
@@ -190,7 +197,7 @@ export function PropValueControl({ id, name, spec, value, onSet, onClear }) {
|
|
|
190
197
|
// EC-591/2f: emptying the field clears the prop (absent), not an explicit ''.
|
|
191
198
|
onChange: (e) => (e.target.value === '' ? onClear() : onSet(e.target.value)), className: "flex w-full rounded-md border border-input bg-background px-2.5 py-1.5 text-sm text-foreground shadow-sm placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/40 outline-none disabled:cursor-not-allowed disabled:opacity-50" }));
|
|
192
199
|
}
|
|
193
|
-
else if (kind === 'asset' || kind === 'object' || kind === 'relation') {
|
|
200
|
+
else if (kind === 'asset' || kind === 'object' || kind === 'relation' || (kind === 'date' && hasWorkspaceContext)) {
|
|
194
201
|
// EC-195/EC-253/EC-262: reuse the CMS field control. `asset` = library picker +
|
|
195
202
|
// preview; `object` = the nested/repeater form; `relation` = the document picker
|
|
196
203
|
// (resolves the ref to its title, instead of stringifying it to "[object Object]").
|
|
@@ -204,7 +211,7 @@ export function PropValueControl({ id, name, spec, value, onSet, onClear }) {
|
|
|
204
211
|
// EC-591/2f: emptying the field clears the prop (absent), not an explicit ''.
|
|
205
212
|
onChange: (e) => (e.target.value === '' ? onClear() : onSet(e.target.value)) }));
|
|
206
213
|
}
|
|
207
|
-
return (_jsxs(Stack, { gap: "1", children: [control,
|
|
214
|
+
return (_jsxs(Stack, { gap: "1", children: [control, propIssues.length > 0 && !readOnly ? (_jsx(Text, { size: "xs", className: "text-destructive", children: cmsValidationIssueMessage(propIssues[0]) })) : null] }));
|
|
208
215
|
}
|
|
209
216
|
/**
|
|
210
217
|
* Read-only stand-in for an `asset`/`relation`/`object` prop when there is no
|