@elytracms/studio 0.0.85 → 0.0.87
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/convex/asset-revalidate.test.ts +186 -0
- package/convex/assets.ts +53 -19
- package/convex/cms.ts +22 -0
- package/convex/delivery.ts +54 -116
- package/convex/engine-version.test.ts +31 -0
- package/convex/functions.ts +3 -3
- package/convex/rail-write-parity.test.ts +180 -0
- package/convex/redirects.ts +33 -11
- package/convex/revalidate.ts +7 -5
- package/convex/triggers.ts +53 -3
- package/dist/components/ai/ai-chat-panel.js +13 -2
- package/dist/components/ai/ai-chat-panel.js.map +1 -1
- package/dist/components/app-views/default-modules.d.ts +20 -20
- package/dist/components/app-views/default-modules.js +27 -48
- package/dist/components/app-views/default-modules.js.map +1 -1
- package/dist/components/app-views/studio-config.d.ts +5 -6
- package/dist/components/app-views/studio-config.js.map +1 -1
- package/dist/components/assets/asset-metadata.d.ts +28 -19
- package/dist/components/assets/asset-metadata.js +24 -31
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-selection.d.ts +24 -5
- package/dist/components/assets/asset-selection.js +39 -9
- package/dist/components/assets/asset-selection.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +17 -14
- package/dist/components/assets/assets-collection-view-source.js +25 -31
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/builder/blocks-model.d.ts +5 -4
- package/dist/components/builder/blocks-model.js +5 -4
- package/dist/components/builder/blocks-model.js.map +1 -1
- package/dist/components/builder/blocks-panel.js +3 -3
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +25 -1
- package/dist/components/builder/builder-store.js +3 -2
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-chrome-css.js +0 -17
- package/dist/components/builder/canvas-chrome-css.js.map +1 -1
- package/dist/components/builder/canvas-chrome.d.ts +10 -12
- package/dist/components/builder/canvas-chrome.js +12 -13
- package/dist/components/builder/canvas-chrome.js.map +1 -1
- package/dist/components/builder/canvas-dnd.d.ts +8 -0
- package/dist/components/builder/canvas-dnd.js +5 -3
- package/dist/components/builder/canvas-dnd.js.map +1 -1
- package/dist/components/builder/canvas-render-context.d.ts +12 -24
- package/dist/components/builder/canvas-render-context.js +15 -44
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/canvas.js +5 -11
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.d.ts +15 -1
- package/dist/components/builder/clipboard-actions.js +35 -12
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +32 -26
- package/dist/components/builder/composition-field-editor.js +47 -54
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/insert-context.d.ts +3 -1
- package/dist/components/builder/insert-context.js +19 -12
- package/dist/components/builder/insert-context.js.map +1 -1
- package/dist/components/builder/page-tree.d.ts +29 -0
- package/dist/components/builder/page-tree.js +56 -58
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/reuse.js +5 -2
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/cms/asset-field.js +20 -32
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/cell-edit.d.ts +7 -0
- package/dist/components/cms/cell-edit.js +9 -1
- package/dist/components/cms/cell-edit.js.map +1 -1
- package/dist/components/cms/cms-composition-validators.js +11 -2
- package/dist/components/cms/cms-composition-validators.js.map +1 -1
- package/dist/components/cms/collection-table.js +11 -0
- package/dist/components/cms/collection-table.js.map +1 -1
- package/dist/components/cms/document-url-path.d.ts +7 -4
- package/dist/components/cms/document-url-path.js +15 -1
- package/dist/components/cms/document-url-path.js.map +1 -1
- package/dist/components/cms/editable-cell.js +5 -2
- package/dist/components/cms/editable-cell.js.map +1 -1
- package/dist/components/cms/field-control.js +4 -0
- package/dist/components/cms/field-control.js.map +1 -1
- package/dist/components/cms/inline-field-errors.d.ts +36 -0
- package/dist/components/cms/inline-field-errors.js +13 -5
- package/dist/components/cms/inline-field-errors.js.map +1 -1
- package/dist/components/cms/rich-text/insert.d.ts +6 -3
- package/dist/components/cms/rich-text/insert.js +9 -6
- package/dist/components/cms/rich-text/insert.js.map +1 -1
- package/dist/components/cms/use-document-versions.js +1 -0
- package/dist/components/cms/use-document-versions.js.map +1 -1
- package/dist/components/cms/use-live-url.d.ts +18 -6
- package/dist/components/cms/use-live-url.js +10 -0
- package/dist/components/cms/use-live-url.js.map +1 -1
- package/dist/components/cms/versions-model.d.ts +0 -12
- package/dist/components/cms/versions-model.js +3 -15
- package/dist/components/cms/versions-model.js.map +1 -1
- package/dist/components/components/component-detail.js +1 -1
- package/dist/components/components/component-detail.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +2 -4
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/components/transfer.d.ts +19 -15
- package/dist/components/components/transfer.js +28 -25
- package/dist/components/components/transfer.js.map +1 -1
- package/dist/components/deployment-setup-gate.js +9 -3
- package/dist/components/deployment-setup-gate.js.map +1 -1
- package/dist/components/project-session.d.ts +9 -0
- package/dist/components/project-session.js +1 -1
- package/dist/components/project-session.js.map +1 -1
- package/dist/components/redirects/redirects-collection-view-source.d.ts +17 -2
- package/dist/components/redirects/redirects-collection-view-source.js +20 -6
- package/dist/components/redirects/redirects-collection-view-source.js.map +1 -1
- package/dist/components/section-surface.js +3 -2
- package/dist/components/section-surface.js.map +1 -1
- package/dist/components/settings-form.js +1 -2
- package/dist/components/settings-form.js.map +1 -1
- package/dist/components/studio-context.js +1 -18
- package/dist/components/studio-context.js.map +1 -1
- package/dist/components/studio-project-screen.js +3 -5
- package/dist/components/studio-project-screen.js.map +1 -1
- package/dist/lib/ai/apply-content.js +73 -29
- package/dist/lib/ai/apply-content.js.map +1 -1
- package/dist/lib/ai/constraints.d.ts +35 -0
- package/dist/lib/ai/constraints.js +155 -72
- package/dist/lib/ai/constraints.js.map +1 -1
- package/dist/lib/ai/index.d.ts +1 -0
- package/dist/lib/ai/index.js +1 -0
- package/dist/lib/ai/index.js.map +1 -1
- package/dist/lib/ai/route-fetch.d.ts +58 -0
- package/dist/lib/ai/route-fetch.js +98 -0
- package/dist/lib/ai/route-fetch.js.map +1 -0
- package/dist/lib/ai/route-provider.d.ts +5 -22
- package/dist/lib/ai/route-provider.js +23 -1
- package/dist/lib/ai/route-provider.js.map +1 -1
- package/dist/lib/ai/route.js +4 -1
- package/dist/lib/ai/route.js.map +1 -1
- package/dist/lib/ai/shape.d.ts +3 -2
- package/dist/lib/ai/shape.js +16 -24
- package/dist/lib/ai/shape.js.map +1 -1
- package/dist/lib/ai/types.d.ts +8 -0
- package/dist/lib/ai/types.js.map +1 -1
- package/dist/lib/ai/update-fields.js +33 -12
- package/dist/lib/ai/update-fields.js.map +1 -1
- package/dist/lib/assets/asset-placements.d.ts +35 -0
- package/dist/lib/assets/asset-placements.js +74 -0
- package/dist/lib/assets/asset-placements.js.map +1 -0
- package/dist/lib/assets/backfill-thumbs.d.ts +9 -8
- package/dist/lib/assets/backfill-thumbs.js +13 -25
- package/dist/lib/assets/backfill-thumbs.js.map +1 -1
- package/dist/lib/clipboard/paste-issues.d.ts +17 -15
- package/dist/lib/clipboard/paste-issues.js +8 -45
- package/dist/lib/clipboard/paste-issues.js.map +1 -1
- package/dist/lib/clipboard/paste-target.d.ts +47 -1
- package/dist/lib/clipboard/paste-target.js +19 -11
- package/dist/lib/clipboard/paste-target.js.map +1 -1
- package/dist/lib/cms/document-gate.d.ts +19 -9
- package/dist/lib/cms/document-gate.js +25 -4
- package/dist/lib/cms/document-gate.js.map +1 -1
- package/dist/lib/cms/published-documents.js +1 -0
- package/dist/lib/cms/published-documents.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +3 -3
- package/dist/lib/data/index.d.ts +0 -3
- package/dist/lib/data/index.js +4 -6
- package/dist/lib/data/index.js.map +1 -1
- package/dist/lib/dnd/drop-rules.d.ts +45 -2
- package/dist/lib/dnd/drop-rules.js +64 -9
- package/dist/lib/dnd/drop-rules.js.map +1 -1
- package/dist/lib/engine-version.d.ts +16 -0
- package/dist/lib/engine-version.js +17 -0
- package/dist/lib/engine-version.js.map +1 -0
- package/dist/lib/i18n/messages.de.js +8 -56
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +8 -53
- package/dist/lib/i18n/messages.en.js +15 -57
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/locale/fallback.js +8 -2
- package/dist/lib/locale/fallback.js.map +1 -1
- package/dist/lib/locale/index.d.ts +0 -1
- package/dist/lib/locale/index.js +0 -1
- package/dist/lib/locale/index.js.map +1 -1
- package/dist/lib/locale/locale-store.d.ts +10 -3
- package/dist/lib/locale/locale-store.js +12 -5
- package/dist/lib/locale/locale-store.js.map +1 -1
- package/dist/lib/operations/session-hydration.d.ts +9 -5
- package/dist/lib/operations/session-hydration.js +10 -10
- package/dist/lib/operations/session-hydration.js.map +1 -1
- package/dist/lib/operations/studio-operations.js +4 -2
- package/dist/lib/operations/studio-operations.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.js +63 -75
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persistence/deployment-readiness.d.ts +8 -1
- package/dist/lib/persistence/deployment-readiness.js +4 -0
- package/dist/lib/persistence/deployment-readiness.js.map +1 -1
- package/dist/lib/persona/labels.d.ts +0 -2
- package/dist/lib/persona/labels.js +1 -7
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/registry/index.d.ts +4 -2
- package/dist/lib/registry/index.js +26 -21
- package/dist/lib/registry/index.js.map +1 -1
- package/dist/lib/registry/project-components.js +0 -3
- package/dist/lib/registry/project-components.js.map +1 -1
- package/dist/lib/routes/route-issues.js +4 -5
- package/dist/lib/routes/route-issues.js.map +1 -1
- package/dist/lib/theme.js +3 -2
- package/dist/lib/theme.js.map +1 -1
- package/dist/lib/webhooks/tags.js +11 -14
- package/dist/lib/webhooks/tags.js.map +1 -1
- package/dist/lib/workspace/index.d.ts +1 -1
- package/dist/lib/workspace/index.js +1 -1
- package/dist/lib/workspace/index.js.map +1 -1
- package/dist/previews/enumerate.d.ts +27 -9
- package/dist/previews/enumerate.js +27 -6
- package/dist/previews/enumerate.js.map +1 -1
- package/dist/previews/manifest-format.d.ts +16 -7
- package/dist/previews/manifest-format.js +0 -21
- package/dist/previews/manifest-format.js.map +1 -1
- package/dist/router/match.d.ts +0 -2
- package/dist/router/match.js +0 -2
- package/dist/router/match.js.map +1 -1
- package/dist/ui/badge.d.ts +1 -1
- package/package.json +2 -2
- package/src/styles/studio.css +5 -4
- package/src/styles/tokens.css +72 -55
- package/convex/content.ts +0 -291
- package/dist/components/collab/collab-context.d.ts +0 -27
- package/dist/components/collab/collab-context.js +0 -39
- package/dist/components/collab/collab-context.js.map +0 -1
- package/dist/components/collab/collab-seed.d.ts +0 -15
- package/dist/components/collab/collab-seed.js +0 -20
- package/dist/components/collab/collab-seed.js.map +0 -1
- package/dist/components/extensions/extensions-view.d.ts +0 -7
- package/dist/components/extensions/extensions-view.js +0 -127
- package/dist/components/extensions/extensions-view.js.map +0 -1
- package/dist/lib/bindings/section-bindings.d.ts +0 -24
- package/dist/lib/bindings/section-bindings.js +0 -9
- package/dist/lib/bindings/section-bindings.js.map +0 -1
- package/dist/lib/data/data-store.d.ts +0 -98
- package/dist/lib/data/data-store.js +0 -211
- package/dist/lib/data/data-store.js.map +0 -1
- package/dist/lib/data/providers.d.ts +0 -143
- package/dist/lib/data/providers.js +0 -255
- package/dist/lib/data/providers.js.map +0 -1
- package/dist/lib/data/sample-capture.d.ts +0 -30
- package/dist/lib/data/sample-capture.js +0 -70
- package/dist/lib/data/sample-capture.js.map +0 -1
- package/dist/lib/data/sources-store.d.ts +0 -42
- package/dist/lib/data/sources-store.js +0 -120
- package/dist/lib/data/sources-store.js.map +0 -1
- package/dist/lib/locale/binding-fallback.d.ts +0 -35
- package/dist/lib/locale/binding-fallback.js +0 -73
- package/dist/lib/locale/binding-fallback.js.map +0 -1
- package/dist/lib/starters/kit-session.d.ts +0 -5
- package/dist/lib/starters/kit-session.js +0 -17
- package/dist/lib/starters/kit-session.js.map +0 -1
package/src/styles/studio.css
CHANGED
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
@import '@fontsource-variable/hanken-grotesk';
|
|
18
18
|
@import '@fontsource-variable/jetbrains-mono';
|
|
19
19
|
/*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* Cool-slate neutrals + a confident
|
|
23
|
-
* token (component ids, path tokens,
|
|
20
|
+
* The colour roles are declared once, hand-written, in tokens.css (EC-607); the
|
|
21
|
+
* `@theme inline` block below maps each to its Tailwind colour and is the one
|
|
22
|
+
* declaration of the fonts and the radius scale. Cool-slate neutrals + a confident
|
|
23
|
+
* cobalt accent; monospace carries every technical token (component ids, path tokens,
|
|
24
|
+
* issue codes) to reinforce the code-first identity.
|
|
24
25
|
*/
|
|
25
26
|
@import './tokens.css';
|
|
26
27
|
|
package/src/styles/tokens.css
CHANGED
|
@@ -1,63 +1,80 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/*
|
|
2
|
+
* Studio colour tokens: the one declaration (EC-607). Hand-written, so edit here.
|
|
3
|
+
*
|
|
4
|
+
* Each role is declared ONCE as `light-dark(<light>, <dark>)`, so a role cannot
|
|
5
|
+
* exist without both values. The `dark` class on <html> (lib/theme.ts) only flips
|
|
6
|
+
* `color-scheme`, which picks the value; it also gives native controls and
|
|
7
|
+
* scrollbars the matching scheme. A role that tracks another is a plain `var()`.
|
|
8
|
+
*
|
|
9
|
+
* Components never use raw colours: studio.css maps each role to a Tailwind colour
|
|
10
|
+
* (`bg-primary`, `text-muted-foreground`, …) and the in-canvas chrome uses no var()
|
|
11
|
+
* at all (canvas-chrome-css.ts). A new role is one line here plus its `@theme inline`
|
|
12
|
+
* line in studio.css; lib/theme-tokens-contract.test.ts fails if a mapped role is missing.
|
|
13
|
+
*
|
|
14
|
+
* Needs light-dark(): Chrome 123, Safari 17.5, Firefox 120.
|
|
15
|
+
*/
|
|
2
16
|
:root {
|
|
3
|
-
|
|
4
|
-
--
|
|
5
|
-
|
|
17
|
+
color-scheme: light;
|
|
18
|
+
--radius: 0.5rem;
|
|
19
|
+
|
|
20
|
+
/* App canvas background */
|
|
21
|
+
--background: light-dark(oklch(0.985 0.002 250), oklch(0.176 0.012 264));
|
|
22
|
+
/* Primary text */
|
|
23
|
+
--foreground: light-dark(oklch(0.21 0.02 264), oklch(0.95 0.005 250));
|
|
24
|
+
/* Card surface */
|
|
25
|
+
--card: light-dark(oklch(1 0 0), oklch(0.205 0.013 264));
|
|
26
|
+
/* Text on cards */
|
|
6
27
|
--card-foreground: var(--foreground);
|
|
7
|
-
|
|
28
|
+
/* Inspector / rail surface */
|
|
29
|
+
--panel: light-dark(oklch(0.974 0.003 255), oklch(0.196 0.013 264));
|
|
30
|
+
/* Text on panels */
|
|
8
31
|
--panel-foreground: var(--foreground);
|
|
9
|
-
|
|
32
|
+
/* Floating surface */
|
|
33
|
+
--popover: light-dark(oklch(1 0 0), oklch(0.214 0.013 264));
|
|
34
|
+
/* Text on popovers */
|
|
10
35
|
--popover-foreground: var(--foreground);
|
|
11
|
-
|
|
12
|
-
--muted
|
|
13
|
-
|
|
14
|
-
--
|
|
15
|
-
|
|
16
|
-
--
|
|
17
|
-
|
|
18
|
-
--
|
|
19
|
-
|
|
20
|
-
--
|
|
21
|
-
|
|
22
|
-
--
|
|
23
|
-
|
|
24
|
-
--
|
|
25
|
-
|
|
26
|
-
--
|
|
27
|
-
|
|
28
|
-
--
|
|
29
|
-
|
|
30
|
-
--
|
|
31
|
-
|
|
36
|
+
/* Subtle fill */
|
|
37
|
+
--muted: light-dark(oklch(0.955 0.004 255), oklch(0.256 0.013 264));
|
|
38
|
+
/* Secondary text */
|
|
39
|
+
--muted-foreground: light-dark(oklch(0.5 0.018 260), oklch(0.66 0.02 258));
|
|
40
|
+
/* Hairline borders */
|
|
41
|
+
--border: light-dark(oklch(0.908 0.005 260), oklch(0.278 0.013 264));
|
|
42
|
+
/* Form control borders */
|
|
43
|
+
--input: light-dark(oklch(0.908 0.005 260), oklch(0.3 0.013 264));
|
|
44
|
+
/* Focus ring */
|
|
45
|
+
--ring: light-dark(oklch(0.55 0.17 256), oklch(0.66 0.16 256));
|
|
46
|
+
/* Primary action (cobalt) */
|
|
47
|
+
--primary: light-dark(oklch(0.55 0.17 256), oklch(0.66 0.16 256));
|
|
48
|
+
/* Text on primary */
|
|
49
|
+
--primary-foreground: light-dark(oklch(0.99 0.005 250), oklch(0.16 0.02 264));
|
|
50
|
+
/* Secondary action */
|
|
51
|
+
--secondary: light-dark(oklch(0.955 0.004 255), oklch(0.256 0.013 264));
|
|
52
|
+
/* Text on secondary */
|
|
53
|
+
--secondary-foreground: light-dark(oklch(0.3 0.02 264), oklch(0.92 0.005 250));
|
|
54
|
+
/* Selected / emphasis fill */
|
|
55
|
+
--accent: light-dark(oklch(0.95 0.022 256), oklch(0.288 0.03 256));
|
|
56
|
+
/* Text on accent */
|
|
57
|
+
--accent-foreground: light-dark(oklch(0.36 0.07 256), oklch(0.88 0.03 256));
|
|
58
|
+
/* Success / valid */
|
|
59
|
+
--success: light-dark(oklch(0.58 0.13 150), oklch(0.7 0.14 150));
|
|
60
|
+
/* Text on success */
|
|
61
|
+
--success-foreground: light-dark(oklch(0.99 0.01 150), oklch(0.16 0.03 150));
|
|
62
|
+
/* Warning */
|
|
63
|
+
--warning: light-dark(oklch(0.68 0.14 70), oklch(0.79 0.14 75));
|
|
64
|
+
/* Text on warning */
|
|
65
|
+
--warning-foreground: light-dark(oklch(0.24 0.04 70), oklch(0.2 0.04 75));
|
|
66
|
+
/* Error / destructive */
|
|
67
|
+
--destructive: light-dark(oklch(0.57 0.2 27), oklch(0.67 0.18 25));
|
|
68
|
+
/* Text on destructive */
|
|
69
|
+
--destructive-foreground: light-dark(oklch(0.99 0.01 27), oklch(0.16 0.03 25));
|
|
70
|
+
/* Informational / bound */
|
|
71
|
+
--info: light-dark(oklch(0.56 0.12 248), oklch(0.7 0.13 245));
|
|
72
|
+
/* Text on info */
|
|
73
|
+
--info-foreground: light-dark(oklch(0.99 0.01 248), oklch(0.16 0.03 245));
|
|
74
|
+
/* Canvas grid lines */
|
|
75
|
+
--grid-line: light-dark(oklch(0.8 0.01 260 / 0.5), oklch(0.5 0.012 264 / 0.32));
|
|
32
76
|
}
|
|
33
77
|
|
|
34
78
|
.dark {
|
|
35
|
-
|
|
36
|
-
--foreground: oklch(0.95 0.005 250);
|
|
37
|
-
--card: oklch(0.205 0.013 264);
|
|
38
|
-
--card-foreground: var(--foreground);
|
|
39
|
-
--panel: oklch(0.196 0.013 264);
|
|
40
|
-
--panel-foreground: var(--foreground);
|
|
41
|
-
--popover: oklch(0.214 0.013 264);
|
|
42
|
-
--popover-foreground: var(--foreground);
|
|
43
|
-
--muted: oklch(0.256 0.013 264);
|
|
44
|
-
--muted-foreground: oklch(0.66 0.02 258);
|
|
45
|
-
--border: oklch(0.278 0.013 264);
|
|
46
|
-
--input: oklch(0.3 0.013 264);
|
|
47
|
-
--ring: oklch(0.66 0.16 256);
|
|
48
|
-
--primary: oklch(0.66 0.16 256);
|
|
49
|
-
--primary-foreground: oklch(0.16 0.02 264);
|
|
50
|
-
--secondary: oklch(0.256 0.013 264);
|
|
51
|
-
--secondary-foreground: oklch(0.92 0.005 250);
|
|
52
|
-
--accent: oklch(0.288 0.03 256);
|
|
53
|
-
--accent-foreground: oklch(0.88 0.03 256);
|
|
54
|
-
--success: oklch(0.7 0.14 150);
|
|
55
|
-
--success-foreground: oklch(0.16 0.03 150);
|
|
56
|
-
--warning: oklch(0.79 0.14 75);
|
|
57
|
-
--warning-foreground: oklch(0.2 0.04 75);
|
|
58
|
-
--destructive: oklch(0.67 0.18 25);
|
|
59
|
-
--destructive-foreground: oklch(0.16 0.03 25);
|
|
60
|
-
--info: oklch(0.7 0.13 245);
|
|
61
|
-
--info-foreground: oklch(0.16 0.03 245);
|
|
62
|
-
--grid-line: oklch(0.5 0.012 264 / 0.32);
|
|
79
|
+
color-scheme: dark;
|
|
63
80
|
}
|
package/convex/content.ts
DELETED
|
@@ -1,291 +0,0 @@
|
|
|
1
|
-
import { documentKey, documentSchema, unfoldValue } from '@elytracms/core/cms-core'
|
|
2
|
-
import type {
|
|
3
|
-
CmsDocument,
|
|
4
|
-
CmsValidationIssue,
|
|
5
|
-
CollectionDef,
|
|
6
|
-
Locale,
|
|
7
|
-
LocaleConfig,
|
|
8
|
-
RedirectRecord,
|
|
9
|
-
RouteRecord,
|
|
10
|
-
} from '@elytracms/core/cms-core'
|
|
11
|
-
import { createContentClient, createContentContext, isDocumentHistory, rawDocument } from '@elytracms/core/content'
|
|
12
|
-
import type {
|
|
13
|
-
ContentClient,
|
|
14
|
-
ContentContext,
|
|
15
|
-
ContentDocumentSource,
|
|
16
|
-
ContentLookup,
|
|
17
|
-
Perspective,
|
|
18
|
-
} from '@elytracms/core/content'
|
|
19
|
-
import type { AssetRecord } from '@elytracms/core/persistence'
|
|
20
|
-
import type { QueryCtx } from './functions'
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* EC-145 — the Convex-side content kit (vision AD-3/AD-4).
|
|
24
|
-
*
|
|
25
|
-
* Custom Convex functions are the query escape hatch ("our query language is
|
|
26
|
-
* TypeScript") — but only if developers never touch raw tables. `createContent`
|
|
27
|
-
* gives a Convex query function the same delivery surface as the Next-side
|
|
28
|
-
* accessors: `get`, `list`, `resolvePage`, plus the `raw` escape hatch, all
|
|
29
|
-
* with ambient `{ locale, perspective }` context.
|
|
30
|
-
*
|
|
31
|
-
* Byte-equivalence with the Next side is guaranteed by construction: the kit
|
|
32
|
-
* loads rows through `ctx.db`, builds the same synchronous `ContentLookup`
|
|
33
|
-
* that `@elytracms/next`'s snapshot builds from a `PersistenceAdapter`, and then
|
|
34
|
-
* runs the EXACT pure functions from `@elytracms/core/content`
|
|
35
|
-
* (`createContentClient` → `resolveDocument`, `query.ts` validation, cache
|
|
36
|
-
* tags). Nothing about resolution semantics is reimplemented here.
|
|
37
|
-
*
|
|
38
|
-
* Loading strategy (honest about v1 scale): the project's schema, documents,
|
|
39
|
-
* and asset metadata are prefetched ONCE per `createContent` call via the
|
|
40
|
-
* indexed `by_project` / `by_project_asset` scans, then every kit call is
|
|
41
|
-
* synchronous over memory — exactly like `createContentSnapshot` on the Next
|
|
42
|
-
* side. Filters and sorts therefore execute in-function over an indexed
|
|
43
|
-
* by-project fetch; see `contentIndexes.ts` for the index requirements this
|
|
44
|
-
* implies and the documented field-level-index upgrade path.
|
|
45
|
-
*
|
|
46
|
-
* Perspective isolation: the lookup holds the raw stored rows (draft state and
|
|
47
|
-
* all), and EVERY read path through `@elytracms/core/content` — `resolveDocument`,
|
|
48
|
-
* relation population, `listDocuments` filtering, slug fallback, and the `raw`
|
|
49
|
-
* escape hatch — applies the EC-142 perspective gate (`selectPerspective`)
|
|
50
|
-
* before any value is exposed. The kit never reads field values around that
|
|
51
|
-
* gate, so a `published` kit cannot observe draft values. (Pre-filtering draft
|
|
52
|
-
* rows out of the lookup would be redundant *and* would change structured
|
|
53
|
-
* issue messages — e.g. `unknown-relation-target` reasons — breaking
|
|
54
|
-
* byte-equivalence with the Next-side accessors.)
|
|
55
|
-
*/
|
|
56
|
-
|
|
57
|
-
const DEFAULT_LOCALES: LocaleConfig = { default: 'en', locales: ['en'] }
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Structured load-time problems (stored blobs that fail their canonical Zod
|
|
61
|
-
* schema, unparsable graph revisions). Never thrown — the kit degrades to the
|
|
62
|
-
* valid subset and reports what it skipped, mirroring the package-wide
|
|
63
|
-
* "structured issues, never crashes" stance.
|
|
64
|
-
*
|
|
65
|
-
* `invalid-stored-schema` is retained for wire/back-compat but is no longer
|
|
66
|
-
* produced: CMS collections are config-owned (EC-183, AD-11) and supplied by the
|
|
67
|
-
* caller (already validated), so there is no stored schema blob to reject.
|
|
68
|
-
*/
|
|
69
|
-
export type ContentKitIssueCode = 'invalid-stored-schema' | 'invalid-stored-document'
|
|
70
|
-
|
|
71
|
-
export interface ContentKitIssue {
|
|
72
|
-
code: ContentKitIssueCode
|
|
73
|
-
message: string
|
|
74
|
-
meta?: Record<string, unknown>
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
export interface CreateContentOptions {
|
|
78
|
-
projectId: string
|
|
79
|
-
/** Draft or published perspective (EC-021); ambient for every kit call. */
|
|
80
|
-
perspective: Perspective
|
|
81
|
-
/** Requested locale; defaults to the project's default locale. */
|
|
82
|
-
locale?: Locale
|
|
83
|
-
/** Override the locale config derived from the project settings. */
|
|
84
|
-
locales?: LocaleConfig
|
|
85
|
-
/**
|
|
86
|
-
* CMS collections (EC-183, AD-11), sourced from `elytra.config.ts` by the
|
|
87
|
-
* caller — the backend no longer stores a schema. Defaults to none (the kit
|
|
88
|
-
* then resolves documents with no collection structure).
|
|
89
|
-
*/
|
|
90
|
-
collections?: readonly CollectionDef[]
|
|
91
|
-
/** Route records served by `resolvePage` (EC-019). */
|
|
92
|
-
routes?: readonly RouteRecord[]
|
|
93
|
-
// Redirects are no longer an option (EC-303): they are editorial DATA, read from
|
|
94
|
-
// the `redirects` table inside `createContent`, not passed by the caller.
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface ContentKit {
|
|
98
|
-
/** The ambient `{ locale, perspective }` context every call resolves under. */
|
|
99
|
-
readonly context: ContentContext
|
|
100
|
-
/** Structured load-time issues (invalid stored blobs); never thrown. */
|
|
101
|
-
readonly loadIssues: readonly ContentKitIssue[]
|
|
102
|
-
/** Structural route issues from router construction (conflicts, loops). */
|
|
103
|
-
readonly routerIssues: readonly CmsValidationIssue[]
|
|
104
|
-
/** Delivery-shaped single-document accessor — same semantics as Next-side `getDocument`. */
|
|
105
|
-
readonly get: ContentClient['getDocument']
|
|
106
|
-
/** Delivery-shaped list accessor — same filter vocabulary as EC-143. */
|
|
107
|
-
readonly list: ContentClient['listDocuments']
|
|
108
|
-
/** Route → page/document resolution (EC-019), when routes were provided. */
|
|
109
|
-
readonly resolvePage: ContentClient['resolvePage']
|
|
110
|
-
/**
|
|
111
|
-
* Escape hatch (EC-142 `rawDocument`): the stored row, untouched — no locale
|
|
112
|
-
* fallback, no population, no asset resolution. The perspective gate still
|
|
113
|
-
* applies: a `published` kit never sees draft rows, even raw.
|
|
114
|
-
*/
|
|
115
|
-
raw(collection: string, id: string): CmsDocument | null
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Create the server-side content kit for one Convex query invocation.
|
|
120
|
-
*
|
|
121
|
-
* Usage inside a Convex query function:
|
|
122
|
-
* ```ts
|
|
123
|
-
* const content = await createContent(ctx, { projectId, perspective: 'published' })
|
|
124
|
-
* const { document: post } = content.get<Post>('post', slug)
|
|
125
|
-
* ```
|
|
126
|
-
*/
|
|
127
|
-
export async function createContent(
|
|
128
|
-
ctx: QueryCtx,
|
|
129
|
-
options: CreateContentOptions,
|
|
130
|
-
): Promise<ContentKit> {
|
|
131
|
-
const { projectId, perspective } = options
|
|
132
|
-
const routes = options.routes ?? []
|
|
133
|
-
const loadIssues: ContentKitIssue[] = []
|
|
134
|
-
|
|
135
|
-
// Redirects are editorial DATA now (EC-303), read from the `redirects` table —
|
|
136
|
-
// only ENABLED entries resolve. (Config redirects are retired; static infra
|
|
137
|
-
// redirects stay native.) Projected to the routing `RedirectRecord` shape.
|
|
138
|
-
const redirectRows = await ctx.db.query('redirects').withIndex('by_redirect').collect()
|
|
139
|
-
const redirects: RedirectRecord[] = redirectRows
|
|
140
|
-
.filter((row) => row.enabled)
|
|
141
|
-
.map((row) => ({ id: row.redirectId, from: row.from, to: row.to, permanent: row.permanent }))
|
|
142
|
-
|
|
143
|
-
// --- Prefetch (the only async part; everything below is synchronous) -----
|
|
144
|
-
|
|
145
|
-
// Config-first identity (EC-182/EC-183, AD-11): locales AND collections are
|
|
146
|
-
// supplied by the caller (sourced from `elytra.config.ts`); the backend has
|
|
147
|
-
// no `projects` row and no `cmsSchemas` table — it stores documents only.
|
|
148
|
-
const locales = options.locales ?? DEFAULT_LOCALES
|
|
149
|
-
const collectionDefs: CollectionDef[] = options.collections ? [...options.collections] : []
|
|
150
|
-
|
|
151
|
-
// One indexed scan over the project's documents (v1 scale; see module doc).
|
|
152
|
-
// A row's `document` is the continuous working **draft**; `publishedVersion`
|
|
153
|
-
// (when set) pins which recorded version is live — the Sanity model (EC-224).
|
|
154
|
-
const documentRows = await ctx.db.query('cmsDocuments').collect()
|
|
155
|
-
|
|
156
|
-
// The recorded version snapshots, indexed by (collection, docId, version), so
|
|
157
|
-
// a published read can serve the *pinned* version rather than the live draft.
|
|
158
|
-
const versionsByKey = new Map<string, Map<number, CmsDocument>>()
|
|
159
|
-
for (const row of await ctx.db.query('documentVersions').collect()) {
|
|
160
|
-
// EC-260: unfold the folded storage form before parsing — the kit resolves over
|
|
161
|
-
// STRUCTURED values, exactly like the Next-side snapshot (byte-equivalence).
|
|
162
|
-
const parsed = documentSchema.safeParse(unfoldValue(row.snapshot))
|
|
163
|
-
if (!parsed.success) continue
|
|
164
|
-
const key = `${row.collection}:${row.docId}`
|
|
165
|
-
let byVersion = versionsByKey.get(key)
|
|
166
|
-
if (!byVersion) {
|
|
167
|
-
byVersion = new Map()
|
|
168
|
-
versionsByKey.set(key, byVersion)
|
|
169
|
-
}
|
|
170
|
-
byVersion.set(row.version, parsed.data)
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// Hybrid source per row (EC-224 A1a): a `publishedVersion` pointer yields a
|
|
174
|
-
// `DocumentHistory` (draft = the live row, published = the pinned snapshot),
|
|
175
|
-
// so the published perspective serves the recorded version, decoupled from
|
|
176
|
-
// the continuously-edited draft. An unpinned row stays a bare `CmsDocument`
|
|
177
|
-
// (the EC-142 gate reads its `state`) — backward-compatible: pre-pointer data
|
|
178
|
-
// resolves exactly as before.
|
|
179
|
-
const parsedSources: { key: string; source: ContentDocumentSource }[] = []
|
|
180
|
-
for (const row of documentRows) {
|
|
181
|
-
// EC-260: unfold the folded storage form before parsing (see the versions loop).
|
|
182
|
-
const parsed = documentSchema.safeParse(unfoldValue(row.document))
|
|
183
|
-
if (!parsed.success) {
|
|
184
|
-
loadIssues.push({
|
|
185
|
-
code: 'invalid-stored-document',
|
|
186
|
-
message: `Stored document "${row.collection}:${row.docId}" does not match the canonical document schema and was skipped.`,
|
|
187
|
-
meta: { projectId, collection: row.collection, docId: row.docId },
|
|
188
|
-
})
|
|
189
|
-
continue
|
|
190
|
-
}
|
|
191
|
-
const draft = parsed.data
|
|
192
|
-
const key = documentKey(draft)
|
|
193
|
-
if (row.publishedVersion === undefined) {
|
|
194
|
-
parsedSources.push({ key, source: draft })
|
|
195
|
-
continue
|
|
196
|
-
}
|
|
197
|
-
// Pinned: serve the recorded snapshot for `published`. A dangling pin
|
|
198
|
-
// (version missing/invalid) under-serves to `null` — never the live draft.
|
|
199
|
-
const published = versionsByKey.get(`${row.collection}:${row.docId}`)?.get(row.publishedVersion)
|
|
200
|
-
parsedSources.push({ key, source: { draft, published, versions: [] } })
|
|
201
|
-
}
|
|
202
|
-
// Deterministic iteration order regardless of row creation order.
|
|
203
|
-
parsedSources.sort((a, b) => (a.key < b.key ? -1 : 1))
|
|
204
|
-
|
|
205
|
-
const assetRows = await ctx.db.query('assets').withIndex('by_asset').collect()
|
|
206
|
-
const assetRecords: AssetRecord[] = []
|
|
207
|
-
for (const row of assetRows) {
|
|
208
|
-
// EC-151 stores a stable serve URL on upload; older rows fall back to a
|
|
209
|
-
// live storage lookup, then to the blob adapter's placeholder convention.
|
|
210
|
-
const url = row.url ?? (await ctx.storage.getUrl(row.storageKey)) ?? undefined
|
|
211
|
-
assetRecords.push({
|
|
212
|
-
id: row.assetId,
|
|
213
|
-
// Single-tenant: rows no longer store projectId; the kit's `projectId`
|
|
214
|
-
// option (the constant slug) satisfies the AssetRecord shape (EC-179).
|
|
215
|
-
projectId,
|
|
216
|
-
filename: row.filename,
|
|
217
|
-
contentType: row.contentType,
|
|
218
|
-
byteSize: row.byteSize,
|
|
219
|
-
...(row.width !== undefined ? { width: row.width } : {}),
|
|
220
|
-
...(row.height !== undefined ? { height: row.height } : {}),
|
|
221
|
-
...(row.alt !== undefined ? { alt: row.alt } : {}),
|
|
222
|
-
// EC-301: focalPoint (EC-230) and the schema-driven metadata bag must reach
|
|
223
|
-
// delivery — both were dropped here, so a studio-set hotspot/metadata never
|
|
224
|
-
// made it into the LIVE snapshot (only the studio canvas, which reads records
|
|
225
|
-
// directly, showed them).
|
|
226
|
-
...(row.focalPoint !== undefined ? { focalPoint: row.focalPoint } : {}),
|
|
227
|
-
...(row.meta !== undefined ? { meta: row.meta } : {}),
|
|
228
|
-
storageKey: row.storageKey,
|
|
229
|
-
...(url !== undefined ? { url } : {}),
|
|
230
|
-
createdAt: row.createdAt,
|
|
231
|
-
updatedAt: row.updatedAt,
|
|
232
|
-
})
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// EC-287: there is no project graph. Pages are `page`-collection documents,
|
|
236
|
-
// resolved by `resolvePage` from the document lookup + routes — no graph load.
|
|
237
|
-
|
|
238
|
-
// --- Index into the synchronous lookup the pure accessors read through ---
|
|
239
|
-
|
|
240
|
-
const collections = new Map<string, CollectionDef>()
|
|
241
|
-
for (const collection of collectionDefs) collections.set(collection.id, collection)
|
|
242
|
-
|
|
243
|
-
const documents = new Map<string, ContentDocumentSource>()
|
|
244
|
-
const byCollection = new Map<string, ContentDocumentSource[]>()
|
|
245
|
-
for (const { key, source } of parsedSources) {
|
|
246
|
-
documents.set(key, source)
|
|
247
|
-
const collection = isDocumentHistory(source) ? source.draft.collection : source.collection
|
|
248
|
-
const list = byCollection.get(collection) ?? []
|
|
249
|
-
list.push(source)
|
|
250
|
-
byCollection.set(collection, list)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
const assets = new Map<string, AssetRecord>()
|
|
254
|
-
for (const record of assetRecords) assets.set(record.id, record)
|
|
255
|
-
|
|
256
|
-
const lookup: ContentLookup = {
|
|
257
|
-
collection: (id) => collections.get(id),
|
|
258
|
-
document: (ref) => documents.get(documentKey(ref)),
|
|
259
|
-
documents: (collectionId) => byCollection.get(collectionId) ?? [],
|
|
260
|
-
asset: (id) => assets.get(id),
|
|
261
|
-
// Same convention as `ConvexBlobStorage.url`: stored serve URL when
|
|
262
|
-
// available, otherwise the explicit unresolved-placeholder scheme.
|
|
263
|
-
assetUrl: (asset) => asset.url ?? `convex://storage/${asset.storageKey}`,
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
const context = createContentContext({
|
|
267
|
-
locale: options.locale ?? locales.default,
|
|
268
|
-
perspective,
|
|
269
|
-
locales,
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
// The EXACT pure client the Next-side accessors run — this is what makes
|
|
273
|
-
// results byte-equivalent across runtimes for the same inputs.
|
|
274
|
-
const client = createContentClient({ lookup, context, routes, redirects })
|
|
275
|
-
|
|
276
|
-
const raw = (collection: string, id: string): CmsDocument | null => {
|
|
277
|
-
const source = documents.get(documentKey({ collection, id }))
|
|
278
|
-
if (!source) return null
|
|
279
|
-
return rawDocument(context, source)
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
return {
|
|
283
|
-
context,
|
|
284
|
-
loadIssues,
|
|
285
|
-
routerIssues: client.routerIssues,
|
|
286
|
-
get: client.getDocument,
|
|
287
|
-
list: client.listDocuments,
|
|
288
|
-
resolvePage: client.resolvePage,
|
|
289
|
-
raw,
|
|
290
|
-
}
|
|
291
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import { Collaboration } from '@elytracms/core/collaboration';
|
|
3
|
-
import type { Actor, PreviewMode } from '@elytracms/core/collaboration';
|
|
4
|
-
/**
|
|
5
|
-
* Per-project collaboration session (Phase 10). Holds one {@link Collaboration} store seeded with
|
|
6
|
-
* an initial version + presence for the current user, and exposes a `mutate` helper that re-renders
|
|
7
|
-
* consumers after an imperative store change. Non-persistent (session): it is the builder canvas's
|
|
8
|
-
* session-scoped presence/perspective store. EC-287 retired the project graph and its publish path,
|
|
9
|
-
* so the seed no longer reflects a pinned graph revision; content publishing is per document
|
|
10
|
-
* (EC-224), surfaced by the CMS document Versions pane.
|
|
11
|
-
*/
|
|
12
|
-
export interface CollabStore {
|
|
13
|
-
collab: Collaboration;
|
|
14
|
-
projectId: string;
|
|
15
|
-
me: Actor;
|
|
16
|
-
/** Draft vs published perspective the canvas/preview renders (EC-123). */
|
|
17
|
-
previewMode: PreviewMode;
|
|
18
|
-
setPreviewMode: (mode: PreviewMode) => void;
|
|
19
|
-
/** Run an imperative store mutation, then re-render consumers. */
|
|
20
|
-
mutate: <T>(fn: () => T) => T;
|
|
21
|
-
}
|
|
22
|
-
declare const useCollab: () => CollabStore;
|
|
23
|
-
export declare function CollabProvider({ projectId, children, }: {
|
|
24
|
-
projectId: string;
|
|
25
|
-
children: ReactNode;
|
|
26
|
-
}): import("react").JSX.Element;
|
|
27
|
-
export { useCollab };
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useMemo, useReducer, useRef } from 'react';
|
|
3
|
-
import { Collaboration, createSequentialClock, createSequentialIds } from '@elytracms/core/collaboration';
|
|
4
|
-
import { createRequiredContext } from '@elytracms/studio/lib/required-context';
|
|
5
|
-
import { seedCollabSession } from './collab-seed.js';
|
|
6
|
-
const { Context: CollabContext, useRequired: useCollab } = createRequiredContext('Collab');
|
|
7
|
-
const ME = { id: 'u-you', name: 'You' };
|
|
8
|
-
export function CollabProvider({ projectId, children, }) {
|
|
9
|
-
const [tick, bump] = useReducer((n) => n + 1, 0);
|
|
10
|
-
const [previewMode, setPreviewModeState] = useReducer((_, next) => next, 'draft');
|
|
11
|
-
const ref = useRef(null);
|
|
12
|
-
if (ref.current === null) {
|
|
13
|
-
const collab = new Collaboration({ clock: createSequentialClock(), ids: createSequentialIds() });
|
|
14
|
-
// Seed one empty Initial version + presence for the current user (EC-122/126).
|
|
15
|
-
seedCollabSession(collab, projectId, { author: ME.name });
|
|
16
|
-
collab.presence.join(projectId, ME);
|
|
17
|
-
ref.current = collab;
|
|
18
|
-
}
|
|
19
|
-
const store = useMemo(() => {
|
|
20
|
-
const collab = ref.current;
|
|
21
|
-
return {
|
|
22
|
-
collab,
|
|
23
|
-
projectId,
|
|
24
|
-
me: ME,
|
|
25
|
-
previewMode,
|
|
26
|
-
setPreviewMode: setPreviewModeState,
|
|
27
|
-
mutate: (fn) => {
|
|
28
|
-
const result = fn();
|
|
29
|
-
bump();
|
|
30
|
-
return result;
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
// `tick` (bumped by `mutate`) and `previewMode` are in deps so consumers
|
|
34
|
-
// re-render after an imperative store mutation or a preview change.
|
|
35
|
-
}, [projectId, previewMode, tick]);
|
|
36
|
-
return _jsx(CollabContext.Provider, { value: store, children: children });
|
|
37
|
-
}
|
|
38
|
-
export { useCollab };
|
|
39
|
-
//# sourceMappingURL=collab-context.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"collab-context.js","sourceRoot":"","sources":["../../../src/components/collab/collab-context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAEnD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAA;AAEzG,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAA;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAqBjD,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,qBAAqB,CAAc,QAAQ,CAAC,CAAA;AAEvG,MAAM,EAAE,GAAU,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAA;AAE9C,MAAM,UAAU,cAAc,CAAC,EAC7B,SAAS,EACT,QAAQ,GAIT;IACC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IACxD,MAAM,CAAC,WAAW,EAAE,mBAAmB,CAAC,GAAG,UAAU,CACnD,CAAC,CAAc,EAAE,IAAiB,EAAE,EAAE,CAAC,IAAI,EAC3C,OAAsB,CACvB,CAAA;IAED,MAAM,GAAG,GAAG,MAAM,CAAuB,IAAI,CAAC,CAAA;IAC9C,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE,EAAE,GAAG,EAAE,mBAAmB,EAAE,EAAE,CAAC,CAAA;QAChG,+EAA+E;QAC/E,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAA;QACzD,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;QACnC,GAAG,CAAC,OAAO,GAAG,MAAM,CAAA;IACtB,CAAC;IAED,MAAM,KAAK,GAAG,OAAO,CAAc,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG,GAAG,CAAC,OAAQ,CAAA;QAC3B,OAAO;YACL,MAAM;YACN,SAAS;YACT,EAAE,EAAE,EAAE;YACN,WAAW;YACX,cAAc,EAAE,mBAAmB;YACnC,MAAM,EAAE,CAAC,EAAE,EAAE,EAAE;gBACb,MAAM,MAAM,GAAG,EAAE,EAAE,CAAA;gBACnB,IAAI,EAAE,CAAA;gBACN,OAAO,MAAM,CAAA;YACf,CAAC;SACF,CAAA;QACD,yEAAyE;QACzE,oEAAoE;IACtE,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAA;IAElC,OAAO,KAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA0B,CAAA;AAClF,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,CAAA","sourcesContent":["import { useMemo, useReducer, useRef } from 'react'\nimport type { ReactNode } from 'react'\nimport { Collaboration, createSequentialClock, createSequentialIds } from '@elytracms/core/collaboration'\nimport type { Actor, PreviewMode } from '@elytracms/core/collaboration'\nimport { createRequiredContext } from '@elytracms/studio/lib/required-context'\nimport { seedCollabSession } from './collab-seed'\n\n/**\n * Per-project collaboration session (Phase 10). Holds one {@link Collaboration} store seeded with\n * an initial version + presence for the current user, and exposes a `mutate` helper that re-renders\n * consumers after an imperative store change. Non-persistent (session): it is the builder canvas's\n * session-scoped presence/perspective store. EC-287 retired the project graph and its publish path,\n * so the seed no longer reflects a pinned graph revision; content publishing is per document\n * (EC-224), surfaced by the CMS document Versions pane.\n */\nexport interface CollabStore {\n collab: Collaboration\n projectId: string\n me: Actor\n /** Draft vs published perspective the canvas/preview renders (EC-123). */\n previewMode: PreviewMode\n setPreviewMode: (mode: PreviewMode) => void\n /** Run an imperative store mutation, then re-render consumers. */\n mutate: <T>(fn: () => T) => T\n}\n\nconst { Context: CollabContext, useRequired: useCollab } = createRequiredContext<CollabStore>('Collab')\n\nconst ME: Actor = { id: 'u-you', name: 'You' }\n\nexport function CollabProvider({\n projectId,\n children,\n}: {\n projectId: string\n children: ReactNode\n}) {\n const [tick, bump] = useReducer((n: number) => n + 1, 0)\n const [previewMode, setPreviewModeState] = useReducer(\n (_: PreviewMode, next: PreviewMode) => next,\n 'draft' as PreviewMode,\n )\n\n const ref = useRef<Collaboration | null>(null)\n if (ref.current === null) {\n const collab = new Collaboration({ clock: createSequentialClock(), ids: createSequentialIds() })\n // Seed one empty Initial version + presence for the current user (EC-122/126).\n seedCollabSession(collab, projectId, { author: ME.name })\n collab.presence.join(projectId, ME)\n ref.current = collab\n }\n\n const store = useMemo<CollabStore>(() => {\n const collab = ref.current!\n return {\n collab,\n projectId,\n me: ME,\n previewMode,\n setPreviewMode: setPreviewModeState,\n mutate: (fn) => {\n const result = fn()\n bump()\n return result\n },\n }\n // `tick` (bumped by `mutate`) and `previewMode` are in deps so consumers\n // re-render after an imperative store mutation or a preview change.\n }, [projectId, previewMode, tick])\n\n return <CollabContext.Provider value={store}>{children}</CollabContext.Provider>\n}\n\nexport { useCollab }\n"]}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { Collaboration } from '@elytracms/core/collaboration';
|
|
2
|
-
/**
|
|
3
|
-
* Seed a fresh per-project {@link Collaboration} session.
|
|
4
|
-
*
|
|
5
|
-
* EC-287: the project graph and its publish path are retired (the DB holds
|
|
6
|
-
* content only), so a session no longer reflects a pinned graph revision. The
|
|
7
|
-
* collaboration store stays the builder's session-scoped presence/perspective
|
|
8
|
-
* store; it seeds one empty "Initial" version so `versions.latest()` is defined,
|
|
9
|
-
* with no graph snapshot and nothing published. Content publishing is per
|
|
10
|
-
* document (EC-224), surfaced by the CMS document Versions pane — not here.
|
|
11
|
-
*/
|
|
12
|
-
export declare function seedCollabSession(collab: Collaboration, projectId: string, options: {
|
|
13
|
-
/** Author recorded on the Initial version. */
|
|
14
|
-
author: string;
|
|
15
|
-
}): void;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Seed a fresh per-project {@link Collaboration} session.
|
|
3
|
-
*
|
|
4
|
-
* EC-287: the project graph and its publish path are retired (the DB holds
|
|
5
|
-
* content only), so a session no longer reflects a pinned graph revision. The
|
|
6
|
-
* collaboration store stays the builder's session-scoped presence/perspective
|
|
7
|
-
* store; it seeds one empty "Initial" version so `versions.latest()` is defined,
|
|
8
|
-
* with no graph snapshot and nothing published. Content publishing is per
|
|
9
|
-
* document (EC-224), surfaced by the CMS document Versions pane — not here.
|
|
10
|
-
*/
|
|
11
|
-
export function seedCollabSession(collab, projectId, options) {
|
|
12
|
-
collab.versions.create(projectId, {
|
|
13
|
-
snapshot: '',
|
|
14
|
-
label: 'Initial',
|
|
15
|
-
message: 'Project opened.',
|
|
16
|
-
author: options.author,
|
|
17
|
-
origin: 'import',
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
//# sourceMappingURL=collab-seed.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"collab-seed.js","sourceRoot":"","sources":["../../../src/components/collab/collab-seed.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAqB,EACrB,SAAiB,EACjB,OAGC;IAED,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE;QAChC,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,iBAAiB;QAC1B,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,MAAM,EAAE,QAAQ;KACjB,CAAC,CAAA;AACJ,CAAC","sourcesContent":["import type { Collaboration } from '@elytracms/core/collaboration'\n\n/**\n * Seed a fresh per-project {@link Collaboration} session.\n *\n * EC-287: the project graph and its publish path are retired (the DB holds\n * content only), so a session no longer reflects a pinned graph revision. The\n * collaboration store stays the builder's session-scoped presence/perspective\n * store; it seeds one empty \"Initial\" version so `versions.latest()` is defined,\n * with no graph snapshot and nothing published. Content publishing is per\n * document (EC-224), surfaced by the CMS document Versions pane — not here.\n */\nexport function seedCollabSession(\n collab: Collaboration,\n projectId: string,\n options: {\n /** Author recorded on the Initial version. */\n author: string\n },\n): void {\n collab.versions.create(projectId, {\n snapshot: '',\n label: 'Initial',\n message: 'Project opened.',\n author: options.author,\n origin: 'import',\n })\n}\n"]}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The Extensions surface (Phase 11, EC-130–137). A live, agent-inspectable view over the
|
|
3
|
-
* extensibility layer: browse a public + private marketplace, install plugins into a host, and
|
|
4
|
-
* inspect what each surface contributes (components, field types, data sources, asset storage,
|
|
5
|
-
* export targets, hooks). All state is deterministic — driven by `@elytracms/core/plugins` fixtures.
|
|
6
|
-
*/
|
|
7
|
-
export declare function ExtensionsView(): import("react").JSX.Element;
|