@elytracms/studio 0.0.32 → 0.0.34
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/app-views/default-modules.js +20 -11
- package/dist/components/app-views/default-modules.js.map +1 -1
- package/dist/components/assets/asset-library.js +21 -13
- package/dist/components/assets/asset-library.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/backend-gate.js +4 -3
- package/dist/components/backend-gate.js.map +1 -1
- package/dist/components/builder/blocks-panel.js +11 -2
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/canvas.js +6 -5
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.js +12 -6
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor.js +7 -4
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/fixture-thumbnail.js +2 -1
- package/dist/components/builder/fixture-thumbnail.js.map +1 -1
- package/dist/components/builder/layout-inspector.d.ts +5 -5
- package/dist/components/builder/layout-inspector.js +21 -20
- package/dist/components/builder/layout-inspector.js.map +1 -1
- package/dist/components/builder/page-tree.js +5 -4
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/property-inspector.js +10 -10
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/reuse-context.js +9 -9
- package/dist/components/builder/reuse-context.js.map +1 -1
- package/dist/components/builder/rich-text-toolbar.js +4 -3
- package/dist/components/builder/rich-text-toolbar.js.map +1 -1
- package/dist/components/builder/spacing-handles.js +4 -3
- package/dist/components/builder/spacing-handles.js.map +1 -1
- package/dist/components/cms/asset-picker.js +8 -7
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/bulk-bar.js +8 -5
- package/dist/components/cms/bulk-bar.js.map +1 -1
- package/dist/components/cms/cell.js +9 -5
- package/dist/components/cms/cell.js.map +1 -1
- package/dist/components/cms/cms-store.d.ts +7 -6
- package/dist/components/cms/cms-store.js +21 -12
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/collection-table.js +18 -7
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/detail-editor.js +45 -29
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/details-pane.js +4 -3
- package/dist/components/cms/details-pane.js.map +1 -1
- package/dist/components/cms/editable-cell.js +4 -4
- package/dist/components/cms/editable-cell.js.map +1 -1
- package/dist/components/cms/field-control.js +29 -21
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/components/cms/field-renderer.js +2 -1
- package/dist/components/cms/field-renderer.js.map +1 -1
- package/dist/components/cms/filter-builder.js +9 -8
- package/dist/components/cms/filter-builder.js.map +1 -1
- package/dist/components/cms/import-export.js +3 -2
- package/dist/components/cms/import-export.js.map +1 -1
- package/dist/components/cms/issues-pane.js +3 -2
- package/dist/components/cms/issues-pane.js.map +1 -1
- package/dist/components/cms/reference-confirm.js +24 -10
- package/dist/components/cms/reference-confirm.js.map +1 -1
- package/dist/components/cms/relation-picker.js +5 -4
- package/dist/components/cms/relation-picker.js.map +1 -1
- package/dist/components/cms/scalar-value-editor.js +5 -5
- package/dist/components/cms/scalar-value-editor.js.map +1 -1
- package/dist/components/cms/version-compare.js +36 -21
- package/dist/components/cms/version-compare.js.map +1 -1
- package/dist/components/cms/versions-pane.js +8 -5
- package/dist/components/cms/versions-pane.js.map +1 -1
- package/dist/components/cms/view-bar.js +3 -2
- package/dist/components/cms/view-bar.js.map +1 -1
- package/dist/components/components/component-detail.js +3 -2
- package/dist/components/components/component-detail.js.map +1 -1
- package/dist/components/components/component-status.js +8 -13
- package/dist/components/components/component-status.js.map +1 -1
- package/dist/components/components/components-index.js +5 -1
- package/dist/components/components/components-index.js.map +1 -1
- package/dist/components/components/field-inspector.js +4 -4
- package/dist/components/components/field-inspector.js.map +1 -1
- package/dist/components/components/fixture-runner.js +4 -1
- package/dist/components/components/fixture-runner.js.map +1 -1
- package/dist/components/components/registry-browser.js +4 -3
- package/dist/components/components/registry-browser.js.map +1 -1
- package/dist/components/delivery-health-banner.js +2 -1
- package/dist/components/delivery-health-banner.js.map +1 -1
- package/dist/components/dev-login-badge.js +2 -1
- package/dist/components/dev-login-badge.js.map +1 -1
- package/dist/components/extensions/extensions-view.js +22 -21
- package/dist/components/extensions/extensions-view.js.map +1 -1
- package/dist/components/guards.js +3 -2
- package/dist/components/guards.js.map +1 -1
- package/dist/components/operation-error.js +3 -2
- package/dist/components/operation-error.js.map +1 -1
- package/dist/components/playground-badge.js +2 -1
- package/dist/components/playground-badge.js.map +1 -1
- package/dist/components/project-list.js +5 -4
- package/dist/components/project-list.js.map +1 -1
- package/dist/components/project-session.js +3 -2
- package/dist/components/project-session.js.map +1 -1
- package/dist/components/project-switcher.js +4 -3
- package/dist/components/project-switcher.js.map +1 -1
- package/dist/components/redirects/redirects-module.js +3 -2
- package/dist/components/redirects/redirects-module.js.map +1 -1
- package/dist/components/references/references-panel.js +7 -6
- package/dist/components/references/references-panel.js.map +1 -1
- package/dist/components/section-nav.js +8 -5
- package/dist/components/section-nav.js.map +1 -1
- package/dist/components/section-state.js +13 -32
- package/dist/components/section-state.js.map +1 -1
- package/dist/components/settings-form.js +2 -1
- package/dist/components/settings-form.js.map +1 -1
- package/dist/components/studio-project-screen.js +3 -2
- package/dist/components/studio-project-screen.js.map +1 -1
- package/dist/components/studio-shell.js +3 -2
- package/dist/components/studio-shell.js.map +1 -1
- package/dist/components/users/users-module.js +5 -4
- package/dist/components/users/users-module.js.map +1 -1
- package/dist/components/workspace-gate.js +2 -1
- package/dist/components/workspace-gate.js.map +1 -1
- package/dist/lib/cms-views/view-model.js +3 -2
- package/dist/lib/cms-views/view-model.js.map +1 -1
- package/dist/lib/i18n/i18n.d.ts +19 -1
- package/dist/lib/i18n/i18n.js +45 -6
- package/dist/lib/i18n/i18n.js.map +1 -1
- package/dist/lib/i18n/index.d.ts +1 -1
- package/dist/lib/i18n/index.js +1 -1
- package/dist/lib/i18n/index.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +11 -4
- package/dist/lib/i18n/messages.en.js +660 -6
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/references/reference-model.js +6 -4
- package/dist/lib/references/reference-model.js.map +1 -1
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ import { Search } from 'lucide-react';
|
|
|
4
4
|
import { useMemo, useState } from 'react';
|
|
5
5
|
import { isPrimitive } from '@elytracms/core/component-registry';
|
|
6
6
|
import { componentStatus, getStudioRegistry } from '@elytracms/studio/lib/registry';
|
|
7
|
+
import { translate } from '@elytracms/studio/lib/i18n';
|
|
7
8
|
import { Code, Input, Row, Spacer, Stack, Text } from '@elytracms/studio/ui';
|
|
8
9
|
import { cn } from '@elytracms/studio/lib/utils';
|
|
9
10
|
import { ComponentStatusDot } from './component-status';
|
|
@@ -35,9 +36,9 @@ export function RegistryBrowser({ projectId, activeComponentId, }) {
|
|
|
35
36
|
}), [studio, query, namespace, category]);
|
|
36
37
|
const primitives = results.filter((m) => isPrimitive(m.id));
|
|
37
38
|
const projects = results.filter((m) => !isPrimitive(m.id));
|
|
38
|
-
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsxs("div", { className: "shrink-0 space-y-2 border-b border-border p-3", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { value: query, onChange: (e) => setQuery(e.target.value), placeholder:
|
|
39
|
-
?
|
|
40
|
-
: '
|
|
39
|
+
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsxs("div", { className: "shrink-0 space-y-2 border-b border-border p-3", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { value: query, onChange: (e) => setQuery(e.target.value), placeholder: translate('components.browser.searchPlaceholder'), className: "pl-8", "aria-label": translate('components.browser.searchAria') })] }), _jsxs(Row, { gap: "1", className: "rounded-md bg-muted/50 p-0.5", role: "group", "aria-label": translate('components.browser.namespaceAria'), children: [_jsx(NamespaceTab, { label: translate('components.browser.all'), count: primitiveCount + projectCount, active: namespace === 'all', onClick: () => selectNamespace('all') }), _jsx(NamespaceTab, { label: translate('components.browser.primitives'), count: primitiveCount, active: namespace === 'base.primitives', onClick: () => selectNamespace('base.primitives') }), _jsx(NamespaceTab, { label: translate('components.browser.project'), count: projectCount, active: namespace === 'project', onClick: () => selectNamespace('project') })] }), categories.length > 0 ? (_jsxs(Row, { gap: "1", wrap: true, children: [_jsx(CategoryChip, { label: translate('components.browser.all'), active: category === null, onClick: () => setCategory(null) }), categories.map((c) => (_jsx(CategoryChip, { label: c, active: category === c, onClick: () => setCategory(c) }, c)))] })) : null] }), _jsx("div", { className: "min-h-0 flex-1 overflow-auto p-2", children: results.length === 0 ? (_jsx(Text, { size: "sm", tone: "muted", className: "p-3", children: query.trim()
|
|
40
|
+
? translate('components.browser.noMatchQuery', { query })
|
|
41
|
+
: translate('components.browser.noMatchFilters') })) : (_jsxs(Stack, { gap: "3", children: [(namespace === 'all' || namespace === 'base.primitives') && primitives.length > 0 ? (_jsx(GroupedList, { heading: "base.primitives.*", count: primitives.length, manifests: primitives, projectId: projectId, activeComponentId: activeComponentId })) : null, (namespace === 'all' || namespace === 'project') && projects.length > 0 ? (_jsx(GroupedList, { heading: "project.*", count: projects.length, manifests: projects, projectId: projectId, activeComponentId: activeComponentId })) : null] })) })] }));
|
|
41
42
|
}
|
|
42
43
|
function NamespaceTab({ label, count, active, onClick, }) {
|
|
43
44
|
return (_jsxs("button", { type: "button", "aria-pressed": active, onClick: onClick, className: cn('flex flex-1 items-center justify-center gap-1.5 rounded-[5px] px-2 py-1 text-xs font-medium transition-colors', active ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'), children: [label, _jsx("span", { className: "font-mono text-[0.65rem] text-muted-foreground", children: count })] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry-browser.js","sourceRoot":"","sources":["../../../src/components/components/registry-browser.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router'\nimport { Search } from 'lucide-react'\nimport { useMemo, useState } from 'react'\nimport { isPrimitive } from '@elytracms/core/component-registry'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport { componentStatus, getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport { Code, Input, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { ComponentStatusDot } from './component-status'\n\ntype NamespaceFilter = 'all' | 'base.primitives' | 'project'\n\nexport function RegistryBrowser({\n projectId,\n activeComponentId,\n}: {\n projectId: string\n activeComponentId?: string\n}) {\n const studio = getStudioRegistry()\n const [query, setQuery] = useState('')\n const [namespace, setNamespace] = useState<NamespaceFilter>('all')\n const [category, setCategory] = useState<string | null>(null)\n\n const primitiveCount = studio.registry.primitives().length\n const projectCount = studio.registry.projectComponents().length\n\n // Switching namespace clears any category that doesn't exist in the new one.\n function selectNamespace(ns: NamespaceFilter) {\n setNamespace(ns)\n setCategory(null)\n }\n\n // Categories are scoped to the active namespace so every chip can yield results.\n const categories = useMemo(() => {\n const set = new Set<string>()\n for (const m of studio.registry.list({ namespace: namespace === 'all' ? undefined : namespace })) {\n if (m.category) set.add(m.category)\n }\n return [...set].sort()\n }, [studio, namespace])\n\n const results = useMemo(\n () =>\n studio.registry.list({\n query: query.trim() || undefined,\n namespace: namespace === 'all' ? undefined : namespace,\n category: category ?? undefined,\n }),\n [studio, query, namespace, category],\n )\n\n const primitives = results.filter((m) => isPrimitive(m.id))\n const projects = results.filter((m) => !isPrimitive(m.id))\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <div className=\"shrink-0 space-y-2 border-b border-border p-3\">\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search components…\"\n className=\"pl-8\"\n aria-label=\"Search components\"\n />\n </div>\n <Row gap=\"1\" className=\"rounded-md bg-muted/50 p-0.5\" role=\"group\" aria-label=\"Filter by namespace\">\n <NamespaceTab label=\"All\" count={primitiveCount + projectCount} active={namespace === 'all'} onClick={() => selectNamespace('all')} />\n <NamespaceTab label=\"Primitives\" count={primitiveCount} active={namespace === 'base.primitives'} onClick={() => selectNamespace('base.primitives')} />\n <NamespaceTab label=\"Project\" count={projectCount} active={namespace === 'project'} onClick={() => selectNamespace('project')} />\n </Row>\n {categories.length > 0 ? (\n <Row gap=\"1\" wrap>\n <CategoryChip label=\"All\" active={category === null} onClick={() => setCategory(null)} />\n {categories.map((c) => (\n <CategoryChip key={c} label={c} active={category === c} onClick={() => setCategory(c)} />\n ))}\n </Row>\n ) : null}\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-auto p-2\">\n {results.length === 0 ? (\n <Text size=\"sm\" tone=\"muted\" className=\"p-3\">\n {query.trim()\n ? `No components match “${query}”.`\n : 'No components match the selected filters.'}\n </Text>\n ) : (\n <Stack gap=\"3\">\n {(namespace === 'all' || namespace === 'base.primitives') && primitives.length > 0 ? (\n <GroupedList\n heading=\"base.primitives.*\"\n count={primitives.length}\n manifests={primitives}\n projectId={projectId}\n activeComponentId={activeComponentId}\n />\n ) : null}\n {(namespace === 'all' || namespace === 'project') && projects.length > 0 ? (\n <GroupedList\n heading=\"project.*\"\n count={projects.length}\n manifests={projects}\n projectId={projectId}\n activeComponentId={activeComponentId}\n />\n ) : null}\n </Stack>\n )}\n </div>\n </div>\n )\n}\n\nfunction NamespaceTab({\n label,\n count,\n active,\n onClick,\n}: {\n label: string\n count: number\n active: boolean\n onClick: () => void\n}) {\n return (\n <button\n type=\"button\"\n aria-pressed={active}\n onClick={onClick}\n className={cn(\n 'flex flex-1 items-center justify-center gap-1.5 rounded-[5px] px-2 py-1 text-xs font-medium transition-colors',\n active ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {label}\n <span className=\"font-mono text-[0.65rem] text-muted-foreground\">{count}</span>\n </button>\n )\n}\n\nfunction CategoryChip({ label, active, onClick }: { label: string; active: boolean; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'rounded-full border px-2 py-0.5 text-xs capitalize transition-colors',\n active\n ? 'border-primary/30 bg-primary/10 text-primary'\n : 'border-border text-muted-foreground hover:bg-muted',\n )}\n >\n {label}\n </button>\n )\n}\n\nfunction GroupedList({\n heading,\n count,\n manifests,\n projectId,\n activeComponentId,\n}: {\n heading: string\n count: number\n manifests: ComponentManifest[]\n projectId: string\n activeComponentId?: string\n}) {\n const studio = getStudioRegistry()\n return (\n <Stack gap=\"1\">\n <Row gap=\"2\" className=\"px-2\">\n <Code tone=\"muted\">{heading}</Code>\n <Spacer />\n <Text size=\"xs\" tone=\"subtle\" mono>\n {count}\n </Text>\n </Row>\n <Stack gap=\"px\">\n {manifests.map((m) => {\n const status = componentStatus(studio, m)\n const active = m.id === activeComponentId\n return (\n <Link\n key={m.id}\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: studioPath.component(m.id) }}\n aria-current={active ? 'page' : undefined}\n className={cn(\n 'flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground hover:bg-muted hover:text-foreground',\n )}\n >\n <ComponentStatusDot status={status} />\n <span className=\"min-w-0 flex-1 truncate font-medium text-foreground\">{m.title ?? m.id}</span>\n {m.category ? (\n <span className=\"shrink-0 text-[0.7rem] capitalize text-muted-foreground\">{m.category}</span>\n ) : null}\n </Link>\n )\n })}\n </Stack>\n </Stack>\n )\n}\n"]}
|
|
1
|
+
{"version":3,"file":"registry-browser.js","sourceRoot":"","sources":["../../../src/components/components/registry-browser.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Link, STUDIO_PROJECT_ROUTE, studioPath } from '@elytracms/studio/router'\nimport { Search } from 'lucide-react'\nimport { useMemo, useState } from 'react'\nimport { isPrimitive } from '@elytracms/core/component-registry'\nimport type { ComponentManifest } from '@elytracms/core/component-registry'\nimport { componentStatus, getStudioRegistry } from '@elytracms/studio/lib/registry'\nimport { translate } from '@elytracms/studio/lib/i18n'\nimport { Code, Input, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\nimport { ComponentStatusDot } from './component-status'\n\ntype NamespaceFilter = 'all' | 'base.primitives' | 'project'\n\nexport function RegistryBrowser({\n projectId,\n activeComponentId,\n}: {\n projectId: string\n activeComponentId?: string\n}) {\n const studio = getStudioRegistry()\n const [query, setQuery] = useState('')\n const [namespace, setNamespace] = useState<NamespaceFilter>('all')\n const [category, setCategory] = useState<string | null>(null)\n\n const primitiveCount = studio.registry.primitives().length\n const projectCount = studio.registry.projectComponents().length\n\n // Switching namespace clears any category that doesn't exist in the new one.\n function selectNamespace(ns: NamespaceFilter) {\n setNamespace(ns)\n setCategory(null)\n }\n\n // Categories are scoped to the active namespace so every chip can yield results.\n const categories = useMemo(() => {\n const set = new Set<string>()\n for (const m of studio.registry.list({ namespace: namespace === 'all' ? undefined : namespace })) {\n if (m.category) set.add(m.category)\n }\n return [...set].sort()\n }, [studio, namespace])\n\n const results = useMemo(\n () =>\n studio.registry.list({\n query: query.trim() || undefined,\n namespace: namespace === 'all' ? undefined : namespace,\n category: category ?? undefined,\n }),\n [studio, query, namespace, category],\n )\n\n const primitives = results.filter((m) => isPrimitive(m.id))\n const projects = results.filter((m) => !isPrimitive(m.id))\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <div className=\"shrink-0 space-y-2 border-b border-border p-3\">\n <div className=\"relative\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={translate('components.browser.searchPlaceholder')}\n className=\"pl-8\"\n aria-label={translate('components.browser.searchAria')}\n />\n </div>\n <Row gap=\"1\" className=\"rounded-md bg-muted/50 p-0.5\" role=\"group\" aria-label={translate('components.browser.namespaceAria')}>\n <NamespaceTab label={translate('components.browser.all')} count={primitiveCount + projectCount} active={namespace === 'all'} onClick={() => selectNamespace('all')} />\n <NamespaceTab label={translate('components.browser.primitives')} count={primitiveCount} active={namespace === 'base.primitives'} onClick={() => selectNamespace('base.primitives')} />\n <NamespaceTab label={translate('components.browser.project')} count={projectCount} active={namespace === 'project'} onClick={() => selectNamespace('project')} />\n </Row>\n {categories.length > 0 ? (\n <Row gap=\"1\" wrap>\n <CategoryChip label={translate('components.browser.all')} active={category === null} onClick={() => setCategory(null)} />\n {categories.map((c) => (\n <CategoryChip key={c} label={c} active={category === c} onClick={() => setCategory(c)} />\n ))}\n </Row>\n ) : null}\n </div>\n\n <div className=\"min-h-0 flex-1 overflow-auto p-2\">\n {results.length === 0 ? (\n <Text size=\"sm\" tone=\"muted\" className=\"p-3\">\n {query.trim()\n ? translate('components.browser.noMatchQuery', { query })\n : translate('components.browser.noMatchFilters')}\n </Text>\n ) : (\n <Stack gap=\"3\">\n {(namespace === 'all' || namespace === 'base.primitives') && primitives.length > 0 ? (\n <GroupedList\n heading=\"base.primitives.*\"\n count={primitives.length}\n manifests={primitives}\n projectId={projectId}\n activeComponentId={activeComponentId}\n />\n ) : null}\n {(namespace === 'all' || namespace === 'project') && projects.length > 0 ? (\n <GroupedList\n heading=\"project.*\"\n count={projects.length}\n manifests={projects}\n projectId={projectId}\n activeComponentId={activeComponentId}\n />\n ) : null}\n </Stack>\n )}\n </div>\n </div>\n )\n}\n\nfunction NamespaceTab({\n label,\n count,\n active,\n onClick,\n}: {\n label: string\n count: number\n active: boolean\n onClick: () => void\n}) {\n return (\n <button\n type=\"button\"\n aria-pressed={active}\n onClick={onClick}\n className={cn(\n 'flex flex-1 items-center justify-center gap-1.5 rounded-[5px] px-2 py-1 text-xs font-medium transition-colors',\n active ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {label}\n <span className=\"font-mono text-[0.65rem] text-muted-foreground\">{count}</span>\n </button>\n )\n}\n\nfunction CategoryChip({ label, active, onClick }: { label: string; active: boolean; onClick: () => void }) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n 'rounded-full border px-2 py-0.5 text-xs capitalize transition-colors',\n active\n ? 'border-primary/30 bg-primary/10 text-primary'\n : 'border-border text-muted-foreground hover:bg-muted',\n )}\n >\n {label}\n </button>\n )\n}\n\nfunction GroupedList({\n heading,\n count,\n manifests,\n projectId,\n activeComponentId,\n}: {\n heading: string\n count: number\n manifests: ComponentManifest[]\n projectId: string\n activeComponentId?: string\n}) {\n const studio = getStudioRegistry()\n return (\n <Stack gap=\"1\">\n <Row gap=\"2\" className=\"px-2\">\n <Code tone=\"muted\">{heading}</Code>\n <Spacer />\n <Text size=\"xs\" tone=\"subtle\" mono>\n {count}\n </Text>\n </Row>\n <Stack gap=\"px\">\n {manifests.map((m) => {\n const status = componentStatus(studio, m)\n const active = m.id === activeComponentId\n return (\n <Link\n key={m.id}\n to={STUDIO_PROJECT_ROUTE}\n params={{ projectId, _splat: studioPath.component(m.id) }}\n aria-current={active ? 'page' : undefined}\n className={cn(\n 'flex items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors',\n active ? 'bg-accent text-accent-foreground' : 'text-muted-foreground hover:bg-muted hover:text-foreground',\n )}\n >\n <ComponentStatusDot status={status} />\n <span className=\"min-w-0 flex-1 truncate font-medium text-foreground\">{m.title ?? m.id}</span>\n {m.category ? (\n <span className=\"shrink-0 text-[0.7rem] capitalize text-muted-foreground\">{m.category}</span>\n ) : null}\n </Link>\n )\n })}\n </Stack>\n </Stack>\n )\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { Rocket, X } from 'lucide-react';
|
|
4
4
|
import { Button, Row, Spacer, Text } from '@elytracms/studio/ui';
|
|
5
|
+
import { translate } from '@elytracms/studio/lib/i18n';
|
|
5
6
|
import { resolveBackendConfig } from '../lib/persistence/backend-mode';
|
|
6
7
|
import { getConvexClient, queryRef } from '../lib/persistence/convex-client';
|
|
7
8
|
import { resolveDeploymentUrl } from '../lib/workspace';
|
|
@@ -39,6 +40,6 @@ export function DeliveryHealthBanner() {
|
|
|
39
40
|
}, []);
|
|
40
41
|
if (dismissed || !missing || missing.length === 0)
|
|
41
42
|
return null;
|
|
42
|
-
return (_jsxs(Row, { gap: "2", className: "shrink-0 border-b border-warning/30 bg-warning/10 px-4 py-1.5 text-warning sm:px-6", "data-testid": "delivery-health-banner", children: [_jsx(Rocket, { className: "size-3.5 shrink-0", "aria-hidden": true }), _jsxs(Text, { size: "xs", className: "text-warning", children: ["Instant publish isn\u2019t fully configured \u2014 ", missing.join(', '), " not set on this Convex deployment. Publishes succeed, but the live site won\u2019t update until you set them (see CONNECT.md) and re-push functions."] }), _jsx(Spacer, {}), _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => setDismissed(true), "aria-label":
|
|
43
|
+
return (_jsxs(Row, { gap: "2", className: "shrink-0 border-b border-warning/30 bg-warning/10 px-4 py-1.5 text-warning sm:px-6", "data-testid": "delivery-health-banner", children: [_jsx(Rocket, { className: "size-3.5 shrink-0", "aria-hidden": true }), _jsxs(Text, { size: "xs", className: "text-warning", children: ["Instant publish isn\u2019t fully configured \u2014 ", missing.join(', '), " not set on this Convex deployment. Publishes succeed, but the live site won\u2019t update until you set them (see CONNECT.md) and re-push functions."] }), _jsx(Spacer, {}), _jsx(Button, { variant: "ghost", size: "icon-sm", onClick: () => setDismissed(true), "aria-label": translate('shell.deliveryHealth.dismiss'), title: translate('shell.deliveryHealth.dismiss'), children: _jsx(X, { "aria-hidden": true }) })] }));
|
|
43
44
|
}
|
|
44
45
|
//# sourceMappingURL=delivery-health-banner.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delivery-health-banner.js","sourceRoot":"","sources":["../../src/components/delivery-health-banner.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAA;AAG3E;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAkB,IAAI,CAAC,CAAA;IAC7D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAA;QACrC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAM;QACpC,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,eAAe,CAAC,oBAAoB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;aAC9C,KAAK,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,CAAC;aAC9C,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,IAAI,CAAC,SAAS;gBAAE,UAAU,CAAC,yBAAyB,CAAC,MAA8B,CAAC,CAAC,CAAA;QACvF,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,iEAAiE;QACnE,CAAC,CAAC,CAAA;QACJ,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;QAClB,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,IAAI,SAAS,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAE9D,OAAO,CACL,MAAC,GAAG,IACF,GAAG,EAAC,GAAG,EACP,SAAS,EAAC,oFAAoF,iBAClF,wBAAwB,aAEpC,KAAC,MAAM,IAAC,SAAS,EAAC,mBAAmB,wBAAe,EACpD,MAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,cAAc,oEACI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,6JAGvD,EACP,KAAC,MAAM,KAAG,EACV,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,SAAS,EACd,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"delivery-health-banner.js","sourceRoot":"","sources":["../../src/components/delivery-health-banner.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAC3C,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,cAAc,CAAA;AACxC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AACtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AACtE,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAA;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAA;AAG3E;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB;IAClC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAkB,IAAI,CAAC,CAAA;IAC7D,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAA;QACrC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAM;QACpC,IAAI,SAAS,GAAG,KAAK,CAAA;QACrB,eAAe,CAAC,oBAAoB,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;aAC9C,KAAK,CAAC,QAAQ,CAAC,yBAAyB,CAAC,EAAE,EAAE,CAAC;aAC9C,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;YACf,IAAI,CAAC,SAAS;gBAAE,UAAU,CAAC,yBAAyB,CAAC,MAA8B,CAAC,CAAC,CAAA;QACvF,CAAC,CAAC;aACD,KAAK,CAAC,GAAG,EAAE;YACV,iEAAiE;QACnE,CAAC,CAAC,CAAA;QACJ,OAAO,GAAG,EAAE;YACV,SAAS,GAAG,IAAI,CAAA;QAClB,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,IAAI,SAAS,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAA;IAE9D,OAAO,CACL,MAAC,GAAG,IACF,GAAG,EAAC,GAAG,EACP,SAAS,EAAC,oFAAoF,iBAClF,wBAAwB,aAEpC,KAAC,MAAM,IAAC,SAAS,EAAC,mBAAmB,wBAAe,EACpD,MAAC,IAAI,IAAC,IAAI,EAAC,IAAI,EAAC,SAAS,EAAC,cAAc,oEACI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,6JAGvD,EACP,KAAC,MAAM,KAAG,EACV,KAAC,MAAM,IACL,OAAO,EAAC,OAAO,EACf,IAAI,EAAC,SAAS,EACd,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,gBACrB,SAAS,CAAC,8BAA8B,CAAC,EACrD,KAAK,EAAE,SAAS,CAAC,8BAA8B,CAAC,YAEhD,KAAC,CAAC,0BAAe,GACV,IACL,CACP,CAAA;AACH,CAAC","sourcesContent":["import { useEffect, useState } from 'react'\nimport { Rocket, X } from 'lucide-react'\nimport { Button, Row, Spacer, Text } from '@elytracms/studio/ui'\nimport { translate } from '@elytracms/studio/lib/i18n'\nimport { resolveBackendConfig } from '../lib/persistence/backend-mode'\nimport { getConvexClient, queryRef } from '../lib/persistence/convex-client'\nimport { resolveDeploymentUrl } from '../lib/workspace'\nimport { missingInstantPublishVars } from '../lib/delivery/instant-publish'\nimport type { DeliveryConfigStatus } from '../lib/delivery/instant-publish'\n\n/**\n * EC-268: a boot-up health check for instant publish (EC-146). When the studio is\n * connected to a Convex deployment, it reads `delivery:deliveryConfig` once and, if\n * any of the delivery env vars are unset, shows a dismissible warning. Without this\n * the pipeline fails SILENTLY — a publish reports success but `scheduleRevalidate`\n * returns before scheduling (no `CANVAS_PROJECT_SCOPE`) and the live site never\n * updates. In playground mode (no backend) instant publish does not apply and the\n * banner never renders. Failure to read config is swallowed — it must never block\n * the studio.\n */\nexport function DeliveryHealthBanner() {\n const [missing, setMissing] = useState<string[] | null>(null)\n const [dismissed, setDismissed] = useState(false)\n\n useEffect(() => {\n const config = resolveBackendConfig()\n if (config.kind !== 'convex') return\n let cancelled = false\n getConvexClient(resolveDeploymentUrl(config.url))\n .query(queryRef('delivery:deliveryConfig'), {})\n .then((status) => {\n if (!cancelled) setMissing(missingInstantPublishVars(status as DeliveryConfigStatus))\n })\n .catch(() => {\n /* config unknown (older deployment, transport) — stay silent. */\n })\n return () => {\n cancelled = true\n }\n }, [])\n\n if (dismissed || !missing || missing.length === 0) return null\n\n return (\n <Row\n gap=\"2\"\n className=\"shrink-0 border-b border-warning/30 bg-warning/10 px-4 py-1.5 text-warning sm:px-6\"\n data-testid=\"delivery-health-banner\"\n >\n <Rocket className=\"size-3.5 shrink-0\" aria-hidden />\n <Text size=\"xs\" className=\"text-warning\">\n Instant publish isn’t fully configured — {missing.join(', ')} not set on this Convex\n deployment. Publishes succeed, but the live site won’t update until you set them (see\n CONNECT.md) and re-push functions.\n </Text>\n <Spacer />\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={() => setDismissed(true)}\n aria-label={translate('shell.deliveryHealth.dismiss')}\n title={translate('shell.deliveryHealth.dismiss')}\n >\n <X aria-hidden />\n </Button>\n </Row>\n )\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { KeyRound } from 'lucide-react';
|
|
3
3
|
import { Badge } from '@elytracms/studio/ui';
|
|
4
4
|
import { isDevAutoLoginActive } from '@elytracms/studio/lib/persistence';
|
|
5
|
+
import { translate } from '@elytracms/studio/lib/i18n';
|
|
5
6
|
/** Tooltip/accessible description — the studio signed in automatically. */
|
|
6
7
|
export const DEV_LOGIN_BADGE_HINT = 'Dev auto-login: the studio signed in automatically from VITE_ELYTRA_DEV_LOGIN (dev builds only). Unset it to test the real sign-in flow.';
|
|
7
8
|
/**
|
|
@@ -13,6 +14,6 @@ export const DEV_LOGIN_BADGE_HINT = 'Dev auto-login: the studio signed in automa
|
|
|
13
14
|
export function DevLoginBadge() {
|
|
14
15
|
if (!isDevAutoLoginActive())
|
|
15
16
|
return null;
|
|
16
|
-
return (_jsxs(Badge, { variant: "warning", title: DEV_LOGIN_BADGE_HINT, "data-testid": "dev-login-badge", children: [_jsx(KeyRound, { "aria-hidden": true }),
|
|
17
|
+
return (_jsxs(Badge, { variant: "warning", title: DEV_LOGIN_BADGE_HINT, "data-testid": "dev-login-badge", children: [_jsx(KeyRound, { "aria-hidden": true }), translate('shell.devLogin.badge')] }));
|
|
17
18
|
}
|
|
18
19
|
//# sourceMappingURL=dev-login-badge.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-login-badge.js","sourceRoot":"","sources":["../../src/components/dev-login-badge.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;
|
|
1
|
+
{"version":3,"file":"dev-login-badge.js","sourceRoot":"","sources":["../../src/components/dev-login-badge.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAC5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAA;AACxE,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAEtD,2EAA2E;AAC3E,MAAM,CAAC,MAAM,oBAAoB,GAC/B,0IAA0I,CAAA;AAE5I;;;;;GAKG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,IAAI,CAAA;IACxC,OAAO,CACL,MAAC,KAAK,IAAC,OAAO,EAAC,SAAS,EAAC,KAAK,EAAE,oBAAoB,iBAAc,iBAAiB,aACjF,KAAC,QAAQ,0BAAe,EACvB,SAAS,CAAC,sBAAsB,CAAC,IAC5B,CACT,CAAA;AACH,CAAC","sourcesContent":["import { KeyRound } from 'lucide-react'\nimport { Badge } from '@elytracms/studio/ui'\nimport { isDevAutoLoginActive } from '@elytracms/studio/lib/persistence'\nimport { translate } from '@elytracms/studio/lib/i18n'\n\n/** Tooltip/accessible description — the studio signed in automatically. */\nexport const DEV_LOGIN_BADGE_HINT =\n 'Dev auto-login: the studio signed in automatically from VITE_ELYTRA_DEV_LOGIN (dev builds only). Unset it to test the real sign-in flow.'\n\n/**\n * Marker for the dev-only unattended auth (see `resolveDevAutoLogin`). When the\n * studio auto-signs-in from `VITE_ELYTRA_DEV_LOGIN` in a dev build, this badge\n * is visible in the shell header so an auto-authenticated session is never\n * silent; in production builds and without the flag it renders nothing.\n */\nexport function DevLoginBadge() {\n if (!isDevAutoLoginActive()) return null\n return (\n <Badge variant=\"warning\" title={DEV_LOGIN_BADGE_HINT} data-testid=\"dev-login-badge\">\n <KeyRound aria-hidden />\n {translate('shell.devLogin.badge')}\n </Badge>\n )\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import { useMemo, useReducer, useState } from 'react';
|
|
|
3
3
|
import { Boxes, Check, Database, Download, HardDrive, Lock, Package, Puzzle, Search, Share2, LayoutTemplate, Type, Webhook, } from 'lucide-react';
|
|
4
4
|
import { BUILTIN_FIELD_TYPES, BUILTIN_SOURCE_KINDS, HOOK_POINTS, MarketplaceClient, PluginHost, privateMarketplace, publicMarketplace, } from '@elytracms/core/plugins';
|
|
5
5
|
import { Badge, Button, Code, Heading, Input, Row, Spacer, Stack, Text } from '@elytracms/studio/ui';
|
|
6
|
+
import { translate } from '@elytracms/studio/lib/i18n';
|
|
6
7
|
import { cn } from '@elytracms/studio/lib/utils';
|
|
7
8
|
/**
|
|
8
9
|
* The Extensions surface (Phase 11, EC-130–137). A live, agent-inspectable view over the
|
|
@@ -32,28 +33,28 @@ export function ExtensionsView() {
|
|
|
32
33
|
// --- Header + tabs ----------------------------------------------------------
|
|
33
34
|
function ExtensionsHeader({ tab, onTab, installedCount, marketCount, }) {
|
|
34
35
|
const tabs = [
|
|
35
|
-
{ id: 'marketplace', label: '
|
|
36
|
-
{ id: 'installed', label: '
|
|
37
|
-
{ id: 'registered', label: '
|
|
36
|
+
{ id: 'marketplace', label: translate('extensions.tab.marketplace'), count: marketCount },
|
|
37
|
+
{ id: 'installed', label: translate('extensions.tab.installed'), count: installedCount },
|
|
38
|
+
{ id: 'registered', label: translate('extensions.tab.registered') },
|
|
38
39
|
];
|
|
39
|
-
return (_jsx("div", { className: "shrink-0 border-b border-border bg-gradient-to-b from-primary/[0.04] to-transparent px-4 py-3 sm:px-6", children: _jsxs(Row, { gap: "3", children: [_jsx("span", { className: "grid size-8 shrink-0 place-items-center rounded-lg bg-primary/15 text-primary", children: _jsx(Puzzle, { className: "size-4" }) }), _jsxs(Stack, { gap: "none", className: "min-w-0", children: [_jsx(Text, { size: "sm", weight: "semibold", children:
|
|
40
|
+
return (_jsx("div", { className: "shrink-0 border-b border-border bg-gradient-to-b from-primary/[0.04] to-transparent px-4 py-3 sm:px-6", children: _jsxs(Row, { gap: "3", children: [_jsx("span", { className: "grid size-8 shrink-0 place-items-center rounded-lg bg-primary/15 text-primary", children: _jsx(Puzzle, { className: "size-4" }) }), _jsxs(Stack, { gap: "none", className: "min-w-0", children: [_jsx(Text, { size: "sm", weight: "semibold", children: translate('extensions.header.title') }), _jsx(Text, { size: "xs", tone: "subtle", children: translate('extensions.header.subtitle') })] }), _jsx(Spacer, {}), _jsx(Row, { gap: "1", className: "rounded-md bg-muted/50 p-0.5", children: tabs.map((t) => (_jsxs("button", { type: "button", "aria-pressed": tab === t.id, onClick: () => onTab(t.id), className: cn('flex items-center gap-1.5 rounded-[5px] px-3 py-1 text-sm font-medium transition-colors', tab === t.id ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'), children: [t.label, t.count !== undefined ? (_jsx("span", { className: "rounded-full bg-muted px-1.5 text-[0.7rem] font-semibold tabular-nums text-muted-foreground", children: t.count })) : null] }, t.id))) })] }) }));
|
|
40
41
|
}
|
|
41
42
|
// --- Marketplace ------------------------------------------------------------
|
|
42
43
|
function MarketplaceTab({ hits, query, onQuery, token, onToken, privateUnlocked, isInstalled, onInstall, results, }) {
|
|
43
|
-
return (_jsxs(Stack, { gap: "6", children: [_jsxs(Row, { gap: "3", wrap: true, children: [_jsxs("div", { className: "relative min-w-0 flex-1", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { value: query, onChange: (e) => onQuery(e.target.value), placeholder:
|
|
44
|
+
return (_jsxs(Stack, { gap: "6", children: [_jsxs(Row, { gap: "3", wrap: true, children: [_jsxs("div", { className: "relative min-w-0 flex-1", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { value: query, onChange: (e) => onQuery(e.target.value), placeholder: translate('extensions.search.placeholder'), className: "pl-8", "aria-label": translate('extensions.search.aria') })] }), _jsxs(Row, { gap: "2", className: "shrink-0", children: [_jsx(Lock, { className: cn('size-3.5', privateUnlocked ? 'text-success' : 'text-muted-foreground') }), _jsx(Input, { value: token, onChange: (e) => onToken(e.target.value), placeholder: translate('extensions.token.placeholder'), "aria-label": translate('extensions.token.placeholder'), className: "w-52" }), privateUnlocked ? _jsx(Badge, { variant: "success", children: translate('extensions.token.unlocked') }) : null] })] }), !privateUnlocked ? (_jsxs(Text, { size: "xs", tone: "subtle", children: ["A private registry is available. Enter its access token (hint: ", _jsx(Code, { tone: "muted", children: "acme-internal-token" }), ") to reveal private listings."] })) : null, hits.length === 0 ? (_jsx(EmptyHint, { icon: _jsx(Search, { className: "size-5" }), title: translate('extensions.empty.noMatch.title'), body: translate('extensions.empty.noMatch.body') })) : (_jsx("div", { className: "grid gap-3 sm:grid-cols-2", children: hits.map(({ registryId, listing }) => (_jsx(ListingCard, { listing: listing, registryId: registryId, installed: isInstalled(listing), result: results[listing.id], onInstall: () => onInstall(listing) }, listing.id))) }))] }));
|
|
44
45
|
}
|
|
45
46
|
function ListingCard({ listing, registryId, installed, result, onInstall, }) {
|
|
46
47
|
const failed = result && !result.ok;
|
|
47
|
-
return (_jsxs("div", { className: "flex flex-col rounded-xl border border-border bg-card/60 p-4 transition-colors hover:border-primary/40", children: [_jsxs(Row, { gap: "2", children: [_jsx("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-foreground/80", children: _jsx(KindIcon, { kind: listing.kind }) }), _jsxs(Stack, { gap: "none", className: "min-w-0", children: [_jsx(Text, { size: "sm", weight: "semibold", className: "truncate", children: listing.name }), _jsxs(Row, { gap: "1", className: "text-muted-foreground", children: [_jsx(KindBadge, { kind: listing.kind }), _jsxs(Code, { tone: "muted", children: ["v", listing.version] })] })] }), _jsx(Spacer, {}), registryId === 'acme-private' ? (_jsxs(Badge, { variant: "outline", children: [_jsx(Lock, { className: "size-3" }), " private"] })) : null] }), _jsx(Text, { size: "xs", tone: "muted", className: "mt-3 line-clamp-3 min-h-0 flex-1", children: listing.description ?? '
|
|
48
|
-
? '
|
|
49
|
-
: result?.issues[0]?.message ?? '
|
|
48
|
+
return (_jsxs("div", { className: "flex flex-col rounded-xl border border-border bg-card/60 p-4 transition-colors hover:border-primary/40", children: [_jsxs(Row, { gap: "2", children: [_jsx("span", { className: "grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-foreground/80", children: _jsx(KindIcon, { kind: listing.kind }) }), _jsxs(Stack, { gap: "none", className: "min-w-0", children: [_jsx(Text, { size: "sm", weight: "semibold", className: "truncate", children: listing.name }), _jsxs(Row, { gap: "1", className: "text-muted-foreground", children: [_jsx(KindBadge, { kind: listing.kind }), _jsxs(Code, { tone: "muted", children: ["v", listing.version] })] })] }), _jsx(Spacer, {}), registryId === 'acme-private' ? (_jsxs(Badge, { variant: "outline", children: [_jsx(Lock, { className: "size-3" }), " private"] })) : null] }), _jsx(Text, { size: "xs", tone: "muted", className: "mt-3 line-clamp-3 min-h-0 flex-1", children: listing.description ?? translate('extensions.listing.noDescription') }), listing.tags && listing.tags.length > 0 ? (_jsx(Row, { gap: "1", wrap: true, className: "mt-3", children: listing.tags.map((tag) => (_jsx("span", { className: "rounded-full bg-muted/70 px-2 py-0.5 text-[0.7rem] text-muted-foreground", children: tag }, tag))) })) : null, _jsxs(Row, { gap: "2", className: "mt-4", children: [_jsx(Text, { size: "xs", tone: "subtle", className: "truncate", children: listing.author ?? translate('extensions.listing.unknownAuthor') }), _jsx(Spacer, {}), installed ? (_jsxs(Button, { size: "sm", variant: "ghost", disabled: true, children: [_jsx(Check, {}), " ", translate('extensions.action.installed')] })) : (_jsxs(Button, { size: "sm", variant: failed ? 'destructive' : 'default', onClick: onInstall, children: [_jsx(Download, {}), " ", failed ? translate('common.retry') : translate('extensions.action.install')] }))] }), failed ? (_jsx(Text, { size: "xs", className: "mt-2 text-destructive", children: result?.blocked === 'access-denied'
|
|
49
|
+
? translate('extensions.error.accessDenied')
|
|
50
|
+
: result?.issues[0]?.message ?? translate('extensions.error.installFailed') })) : null] }));
|
|
50
51
|
}
|
|
51
52
|
// --- Installed --------------------------------------------------------------
|
|
52
53
|
function InstalledTab({ installed }) {
|
|
53
54
|
if (installed.length === 0) {
|
|
54
|
-
return (_jsx(EmptyHint, { icon: _jsx(Boxes, { className: "size-5" }), title:
|
|
55
|
+
return (_jsx(EmptyHint, { icon: _jsx(Boxes, { className: "size-5" }), title: translate('extensions.empty.installed.title'), body: translate('extensions.empty.installed.body') }));
|
|
55
56
|
}
|
|
56
|
-
return (_jsx(Stack, { gap: "3", children: installed.map((plugin) => (_jsxs("div", { className: "rounded-xl border border-border bg-card/60 p-4", children: [_jsxs(Row, { gap: "2", children: [_jsx(Package, { className: "size-4 text-primary" }), _jsx(Text, { size: "sm", weight: "semibold", children: plugin.name }), _jsxs(Code, { tone: "muted", children: ["v", plugin.version] }), _jsx(Spacer, {}), _jsx(Text, { size: "xs", tone: "subtle", children: plugin.author ?? '' })] }), plugin.description ? (_jsx(Text, { size: "xs", tone: "muted", className: "mt-2", children: plugin.description })) : null, _jsxs(Row, { gap: "2", wrap: true, className: "mt-3", children: [_jsx(ContributionChip, { icon: _jsx(Boxes, {}), label:
|
|
57
|
+
return (_jsx(Stack, { gap: "3", children: installed.map((plugin) => (_jsxs("div", { className: "rounded-xl border border-border bg-card/60 p-4", children: [_jsxs(Row, { gap: "2", children: [_jsx(Package, { className: "size-4 text-primary" }), _jsx(Text, { size: "sm", weight: "semibold", children: plugin.name }), _jsxs(Code, { tone: "muted", children: ["v", plugin.version] }), _jsx(Spacer, {}), _jsx(Text, { size: "xs", tone: "subtle", children: plugin.author ?? '' })] }), plugin.description ? (_jsx(Text, { size: "xs", tone: "muted", className: "mt-2", children: plugin.description })) : null, _jsxs(Row, { gap: "2", wrap: true, className: "mt-3", children: [_jsx(ContributionChip, { icon: _jsx(Boxes, {}), label: translate('extensions.contrib.components'), count: plugin.contributes.components }), _jsx(ContributionChip, { icon: _jsx(Type, {}), label: translate('extensions.contrib.fieldTypes'), count: plugin.contributes.fieldTypes }), _jsx(ContributionChip, { icon: _jsx(Database, {}), label: translate('extensions.contrib.dataSources'), count: plugin.contributes.dataSources }), _jsx(ContributionChip, { icon: _jsx(HardDrive, {}), label: translate('extensions.contrib.assetStorage'), count: plugin.contributes.assetStorage }), _jsx(ContributionChip, { icon: _jsx(Share2, {}), label: translate('extensions.contrib.exportTargets'), count: plugin.contributes.exportTargets }), _jsx(ContributionChip, { icon: _jsx(LayoutTemplate, {}), label: translate('extensions.contrib.templates'), count: plugin.contributes.templates }), _jsx(ContributionChip, { icon: _jsx(Webhook, {}), label: translate('extensions.contrib.hooks'), count: plugin.contributes.hooks })] })] }, plugin.id))) }));
|
|
57
58
|
}
|
|
58
59
|
function ContributionChip({ icon, label, count }) {
|
|
59
60
|
if (count === 0)
|
|
@@ -63,7 +64,7 @@ function ContributionChip({ icon, label, count }) {
|
|
|
63
64
|
// --- Registered (inspect) ---------------------------------------------------
|
|
64
65
|
function RegisteredTab({ host }) {
|
|
65
66
|
const hookPoints = host.hooks.points();
|
|
66
|
-
return (_jsxs(Stack, { gap: "6", children: [_jsx(Text, { size: "xs", tone: "subtle", children:
|
|
67
|
+
return (_jsxs(Stack, { gap: "6", children: [_jsx(Text, { size: "xs", tone: "subtle", children: translate('extensions.registered.intro') }), _jsx(InspectGroup, { icon: _jsx(Boxes, {}), title: translate('extensions.registered.components.title'), sub: "base.primitives.* + project + vendor packages", children: _jsx(ChipRow, { items: host.components.projectComponents().map((m) => m.id), empty: translate('extensions.registered.components.empty') }) }), _jsx(InspectGroup, { icon: _jsx(Type, {}), title: translate('extensions.registered.fieldTypes.title'), children: _jsx(ChipRow, { items: [...BUILTIN_FIELD_TYPES], tone: "builtin", suffix: host.fieldTypes.list().map((f) => f.kind) }) }), _jsx(InspectGroup, { icon: _jsx(Database, {}), title: translate('extensions.registered.dataSources.title'), children: _jsx(ChipRow, { items: [...BUILTIN_SOURCE_KINDS], tone: "builtin", suffix: host.dataSources.list().map((a) => a.kind) }) }), _jsx(InspectGroup, { icon: _jsx(HardDrive, {}), title: translate('extensions.registered.assetStorage.title'), children: _jsx(ChipRow, { items: host.assetStorage.list().map((a) => `${a.kind} · ${a.title}`), empty: translate('extensions.registered.assetStorage.empty') }) }), _jsx(InspectGroup, { icon: _jsx(Share2, {}), title: translate('extensions.registered.exportTargets.title'), children: _jsx(ChipRow, { items: ['next-app-router · reference'], tone: "builtin", suffix: host.exportTargets.list().map((t) => `${t.id} · ${t.title}`) }) }), _jsx(InspectGroup, { icon: _jsx(Webhook, {}), title: translate('extensions.registered.hookPoints.title'), children: _jsx(ChipRow, { items: [...HOOK_POINTS], tone: "builtin", suffix: hookPoints.flatMap((p) => host.hooks.list(p).map((t) => `${p}${t.plugin ? ` ← ${t.plugin}` : ''}`)) }) })] }));
|
|
67
68
|
}
|
|
68
69
|
function InspectGroup({ icon, title, sub, children, }) {
|
|
69
70
|
return (_jsxs(Stack, { gap: "2", children: [_jsxs(Row, { gap: "2", children: [_jsx("span", { className: "grid size-5 place-items-center text-primary [&_svg]:size-4", children: icon }), _jsx(Text, { size: "sm", weight: "semibold", children: title }), sub ? (_jsx(Text, { size: "xs", tone: "subtle", children: sub })) : null] }), children] }));
|
|
@@ -71,7 +72,7 @@ function InspectGroup({ icon, title, sub, children, }) {
|
|
|
71
72
|
function ChipRow({ items, suffix, tone, empty, }) {
|
|
72
73
|
const all = [...items.map((v) => ({ v, builtin: tone === 'builtin' })), ...(suffix ?? []).map((v) => ({ v, builtin: false }))];
|
|
73
74
|
if (all.length === 0) {
|
|
74
|
-
return (_jsx(Text, { size: "xs", tone: "subtle", children: empty ?? '
|
|
75
|
+
return (_jsx(Text, { size: "xs", tone: "subtle", children: empty ?? translate('common.none') }));
|
|
75
76
|
}
|
|
76
77
|
return (_jsx(Row, { gap: "1", wrap: true, children: all.map(({ v, builtin }) => (_jsx("span", { className: cn('rounded-md border px-2 py-0.5 font-mono text-xs', builtin
|
|
77
78
|
? 'border-border/60 bg-muted/40 text-muted-foreground'
|
|
@@ -81,14 +82,14 @@ function ChipRow({ items, suffix, tone, empty, }) {
|
|
|
81
82
|
function EmptyHint({ icon, title, body }) {
|
|
82
83
|
return (_jsxs(Stack, { gap: "2", align: "center", className: "rounded-xl border border-dashed border-border/70 px-6 py-16 text-center", children: [_jsx("span", { className: "grid size-10 place-items-center rounded-full bg-muted text-muted-foreground", children: icon }), _jsx(Heading, { level: 3, size: "h4", children: title }), _jsx(Text, { size: "sm", tone: "muted", className: "max-w-sm", children: body })] }));
|
|
83
84
|
}
|
|
84
|
-
const
|
|
85
|
-
plugin: 'plugin',
|
|
86
|
-
'component-package': '
|
|
87
|
-
'field-type': '
|
|
88
|
-
'data-source': '
|
|
89
|
-
'asset-storage': '
|
|
90
|
-
'export-target': '
|
|
91
|
-
template: 'template',
|
|
85
|
+
const KIND_LABEL_KEY = {
|
|
86
|
+
plugin: 'extensions.kind.plugin',
|
|
87
|
+
'component-package': 'extensions.kind.componentPackage',
|
|
88
|
+
'field-type': 'extensions.kind.fieldType',
|
|
89
|
+
'data-source': 'extensions.kind.dataSource',
|
|
90
|
+
'asset-storage': 'extensions.kind.assetStorage',
|
|
91
|
+
'export-target': 'extensions.kind.exportTarget',
|
|
92
|
+
template: 'extensions.kind.template',
|
|
92
93
|
};
|
|
93
94
|
function KindBadge({ kind }) {
|
|
94
95
|
const variant = kind === 'plugin'
|
|
@@ -100,7 +101,7 @@ function KindBadge({ kind }) {
|
|
|
100
101
|
: kind === 'template'
|
|
101
102
|
? 'info'
|
|
102
103
|
: 'outline';
|
|
103
|
-
return _jsx(Badge, { variant: variant, children:
|
|
104
|
+
return _jsx(Badge, { variant: variant, children: translate(KIND_LABEL_KEY[kind]) });
|
|
104
105
|
}
|
|
105
106
|
function KindIcon({ kind }) {
|
|
106
107
|
const className = 'size-4';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extensions-view.js","sourceRoot":"","sources":["../../../src/components/extensions/extensions-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useReducer, useState } from 'react'\nimport {\n Boxes,\n Check,\n Database,\n Download,\n HardDrive,\n Lock,\n Package,\n Puzzle,\n Search,\n Share2,\n LayoutTemplate,\n Type,\n Webhook,\n} from 'lucide-react'\nimport {\n BUILTIN_FIELD_TYPES,\n BUILTIN_SOURCE_KINDS,\n HOOK_POINTS,\n MarketplaceClient,\n PluginHost,\n privateMarketplace,\n publicMarketplace,\n} from '@elytracms/core/plugins'\nimport type { ExtensionKind, ExtensionListing, InstalledPlugin, MarketplaceInstallResult } from '@elytracms/core/plugins'\nimport { Badge, Button, Code, Heading, Input, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { cn } from '@elytracms/studio/lib/utils'\n\ntype Tab = 'marketplace' | 'installed' | 'registered'\n\n/**\n * The Extensions surface (Phase 11, EC-130–137). A live, agent-inspectable view over the\n * extensibility layer: browse a public + private marketplace, install plugins into a host, and\n * inspect what each surface contributes (components, field types, data sources, asset storage,\n * export targets, hooks). All state is deterministic — driven by `@elytracms/core/plugins` fixtures.\n */\nexport function ExtensionsView() {\n // One host for the session; PluginHost mutates in place, so a bump reducer drives re-render.\n const [host] = useState(() => new PluginHost())\n const [, bump] = useReducer((n: number) => n + 1, 0)\n const [tab, setTab] = useState<Tab>('marketplace')\n const [token, setToken] = useState('')\n const [query, setQuery] = useState('')\n const [results, setResults] = useState<Record<string, MarketplaceInstallResult>>({})\n\n const client = useMemo(\n () => new MarketplaceClient([publicMarketplace, privateMarketplace], token.trim() ? { 'acme-private': token.trim() } : {}),\n [token],\n )\n\n const hits = client.search(query.trim() ? { query: query.trim() } : {})\n const privateUnlocked = client.accessibleRegistries().some((r) => r.id === 'acme-private')\n const installedCount = host.list().length\n\n function install(listing: ExtensionListing) {\n const result = client.install(host, listing.id)\n setResults((prev) => ({ ...prev, [listing.id]: result }))\n bump()\n }\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <ExtensionsHeader\n tab={tab}\n onTab={setTab}\n installedCount={installedCount}\n marketCount={hits.length}\n />\n\n <div className=\"min-h-0 flex-1 overflow-auto px-4 py-5 sm:px-6\">\n <div className=\"mx-auto w-full max-w-5xl\">\n {tab === 'marketplace' ? (\n <MarketplaceTab\n hits={hits}\n query={query}\n onQuery={setQuery}\n token={token}\n onToken={setToken}\n privateUnlocked={privateUnlocked}\n isInstalled={(l) => host.isInstalled(l.plugin.id)}\n onInstall={install}\n results={results}\n />\n ) : tab === 'installed' ? (\n <InstalledTab installed={host.list()} />\n ) : (\n <RegisteredTab host={host} />\n )}\n </div>\n </div>\n </div>\n )\n}\n\n// --- Header + tabs ----------------------------------------------------------\n\nfunction ExtensionsHeader({\n tab,\n onTab,\n installedCount,\n marketCount,\n}: {\n tab: Tab\n onTab: (t: Tab) => void\n installedCount: number\n marketCount: number\n}) {\n const tabs: { id: Tab; label: string; count?: number }[] = [\n { id: 'marketplace', label: 'Marketplace', count: marketCount },\n { id: 'installed', label: 'Installed', count: installedCount },\n { id: 'registered', label: 'Registered' },\n ]\n return (\n <div className=\"shrink-0 border-b border-border bg-gradient-to-b from-primary/[0.04] to-transparent px-4 py-3 sm:px-6\">\n <Row gap=\"3\">\n <span className=\"grid size-8 shrink-0 place-items-center rounded-lg bg-primary/15 text-primary\">\n <Puzzle className=\"size-4\" />\n </span>\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\">\n Extensibility\n </Text>\n <Text size=\"xs\" tone=\"subtle\">\n Components · field types · data sources · asset storage · export targets · templates · hooks\n </Text>\n </Stack>\n <Spacer />\n <Row gap=\"1\" className=\"rounded-md bg-muted/50 p-0.5\">\n {tabs.map((t) => (\n <button\n key={t.id}\n type=\"button\"\n aria-pressed={tab === t.id}\n onClick={() => onTab(t.id)}\n className={cn(\n 'flex items-center gap-1.5 rounded-[5px] px-3 py-1 text-sm font-medium transition-colors',\n tab === t.id ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {t.label}\n {t.count !== undefined ? (\n <span className=\"rounded-full bg-muted px-1.5 text-[0.7rem] font-semibold tabular-nums text-muted-foreground\">\n {t.count}\n </span>\n ) : null}\n </button>\n ))}\n </Row>\n </Row>\n </div>\n )\n}\n\n// --- Marketplace ------------------------------------------------------------\n\nfunction MarketplaceTab({\n hits,\n query,\n onQuery,\n token,\n onToken,\n privateUnlocked,\n isInstalled,\n onInstall,\n results,\n}: {\n hits: { registryId: string; listing: ExtensionListing }[]\n query: string\n onQuery: (q: string) => void\n token: string\n onToken: (t: string) => void\n privateUnlocked: boolean\n isInstalled: (l: ExtensionListing) => boolean\n onInstall: (l: ExtensionListing) => void\n results: Record<string, MarketplaceInstallResult>\n}) {\n return (\n <Stack gap=\"6\">\n <Row gap=\"3\" wrap>\n <div className=\"relative min-w-0 flex-1\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={query}\n onChange={(e) => onQuery(e.target.value)}\n placeholder=\"Search extensions…\"\n className=\"pl-8\"\n aria-label=\"Search extensions\"\n />\n </div>\n <Row gap=\"2\" className=\"shrink-0\">\n <Lock className={cn('size-3.5', privateUnlocked ? 'text-success' : 'text-muted-foreground')} />\n <Input\n value={token}\n onChange={(e) => onToken(e.target.value)}\n placeholder=\"Private registry token\"\n aria-label=\"Private registry token\"\n className=\"w-52\"\n />\n {privateUnlocked ? <Badge variant=\"success\">unlocked</Badge> : null}\n </Row>\n </Row>\n\n {!privateUnlocked ? (\n <Text size=\"xs\" tone=\"subtle\">\n A private registry is available. Enter its access token (hint: <Code tone=\"muted\">acme-internal-token</Code>) to\n reveal private listings.\n </Text>\n ) : null}\n\n {hits.length === 0 ? (\n <EmptyHint icon={<Search className=\"size-5\" />} title=\"No extensions match\" body=\"Try a different search term.\" />\n ) : (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {hits.map(({ registryId, listing }) => (\n <ListingCard\n key={listing.id}\n listing={listing}\n registryId={registryId}\n installed={isInstalled(listing)}\n result={results[listing.id]}\n onInstall={() => onInstall(listing)}\n />\n ))}\n </div>\n )}\n </Stack>\n )\n}\n\nfunction ListingCard({\n listing,\n registryId,\n installed,\n result,\n onInstall,\n}: {\n listing: ExtensionListing\n registryId: string\n installed: boolean\n result: MarketplaceInstallResult | undefined\n onInstall: () => void\n}) {\n const failed = result && !result.ok\n return (\n <div className=\"flex flex-col rounded-xl border border-border bg-card/60 p-4 transition-colors hover:border-primary/40\">\n <Row gap=\"2\">\n <span className=\"grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-foreground/80\">\n <KindIcon kind={listing.kind} />\n </span>\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\" className=\"truncate\">\n {listing.name}\n </Text>\n <Row gap=\"1\" className=\"text-muted-foreground\">\n <KindBadge kind={listing.kind} />\n <Code tone=\"muted\">v{listing.version}</Code>\n </Row>\n </Stack>\n <Spacer />\n {registryId === 'acme-private' ? (\n <Badge variant=\"outline\">\n <Lock className=\"size-3\" /> private\n </Badge>\n ) : null}\n </Row>\n\n <Text size=\"xs\" tone=\"muted\" className=\"mt-3 line-clamp-3 min-h-0 flex-1\">\n {listing.description ?? 'No description provided.'}\n </Text>\n\n {listing.tags && listing.tags.length > 0 ? (\n <Row gap=\"1\" wrap className=\"mt-3\">\n {listing.tags.map((tag) => (\n <span key={tag} className=\"rounded-full bg-muted/70 px-2 py-0.5 text-[0.7rem] text-muted-foreground\">\n {tag}\n </span>\n ))}\n </Row>\n ) : null}\n\n <Row gap=\"2\" className=\"mt-4\">\n <Text size=\"xs\" tone=\"subtle\" className=\"truncate\">\n {listing.author ?? 'Unknown author'}\n </Text>\n <Spacer />\n {installed ? (\n <Button size=\"sm\" variant=\"ghost\" disabled>\n <Check /> Installed\n </Button>\n ) : (\n <Button size=\"sm\" variant={failed ? 'destructive' : 'default'} onClick={onInstall}>\n <Download /> {failed ? 'Retry' : 'Install'}\n </Button>\n )}\n </Row>\n\n {failed ? (\n <Text size=\"xs\" className=\"mt-2 text-destructive\">\n {result?.blocked === 'access-denied'\n ? 'Access denied — a valid token is required.'\n : result?.issues[0]?.message ?? 'Installation failed.'}\n </Text>\n ) : null}\n </div>\n )\n}\n\n// --- Installed --------------------------------------------------------------\n\nfunction InstalledTab({ installed }: { installed: InstalledPlugin[] }) {\n if (installed.length === 0) {\n return (\n <EmptyHint\n icon={<Boxes className=\"size-5\" />}\n title=\"Nothing installed yet\"\n body=\"Install an extension from the marketplace to see what it contributes here.\"\n />\n )\n }\n return (\n <Stack gap=\"3\">\n {installed.map((plugin) => (\n <div key={plugin.id} className=\"rounded-xl border border-border bg-card/60 p-4\">\n <Row gap=\"2\">\n <Package className=\"size-4 text-primary\" />\n <Text size=\"sm\" weight=\"semibold\">\n {plugin.name}\n </Text>\n <Code tone=\"muted\">v{plugin.version}</Code>\n <Spacer />\n <Text size=\"xs\" tone=\"subtle\">\n {plugin.author ?? ''}\n </Text>\n </Row>\n {plugin.description ? (\n <Text size=\"xs\" tone=\"muted\" className=\"mt-2\">\n {plugin.description}\n </Text>\n ) : null}\n <Row gap=\"2\" wrap className=\"mt-3\">\n <ContributionChip icon={<Boxes />} label=\"components\" count={plugin.contributes.components} />\n <ContributionChip icon={<Type />} label=\"field types\" count={plugin.contributes.fieldTypes} />\n <ContributionChip icon={<Database />} label=\"data sources\" count={plugin.contributes.dataSources} />\n <ContributionChip icon={<HardDrive />} label=\"asset storage\" count={plugin.contributes.assetStorage} />\n <ContributionChip icon={<Share2 />} label=\"export targets\" count={plugin.contributes.exportTargets} />\n <ContributionChip icon={<LayoutTemplate />} label=\"templates\" count={plugin.contributes.templates} />\n <ContributionChip icon={<Webhook />} label=\"hooks\" count={plugin.contributes.hooks} />\n </Row>\n </div>\n ))}\n </Stack>\n )\n}\n\nfunction ContributionChip({ icon, label, count }: { icon: React.ReactNode; label: string; count: number }) {\n if (count === 0) return null\n return (\n <span className=\"inline-flex items-center gap-1.5 rounded-md border border-border/60 bg-muted/40 px-2 py-1 text-xs text-muted-foreground\">\n <span className=\"grid size-3.5 place-items-center text-primary [&_svg]:size-3.5\">{icon}</span>\n <span className=\"font-semibold tabular-nums text-foreground\">{count}</span>\n {label}\n </span>\n )\n}\n\n// --- Registered (inspect) ---------------------------------------------------\n\nfunction RegisteredTab({ host }: { host: PluginHost }) {\n const hookPoints = host.hooks.points()\n return (\n <Stack gap=\"6\">\n <Text size=\"xs\" tone=\"subtle\">\n Live registries on the plugin host. Built-in capabilities are always present; installing an extension adds to\n them.\n </Text>\n\n <InspectGroup icon={<Boxes />} title=\"Components\" sub=\"base.primitives.* + project + vendor packages\">\n <ChipRow items={host.components.projectComponents().map((m) => m.id)} empty=\"No project components registered.\" />\n </InspectGroup>\n\n <InspectGroup icon={<Type />} title=\"Field types\">\n <ChipRow\n items={[...BUILTIN_FIELD_TYPES]}\n tone=\"builtin\"\n suffix={host.fieldTypes.list().map((f) => f.kind)}\n />\n </InspectGroup>\n\n <InspectGroup icon={<Database />} title=\"Data source kinds\">\n <ChipRow items={[...BUILTIN_SOURCE_KINDS]} tone=\"builtin\" suffix={host.dataSources.list().map((a) => a.kind)} />\n </InspectGroup>\n\n <InspectGroup icon={<HardDrive />} title=\"Asset storage backends\">\n <ChipRow items={host.assetStorage.list().map((a) => `${a.kind} · ${a.title}`)} empty=\"No storage adapters installed.\" />\n </InspectGroup>\n\n <InspectGroup icon={<Share2 />} title=\"Export targets\">\n <ChipRow\n items={['next-app-router · reference']}\n tone=\"builtin\"\n suffix={host.exportTargets.list().map((t) => `${t.id} · ${t.title}`)}\n />\n </InspectGroup>\n\n <InspectGroup icon={<Webhook />} title=\"Hook points\">\n <ChipRow\n items={[...HOOK_POINTS]}\n tone=\"builtin\"\n suffix={hookPoints.flatMap((p) => host.hooks.list(p).map((t) => `${p}${t.plugin ? ` ← ${t.plugin}` : ''}`))}\n />\n </InspectGroup>\n </Stack>\n )\n}\n\nfunction InspectGroup({\n icon,\n title,\n sub,\n children,\n}: {\n icon: React.ReactNode\n title: string\n sub?: string\n children: React.ReactNode\n}) {\n return (\n <Stack gap=\"2\">\n <Row gap=\"2\">\n <span className=\"grid size-5 place-items-center text-primary [&_svg]:size-4\">{icon}</span>\n <Text size=\"sm\" weight=\"semibold\">\n {title}\n </Text>\n {sub ? (\n <Text size=\"xs\" tone=\"subtle\">\n {sub}\n </Text>\n ) : null}\n </Row>\n {children}\n </Stack>\n )\n}\n\nfunction ChipRow({\n items,\n suffix,\n tone,\n empty,\n}: {\n items: string[]\n suffix?: string[]\n tone?: 'builtin'\n empty?: string\n}) {\n const all = [...items.map((v) => ({ v, builtin: tone === 'builtin' })), ...(suffix ?? []).map((v) => ({ v, builtin: false }))]\n if (all.length === 0) {\n return (\n <Text size=\"xs\" tone=\"subtle\">\n {empty ?? 'None.'}\n </Text>\n )\n }\n return (\n <Row gap=\"1\" wrap>\n {all.map(({ v, builtin }) => (\n <span\n key={v}\n className={cn(\n 'rounded-md border px-2 py-0.5 font-mono text-xs',\n builtin\n ? 'border-border/60 bg-muted/40 text-muted-foreground'\n : 'border-primary/30 bg-primary/10 text-primary',\n )}\n >\n {v}\n </span>\n ))}\n </Row>\n )\n}\n\n// --- Shared bits -------------------------------------------------------------\n\nfunction EmptyHint({ icon, title, body }: { icon: React.ReactNode; title: string; body: string }) {\n return (\n <Stack gap=\"2\" align=\"center\" className=\"rounded-xl border border-dashed border-border/70 px-6 py-16 text-center\">\n <span className=\"grid size-10 place-items-center rounded-full bg-muted text-muted-foreground\">{icon}</span>\n <Heading level={3} size=\"h4\">\n {title}\n </Heading>\n <Text size=\"sm\" tone=\"muted\" className=\"max-w-sm\">\n {body}\n </Text>\n </Stack>\n )\n}\n\nconst KIND_LABEL: Record<ExtensionKind, string> = {\n plugin: 'plugin',\n 'component-package': 'components',\n 'field-type': 'field type',\n 'data-source': 'data source',\n 'asset-storage': 'asset storage',\n 'export-target': 'export target',\n template: 'template',\n}\n\nfunction KindBadge({ kind }: { kind: ExtensionKind }) {\n const variant =\n kind === 'plugin'\n ? 'primary'\n : kind === 'field-type'\n ? 'success'\n : kind === 'data-source'\n ? 'warning'\n : kind === 'template'\n ? 'info'\n : 'outline'\n return <Badge variant={variant}>{KIND_LABEL[kind]}</Badge>\n}\n\nfunction KindIcon({ kind }: { kind: ExtensionKind }) {\n const className = 'size-4'\n switch (kind) {\n case 'plugin':\n return <Puzzle className={className} />\n case 'component-package':\n return <Boxes className={className} />\n case 'field-type':\n return <Type className={className} />\n case 'data-source':\n return <Database className={className} />\n case 'asset-storage':\n return <HardDrive className={className} />\n case 'export-target':\n return <Share2 className={className} />\n case 'template':\n return <LayoutTemplate className={className} />\n default:\n return <Package className={className} />\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"extensions-view.js","sourceRoot":"","sources":["../../../src/components/extensions/extensions-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useMemo, useReducer, useState } from 'react'\nimport {\n Boxes,\n Check,\n Database,\n Download,\n HardDrive,\n Lock,\n Package,\n Puzzle,\n Search,\n Share2,\n LayoutTemplate,\n Type,\n Webhook,\n} from 'lucide-react'\nimport {\n BUILTIN_FIELD_TYPES,\n BUILTIN_SOURCE_KINDS,\n HOOK_POINTS,\n MarketplaceClient,\n PluginHost,\n privateMarketplace,\n publicMarketplace,\n} from '@elytracms/core/plugins'\nimport type { ExtensionKind, ExtensionListing, InstalledPlugin, MarketplaceInstallResult } from '@elytracms/core/plugins'\nimport { Badge, Button, Code, Heading, Input, Row, Spacer, Stack, Text } from '@elytracms/studio/ui'\nimport { translate } from '@elytracms/studio/lib/i18n'\nimport { cn } from '@elytracms/studio/lib/utils'\n\ntype Tab = 'marketplace' | 'installed' | 'registered'\n\n/**\n * The Extensions surface (Phase 11, EC-130–137). A live, agent-inspectable view over the\n * extensibility layer: browse a public + private marketplace, install plugins into a host, and\n * inspect what each surface contributes (components, field types, data sources, asset storage,\n * export targets, hooks). All state is deterministic — driven by `@elytracms/core/plugins` fixtures.\n */\nexport function ExtensionsView() {\n // One host for the session; PluginHost mutates in place, so a bump reducer drives re-render.\n const [host] = useState(() => new PluginHost())\n const [, bump] = useReducer((n: number) => n + 1, 0)\n const [tab, setTab] = useState<Tab>('marketplace')\n const [token, setToken] = useState('')\n const [query, setQuery] = useState('')\n const [results, setResults] = useState<Record<string, MarketplaceInstallResult>>({})\n\n const client = useMemo(\n () => new MarketplaceClient([publicMarketplace, privateMarketplace], token.trim() ? { 'acme-private': token.trim() } : {}),\n [token],\n )\n\n const hits = client.search(query.trim() ? { query: query.trim() } : {})\n const privateUnlocked = client.accessibleRegistries().some((r) => r.id === 'acme-private')\n const installedCount = host.list().length\n\n function install(listing: ExtensionListing) {\n const result = client.install(host, listing.id)\n setResults((prev) => ({ ...prev, [listing.id]: result }))\n bump()\n }\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\">\n <ExtensionsHeader\n tab={tab}\n onTab={setTab}\n installedCount={installedCount}\n marketCount={hits.length}\n />\n\n <div className=\"min-h-0 flex-1 overflow-auto px-4 py-5 sm:px-6\">\n <div className=\"mx-auto w-full max-w-5xl\">\n {tab === 'marketplace' ? (\n <MarketplaceTab\n hits={hits}\n query={query}\n onQuery={setQuery}\n token={token}\n onToken={setToken}\n privateUnlocked={privateUnlocked}\n isInstalled={(l) => host.isInstalled(l.plugin.id)}\n onInstall={install}\n results={results}\n />\n ) : tab === 'installed' ? (\n <InstalledTab installed={host.list()} />\n ) : (\n <RegisteredTab host={host} />\n )}\n </div>\n </div>\n </div>\n )\n}\n\n// --- Header + tabs ----------------------------------------------------------\n\nfunction ExtensionsHeader({\n tab,\n onTab,\n installedCount,\n marketCount,\n}: {\n tab: Tab\n onTab: (t: Tab) => void\n installedCount: number\n marketCount: number\n}) {\n const tabs: { id: Tab; label: string; count?: number }[] = [\n { id: 'marketplace', label: translate('extensions.tab.marketplace'), count: marketCount },\n { id: 'installed', label: translate('extensions.tab.installed'), count: installedCount },\n { id: 'registered', label: translate('extensions.tab.registered') },\n ]\n return (\n <div className=\"shrink-0 border-b border-border bg-gradient-to-b from-primary/[0.04] to-transparent px-4 py-3 sm:px-6\">\n <Row gap=\"3\">\n <span className=\"grid size-8 shrink-0 place-items-center rounded-lg bg-primary/15 text-primary\">\n <Puzzle className=\"size-4\" />\n </span>\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\">\n {translate('extensions.header.title')}\n </Text>\n <Text size=\"xs\" tone=\"subtle\">\n {translate('extensions.header.subtitle')}\n </Text>\n </Stack>\n <Spacer />\n <Row gap=\"1\" className=\"rounded-md bg-muted/50 p-0.5\">\n {tabs.map((t) => (\n <button\n key={t.id}\n type=\"button\"\n aria-pressed={tab === t.id}\n onClick={() => onTab(t.id)}\n className={cn(\n 'flex items-center gap-1.5 rounded-[5px] px-3 py-1 text-sm font-medium transition-colors',\n tab === t.id ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground',\n )}\n >\n {t.label}\n {t.count !== undefined ? (\n <span className=\"rounded-full bg-muted px-1.5 text-[0.7rem] font-semibold tabular-nums text-muted-foreground\">\n {t.count}\n </span>\n ) : null}\n </button>\n ))}\n </Row>\n </Row>\n </div>\n )\n}\n\n// --- Marketplace ------------------------------------------------------------\n\nfunction MarketplaceTab({\n hits,\n query,\n onQuery,\n token,\n onToken,\n privateUnlocked,\n isInstalled,\n onInstall,\n results,\n}: {\n hits: { registryId: string; listing: ExtensionListing }[]\n query: string\n onQuery: (q: string) => void\n token: string\n onToken: (t: string) => void\n privateUnlocked: boolean\n isInstalled: (l: ExtensionListing) => boolean\n onInstall: (l: ExtensionListing) => void\n results: Record<string, MarketplaceInstallResult>\n}) {\n return (\n <Stack gap=\"6\">\n <Row gap=\"3\" wrap>\n <div className=\"relative min-w-0 flex-1\">\n <Search className=\"pointer-events-none absolute left-2.5 top-1/2 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n value={query}\n onChange={(e) => onQuery(e.target.value)}\n placeholder={translate('extensions.search.placeholder')}\n className=\"pl-8\"\n aria-label={translate('extensions.search.aria')}\n />\n </div>\n <Row gap=\"2\" className=\"shrink-0\">\n <Lock className={cn('size-3.5', privateUnlocked ? 'text-success' : 'text-muted-foreground')} />\n <Input\n value={token}\n onChange={(e) => onToken(e.target.value)}\n placeholder={translate('extensions.token.placeholder')}\n aria-label={translate('extensions.token.placeholder')}\n className=\"w-52\"\n />\n {privateUnlocked ? <Badge variant=\"success\">{translate('extensions.token.unlocked')}</Badge> : null}\n </Row>\n </Row>\n\n {!privateUnlocked ? (\n <Text size=\"xs\" tone=\"subtle\">\n A private registry is available. Enter its access token (hint: <Code tone=\"muted\">acme-internal-token</Code>) to\n reveal private listings.\n </Text>\n ) : null}\n\n {hits.length === 0 ? (\n <EmptyHint\n icon={<Search className=\"size-5\" />}\n title={translate('extensions.empty.noMatch.title')}\n body={translate('extensions.empty.noMatch.body')}\n />\n ) : (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {hits.map(({ registryId, listing }) => (\n <ListingCard\n key={listing.id}\n listing={listing}\n registryId={registryId}\n installed={isInstalled(listing)}\n result={results[listing.id]}\n onInstall={() => onInstall(listing)}\n />\n ))}\n </div>\n )}\n </Stack>\n )\n}\n\nfunction ListingCard({\n listing,\n registryId,\n installed,\n result,\n onInstall,\n}: {\n listing: ExtensionListing\n registryId: string\n installed: boolean\n result: MarketplaceInstallResult | undefined\n onInstall: () => void\n}) {\n const failed = result && !result.ok\n return (\n <div className=\"flex flex-col rounded-xl border border-border bg-card/60 p-4 transition-colors hover:border-primary/40\">\n <Row gap=\"2\">\n <span className=\"grid size-9 shrink-0 place-items-center rounded-lg bg-muted text-foreground/80\">\n <KindIcon kind={listing.kind} />\n </span>\n <Stack gap=\"none\" className=\"min-w-0\">\n <Text size=\"sm\" weight=\"semibold\" className=\"truncate\">\n {listing.name}\n </Text>\n <Row gap=\"1\" className=\"text-muted-foreground\">\n <KindBadge kind={listing.kind} />\n <Code tone=\"muted\">v{listing.version}</Code>\n </Row>\n </Stack>\n <Spacer />\n {registryId === 'acme-private' ? (\n <Badge variant=\"outline\">\n <Lock className=\"size-3\" /> private\n </Badge>\n ) : null}\n </Row>\n\n <Text size=\"xs\" tone=\"muted\" className=\"mt-3 line-clamp-3 min-h-0 flex-1\">\n {listing.description ?? translate('extensions.listing.noDescription')}\n </Text>\n\n {listing.tags && listing.tags.length > 0 ? (\n <Row gap=\"1\" wrap className=\"mt-3\">\n {listing.tags.map((tag) => (\n <span key={tag} className=\"rounded-full bg-muted/70 px-2 py-0.5 text-[0.7rem] text-muted-foreground\">\n {tag}\n </span>\n ))}\n </Row>\n ) : null}\n\n <Row gap=\"2\" className=\"mt-4\">\n <Text size=\"xs\" tone=\"subtle\" className=\"truncate\">\n {listing.author ?? translate('extensions.listing.unknownAuthor')}\n </Text>\n <Spacer />\n {installed ? (\n <Button size=\"sm\" variant=\"ghost\" disabled>\n <Check /> {translate('extensions.action.installed')}\n </Button>\n ) : (\n <Button size=\"sm\" variant={failed ? 'destructive' : 'default'} onClick={onInstall}>\n <Download /> {failed ? translate('common.retry') : translate('extensions.action.install')}\n </Button>\n )}\n </Row>\n\n {failed ? (\n <Text size=\"xs\" className=\"mt-2 text-destructive\">\n {result?.blocked === 'access-denied'\n ? translate('extensions.error.accessDenied')\n : result?.issues[0]?.message ?? translate('extensions.error.installFailed')}\n </Text>\n ) : null}\n </div>\n )\n}\n\n// --- Installed --------------------------------------------------------------\n\nfunction InstalledTab({ installed }: { installed: InstalledPlugin[] }) {\n if (installed.length === 0) {\n return (\n <EmptyHint\n icon={<Boxes className=\"size-5\" />}\n title={translate('extensions.empty.installed.title')}\n body={translate('extensions.empty.installed.body')}\n />\n )\n }\n return (\n <Stack gap=\"3\">\n {installed.map((plugin) => (\n <div key={plugin.id} className=\"rounded-xl border border-border bg-card/60 p-4\">\n <Row gap=\"2\">\n <Package className=\"size-4 text-primary\" />\n <Text size=\"sm\" weight=\"semibold\">\n {plugin.name}\n </Text>\n <Code tone=\"muted\">v{plugin.version}</Code>\n <Spacer />\n <Text size=\"xs\" tone=\"subtle\">\n {plugin.author ?? ''}\n </Text>\n </Row>\n {plugin.description ? (\n <Text size=\"xs\" tone=\"muted\" className=\"mt-2\">\n {plugin.description}\n </Text>\n ) : null}\n <Row gap=\"2\" wrap className=\"mt-3\">\n <ContributionChip icon={<Boxes />} label={translate('extensions.contrib.components')} count={plugin.contributes.components} />\n <ContributionChip icon={<Type />} label={translate('extensions.contrib.fieldTypes')} count={plugin.contributes.fieldTypes} />\n <ContributionChip icon={<Database />} label={translate('extensions.contrib.dataSources')} count={plugin.contributes.dataSources} />\n <ContributionChip icon={<HardDrive />} label={translate('extensions.contrib.assetStorage')} count={plugin.contributes.assetStorage} />\n <ContributionChip icon={<Share2 />} label={translate('extensions.contrib.exportTargets')} count={plugin.contributes.exportTargets} />\n <ContributionChip icon={<LayoutTemplate />} label={translate('extensions.contrib.templates')} count={plugin.contributes.templates} />\n <ContributionChip icon={<Webhook />} label={translate('extensions.contrib.hooks')} count={plugin.contributes.hooks} />\n </Row>\n </div>\n ))}\n </Stack>\n )\n}\n\nfunction ContributionChip({ icon, label, count }: { icon: React.ReactNode; label: string; count: number }) {\n if (count === 0) return null\n return (\n <span className=\"inline-flex items-center gap-1.5 rounded-md border border-border/60 bg-muted/40 px-2 py-1 text-xs text-muted-foreground\">\n <span className=\"grid size-3.5 place-items-center text-primary [&_svg]:size-3.5\">{icon}</span>\n <span className=\"font-semibold tabular-nums text-foreground\">{count}</span>\n {label}\n </span>\n )\n}\n\n// --- Registered (inspect) ---------------------------------------------------\n\nfunction RegisteredTab({ host }: { host: PluginHost }) {\n const hookPoints = host.hooks.points()\n return (\n <Stack gap=\"6\">\n <Text size=\"xs\" tone=\"subtle\">\n {translate('extensions.registered.intro')}\n </Text>\n\n <InspectGroup icon={<Boxes />} title={translate('extensions.registered.components.title')} sub=\"base.primitives.* + project + vendor packages\">\n <ChipRow items={host.components.projectComponents().map((m) => m.id)} empty={translate('extensions.registered.components.empty')} />\n </InspectGroup>\n\n <InspectGroup icon={<Type />} title={translate('extensions.registered.fieldTypes.title')}>\n <ChipRow\n items={[...BUILTIN_FIELD_TYPES]}\n tone=\"builtin\"\n suffix={host.fieldTypes.list().map((f) => f.kind)}\n />\n </InspectGroup>\n\n <InspectGroup icon={<Database />} title={translate('extensions.registered.dataSources.title')}>\n <ChipRow items={[...BUILTIN_SOURCE_KINDS]} tone=\"builtin\" suffix={host.dataSources.list().map((a) => a.kind)} />\n </InspectGroup>\n\n <InspectGroup icon={<HardDrive />} title={translate('extensions.registered.assetStorage.title')}>\n <ChipRow items={host.assetStorage.list().map((a) => `${a.kind} · ${a.title}`)} empty={translate('extensions.registered.assetStorage.empty')} />\n </InspectGroup>\n\n <InspectGroup icon={<Share2 />} title={translate('extensions.registered.exportTargets.title')}>\n <ChipRow\n items={['next-app-router · reference']}\n tone=\"builtin\"\n suffix={host.exportTargets.list().map((t) => `${t.id} · ${t.title}`)}\n />\n </InspectGroup>\n\n <InspectGroup icon={<Webhook />} title={translate('extensions.registered.hookPoints.title')}>\n <ChipRow\n items={[...HOOK_POINTS]}\n tone=\"builtin\"\n suffix={hookPoints.flatMap((p) => host.hooks.list(p).map((t) => `${p}${t.plugin ? ` ← ${t.plugin}` : ''}`))}\n />\n </InspectGroup>\n </Stack>\n )\n}\n\nfunction InspectGroup({\n icon,\n title,\n sub,\n children,\n}: {\n icon: React.ReactNode\n title: string\n sub?: string\n children: React.ReactNode\n}) {\n return (\n <Stack gap=\"2\">\n <Row gap=\"2\">\n <span className=\"grid size-5 place-items-center text-primary [&_svg]:size-4\">{icon}</span>\n <Text size=\"sm\" weight=\"semibold\">\n {title}\n </Text>\n {sub ? (\n <Text size=\"xs\" tone=\"subtle\">\n {sub}\n </Text>\n ) : null}\n </Row>\n {children}\n </Stack>\n )\n}\n\nfunction ChipRow({\n items,\n suffix,\n tone,\n empty,\n}: {\n items: string[]\n suffix?: string[]\n tone?: 'builtin'\n empty?: string\n}) {\n const all = [...items.map((v) => ({ v, builtin: tone === 'builtin' })), ...(suffix ?? []).map((v) => ({ v, builtin: false }))]\n if (all.length === 0) {\n return (\n <Text size=\"xs\" tone=\"subtle\">\n {empty ?? translate('common.none')}\n </Text>\n )\n }\n return (\n <Row gap=\"1\" wrap>\n {all.map(({ v, builtin }) => (\n <span\n key={v}\n className={cn(\n 'rounded-md border px-2 py-0.5 font-mono text-xs',\n builtin\n ? 'border-border/60 bg-muted/40 text-muted-foreground'\n : 'border-primary/30 bg-primary/10 text-primary',\n )}\n >\n {v}\n </span>\n ))}\n </Row>\n )\n}\n\n// --- Shared bits -------------------------------------------------------------\n\nfunction EmptyHint({ icon, title, body }: { icon: React.ReactNode; title: string; body: string }) {\n return (\n <Stack gap=\"2\" align=\"center\" className=\"rounded-xl border border-dashed border-border/70 px-6 py-16 text-center\">\n <span className=\"grid size-10 place-items-center rounded-full bg-muted text-muted-foreground\">{icon}</span>\n <Heading level={3} size=\"h4\">\n {title}\n </Heading>\n <Text size=\"sm\" tone=\"muted\" className=\"max-w-sm\">\n {body}\n </Text>\n </Stack>\n )\n}\n\nconst KIND_LABEL_KEY: Record<ExtensionKind, string> = {\n plugin: 'extensions.kind.plugin',\n 'component-package': 'extensions.kind.componentPackage',\n 'field-type': 'extensions.kind.fieldType',\n 'data-source': 'extensions.kind.dataSource',\n 'asset-storage': 'extensions.kind.assetStorage',\n 'export-target': 'extensions.kind.exportTarget',\n template: 'extensions.kind.template',\n}\n\nfunction KindBadge({ kind }: { kind: ExtensionKind }) {\n const variant =\n kind === 'plugin'\n ? 'primary'\n : kind === 'field-type'\n ? 'success'\n : kind === 'data-source'\n ? 'warning'\n : kind === 'template'\n ? 'info'\n : 'outline'\n return <Badge variant={variant}>{translate(KIND_LABEL_KEY[kind])}</Badge>\n}\n\nfunction KindIcon({ kind }: { kind: ExtensionKind }) {\n const className = 'size-4'\n switch (kind) {\n case 'plugin':\n return <Puzzle className={className} />\n case 'component-package':\n return <Boxes className={className} />\n case 'field-type':\n return <Type className={className} />\n case 'data-source':\n return <Database className={className} />\n case 'asset-storage':\n return <HardDrive className={className} />\n case 'export-target':\n return <Share2 className={className} />\n case 'template':\n return <LayoutTemplate className={className} />\n default:\n return <Package className={className} />\n }\n}\n"]}
|
|
@@ -3,12 +3,13 @@ import { useBlocker } from '@elytracms/studio/router';
|
|
|
3
3
|
import { TriangleAlert } from 'lucide-react';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
import { Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, Row, } from '@elytracms/studio/ui';
|
|
6
|
+
import { translate } from '@elytracms/studio/lib/i18n';
|
|
6
7
|
/**
|
|
7
8
|
* Reusable route-transition + unsaved-change guard (brief §8.1, §8.7). Blocks
|
|
8
9
|
* in-app navigation (and the browser unload) while `when` is true, then offers
|
|
9
10
|
* save / discard / cancel. Used by Settings now; reusable in the Builder later.
|
|
10
11
|
*/
|
|
11
|
-
export function UnsavedChangesGuard({ when, onSave, title = '
|
|
12
|
+
export function UnsavedChangesGuard({ when, onSave, title = translate('shell.unsavedChanges.title'), description = translate('shell.unsavedChanges.body'), saveLabel = translate('common.saveChanges'), }) {
|
|
12
13
|
const { status, proceed, reset } = useBlocker({
|
|
13
14
|
shouldBlockFn: () => when,
|
|
14
15
|
enableBeforeUnload: () => when,
|
|
@@ -29,6 +30,6 @@ export function UnsavedChangesGuard({ when, onSave, title = 'Unsaved changes', d
|
|
|
29
30
|
setSaving(false);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
return (_jsx(Dialog, { open: blocked, onOpenChange: (open) => (!open ? reset?.() : undefined), children: _jsxs(DialogContent, { className: "max-w-md", children: [_jsxs(DialogHeader, { children: [_jsxs(Row, { gap: "2", children: [_jsx("span", { className: "grid size-8 place-items-center rounded-lg border border-warning/30 bg-warning/10 text-warning", children: _jsx(TriangleAlert, { className: "size-4" }) }), _jsx(DialogTitle, { children: title })] }), _jsx(DialogDescription, { className: "pt-1", children: description })] }), _jsxs(DialogFooter, { className: "flex-col-reverse gap-2 sm:flex-row sm:justify-between", children: [_jsx(Button, { variant: "ghost", onClick: () => reset?.(), disabled: saving, children:
|
|
33
|
+
return (_jsx(Dialog, { open: blocked, onOpenChange: (open) => (!open ? reset?.() : undefined), children: _jsxs(DialogContent, { className: "max-w-md", children: [_jsxs(DialogHeader, { children: [_jsxs(Row, { gap: "2", children: [_jsx("span", { className: "grid size-8 place-items-center rounded-lg border border-warning/30 bg-warning/10 text-warning", children: _jsx(TriangleAlert, { className: "size-4" }) }), _jsx(DialogTitle, { children: title })] }), _jsx(DialogDescription, { className: "pt-1", children: description })] }), _jsxs(DialogFooter, { className: "flex-col-reverse gap-2 sm:flex-row sm:justify-between", children: [_jsx(Button, { variant: "ghost", onClick: () => reset?.(), disabled: saving, children: translate('common.cancel') }), _jsxs(Row, { gap: "2", justify: "end", children: [_jsx(Button, { variant: "outline", onClick: () => proceed?.(), disabled: saving, children: translate('common.discard') }), _jsx(Button, { onClick: handleSave, disabled: saving, children: saving ? translate('shell.unsavedChanges.saving') : saveLabel })] })] })] }) }));
|
|
33
34
|
}
|
|
34
35
|
//# sourceMappingURL=guards.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/components/guards.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EACL,MAAM,EACN,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,GAAG,GACJ,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"guards.js","sourceRoot":"","sources":["../../src/components/guards.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAChC,OAAO,EACL,MAAM,EACN,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,GAAG,GACJ,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAetD;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,IAAI,EACJ,MAAM,EACN,KAAK,GAAG,SAAS,CAAC,4BAA4B,CAAC,EAC/C,WAAW,GAAG,SAAS,CAAC,2BAA2B,CAAC,EACpD,SAAS,GAAG,SAAS,CAAC,oBAAoB,CAAC,GAClB;IACzB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC;QAC5C,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;QACzB,kBAAkB,EAAE,GAAG,EAAE,CAAC,IAAI;QAC9B,YAAY,EAAE,IAAI;KACnB,CAAC,CAAA;IACF,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAG,MAAM,KAAK,SAAS,CAAA;IAEpC,KAAK,UAAU,UAAU;QACvB,SAAS,CAAC,IAAI,CAAC,CAAA;QACf,IAAI,CAAC;YACH,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAA;YACrC,IAAI,EAAE;gBAAE,OAAO,EAAE,EAAE,CAAA;;gBACd,KAAK,EAAE,EAAE,CAAA;QAChB,CAAC;gBAAS,CAAC;YACT,SAAS,CAAC,KAAK,CAAC,CAAA;QAClB,CAAC;IACH,CAAC;IAED,OAAO,CACL,KAAC,MAAM,IAAC,IAAI,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,YAC5E,MAAC,aAAa,IAAC,SAAS,EAAC,UAAU,aACjC,MAAC,YAAY,eACX,MAAC,GAAG,IAAC,GAAG,EAAC,GAAG,aACV,eAAM,SAAS,EAAC,+FAA+F,YAC7G,KAAC,aAAa,IAAC,SAAS,EAAC,QAAQ,GAAG,GAC/B,EACP,KAAC,WAAW,cAAE,KAAK,GAAe,IAC9B,EACN,KAAC,iBAAiB,IAAC,SAAS,EAAC,MAAM,YAAE,WAAW,GAAqB,IACxD,EACf,MAAC,YAAY,IAAC,SAAS,EAAC,uDAAuD,aAC7E,KAAC,MAAM,IAAC,OAAO,EAAC,OAAO,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,YAC/D,SAAS,CAAC,eAAe,CAAC,GACpB,EACT,MAAC,GAAG,IAAC,GAAG,EAAC,GAAG,EAAC,OAAO,EAAC,KAAK,aACxB,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,MAAM,YACnE,SAAS,CAAC,gBAAgB,CAAC,GACrB,EACT,KAAC,MAAM,IAAC,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAC1C,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC,CAAC,CAAC,SAAS,GACvD,IACL,IACO,IACD,GACT,CACV,CAAA;AACH,CAAC","sourcesContent":["import { useBlocker } from '@elytracms/studio/router'\nimport { TriangleAlert } from 'lucide-react'\nimport { useState } from 'react'\nimport {\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Row,\n} from '@elytracms/studio/ui'\nimport { translate } from '@elytracms/studio/lib/i18n'\n\nexport interface UnsavedChangesGuardProps {\n /** Block navigation while true (i.e. the surface has unsaved edits). */\n when: boolean\n /**\n * Save handler. Resolve `true` to allow the pending navigation, `false` to\n * keep the user on the page (e.g. validation failed). Defaults to allowing.\n */\n onSave?: () => boolean | Promise<boolean>\n title?: string\n description?: string\n saveLabel?: string\n}\n\n/**\n * Reusable route-transition + unsaved-change guard (brief §8.1, §8.7). Blocks\n * in-app navigation (and the browser unload) while `when` is true, then offers\n * save / discard / cancel. Used by Settings now; reusable in the Builder later.\n */\nexport function UnsavedChangesGuard({\n when,\n onSave,\n title = translate('shell.unsavedChanges.title'),\n description = translate('shell.unsavedChanges.body'),\n saveLabel = translate('common.saveChanges'),\n}: UnsavedChangesGuardProps) {\n const { status, proceed, reset } = useBlocker({\n shouldBlockFn: () => when,\n enableBeforeUnload: () => when,\n withResolver: true,\n })\n const [saving, setSaving] = useState(false)\n const blocked = status === 'blocked'\n\n async function handleSave() {\n setSaving(true)\n try {\n const ok = (await onSave?.()) ?? true\n if (ok) proceed?.()\n else reset?.()\n } finally {\n setSaving(false)\n }\n }\n\n return (\n <Dialog open={blocked} onOpenChange={(open) => (!open ? reset?.() : undefined)}>\n <DialogContent className=\"max-w-md\">\n <DialogHeader>\n <Row gap=\"2\">\n <span className=\"grid size-8 place-items-center rounded-lg border border-warning/30 bg-warning/10 text-warning\">\n <TriangleAlert className=\"size-4\" />\n </span>\n <DialogTitle>{title}</DialogTitle>\n </Row>\n <DialogDescription className=\"pt-1\">{description}</DialogDescription>\n </DialogHeader>\n <DialogFooter className=\"flex-col-reverse gap-2 sm:flex-row sm:justify-between\">\n <Button variant=\"ghost\" onClick={() => reset?.()} disabled={saving}>\n {translate('common.cancel')}\n </Button>\n <Row gap=\"2\" justify=\"end\">\n <Button variant=\"outline\" onClick={() => proceed?.()} disabled={saving}>\n {translate('common.discard')}\n </Button>\n <Button onClick={handleSave} disabled={saving}>\n {saving ? translate('shell.unsavedChanges.saving') : saveLabel}\n </Button>\n </Row>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )\n}\n"]}
|
|
@@ -3,6 +3,7 @@ import { CircleAlert, LogIn, X } from 'lucide-react';
|
|
|
3
3
|
import { SESSION_EXPIRED_MESSAGE, SIGN_IN_AGAIN_LABEL, isSessionExpiredError, signInHref, } from '@elytracms/studio/lib/auth-errors';
|
|
4
4
|
import { Badge, Button, Row, Stack, Text } from '@elytracms/studio/ui';
|
|
5
5
|
import { operationErrorLabel } from '@elytracms/studio/lib/persona/labels';
|
|
6
|
+
import { translate } from '@elytracms/studio/lib/i18n';
|
|
6
7
|
import { useOptionalAuth } from './auth-context';
|
|
7
8
|
/**
|
|
8
9
|
* Shared error surface for failed/denied operations (EC-141). Every studio
|
|
@@ -23,7 +24,7 @@ export function OperationErrorBanner({ error, onDismiss, className, }) {
|
|
|
23
24
|
// The raw graph path (`pages.0.root.slots…`) is structural
|
|
24
25
|
// machine addressing — kept inspectable on hover, never shown
|
|
25
26
|
// as visible copy to a non-technical editor (EC-192).
|
|
26
|
-
title: issue.path && issue.path.length > 0 ? issue.path.join('.') : undefined, children: issue.message }, `${issue.code}-${i}`))) })) : null] }), onDismiss ? (_jsx(Button, { size: "icon-sm", variant: "ghost", "aria-label":
|
|
27
|
+
title: issue.path && issue.path.length > 0 ? issue.path.join('.') : undefined, children: issue.message }, `${issue.code}-${i}`))) })) : null] }), onDismiss ? (_jsx(Button, { size: "icon-sm", variant: "ghost", "aria-label": translate('error.dismiss'), onClick: onDismiss, className: "shrink-0", children: _jsx(X, {}) })) : null] }) }));
|
|
27
28
|
}
|
|
28
29
|
/**
|
|
29
30
|
* The session-expired rendering of the banner: plain-language copy plus a
|
|
@@ -49,6 +50,6 @@ function SessionExpiredBanner({ onDismiss, className, }) {
|
|
|
49
50
|
}
|
|
50
51
|
window.location.assign(href);
|
|
51
52
|
}
|
|
52
|
-
return (_jsx("div", { role: "alert", className: 'rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 ' + (className ?? ''), children: _jsxs(Row, { gap: "2", align: "start", children: [_jsx(CircleAlert, { className: "mt-0.5 size-4 shrink-0 text-destructive" }), _jsx(Stack, { gap: "1", className: "min-w-0 flex-1", children: _jsxs(Row, { gap: "2", align: "center", children: [_jsx(Badge, { variant: "error", children:
|
|
53
|
+
return (_jsx("div", { role: "alert", className: 'rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 ' + (className ?? ''), children: _jsxs(Row, { gap: "2", align: "start", children: [_jsx(CircleAlert, { className: "mt-0.5 size-4 shrink-0 text-destructive" }), _jsx(Stack, { gap: "1", className: "min-w-0 flex-1", children: _jsxs(Row, { gap: "2", align: "center", children: [_jsx(Badge, { variant: "error", children: translate('error.signedOut') }), _jsx(Text, { size: "sm", className: "text-destructive", children: SESSION_EXPIRED_MESSAGE })] }) }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => void handleSignInAgain(), className: "shrink-0", children: [_jsx(LogIn, {}), " ", SIGN_IN_AGAIN_LABEL] }), onDismiss ? (_jsx(Button, { size: "icon-sm", variant: "ghost", "aria-label": translate('error.dismiss'), onClick: onDismiss, className: "shrink-0", children: _jsx(X, {}) })) : null] }) }));
|
|
53
54
|
}
|
|
54
55
|
//# sourceMappingURL=operation-error.js.map
|