@velastack/cms 0.3.1 → 0.5.0

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 (132) hide show
  1. package/README.md +107 -18
  2. package/dist/backend/index.d.ts +1 -1
  3. package/dist/backend/routes/release.js +2 -2
  4. package/dist/backend/routes/seed.d.ts +6 -0
  5. package/dist/backend/routes/seed.js +96 -0
  6. package/dist/backend/routes/table.js +3 -0
  7. package/dist/backend/store/migrations/0004-release-publisher.d.ts +1 -0
  8. package/dist/backend/store/migrations/0004-release-publisher.js +15 -0
  9. package/dist/backend/store/migrations/index.js +3 -1
  10. package/dist/backend/store/queries.d.ts +9 -3
  11. package/dist/backend/store/queries.js +105 -11
  12. package/dist/cms.js +13 -16
  13. package/dist/components/admin-bar/admin-bar-internal.svelte +4 -4
  14. package/dist/components/admin-bar/admin-bar.css +1 -1
  15. package/dist/components/admin-bar/field-input.svelte +220 -0
  16. package/dist/components/admin-bar/field-input.svelte.d.ts +29 -0
  17. package/dist/components/admin-bar/history-panel.svelte +4 -5
  18. package/dist/components/admin-bar/icons/pencil.svelte +19 -0
  19. package/dist/components/admin-bar/icons/pencil.svelte.d.ts +3 -0
  20. package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte +1 -1
  21. package/dist/components/admin-bar/locales-panel.svelte +42 -1
  22. package/dist/components/admin-bar/page-config.d.ts +8 -1
  23. package/dist/components/admin-bar/page-config.js +15 -2
  24. package/dist/components/admin-bar/reorder-buttons.svelte +52 -0
  25. package/dist/components/admin-bar/reorder-buttons.svelte.d.ts +10 -0
  26. package/dist/components/admin-bar/seo-panel.svelte +144 -189
  27. package/dist/components/admin-bar/site-options-panel.svelte +115 -0
  28. package/dist/components/admin-bar/site-options-panel.svelte.d.ts +7 -0
  29. package/dist/components/admin-bar/structured-editor-popover.svelte +250 -0
  30. package/dist/components/admin-bar/structured-editor-popover.svelte.d.ts +48 -0
  31. package/dist/components/admin-bar/ui/checkbox/checkbox.svelte +36 -0
  32. package/dist/components/admin-bar/ui/checkbox/checkbox.svelte.d.ts +5 -0
  33. package/dist/components/admin-bar/ui/checkbox/index.d.ts +2 -0
  34. package/dist/components/admin-bar/ui/checkbox/index.js +2 -0
  35. package/dist/components/admin-bar/ui/popover/index.d.ts +5 -0
  36. package/dist/components/admin-bar/ui/popover/index.js +7 -0
  37. package/dist/components/admin-bar/ui/popover/popover-close.svelte +7 -0
  38. package/dist/components/admin-bar/ui/popover/popover-close.svelte.d.ts +4 -0
  39. package/dist/components/admin-bar/ui/popover/popover-content.svelte +35 -0
  40. package/dist/components/admin-bar/ui/popover/popover-content.svelte.d.ts +10 -0
  41. package/dist/components/admin-bar/ui/popover/popover-trigger.svelte +7 -0
  42. package/dist/components/admin-bar/ui/popover/popover-trigger.svelte.d.ts +4 -0
  43. package/dist/components/admin-bar/ui/popover/popover.svelte +7 -0
  44. package/dist/components/admin-bar/ui/popover/popover.svelte.d.ts +3 -0
  45. package/dist/components/admin-bar/ui/sheet/index.d.ts +10 -0
  46. package/dist/components/admin-bar/ui/sheet/index.js +12 -0
  47. package/dist/components/admin-bar/ui/sheet/sheet-close.svelte +7 -0
  48. package/dist/components/admin-bar/ui/sheet/sheet-close.svelte.d.ts +4 -0
  49. package/dist/components/admin-bar/ui/sheet/sheet-content.svelte +64 -0
  50. package/dist/components/admin-bar/ui/sheet/sheet-content.svelte.d.ts +17 -0
  51. package/dist/components/admin-bar/ui/sheet/sheet-description.svelte +17 -0
  52. package/dist/components/admin-bar/ui/sheet/sheet-description.svelte.d.ts +4 -0
  53. package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte +23 -0
  54. package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte.d.ts +5 -0
  55. package/dist/components/admin-bar/ui/sheet/sheet-header.svelte +20 -0
  56. package/dist/components/admin-bar/ui/sheet/sheet-header.svelte.d.ts +5 -0
  57. package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte +20 -0
  58. package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
  59. package/dist/components/admin-bar/ui/sheet/sheet-title.svelte +17 -0
  60. package/dist/components/admin-bar/ui/sheet/sheet-title.svelte.d.ts +4 -0
  61. package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte +7 -0
  62. package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
  63. package/dist/components/admin-bar/ui/sheet/sheet.svelte +7 -0
  64. package/dist/components/admin-bar/ui/sheet/sheet.svelte.d.ts +3 -0
  65. package/dist/components/admin-bar/ui/switch/index.d.ts +2 -0
  66. package/dist/components/admin-bar/ui/switch/index.js +2 -0
  67. package/dist/components/admin-bar/ui/switch/switch.svelte +27 -0
  68. package/dist/components/admin-bar/ui/switch/switch.svelte.d.ts +5 -0
  69. package/dist/components/admin-bar/ui/tabs/index.d.ts +5 -0
  70. package/dist/components/admin-bar/ui/tabs/index.js +7 -0
  71. package/dist/components/admin-bar/ui/tabs/tabs-content.svelte +17 -0
  72. package/dist/components/admin-bar/ui/tabs/tabs-content.svelte.d.ts +4 -0
  73. package/dist/components/admin-bar/ui/tabs/tabs-list.svelte +16 -0
  74. package/dist/components/admin-bar/ui/tabs/tabs-list.svelte.d.ts +4 -0
  75. package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte +20 -0
  76. package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  77. package/dist/components/admin-bar/ui/tabs/tabs.svelte +19 -0
  78. package/dist/components/admin-bar/ui/tabs/tabs.svelte.d.ts +4 -0
  79. package/dist/components/cms/cms-boolean.svelte +9 -18
  80. package/dist/components/cms/cms-boolean.svelte.d.ts +1 -0
  81. package/dist/components/cms/cms-date-time-editable.svelte +3 -3
  82. package/dist/components/cms/cms-date-time.svelte +17 -17
  83. package/dist/components/cms/cms-date-time.svelte.d.ts +2 -1
  84. package/dist/components/cms/cms-image-editable.svelte +13 -4
  85. package/dist/components/cms/cms-image.svelte +37 -30
  86. package/dist/components/cms/cms-image.svelte.d.ts +11 -4
  87. package/dist/components/cms/cms-link.svelte +26 -19
  88. package/dist/components/cms/cms-link.svelte.d.ts +2 -0
  89. package/dist/components/cms/cms-markdown.svelte +15 -16
  90. package/dist/components/cms/cms-markdown.svelte.d.ts +1 -0
  91. package/dist/components/cms/cms-number-editable.svelte +4 -2
  92. package/dist/components/cms/cms-number.svelte +18 -17
  93. package/dist/components/cms/cms-number.svelte.d.ts +2 -1
  94. package/dist/components/cms/cms-repeater.svelte +15 -18
  95. package/dist/components/cms/cms-repeater.svelte.d.ts +1 -0
  96. package/dist/components/cms/cms-rich-text.svelte +17 -22
  97. package/dist/components/cms/cms-rich-text.svelte.d.ts +1 -0
  98. package/dist/components/cms/cms-store.svelte.d.ts +14 -0
  99. package/dist/components/cms/cms-store.svelte.js +39 -2
  100. package/dist/components/cms/cms-text.svelte +23 -30
  101. package/dist/components/cms/cms-text.svelte.d.ts +3 -1
  102. package/dist/components/cms/scope.d.ts +25 -5
  103. package/dist/components/cms/structured-registry.d.ts +10 -0
  104. package/dist/components/cms/structured-registry.js +6 -0
  105. package/dist/components/cms/use-cms-field.svelte.d.ts +54 -0
  106. package/dist/components/cms/use-cms-field.svelte.js +83 -0
  107. package/dist/core/metadata.d.ts +44 -0
  108. package/dist/core/metadata.js +59 -0
  109. package/dist/core/structured.d.ts +108 -0
  110. package/dist/core/structured.js +184 -0
  111. package/dist/core/wire.d.ts +42 -2
  112. package/dist/editor.d.ts +22 -0
  113. package/dist/editor.js +21 -0
  114. package/dist/index.d.ts +12 -4
  115. package/dist/index.js +13 -3
  116. package/dist/server/load-cms.js +1 -0
  117. package/package.json +15 -6
  118. package/plugin/README.md +22 -2
  119. package/plugin/dist/build.d.ts +74 -0
  120. package/plugin/dist/build.js +210 -0
  121. package/plugin/dist/build.js.map +1 -0
  122. package/plugin/dist/index.d.ts +10 -1
  123. package/plugin/dist/index.js +63 -4
  124. package/plugin/dist/index.js.map +1 -1
  125. package/plugin/dist/manifest.d.ts +31 -0
  126. package/plugin/dist/manifest.js +146 -41
  127. package/plugin/dist/manifest.js.map +1 -1
  128. package/plugin/dist/parse-svelte.d.ts +15 -0
  129. package/plugin/dist/parse-svelte.js +26 -16
  130. package/plugin/dist/parse-svelte.js.map +1 -1
  131. package/dist/components/admin-bar/site-settings-panel.svelte +0 -225
  132. package/dist/components/admin-bar/site-settings-panel.svelte.d.ts +0 -7
@@ -1,225 +0,0 @@
1
- <script lang="ts">
2
- import { page } from '$app/state';
3
- import ImagesIcon from './icons/images.svelte';
4
- import { cmsStore, type MediaItem } from '../cms/cms-store.svelte.js';
5
- import CmsMediaPicker from '../cms/cms-media-picker.svelte';
6
- import type { CmsPayload, SiteFieldSchema, SiteSchema } from '../cms/scope.js';
7
- import { clickOutside } from './click-outside.js';
8
- import PanelFooter from './panel-footer.svelte';
9
- import PanelHeader from './panel-header.svelte';
10
- import Panel from './panel.svelte';
11
- import { Button } from './ui/button/index.js';
12
- import { Input } from './ui/input/index.js';
13
- import { Textarea } from './ui/textarea/index.js';
14
-
15
- type Props = { onClose: () => void; onSave: () => void | Promise<void> };
16
- let { onClose, onSave }: Props = $props();
17
-
18
- const cms = $derived(page.data.cms as CmsPayload | undefined);
19
- const schema = $derived<SiteSchema>(cms?.site?.schema ?? {});
20
- const endpoint = $derived(cms?.endpoint ?? '/api/cms');
21
-
22
- // Flat (path → schema) view for save/reset; sections preserved for layout.
23
- const sections = $derived(Object.entries(schema));
24
- const allFieldPaths = $derived.by(() => {
25
- const out: Array<{ path: string; schema: SiteFieldSchema }> = [];
26
- for (const [sectionKey, section] of sections) {
27
- for (const [fieldKey, fieldSchema] of Object.entries(section.fields)) {
28
- out.push({ path: `${sectionKey}.${fieldKey}`, schema: fieldSchema });
29
- }
30
- }
31
- return out;
32
- });
33
-
34
- const persistedValue = (path: string): unknown => cmsStore.getSiteValue(path);
35
-
36
- // Local form state — typing only updates `local`; nothing reaches
37
- // `cmsStore.siteDraft` until Save fires (matches seo-panel.svelte). That
38
- // keeps the bar's "X drafts" count from flickering as the user explores.
39
- let local = $state<Record<string, unknown>>({});
40
-
41
- $effect(() => {
42
- const next: Record<string, unknown> = {};
43
- for (const { path } of allFieldPaths) next[path] = persistedValue(path);
44
- local = next;
45
- });
46
-
47
- // Per-field media library popover state — keyed by field path.
48
- let openLibrary = $state<string | null>(null);
49
-
50
- const fieldLabelClass = 'vela:text-[12px] vela:text-bar-text-secondary';
51
-
52
- const stringValue = (v: unknown): string => (typeof v === 'string' ? v : '');
53
- const numberValue = (v: unknown): number | null =>
54
- typeof v === 'number' && !Number.isNaN(v) ? v : null;
55
-
56
- const setNumber = (path: string, raw: string) => {
57
- if (raw === '') local[path] = undefined;
58
- else {
59
- const n = Number(raw);
60
- local[path] = Number.isFinite(n) ? n : undefined;
61
- }
62
- };
63
-
64
- const onLibrarySelect = (path: string, item: MediaItem) => {
65
- local[path] = item.url;
66
- openLibrary = null;
67
- };
68
-
69
- const handleSave = async () => {
70
- for (const { path } of allFieldPaths) {
71
- const v = local[path];
72
- if (v !== persistedValue(path)) cmsStore.setSiteValue(path, v);
73
- }
74
- await onSave();
75
- };
76
- </script>
77
-
78
- <Panel ariaLabel="Site settings" {onClose}>
79
- <PanelHeader title="Site settings" {onClose} />
80
-
81
- <form
82
- class="vela:overflow-y-auto vela:px-4 vela:pb-4 vela:flex vela:flex-col vela:gap-5"
83
- onsubmit={(e) => {
84
- e.preventDefault();
85
- handleSave();
86
- }}
87
- >
88
- {#if sections.length === 0}
89
- <p class="vela:text-[13px] vela:text-bar-text-tertiary vela:py-2">
90
- No site settings have been declared. Pass a <code>site</code> schema to
91
- <code>createCms()</code> to add fields here.
92
- </p>
93
- {:else}
94
- {#each sections as [sectionKey, section] (sectionKey)}
95
- <section class="vela:flex vela:flex-col vela:gap-3">
96
- <h3
97
- class="vela:text-[10px] vela:font-semibold vela:uppercase vela:tracking-widest vela:text-bar-text-tertiary vela:m-0"
98
- >
99
- {section.label}
100
- </h3>
101
-
102
- {#each Object.entries(section.fields) as [fieldKey, fieldSchema] (fieldKey)}
103
- {@const path = `${sectionKey}.${fieldKey}`}
104
- {#if fieldSchema.type === 'markdown'}
105
- <label class="vela:flex vela:flex-col vela:gap-1.5">
106
- <span class={fieldLabelClass}>{fieldSchema.label}</span>
107
- <Textarea
108
- value={stringValue(local[path])}
109
- placeholder={fieldSchema.placeholder ?? ''}
110
- oninput={(e) => (local[path] = e.currentTarget.value)}
111
- />
112
- </label>
113
- {:else if fieldSchema.type === 'number'}
114
- <label class="vela:flex vela:flex-col vela:gap-1.5">
115
- <span class={fieldLabelClass}>{fieldSchema.label}</span>
116
- <Input
117
- type="number"
118
- value={numberValue(local[path]) ?? ''}
119
- placeholder={fieldSchema.placeholder ?? ''}
120
- oninput={(e) => setNumber(path, e.currentTarget.value)}
121
- />
122
- </label>
123
- {:else if fieldSchema.type === 'datetime'}
124
- <label class="vela:flex vela:flex-col vela:gap-1.5">
125
- <span class={fieldLabelClass}>{fieldSchema.label}</span>
126
- <Input
127
- type="datetime-local"
128
- value={stringValue(local[path])}
129
- oninput={(e) => (local[path] = e.currentTarget.value)}
130
- />
131
- </label>
132
- {:else if fieldSchema.type === 'color'}
133
- <label class="vela:flex vela:flex-col vela:gap-1.5">
134
- <span class={fieldLabelClass}>{fieldSchema.label}</span>
135
- <div class="vela:flex vela:items-center vela:gap-2">
136
- <input
137
- type="color"
138
- value={stringValue(local[path]) || '#000000'}
139
- oninput={(e) => (local[path] = e.currentTarget.value)}
140
- class="vela:h-9 vela:w-12 vela:rounded vela:border vela:border-[var(--cms-bar-divider)] vela:bg-[var(--cms-bar-bg-hover)] vela:cursor-pointer"
141
- />
142
- <Input
143
- type="text"
144
- value={stringValue(local[path])}
145
- placeholder={fieldSchema.placeholder ?? '#1f1f1f'}
146
- oninput={(e) => (local[path] = e.currentTarget.value)}
147
- />
148
- </div>
149
- </label>
150
- {:else if fieldSchema.type === 'url'}
151
- <label class="vela:flex vela:flex-col vela:gap-1.5">
152
- <span class={fieldLabelClass}>{fieldSchema.label}</span>
153
- <Input
154
- type="url"
155
- value={stringValue(local[path])}
156
- placeholder={fieldSchema.placeholder ?? 'https://…'}
157
- oninput={(e) => (local[path] = e.currentTarget.value)}
158
- />
159
- </label>
160
- {:else if fieldSchema.type === 'image'}
161
- <div class="vela:flex vela:flex-col vela:gap-1.5">
162
- <span class={fieldLabelClass}>{fieldSchema.label}</span>
163
- <div class="vela:relative vela:flex vela:items-center vela:gap-2">
164
- <Input
165
- type="url"
166
- value={stringValue(local[path])}
167
- placeholder={fieldSchema.placeholder ?? 'https://…'}
168
- oninput={(e) => (local[path] = e.currentTarget.value)}
169
- />
170
- <Button
171
- type="button"
172
- variant="ghost"
173
- size="pill-icon"
174
- aria-label="Choose from media library"
175
- onclick={() => (openLibrary = openLibrary === path ? null : path)}
176
- >
177
- <ImagesIcon class="vela:size-4" />
178
- </Button>
179
- {#if openLibrary === path}
180
- <div
181
- role="dialog"
182
- aria-label="Choose from media library"
183
- class="vela:absolute vela:right-0 vela:top-full vela:mt-1 vela:z-30
184
- vela:p-2 vela:rounded-md vela:bg-bar-bg
185
- vela:border vela:border-[var(--cms-bar-divider)]
186
- vela:shadow-[0_8px_24px_rgba(0,0,0,0.35)]"
187
- use:clickOutside={() => (openLibrary = null)}
188
- >
189
- <CmsMediaPicker {endpoint} onSelect={(item) => onLibrarySelect(path, item)} />
190
- </div>
191
- {/if}
192
- </div>
193
- {#if stringValue(local[path])}
194
- <img
195
- src={stringValue(local[path])}
196
- alt=""
197
- class="vela:max-h-24 vela:w-auto vela:rounded vela:border vela:border-[var(--cms-bar-divider)] vela:object-contain vela:bg-[var(--cms-bar-bg-hover)]"
198
- />
199
- {/if}
200
- </div>
201
- {:else}
202
- <label class="vela:flex vela:flex-col vela:gap-1.5">
203
- <span class={fieldLabelClass}>{fieldSchema.label}</span>
204
- <Input
205
- type="text"
206
- value={stringValue(local[path])}
207
- placeholder={fieldSchema.placeholder ?? ''}
208
- oninput={(e) => (local[path] = e.currentTarget.value)}
209
- />
210
- </label>
211
- {/if}
212
- {/each}
213
- </section>
214
- {/each}
215
- {/if}
216
- </form>
217
-
218
- <PanelFooter>
219
- <span>Save to keep your changes</span>
220
- <div class="vela:flex vela:items-center vela:gap-1.5">
221
- <Button variant="ghost" size="pill" onclick={onClose}>Cancel</Button>
222
- <Button size="pill" onclick={handleSave}>Save</Button>
223
- </div>
224
- </PanelFooter>
225
- </Panel>
@@ -1,7 +0,0 @@
1
- type Props = {
2
- onClose: () => void;
3
- onSave: () => void | Promise<void>;
4
- };
5
- declare const SiteSettingsPanel: import("svelte").Component<Props, {}, "">;
6
- type SiteSettingsPanel = ReturnType<typeof SiteSettingsPanel>;
7
- export default SiteSettingsPanel;