@elytracms/studio 0.0.77 → 0.0.79

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.
Files changed (90) hide show
  1. package/convex/contract-parity.test.ts +238 -0
  2. package/convex/tsconfig.json +3 -1
  3. package/dist/components/app-views/default-modules.js +5 -1
  4. package/dist/components/app-views/default-modules.js.map +1 -1
  5. package/dist/components/assets/asset-thumb.js +12 -11
  6. package/dist/components/assets/asset-thumb.js.map +1 -1
  7. package/dist/components/builder/blocks-panel.d.ts +11 -5
  8. package/dist/components/builder/blocks-panel.js +18 -24
  9. package/dist/components/builder/blocks-panel.js.map +1 -1
  10. package/dist/components/builder/canvas-render-context.d.ts +22 -0
  11. package/dist/components/builder/canvas-render-context.js +65 -9
  12. package/dist/components/builder/canvas-render-context.js.map +1 -1
  13. package/dist/components/builder/reuse.d.ts +25 -0
  14. package/dist/components/builder/reuse.js +11 -2
  15. package/dist/components/builder/reuse.js.map +1 -1
  16. package/dist/components/cms/asset-field.js +52 -19
  17. package/dist/components/cms/asset-field.js.map +1 -1
  18. package/dist/components/cms/asset-picker-core.d.ts +40 -0
  19. package/dist/components/cms/asset-picker-core.js +21 -0
  20. package/dist/components/cms/asset-picker-core.js.map +1 -1
  21. package/dist/components/cms/asset-picker.d.ts +11 -2
  22. package/dist/components/cms/asset-picker.js +34 -13
  23. package/dist/components/cms/asset-picker.js.map +1 -1
  24. package/dist/components/cms/cell.js +2 -1
  25. package/dist/components/cms/cell.js.map +1 -1
  26. package/dist/components/cms/cms-store.d.ts +8 -1
  27. package/dist/components/cms/cms-store.js +8 -7
  28. package/dist/components/cms/cms-store.js.map +1 -1
  29. package/dist/components/cms/collection-table.js +8 -2
  30. package/dist/components/cms/collection-table.js.map +1 -1
  31. package/dist/components/cms/date-input-core.d.ts +64 -0
  32. package/dist/components/cms/date-input-core.js +78 -0
  33. package/dist/components/cms/date-input-core.js.map +1 -0
  34. package/dist/components/cms/date-input.d.ts +43 -0
  35. package/dist/components/cms/date-input.js +109 -0
  36. package/dist/components/cms/date-input.js.map +1 -0
  37. package/dist/components/cms/detail-editor.js.map +1 -1
  38. package/dist/components/cms/document-diff-view.js +2 -1
  39. package/dist/components/cms/document-diff-view.js.map +1 -1
  40. package/dist/components/cms/document-staging.d.ts +15 -4
  41. package/dist/components/cms/document-staging.js +26 -15
  42. package/dist/components/cms/document-staging.js.map +1 -1
  43. package/dist/components/cms/editable-cell.js +39 -5
  44. package/dist/components/cms/editable-cell.js.map +1 -1
  45. package/dist/components/cms/field-control.js +38 -7
  46. package/dist/components/cms/field-control.js.map +1 -1
  47. package/dist/components/cms/scalar-value-editor.js +4 -1
  48. package/dist/components/cms/scalar-value-editor.js.map +1 -1
  49. package/dist/components/cms/slug-auto-derive.d.ts +41 -0
  50. package/dist/components/cms/slug-auto-derive.js +14 -0
  51. package/dist/components/cms/slug-auto-derive.js.map +1 -0
  52. package/dist/components/components/transfer-dialog.js +3 -1
  53. package/dist/components/components/transfer-dialog.js.map +1 -1
  54. package/dist/components/project-session.d.ts +44 -22
  55. package/dist/components/project-session.js +72 -36
  56. package/dist/components/project-session.js.map +1 -1
  57. package/dist/lib/assets/asset-url.d.ts +20 -0
  58. package/dist/lib/assets/asset-url.js +25 -0
  59. package/dist/lib/assets/asset-url.js.map +1 -0
  60. package/dist/lib/assets/browser-blob-storage.d.ts +80 -0
  61. package/dist/lib/assets/browser-blob-storage.js +86 -0
  62. package/dist/lib/assets/browser-blob-storage.js.map +1 -0
  63. package/dist/lib/assets/index.d.ts +2 -0
  64. package/dist/lib/assets/index.js +2 -0
  65. package/dist/lib/assets/index.js.map +1 -1
  66. package/dist/lib/data/collection-content.d.ts +20 -1
  67. package/dist/lib/data/collection-content.js +51 -1
  68. package/dist/lib/data/collection-content.js.map +1 -1
  69. package/dist/lib/data/content-session-refresh.d.ts +74 -0
  70. package/dist/lib/data/content-session-refresh.js +138 -0
  71. package/dist/lib/data/content-session-refresh.js.map +1 -0
  72. package/dist/lib/data/index.d.ts +2 -0
  73. package/dist/lib/data/index.js +2 -0
  74. package/dist/lib/data/index.js.map +1 -1
  75. package/dist/lib/data/playground-unload-guard.d.ts +22 -0
  76. package/dist/lib/data/playground-unload-guard.js +73 -0
  77. package/dist/lib/data/playground-unload-guard.js.map +1 -0
  78. package/dist/lib/i18n/messages.de.js +3 -1
  79. package/dist/lib/i18n/messages.de.js.map +1 -1
  80. package/dist/lib/i18n/messages.en.d.ts +2 -0
  81. package/dist/lib/i18n/messages.en.js +5 -1
  82. package/dist/lib/i18n/messages.en.js.map +1 -1
  83. package/dist/lib/persistence/convex-adapter.js +3 -3
  84. package/dist/lib/persistence/convex-adapter.js.map +1 -1
  85. package/dist/lib/persistence/index.js +6 -1
  86. package/dist/lib/persistence/index.js.map +1 -1
  87. package/dist/ui/input.d.ts +8 -3
  88. package/dist/ui/input.js +6 -1
  89. package/dist/ui/input.js.map +1 -1
  90. package/package.json +3 -2
@@ -0,0 +1,22 @@
1
+ import type { OperationEvent } from '@elytracms/studio/lib/operations';
2
+ /** Should this operation event arm the playground unload guard? */
3
+ export declare function shouldArmUnloadGuard(event: OperationEvent, playground?: boolean): boolean;
4
+ export interface UnloadGuardState {
5
+ /** A qualifying write happened — register the listener once. */
6
+ arm(): void;
7
+ /** Is the guard live (listener registered)? */
8
+ isArmed(): boolean;
9
+ }
10
+ /**
11
+ * The arm-once state machine. `register` is the injected DOM seam — it is
12
+ * called exactly once, on the first arm, with the handler that flags the
13
+ * unload prompt (`event.preventDefault()` + legacy `returnValue`).
14
+ */
15
+ export declare function createUnloadGuardState(register: (handler: (event: BeforeUnloadEvent) => void) => void): UnloadGuardState;
16
+ /**
17
+ * Feed an operation event to the guard (the project session's event-bus
18
+ * subscription calls this alongside the content-session staleness mark).
19
+ */
20
+ export declare function notePlaygroundWriteForUnloadGuard(event: OperationEvent): void;
21
+ /** Introspection seam (live verification + tests): is the page-level guard armed? */
22
+ export declare function isPlaygroundUnloadGuardArmed(): boolean;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * EC-461 — the playground `beforeunload` guard.
3
+ *
4
+ * The playground's world is one in-memory adapter: a full page unload — a
5
+ * reload, a Vite full-reload after a source edit (HMR), a hard top-level
6
+ * navigation, a closed tab — destroys every authored document, schema change,
7
+ * asset and publish irrecoverably. That is documented semantics, but losing it
8
+ * SILENTLY is not acceptable once the session actually holds authored state.
9
+ *
10
+ * The rule (stated once, applied everywhere): the guard arms in PLAYGROUND
11
+ * mode only, the first time a content-bearing write command succeeds on the
12
+ * operations event bus (the same `isContentSessionWrite` predicate the EC-460
13
+ * content-session sync uses — documents/schema/assets), and never disarms for
14
+ * the rest of the page's life: any such write means the world has diverged
15
+ * from its deterministic seed, and nothing short of the unload itself brings
16
+ * it back. Connected mode never arms — writes persist to the backend within
17
+ * the autosave rhythm, in-app navigation flushes pending autosaves on unmount,
18
+ * and explicit-save rails carry their own `UnsavedChangesGuard`; a blanket
19
+ * unload prompt there would cry wolf on every visit.
20
+ *
21
+ * The decision core ({@link createUnloadGuardState}) is pure (house pattern);
22
+ * the module singleton below injects the real `window` listener registration.
23
+ * Browsers require sticky user activation to actually show the dialog — an
24
+ * un-interacted-with tab reloads silently regardless, which is fine: any
25
+ * authored write implies interaction.
26
+ */
27
+ import { isPlaygroundMode } from '@elytracms/studio/lib/persistence';
28
+ import { isContentSessionWrite } from './content-session-refresh.js';
29
+ /** Should this operation event arm the playground unload guard? */
30
+ export function shouldArmUnloadGuard(event, playground = isPlaygroundMode()) {
31
+ return playground && isContentSessionWrite(event);
32
+ }
33
+ /**
34
+ * The arm-once state machine. `register` is the injected DOM seam — it is
35
+ * called exactly once, on the first arm, with the handler that flags the
36
+ * unload prompt (`event.preventDefault()` + legacy `returnValue`).
37
+ */
38
+ export function createUnloadGuardState(register) {
39
+ let armed = false;
40
+ return {
41
+ arm() {
42
+ if (armed)
43
+ return;
44
+ armed = true;
45
+ register((event) => {
46
+ event.preventDefault();
47
+ // Legacy channel — some browsers still require a truthy returnValue.
48
+ event.returnValue = '';
49
+ });
50
+ },
51
+ isArmed() {
52
+ return armed;
53
+ },
54
+ };
55
+ }
56
+ // --- App wiring (module singleton) -------------------------------------------------
57
+ const guard = createUnloadGuardState((handler) => {
58
+ if (typeof window !== 'undefined')
59
+ window.addEventListener('beforeunload', handler);
60
+ });
61
+ /**
62
+ * Feed an operation event to the guard (the project session's event-bus
63
+ * subscription calls this alongside the content-session staleness mark).
64
+ */
65
+ export function notePlaygroundWriteForUnloadGuard(event) {
66
+ if (shouldArmUnloadGuard(event))
67
+ guard.arm();
68
+ }
69
+ /** Introspection seam (live verification + tests): is the page-level guard armed? */
70
+ export function isPlaygroundUnloadGuardArmed() {
71
+ return guard.isArmed();
72
+ }
73
+ //# sourceMappingURL=playground-unload-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playground-unload-guard.js","sourceRoot":"","sources":["../../../src/lib/data/playground-unload-guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAEpE,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAA;AAEjE,mEAAmE;AACnE,MAAM,UAAU,oBAAoB,CAClC,KAAqB,EACrB,aAAsB,gBAAgB,EAAE;IAExC,OAAO,UAAU,IAAI,qBAAqB,CAAC,KAAK,CAAC,CAAA;AACnD,CAAC;AASD;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAA+D;IAE/D,IAAI,KAAK,GAAG,KAAK,CAAA;IACjB,OAAO;QACL,GAAG;YACD,IAAI,KAAK;gBAAE,OAAM;YACjB,KAAK,GAAG,IAAI,CAAA;YACZ,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE;gBACjB,KAAK,CAAC,cAAc,EAAE,CAAA;gBACtB,qEAAqE;gBACrE,KAAK,CAAC,WAAW,GAAG,EAAE,CAAA;YACxB,CAAC,CAAC,CAAA;QACJ,CAAC;QACD,OAAO;YACL,OAAO,KAAK,CAAA;QACd,CAAC;KACF,CAAA;AACH,CAAC;AAED,sFAAsF;AAEtF,MAAM,KAAK,GAAG,sBAAsB,CAAC,CAAC,OAAO,EAAE,EAAE;IAC/C,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;AACrF,CAAC,CAAC,CAAA;AAEF;;;GAGG;AACH,MAAM,UAAU,iCAAiC,CAAC,KAAqB;IACrE,IAAI,oBAAoB,CAAC,KAAK,CAAC;QAAE,KAAK,CAAC,GAAG,EAAE,CAAA;AAC9C,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,4BAA4B;IAC1C,OAAO,KAAK,CAAC,OAAO,EAAE,CAAA;AACxB,CAAC","sourcesContent":["/**\n * EC-461 — the playground `beforeunload` guard.\n *\n * The playground's world is one in-memory adapter: a full page unload — a\n * reload, a Vite full-reload after a source edit (HMR), a hard top-level\n * navigation, a closed tab — destroys every authored document, schema change,\n * asset and publish irrecoverably. That is documented semantics, but losing it\n * SILENTLY is not acceptable once the session actually holds authored state.\n *\n * The rule (stated once, applied everywhere): the guard arms in PLAYGROUND\n * mode only, the first time a content-bearing write command succeeds on the\n * operations event bus (the same `isContentSessionWrite` predicate the EC-460\n * content-session sync uses — documents/schema/assets), and never disarms for\n * the rest of the page's life: any such write means the world has diverged\n * from its deterministic seed, and nothing short of the unload itself brings\n * it back. Connected mode never arms — writes persist to the backend within\n * the autosave rhythm, in-app navigation flushes pending autosaves on unmount,\n * and explicit-save rails carry their own `UnsavedChangesGuard`; a blanket\n * unload prompt there would cry wolf on every visit.\n *\n * The decision core ({@link createUnloadGuardState}) is pure (house pattern);\n * the module singleton below injects the real `window` listener registration.\n * Browsers require sticky user activation to actually show the dialog — an\n * un-interacted-with tab reloads silently regardless, which is fine: any\n * authored write implies interaction.\n */\nimport { isPlaygroundMode } from '@elytracms/studio/lib/persistence'\nimport type { OperationEvent } from '@elytracms/studio/lib/operations'\nimport { isContentSessionWrite } from './content-session-refresh'\n\n/** Should this operation event arm the playground unload guard? */\nexport function shouldArmUnloadGuard(\n event: OperationEvent,\n playground: boolean = isPlaygroundMode(),\n): boolean {\n return playground && isContentSessionWrite(event)\n}\n\nexport interface UnloadGuardState {\n /** A qualifying write happened — register the listener once. */\n arm(): void\n /** Is the guard live (listener registered)? */\n isArmed(): boolean\n}\n\n/**\n * The arm-once state machine. `register` is the injected DOM seam — it is\n * called exactly once, on the first arm, with the handler that flags the\n * unload prompt (`event.preventDefault()` + legacy `returnValue`).\n */\nexport function createUnloadGuardState(\n register: (handler: (event: BeforeUnloadEvent) => void) => void,\n): UnloadGuardState {\n let armed = false\n return {\n arm() {\n if (armed) return\n armed = true\n register((event) => {\n event.preventDefault()\n // Legacy channel — some browsers still require a truthy returnValue.\n event.returnValue = ''\n })\n },\n isArmed() {\n return armed\n },\n }\n}\n\n// --- App wiring (module singleton) -------------------------------------------------\n\nconst guard = createUnloadGuardState((handler) => {\n if (typeof window !== 'undefined') window.addEventListener('beforeunload', handler)\n})\n\n/**\n * Feed an operation event to the guard (the project session's event-bus\n * subscription calls this alongside the content-session staleness mark).\n */\nexport function notePlaygroundWriteForUnloadGuard(event: OperationEvent): void {\n if (shouldArmUnloadGuard(event)) guard.arm()\n}\n\n/** Introspection seam (live verification + tests): is the page-level guard armed? */\nexport function isPlaygroundUnloadGuardArmed(): boolean {\n return guard.isArmed()\n}\n"]}
@@ -215,7 +215,7 @@ export const deMessages = {
215
215
  'cms.list.emptyNone': 'Noch keine {noun}.',
216
216
  'cms.list.emptyFiltered': 'Keine Dokumente entsprechen den Filtern der aktuellen Ansicht.',
217
217
  'cms.list.selectAll': 'Alle Dokumente in der Ansicht auswählen',
218
- 'cms.list.selectRow': '{id} auswählen',
218
+ 'cms.list.selectRow': '{title} auswählen',
219
219
  'cms.list.column.title': 'Titel',
220
220
  'cms.list.column.state': 'Status',
221
221
  // EC-448 — Icon-Header der fixierten Status-Punkt-Spalte (nur `aria-label`/`title`).
@@ -306,6 +306,7 @@ export const deMessages = {
306
306
  'cms.cell.blockCount.other': '{count} Blöcke',
307
307
  'cms.cell.createsVariantTitle': 'Beim Speichern wird die {locale}-Übersetzung dieses Feldes erstellt.',
308
308
  'cms.cell.newVariant': 'neu',
309
+ 'cms.cell.editAria': '{field} von {title} bearbeiten',
309
310
  // ─────────────────────────────────────────────────────────────────────────
310
311
  // CMS — document detail editor
311
312
  // ─────────────────────────────────────────────────────────────────────────
@@ -940,6 +941,7 @@ export const deMessages = {
940
941
  'builder.canvas.reusableMissingTitle': 'Dieses wiederverwendbare Element fehlt',
941
942
  'builder.canvas.reusableUnpublishedHint': 'Veröffentlichen Sie es, um es hier und auf Live-Seiten anzuzeigen — oder öffnen Sie es im Eigenschaften-Panel, um weiter zu bearbeiten.',
942
943
  'builder.canvas.reusableMissingHint': 'Öffnen Sie das „Element“ der Einbettung im Eigenschaften-Panel, um die Referenz zu korrigieren.',
944
+ 'builder.canvas.listingInvalidTitle': 'Diese Liste kann nicht ausgeführt werden:',
943
945
  'builder.canvas.viewportPreviewAria': '{label} Vorschau',
944
946
  'builder.canvas.viewportWidthTitle': '{label} Breite',
945
947
  'builder.canvas.breakpointsIssueLabel': 'Breakpoints',