@velastack/cms 0.2.3 → 0.2.5

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.
@@ -393,10 +393,6 @@
393
393
  cmsStore.loadAndApplySiteOverlay(endpoint, intent.previewKey)
394
394
  ]);
395
395
  break;
396
- case 'clear-overlay':
397
- versionRelease = null;
398
- cmsStore.clearOverlay();
399
- break;
400
396
  }
401
397
  }
402
398
  })();
@@ -226,7 +226,8 @@
226
226
  data-popover-open={pageSelectOpen ? '' : undefined}
227
227
  >
228
228
  {#if children}
229
- <span class="cms-link-edit__custom">
229
+ <!-- svelte-ignore a11y_no_static_element_interactions -->
230
+ <span class="cms-link-edit__custom" onclickcapture={blockNav}>
230
231
  {@render children(renderProps)}
231
232
  </span>
232
233
  {:else}
@@ -390,6 +391,15 @@
390
391
  white-space: nowrap;
391
392
  font-family: ui-sans-serif, system-ui, sans-serif;
392
393
  }
394
+ /* Bridge the gap between the link and the toolbar so hover isn't lost crossing it. */
395
+ .cms-link-edit__toolbar::after {
396
+ content: '';
397
+ position: absolute;
398
+ top: 100%;
399
+ left: 0;
400
+ right: 0;
401
+ height: 0.5rem;
402
+ }
393
403
  .cms-link-edit:hover .cms-link-edit__toolbar,
394
404
  .cms-link-edit:focus-within .cms-link-edit__toolbar,
395
405
  .cms-link-edit[data-popover-open] .cms-link-edit__toolbar {
@@ -43,6 +43,12 @@
43
43
  </script>
44
44
 
45
45
  {#if editable && ref}
46
+ <!-- Mounted straight into edit mode (navigation while editing): the
47
+ children branch below never rendered, so render it hidden once to
48
+ capture the default markup. Removed as soon as it's captured. -->
49
+ {#if children && initialFromChildren === undefined}
50
+ <div bind:this={childrenEl} class="cms-rich-text-capture">{@render children()}</div>
51
+ {/if}
46
52
  {#await import('./cms-rich-text-editable.svelte') then { default: Editable }}
47
53
  <Editable scope={ref} {name} initial={editInitial} />
48
54
  {/await}
@@ -63,6 +69,9 @@
63
69
  .cms-rich-text-children {
64
70
  display: contents;
65
71
  }
72
+ .cms-rich-text-capture {
73
+ display: none;
74
+ }
66
75
  .cms-missing {
67
76
  padding: 0.25rem 0.5rem;
68
77
  border: 1px dashed rgba(127, 127, 127, 0.6);
@@ -73,6 +73,12 @@
73
73
  </script>
74
74
 
75
75
  {#if editable && ref}
76
+ <!-- Mounted straight into edit mode (navigation while editing): the
77
+ children branch below never rendered, so render it hidden once to
78
+ capture the default text. Removed as soon as it's captured. -->
79
+ {#if children && initialFromChildren === undefined}
80
+ <span bind:this={childrenEl} class="cms-text-capture">{@render children()}</span>
81
+ {/if}
76
82
  <span
77
83
  bind:this={el}
78
84
  class="cms-text-editable"
@@ -118,6 +124,9 @@
118
124
  .cms-text-children {
119
125
  display: contents;
120
126
  }
127
+ .cms-text-capture {
128
+ display: none;
129
+ }
121
130
 
122
131
  .cms-missing {
123
132
  display: inline-block;
@@ -20,16 +20,15 @@ export type OverlayIntent = {
20
20
  versionKey: string;
21
21
  locale: string;
22
22
  }
23
- /** `previewKey: null` fetches published-only — used when previewing a
24
- * non-default locale without an open draft, so the overlay carries the
25
- * locale's published tree (with default-locale fallback merged by
26
- * `loadAndApplyOverlay`'s dual-fetch). */
23
+ /** `previewKey: null` fetches published-only. Used whenever there is no
24
+ * open draft: the overlay then carries the locale's *current* published
25
+ * tree (with default-locale fallback merged by `loadAndApplyOverlay`'s
26
+ * dual-fetch), masking `page.data.cms.docs` — which on a static-export
27
+ * site is frozen at build time and goes stale with every publish. */
27
28
  | {
28
29
  kind: 'load-overlay';
29
30
  previewKey: string | null;
30
31
  locale: string;
31
- } | {
32
- kind: 'clear-overlay';
33
32
  };
34
33
  export interface OverlaySyncInput {
35
34
  /** `?version=…` URL param: when set, we're in past-release snapshot mode. */
@@ -38,10 +37,10 @@ export interface OverlaySyncInput {
38
37
  locale: string;
39
38
  /**
40
39
  * `page.data.cms.locale` — the locale the server rendered for this request.
41
- * When `locale === pageLocale`, the page's `cms.docs` already provides the
42
- * base content (no overlay needed for "show the published tree"). When
43
- * they differ, we must load the overlay so non-default-locale views see
44
- * content (with default-locale fallback) rather than empty fields.
40
+ * Kept on the input for parity with the store's `mergedTree`, which only
41
+ * folds `cms.docs` into the base when `locale === pageLocale`. The sync
42
+ * decision no longer branches on it: the published overlay is loaded
43
+ * either way (see rule 7).
45
44
  */
46
45
  pageLocale: string;
47
46
  /** Current open-release preview_key from `cmsStore.openRelease`, or null. */
@@ -66,16 +65,16 @@ export interface OverlaySyncInput {
66
65
  * first; the param change re-runs the effect into rule 5.
67
66
  * 5. With an open release whose key matches: load the draft overlay.
68
67
  * 6. With no open release but a stale `?preview=`: strip the param. Then
69
- * fall through to rule 7's locale logic in the *same* intent batch so the
70
- * field render isn't briefly empty between strip and the next effect run.
71
- * 7. With no open release and no draft overlay needed:
72
- * - `locale === pageLocale`: clear the overlay — the page's `cms.docs` is
73
- * authoritative and matching, so the field reads from base directly.
74
- * - `locale !== pageLocale`: load published-only overlay. Without this,
75
- * `mergedTree(non-pageLocale)` would have empty base AND empty overlay,
76
- * and fields would fall through to their component fallback even though
77
- * a default-locale value exists. The dual-fetch in `loadAndApplyOverlay`
78
- * composes the `requested → default → undefined` chain.
68
+ * fall through to rule 7 in the *same* intent batch so the field render
69
+ * isn't briefly empty between strip and the next effect run.
70
+ * 7. With no open release: load the published-only overlay for `locale`.
71
+ * The page's `cms.docs` is NOT authoritative for an editor — on a
72
+ * static-export site it was captured at build time, so after any later
73
+ * publish it lags the backend until the next deploy. The overlay fetched
74
+ * from `/docs` is always current, and for `locale !== pageLocale` it is
75
+ * the only source of content at all (`mergedTree` folds in no base for
76
+ * other locales). The dual-fetch in `loadAndApplyOverlay` composes the
77
+ * `requested → default → undefined` chain.
79
78
  */
80
79
  export declare function deriveOverlayIntents(input: OverlaySyncInput): OverlayIntent[];
81
80
  /** Stable cache key for `(scope, locale)` overlay/draft buckets. */
@@ -21,16 +21,16 @@
21
21
  * first; the param change re-runs the effect into rule 5.
22
22
  * 5. With an open release whose key matches: load the draft overlay.
23
23
  * 6. With no open release but a stale `?preview=`: strip the param. Then
24
- * fall through to rule 7's locale logic in the *same* intent batch so the
25
- * field render isn't briefly empty between strip and the next effect run.
26
- * 7. With no open release and no draft overlay needed:
27
- * - `locale === pageLocale`: clear the overlay — the page's `cms.docs` is
28
- * authoritative and matching, so the field reads from base directly.
29
- * - `locale !== pageLocale`: load published-only overlay. Without this,
30
- * `mergedTree(non-pageLocale)` would have empty base AND empty overlay,
31
- * and fields would fall through to their component fallback even though
32
- * a default-locale value exists. The dual-fetch in `loadAndApplyOverlay`
33
- * composes the `requested → default → undefined` chain.
24
+ * fall through to rule 7 in the *same* intent batch so the field render
25
+ * isn't briefly empty between strip and the next effect run.
26
+ * 7. With no open release: load the published-only overlay for `locale`.
27
+ * The page's `cms.docs` is NOT authoritative for an editor — on a
28
+ * static-export site it was captured at build time, so after any later
29
+ * publish it lags the backend until the next deploy. The overlay fetched
30
+ * from `/docs` is always current, and for `locale !== pageLocale` it is
31
+ * the only source of content at all (`mergedTree` folds in no base for
32
+ * other locales). The dual-fetch in `loadAndApplyOverlay` composes the
33
+ * `requested → default → undefined` chain.
34
34
  */
35
35
  export function deriveOverlayIntents(input) {
36
36
  const intents = [];
@@ -58,12 +58,7 @@ export function deriveOverlayIntents(input) {
58
58
  if (input.previewParam) {
59
59
  intents.push({ kind: 'set-preview-param', value: null });
60
60
  }
61
- if (input.locale !== input.pageLocale) {
62
- intents.push({ kind: 'load-overlay', previewKey: null, locale: input.locale });
63
- }
64
- else {
65
- intents.push({ kind: 'clear-overlay' });
66
- }
61
+ intents.push({ kind: 'load-overlay', previewKey: null, locale: input.locale });
67
62
  return intents;
68
63
  }
69
64
  /** Stable cache key for `(scope, locale)` overlay/draft buckets. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velastack/cms",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "A scope-aware CMS for SvelteKit, for static or dynamic sites.",
5
5
  "keywords": [
6
6
  "svelte",