@elytracms/studio 0.0.67 → 0.0.69
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.d.ts +4 -2
- package/dist/components/assets/asset-detail.js +4 -2
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +30 -19
- package/dist/components/assets/assets-collection-view-source.js +55 -23
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/builder/canvas-chrome-css.js +6 -1
- package/dist/components/builder/canvas-chrome-css.js.map +1 -1
- package/dist/components/builder/property-inspector.d.ts +0 -21
- package/dist/components/builder/property-inspector.js +5 -22
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/selection-overlay.d.ts +17 -4
- package/dist/components/builder/selection-overlay.js +17 -15
- package/dist/components/builder/selection-overlay.js.map +1 -1
- package/dist/components/builder/spacing-handles.d.ts +26 -1
- package/dist/components/builder/spacing-handles.js +66 -3
- package/dist/components/builder/spacing-handles.js.map +1 -1
- package/dist/components/cms/asset-picker-core.d.ts +52 -0
- package/dist/components/cms/asset-picker-core.js +69 -0
- package/dist/components/cms/asset-picker-core.js.map +1 -0
- package/dist/components/cms/asset-picker.d.ts +16 -4
- package/dist/components/cms/asset-picker.js +34 -50
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/bulk-bar.d.ts +11 -1
- package/dist/components/cms/bulk-bar.js +10 -3
- package/dist/components/cms/bulk-bar.js.map +1 -1
- package/dist/components/cms/collection-table.js +19 -2
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/detail-editor.js +45 -54
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/field-control.js +5 -1
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/components/cms/prop-fields.js +5 -1
- package/dist/components/cms/prop-fields.js.map +1 -1
- package/dist/components/cms/prop-visibility.d.ts +3 -0
- package/dist/components/cms/prop-visibility.js +31 -0
- package/dist/components/cms/prop-visibility.js.map +1 -0
- package/dist/components/cms/reference-confirm.js +5 -1
- package/dist/components/cms/reference-confirm.js.map +1 -1
- package/dist/components/cms/rich-text/component-embed.d.ts +8 -6
- package/dist/components/cms/rich-text/component-embed.js +21 -62
- package/dist/components/cms/rich-text/component-embed.js.map +1 -1
- package/dist/components/cms/rich-text/editor.d.ts +33 -4
- package/dist/components/cms/rich-text/editor.js +52 -22
- package/dist/components/cms/rich-text/editor.js.map +1 -1
- package/dist/components/cms/rich-text/embed-props.d.ts +60 -27
- package/dist/components/cms/rich-text/embed-props.js +102 -45
- package/dist/components/cms/rich-text/embed-props.js.map +1 -1
- package/dist/components/rail-view-source.d.ts +50 -1
- package/dist/components/rail-view-source.js +56 -2
- package/dist/components/rail-view-source.js.map +1 -1
- package/dist/components/redirects/redirects-collection-view-source.d.ts +3 -2
- package/dist/components/redirects/redirects-collection-view-source.js +4 -3
- package/dist/components/redirects/redirects-collection-view-source.js.map +1 -1
- package/dist/components/users/users-collection-view-source.js +1 -1
- package/dist/components/users/users-collection-view-source.js.map +1 -1
- package/dist/lib/collection-view/collection-view-source.d.ts +12 -0
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/dnd/gap-drag.d.ts +8 -1
- package/dist/lib/dnd/gap-drag.js +4 -0
- package/dist/lib/dnd/gap-drag.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +3 -2
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +1 -1
- package/dist/lib/i18n/messages.en.js +4 -2
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/references/references-store.d.ts +8 -1
- package/dist/lib/references/references-store.js +12 -2
- package/dist/lib/references/references-store.js.map +1 -1
- package/dist/ui/expandable-surface.d.ts +35 -25
- package/dist/ui/expandable-surface.js +41 -21
- package/dist/ui/expandable-surface.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/surface-geometry.d.ts +71 -0
- package/dist/ui/surface-geometry.js +64 -0
- package/dist/ui/surface-geometry.js.map +1 -0
- package/package.json +2 -2
- package/src/styles/studio.css +30 -0
- package/dist/components/cms/rich-text/embed-inspector-context.d.ts +0 -50
- package/dist/components/cms/rich-text/embed-inspector-context.js +0 -12
- package/dist/components/cms/rich-text/embed-inspector-context.js.map +0 -1
- package/dist/components/cms/rich-text/embed-inspector.d.ts +0 -25
- package/dist/components/cms/rich-text/embed-inspector.js +0 -48
- package/dist/components/cms/rich-text/embed-inspector.js.map +0 -1
- package/dist/components/cms/use-embed-inspector-host.d.ts +0 -12
- package/dist/components/cms/use-embed-inspector-host.js +0 -17
- package/dist/components/cms/use-embed-inspector-host.js.map +0 -1
|
@@ -34,10 +34,6 @@ import { VersionCompare } from './version-compare-lazy.js';
|
|
|
34
34
|
import { IssuesPane } from './issues-pane.js';
|
|
35
35
|
import { DetailsPane } from './details-pane.js';
|
|
36
36
|
import { DocumentUrlPath } from './document-url-path.js';
|
|
37
|
-
// 0.0.41: selection-driven embed inspector. Both modules are deliberately TipTap-free
|
|
38
|
-
// so the editor runtime stays behind rich-text/lazy (EC-322) — see their doc comments.
|
|
39
|
-
import { EmbedInspectorProvider } from './rich-text/embed-inspector-context.js';
|
|
40
|
-
import { EmbedInspector } from './rich-text/embed-inspector.js';
|
|
41
37
|
import { useSetBreadcrumb } from '../breadcrumb-context.js';
|
|
42
38
|
import { useAiCurrentDocumentTap } from '@elytracms/studio/lib/ai-current-document';
|
|
43
39
|
import { resolveDeploymentRoutes } from '@elytracms/studio/lib/workspace';
|
|
@@ -51,7 +47,6 @@ import { usePublishController, publishGate } from './use-publish-controller.js';
|
|
|
51
47
|
import { useFieldFocus } from './use-field-focus.js';
|
|
52
48
|
import { useCompareSelection } from './use-compare-selection.js';
|
|
53
49
|
import { useLiveUrl } from './use-live-url.js';
|
|
54
|
-
import { useEmbedInspectorHost } from './use-embed-inspector-host.js';
|
|
55
50
|
export function DetailEditor({ projectId, collectionId, documentId, focusPath, }) {
|
|
56
51
|
// AD-19: the edit shell is a portable surface over a CollectionViewSource, just
|
|
57
52
|
// like the list. `DetailEditor` is the CMS entry point — it builds the CMS source
|
|
@@ -235,10 +230,6 @@ function EditorBody({ projectId, collection, doc, focusPath, formAppendix, }) {
|
|
|
235
230
|
focusPath,
|
|
236
231
|
setActiveTab,
|
|
237
232
|
});
|
|
238
|
-
// 0.0.41 — the selection-driven embed-inspector host: a rich-text `componentEmbed`
|
|
239
|
-
// selection swaps the inspector sidebar for the embed's prop form (the `api` is fed
|
|
240
|
-
// to the rich-text field through the EmbedInspector context).
|
|
241
|
-
const { activeEmbed, embedInspectorApi } = useEmbedInspectorHost();
|
|
242
233
|
// EC-298 — the sticky version-compare selection. Opening it focuses the Compare tab
|
|
243
234
|
// + the Versions pane; tabbing to the real fields keeps it open (only its ✕ closes
|
|
244
235
|
// it). `activeTab === COMPARE_TAB` is when the diff is visible.
|
|
@@ -492,51 +483,51 @@ function EditorBody({ projectId, collection, doc, focusPath, formAppendix, }) {
|
|
|
492
483
|
setCompareBase,
|
|
493
484
|
setCompareTarget,
|
|
494
485
|
exitCompare,
|
|
495
|
-
}, children:
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
486
|
+
}, children: _jsxs("div", { className: cn('flex h-full min-h-0 flex-col', viewReadOnly && 'bg-info/[0.04]'), children: [_jsxs("div", { className: "shrink-0 border-b border-border px-4 py-3 sm:px-6", children: [_jsxs(Row, { gap: "3", align: "start", children: [_jsxs(Stack, { gap: "1", className: "min-w-0", children: [_jsxs(Row, { gap: "2", align: "center", className: "min-w-0", children: [_jsx(Heading, { level: 1, size: "h2", className: "truncate", children: singleton ? localizedLabel(collection.form?.label, collection.id) : title || doc.id }), singleton ? null : _jsx(FallbackChip, { fallback: titleFallback, testId: "doc-title-fallback" })] }), routableCollection ? (_jsx(DocumentUrlPath, { projectId: projectId, collection: collection, doc: draft, siblings: source.documents(), routes: resolveDeploymentRoutes(), localeConfig: source.localeConfig, locale: locale, live: headerLive })) : null] }), _jsx(Spacer, {}), _jsxs(Stack, { gap: "none", align: "end", className: "min-w-0", children: [_jsx(Text, { size: "xs", tone: "muted", className: "whitespace-nowrap", "data-testid": "autosave-status", children: source.lastError
|
|
487
|
+
? translate('cms.editor.saveFailed')
|
|
488
|
+
: explicitSave
|
|
489
|
+
? dirty
|
|
490
|
+
? translate('cms.editor.unsavedChanges')
|
|
491
|
+
: translate('cms.editor.saved')
|
|
492
|
+
: dirty
|
|
493
|
+
? translate('cms.editor.saving')
|
|
494
|
+
: translate('cms.editor.saved') }), source.lastError?.message ? (_jsx(Text, { size: "xs", className: "max-w-64 truncate text-destructive", title: source.lastError.message, "data-testid": "save-error-message", children: source.lastError.message })) : null] }), canPublish ? _jsx(DocStateBadge, { published: published }) : null, canPublish ? (_jsxs(Row, { gap: "px", align: "center", children: [_jsx(Button, { size: "sm", onClick: handlePublish, disabled: publishDisabled, title: publishTitle, className: canPublishClose ? 'rounded-r-none' : undefined, "data-testid": "doc-publish", children: publishButtonLabel }), canPublishClose ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { size: "sm", disabled: publishDisabled, "aria-label": translate('cms.editor.publishActions'), "data-testid": "doc-publish-actions", className: "rounded-l-none border-l border-primary-foreground/25 px-1.5", children: _jsx(ChevronDown, { className: "size-3.5" }) }) }), _jsx(DropdownMenuContent, { align: "end", children: _jsxs(DropdownMenuItem, { onClick: handlePublishAndClose, "data-testid": "doc-publish-and-close", children: [_jsx(Save, {}), " ", translate('cms.editor.publishAndClose')] }) })] })) : null] })) : null, explicitSave ? (_jsxs(Button, { size: "sm", onClick: save, disabled: !dirty, "data-testid": "doc-save", children: [_jsx(Check, {}), " ", translate('common.save')] })) : null, !viewReadOnly ? (_jsx(TranslateDocumentAction, { projectId: projectId, collection: collection, docRef: ref, document: draft, localeConfig: source.localeConfig, localesEnabled: canLocales, onApplied: (next) => {
|
|
495
|
+
source.save(next);
|
|
496
|
+
replaceDraft(next);
|
|
497
|
+
} })) : null, published || !singleton ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", size: "icon-sm", "aria-label": translate('cms.editor.moreActions'), children: _jsx(MoreHorizontal, {}) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [discardStatus !== 'hidden' ? (_jsxs(DropdownMenuItem, { "data-testid": "doc-discard-draft", disabled: discardStatus !== 'ready', title: discardDisabledReason, onClick: () => setDiscardConfirm(true), children: [_jsx(RotateCcw, {}), " ", translate('cms.editor.discardDraft')] })) : null, published ? (_jsxs(DropdownMenuItem, { onClick: () => setConfirmAction('unpublish'), children: [_jsx(EyeOff, {}), " ", translate('cms.editor.unpublish')] })) : null, singleton ? null : (_jsxs(DropdownMenuItem, { "data-testid": "doc-delete", className: "text-destructive", onClick: () => setConfirmAction('delete'), children: [_jsx(Trash2, {}), " ", translate('common.delete')] }))] })] })) : null] }), showLensRow ? (_jsxs(Row, { gap: "3", className: "mt-3", wrap: true, children: [_jsxs(Row, { gap: "1", align: "center", children: [showContentTabs ? tabs.map((tab) => renderContentTab(tab)) : null, showReferences ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "mx-1 h-4 w-px bg-border", "aria-hidden": true }), renderContentTab(REFERENCES_TAB)] })) : null, compare ? (_jsxs("span", { className: cn('inline-flex items-center gap-1 rounded-md px-2.5 py-1 text-xs font-medium transition-colors', activeTab === COMPARE_TAB
|
|
498
|
+
? 'bg-accent text-accent-foreground'
|
|
499
|
+
: 'text-muted-foreground hover:bg-muted'), children: [_jsxs("button", { type: "button", onClick: () => setActiveTab(COMPARE_TAB), "aria-pressed": activeTab === COMPARE_TAB, className: "inline-flex items-center gap-1", children: [_jsx(GitCompareArrows, { className: "size-3", "aria-hidden": true }), " ", translate('cms.version.compare')] }), _jsx("button", { type: "button", onClick: exitCompare, "aria-label": translate('cms.version.closeCompare'), className: "ml-0.5 rounded p-0.5 hover:bg-background/40", children: _jsx(X, { className: "size-3" }) })] })) : null] }), _jsx(Spacer, {}), canLocales ? _jsx(LocaleSwitcher, {}) : null, canPublish ? (_jsxs(Row, { gap: "px", className: "rounded-md bg-muted/60 p-0.5", children: [_jsx(PerspectiveButton, { label: translate('cms.editor.draftState'), active: perspective === 'draft', onClick: () => setPerspective('draft') }), _jsx(PerspectiveButton, { label: translate('cms.editor.publishedState'), active: perspective === 'published', accent: "info", disabled: !published, title: published ? undefined : translate('cms.editor.publishToViewPublished'), onClick: () => setPerspective('published') })] })) : null] })) : null] }), viewReadOnly ? (_jsxs(Row, { gap: "2", className: "shrink-0 border-b border-info/30 bg-info/10 px-4 py-1.5 text-info sm:px-6", "data-testid": "published-view-banner", children: [_jsx(Lock, { className: "size-3.5 shrink-0", "aria-hidden": true }), _jsx(Text, { size: "xs", className: "text-info", children: translate('cms.editor.publishedReadOnlyBanner') }), _jsx(Spacer, {}), _jsx("button", { type: "button", onClick: () => setPerspective('draft'), className: "text-xs font-medium underline-offset-2 hover:underline", children: translate('cms.editor.switchToDraft') })] })) : null, publishedPending ? (_jsx("div", { className: "grid min-h-0 flex-1 place-items-center p-8", children: _jsx(Text, { size: "sm", tone: "muted", children: publishedSnapshot.status === 'loading'
|
|
500
|
+
? translate('cms.editor.loadingPublishedVersion')
|
|
501
|
+
: translate('cms.editor.noPublishedVersion') }) })) : activeTab === COMPARE_TAB && compare ? (_jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden", children: [_jsx("div", { className: "min-h-0 flex-1 overflow-auto", children: _jsx(VersionCompare, {}) }), _jsx(InspectorSidebar, { panes: trailingPanes, activeId: inspectorPaneId, onActiveChange: setInspectorPaneId, className: "w-[320px] shrink-0 border-l border-border" })] })) : canvasField ? (_jsx("div", { className: "min-h-0 flex-1 overflow-hidden", children: _jsx(CompositionFieldEditor, { field: canvasField, value: getValue(canvasField), onChange: (v) => setValue(canvasField, v), readOnly: viewReadOnly || source.isFieldReadOnly(canvasField), trailingPanes: trailingPanes }, `${canvasField.name}:${restoreNonce}:${perspective}`) })) : activeTab === REFERENCES_TAB ? (_jsx("div", { className: "flex min-h-0 flex-1 overflow-hidden", children: _jsx("div", { className: "min-h-0 flex-1 overflow-auto p-4 sm:p-6", children: _jsx("div", { className: "mx-auto w-full max-w-2xl", children: _jsx(ReferencesPanel, { projectId: projectId, source: { type: 'document', id: documentKey(ref) }, target: { type: 'document', id: documentKey(ref) } }) }) }) })) : (_jsxs("div", { className: "flex min-h-0 flex-1 overflow-hidden", children: [_jsx("div", { className: "min-h-0 flex-1 overflow-auto p-4 sm:p-6", children: _jsx("div", { className: "mx-auto w-full max-w-2xl", children: _jsxs(Stack, { gap: "6", children: [groups.map((group) => {
|
|
502
|
+
// EC-306: a conditionally/statically hidden group section is skipped
|
|
503
|
+
// entirely (its fields are also exempt from validation).
|
|
504
|
+
if (hiddenGroups.has(group.name))
|
|
505
|
+
return null;
|
|
506
|
+
// EC-273/EC-240: drop a fieldset whose every field is hidden — whether
|
|
507
|
+
// content-conditionally or for this principal — so the form never
|
|
508
|
+
// shows an empty section header.
|
|
509
|
+
const visible = group.fields.filter(isFieldShown);
|
|
510
|
+
if (visible.length === 0)
|
|
511
|
+
return null;
|
|
512
|
+
const section = group.section;
|
|
513
|
+
// EC-241: a section `title` is a LocalizedString ({ en, de } or a plain
|
|
514
|
+
// string) — resolve it against the active UI locale before rendering.
|
|
515
|
+
const sectionTitle = section?.title !== undefined ? localizedLabel(section.title, group.name) : undefined;
|
|
516
|
+
return (_jsx(CollapsibleSection, { collapsible: section?.collapsible, defaultOpen: section?.defaultOpen, title: _jsx(Text, { size: "sm", weight: "semibold", className: sectionTitle || group.name === DEFAULT_FIELD_GROUP ? undefined : 'capitalize', children: sectionTitle ??
|
|
517
|
+
(group.name === DEFAULT_FIELD_GROUP
|
|
518
|
+
? translate('cms.editor.defaultGroup')
|
|
519
|
+
: group.name) }), children: _jsx("div", { className: "grid grid-cols-1 gap-4 p-4 md:grid-cols-12", children: visible.map((field) => (_jsx("div", { className: cn('col-span-1', fieldWidthColSpan(field.form?.width)), children: renderFieldRow(field) }, field.name))) }) }, group.name));
|
|
520
|
+
}), formAppendix] }) }) }), _jsx(InspectorSidebar, { panes: trailingPanes, activeId: inspectorPaneId, onActiveChange: setInspectorPaneId, className: "w-[320px] shrink-0 border-l border-border" })] })), explicitSave ? (_jsx(UnsavedChangesGuard, { when: dirty, onSave: () => {
|
|
521
|
+
save();
|
|
522
|
+
return true;
|
|
523
|
+
}, description: translate('cms.editor.unsavedChangesGuard') })) : null, confirmAction !== null ? (_jsx(ReferenceConfirmDialog, { projectId: projectId, action: confirmAction, targets: confirmTargets, open: true, onOpenChange: (open) => {
|
|
524
|
+
if (!open)
|
|
525
|
+
setConfirmAction(null);
|
|
526
|
+
}, onConfirm: handleConfirmedAction })) : null, _jsx(Dialog, { open: discardConfirm, onOpenChange: (open) => { if (!open)
|
|
527
|
+
setDiscardConfirm(false); }, children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: translate('cms.editor.discardDraftTitle') }), _jsx(DialogDescription, { children: translate('cms.editor.discardDraftDescription') })] }), _jsxs(DialogFooter, { className: "mt-4", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: () => setDiscardConfirm(false), disabled: discardBusy, children: translate('common.cancel') }), _jsx(Button, { variant: "destructive", size: "sm", "data-testid": "discard-draft-confirm", disabled: discardBusy, onClick: () => void handleDiscardDraft(), children: discardBusy ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "animate-spin" }), " ", translate('cms.editor.discardingDraft')] })) : (_jsxs(_Fragment, { children: [_jsx(RotateCcw, {}), " ", translate('cms.editor.discardDraftConfirm')] })) })] })] }) }), _jsx(Dialog, { open: publishConfirm, onOpenChange: (open) => { if (!open)
|
|
528
|
+
cancelPublishConfirm(); }, children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: translate('cms.editor.publishUnpublishedRefsTitle') }), _jsx(DialogDescription, { children: translate('cms.editor.publishUnpublishedRefsDescription') })] }), _jsxs(Stack, { gap: "1", children: [referenceIssues.map((issue, i) => (_jsxs(Text, { size: "xs", tone: "muted", children: ["\u2022 ", issue.message] }, `${issue.meta?.id ?? i}`))), schemaIssues.length > 0 ? (_jsx(Text, { size: "xs", tone: "muted", className: "mt-1", children: translate(schemaIssues.length === 1
|
|
529
|
+
? 'cms.editor.publishAlsoHasIssues.one'
|
|
530
|
+
: 'cms.editor.publishAlsoHasIssues.other', { count: schemaIssues.length }) })) : null] }), _jsxs(DialogFooter, { className: "mt-4", children: [_jsx(Button, { variant: "ghost", size: "sm", onClick: cancelPublishConfirm, children: translate('common.cancel') }), _jsx(Button, { size: "sm", "data-testid": "publish-anyway", onClick: confirmPublish, children: translate('cms.editor.publishAnyway') })] })] }) })] }) }));
|
|
540
531
|
}
|
|
541
532
|
/**
|
|
542
533
|
* EC-300/AD-16 — errors for composition embeds (hard references) whose target isn't
|