@velastack/cms 0.4.0 → 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 (127) hide show
  1. package/README.md +107 -18
  2. package/dist/backend/index.d.ts +1 -1
  3. package/dist/backend/routes/seed.d.ts +6 -0
  4. package/dist/backend/routes/seed.js +96 -0
  5. package/dist/backend/routes/table.js +3 -0
  6. package/dist/backend/store/queries.d.ts +6 -1
  7. package/dist/backend/store/queries.js +89 -0
  8. package/dist/cms.js +13 -16
  9. package/dist/components/admin-bar/admin-bar-internal.svelte +4 -4
  10. package/dist/components/admin-bar/admin-bar.css +1 -1
  11. package/dist/components/admin-bar/field-input.svelte +220 -0
  12. package/dist/components/admin-bar/field-input.svelte.d.ts +29 -0
  13. package/dist/components/admin-bar/icons/pencil.svelte +19 -0
  14. package/dist/components/admin-bar/icons/pencil.svelte.d.ts +3 -0
  15. package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte +1 -1
  16. package/dist/components/admin-bar/locales-panel.svelte +42 -1
  17. package/dist/components/admin-bar/page-config.d.ts +8 -1
  18. package/dist/components/admin-bar/page-config.js +15 -2
  19. package/dist/components/admin-bar/reorder-buttons.svelte +52 -0
  20. package/dist/components/admin-bar/reorder-buttons.svelte.d.ts +10 -0
  21. package/dist/components/admin-bar/seo-panel.svelte +144 -189
  22. package/dist/components/admin-bar/site-options-panel.svelte +115 -0
  23. package/dist/components/admin-bar/site-options-panel.svelte.d.ts +7 -0
  24. package/dist/components/admin-bar/structured-editor-popover.svelte +250 -0
  25. package/dist/components/admin-bar/structured-editor-popover.svelte.d.ts +48 -0
  26. package/dist/components/admin-bar/ui/checkbox/checkbox.svelte +36 -0
  27. package/dist/components/admin-bar/ui/checkbox/checkbox.svelte.d.ts +5 -0
  28. package/dist/components/admin-bar/ui/checkbox/index.d.ts +2 -0
  29. package/dist/components/admin-bar/ui/checkbox/index.js +2 -0
  30. package/dist/components/admin-bar/ui/popover/index.d.ts +5 -0
  31. package/dist/components/admin-bar/ui/popover/index.js +7 -0
  32. package/dist/components/admin-bar/ui/popover/popover-close.svelte +7 -0
  33. package/dist/components/admin-bar/ui/popover/popover-close.svelte.d.ts +4 -0
  34. package/dist/components/admin-bar/ui/popover/popover-content.svelte +35 -0
  35. package/dist/components/admin-bar/ui/popover/popover-content.svelte.d.ts +10 -0
  36. package/dist/components/admin-bar/ui/popover/popover-trigger.svelte +7 -0
  37. package/dist/components/admin-bar/ui/popover/popover-trigger.svelte.d.ts +4 -0
  38. package/dist/components/admin-bar/ui/popover/popover.svelte +7 -0
  39. package/dist/components/admin-bar/ui/popover/popover.svelte.d.ts +3 -0
  40. package/dist/components/admin-bar/ui/sheet/index.d.ts +10 -0
  41. package/dist/components/admin-bar/ui/sheet/index.js +12 -0
  42. package/dist/components/admin-bar/ui/sheet/sheet-close.svelte +7 -0
  43. package/dist/components/admin-bar/ui/sheet/sheet-close.svelte.d.ts +4 -0
  44. package/dist/components/admin-bar/ui/sheet/sheet-content.svelte +64 -0
  45. package/dist/components/admin-bar/ui/sheet/sheet-content.svelte.d.ts +17 -0
  46. package/dist/components/admin-bar/ui/sheet/sheet-description.svelte +17 -0
  47. package/dist/components/admin-bar/ui/sheet/sheet-description.svelte.d.ts +4 -0
  48. package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte +23 -0
  49. package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte.d.ts +5 -0
  50. package/dist/components/admin-bar/ui/sheet/sheet-header.svelte +20 -0
  51. package/dist/components/admin-bar/ui/sheet/sheet-header.svelte.d.ts +5 -0
  52. package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte +20 -0
  53. package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
  54. package/dist/components/admin-bar/ui/sheet/sheet-title.svelte +17 -0
  55. package/dist/components/admin-bar/ui/sheet/sheet-title.svelte.d.ts +4 -0
  56. package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte +7 -0
  57. package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
  58. package/dist/components/admin-bar/ui/sheet/sheet.svelte +7 -0
  59. package/dist/components/admin-bar/ui/sheet/sheet.svelte.d.ts +3 -0
  60. package/dist/components/admin-bar/ui/switch/index.d.ts +2 -0
  61. package/dist/components/admin-bar/ui/switch/index.js +2 -0
  62. package/dist/components/admin-bar/ui/switch/switch.svelte +27 -0
  63. package/dist/components/admin-bar/ui/switch/switch.svelte.d.ts +5 -0
  64. package/dist/components/admin-bar/ui/tabs/index.d.ts +5 -0
  65. package/dist/components/admin-bar/ui/tabs/index.js +7 -0
  66. package/dist/components/admin-bar/ui/tabs/tabs-content.svelte +17 -0
  67. package/dist/components/admin-bar/ui/tabs/tabs-content.svelte.d.ts +4 -0
  68. package/dist/components/admin-bar/ui/tabs/tabs-list.svelte +16 -0
  69. package/dist/components/admin-bar/ui/tabs/tabs-list.svelte.d.ts +4 -0
  70. package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte +20 -0
  71. package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
  72. package/dist/components/admin-bar/ui/tabs/tabs.svelte +19 -0
  73. package/dist/components/admin-bar/ui/tabs/tabs.svelte.d.ts +4 -0
  74. package/dist/components/cms/cms-boolean.svelte +9 -18
  75. package/dist/components/cms/cms-boolean.svelte.d.ts +1 -0
  76. package/dist/components/cms/cms-date-time-editable.svelte +3 -3
  77. package/dist/components/cms/cms-date-time.svelte +17 -17
  78. package/dist/components/cms/cms-date-time.svelte.d.ts +2 -1
  79. package/dist/components/cms/cms-image-editable.svelte +13 -4
  80. package/dist/components/cms/cms-image.svelte +37 -30
  81. package/dist/components/cms/cms-image.svelte.d.ts +11 -4
  82. package/dist/components/cms/cms-link.svelte +26 -19
  83. package/dist/components/cms/cms-link.svelte.d.ts +2 -0
  84. package/dist/components/cms/cms-markdown.svelte +15 -16
  85. package/dist/components/cms/cms-markdown.svelte.d.ts +1 -0
  86. package/dist/components/cms/cms-number-editable.svelte +4 -2
  87. package/dist/components/cms/cms-number.svelte +18 -17
  88. package/dist/components/cms/cms-number.svelte.d.ts +2 -1
  89. package/dist/components/cms/cms-repeater.svelte +15 -18
  90. package/dist/components/cms/cms-repeater.svelte.d.ts +1 -0
  91. package/dist/components/cms/cms-rich-text.svelte +17 -22
  92. package/dist/components/cms/cms-rich-text.svelte.d.ts +1 -0
  93. package/dist/components/cms/cms-store.svelte.d.ts +14 -0
  94. package/dist/components/cms/cms-store.svelte.js +39 -2
  95. package/dist/components/cms/cms-text.svelte +23 -30
  96. package/dist/components/cms/cms-text.svelte.d.ts +3 -1
  97. package/dist/components/cms/scope.d.ts +25 -5
  98. package/dist/components/cms/structured-registry.d.ts +10 -0
  99. package/dist/components/cms/structured-registry.js +6 -0
  100. package/dist/components/cms/use-cms-field.svelte.d.ts +54 -0
  101. package/dist/components/cms/use-cms-field.svelte.js +83 -0
  102. package/dist/core/metadata.d.ts +44 -0
  103. package/dist/core/metadata.js +59 -0
  104. package/dist/core/structured.d.ts +108 -0
  105. package/dist/core/structured.js +184 -0
  106. package/dist/core/wire.d.ts +31 -1
  107. package/dist/editor.d.ts +22 -0
  108. package/dist/editor.js +21 -0
  109. package/dist/index.d.ts +12 -4
  110. package/dist/index.js +13 -3
  111. package/dist/server/load-cms.js +1 -0
  112. package/package.json +12 -3
  113. package/plugin/README.md +22 -2
  114. package/plugin/dist/build.d.ts +74 -0
  115. package/plugin/dist/build.js +210 -0
  116. package/plugin/dist/build.js.map +1 -0
  117. package/plugin/dist/index.d.ts +10 -1
  118. package/plugin/dist/index.js +63 -4
  119. package/plugin/dist/index.js.map +1 -1
  120. package/plugin/dist/manifest.d.ts +31 -0
  121. package/plugin/dist/manifest.js +146 -41
  122. package/plugin/dist/manifest.js.map +1 -1
  123. package/plugin/dist/parse-svelte.d.ts +15 -0
  124. package/plugin/dist/parse-svelte.js +26 -16
  125. package/plugin/dist/parse-svelte.js.map +1 -1
  126. package/dist/components/admin-bar/site-settings-panel.svelte +0 -225
  127. package/dist/components/admin-bar/site-settings-panel.svelte.d.ts +0 -7
@@ -0,0 +1,250 @@
1
+ <script lang="ts" generics="T extends Record<string, unknown>">
2
+ /**
3
+ * The editor every structured component opens: a popover anchored to the
4
+ * slot (a bottom sheet under 600px, per DESIGN.md §8.2) holding a form
5
+ * over a local draft, committed to the CMS draft on Done.
6
+ *
7
+ * Locales are tabs. The default locale's tab is the component's own form
8
+ * (`editor` snippet) and owns the structure; every other locale's tab
9
+ * lists the translatable strings with the default text as reference and
10
+ * writes only `<name>.$t.<id>.<field>` (see `core/structured.ts`). The
11
+ * popover opens on the locale the editor is previewing.
12
+ */
13
+ import { onMount, type Snippet } from 'svelte';
14
+ import { cmsStore } from '../cms/cms-store.svelte.js';
15
+ import type { CmsField } from '../cms/use-cms-field.svelte.js';
16
+ import {
17
+ stripTranslations,
18
+ translatableFields,
19
+ translationPath,
20
+ type Structured,
21
+ type TranslatableField
22
+ } from '../../core/structured.js';
23
+ import CssRoot from './css-root.svelte';
24
+ import PencilIcon from './icons/pencil.svelte';
25
+ import { Button } from './ui/button/index.js';
26
+ import { Input } from './ui/input/index.js';
27
+ import * as Popover from './ui/popover/index.js';
28
+ import * as Sheet from './ui/sheet/index.js';
29
+ import * as Tabs from './ui/tabs/index.js';
30
+
31
+ type Props = {
32
+ field: CmsField<T>;
33
+ schema: Structured<T>;
34
+ /** Human label for the header, e.g. "Opening hours". */
35
+ label: string;
36
+ open?: boolean;
37
+ /** What the visitor sees; rendered in place with the edit affordance. */
38
+ preview: Snippet;
39
+ /** The default-locale form over a local draft. */
40
+ editor: Snippet<[T, (next: T) => void]>;
41
+ };
42
+ let { field, schema, label, open = $bindable(false), preview, editor }: Props = $props();
43
+
44
+ const locales = $derived(cmsStore.locales);
45
+ const defaultLocale = $derived(cmsStore.defaultLocale);
46
+ const otherLocales = $derived(locales.filter((l) => l !== defaultLocale));
47
+
48
+ // Local drafts: structure for the default locale, strings per other locale.
49
+ let draft = $state<T>({} as T);
50
+ let translations = $state<Record<string, Record<string, string>>>({});
51
+ let tab = $state('');
52
+
53
+ const reset = () => {
54
+ draft = structuredClone($state.snapshot(field.current)) as T;
55
+ translations = {};
56
+ tab = locales.includes(cmsStore.activeLocale) ? cmsStore.activeLocale : defaultLocale;
57
+ };
58
+
59
+ $effect(() => {
60
+ if (open) reset();
61
+ });
62
+
63
+ $effect(() => {
64
+ if (open && tab && tab !== defaultLocale) void cmsStore.loadLocaleOverlay(tab);
65
+ });
66
+
67
+ const update = (next: T) => {
68
+ draft = next;
69
+ };
70
+
71
+ const fields = $derived<TranslatableField[]>(translatableFields(draft, schema));
72
+
73
+ /** Stored translation for a field in `locale`, unless edited in this session. */
74
+ const translationValue = (locale: string, f: TranslatableField): string => {
75
+ const local = translations[locale]?.[`${f.id}.${f.field}`];
76
+ if (local !== undefined) return local;
77
+ const stored = field.getIn(locale, `$t.${f.id}.${f.field}`);
78
+ return typeof stored === 'string' ? stored : '';
79
+ };
80
+ const setTranslation = (locale: string, f: TranslatableField, value: string) => {
81
+ translations = {
82
+ ...translations,
83
+ [locale]: { ...(translations[locale] ?? {}), [`${f.id}.${f.field}`]: value }
84
+ };
85
+ };
86
+
87
+ const done = () => {
88
+ field.set(stripTranslations($state.snapshot(draft)), defaultLocale);
89
+ for (const [locale, strings] of Object.entries(translations)) {
90
+ for (const [key, value] of Object.entries(strings)) {
91
+ const dot = key.indexOf('.');
92
+ const id = key.slice(0, dot);
93
+ const f = key.slice(dot + 1);
94
+ field.setAt(translationPath('', id, f).slice(1), value === '' ? null : value, locale);
95
+ }
96
+ }
97
+ open = false;
98
+ };
99
+
100
+ const clear = () => {
101
+ field.set(null, defaultLocale);
102
+ open = false;
103
+ };
104
+
105
+ // Under 600px the popover becomes a bottom sheet (DESIGN.md §8.2).
106
+ let isMobile = $state(false);
107
+ onMount(() => {
108
+ const mq = window.matchMedia('(max-width: 600px)');
109
+ const sync = () => (isMobile = mq.matches);
110
+ sync();
111
+ mq.addEventListener('change', sync);
112
+ return () => mq.removeEventListener('change', sync);
113
+ });
114
+ </script>
115
+
116
+ {#snippet body()}
117
+ <div class="vela:flex vela:items-center vela:justify-between vela:px-4 vela:pt-3.5 vela:pb-2">
118
+ <div class="vela:flex vela:items-baseline vela:gap-2 vela:min-w-0">
119
+ <h2 class="vela:text-[14px] vela:font-semibold vela:m-0">{label}</h2>
120
+ <span class="vela:font-mono vela:text-[11px] vela:text-bar-text-tertiary vela:truncate">
121
+ {field.name}
122
+ </span>
123
+ </div>
124
+ </div>
125
+
126
+ {#if otherLocales.length > 0}
127
+ <Tabs.Root bind:value={tab} class="vela:px-4">
128
+ <Tabs.List aria-label="Language">
129
+ {#each locales as locale (locale)}
130
+ <Tabs.Trigger value={locale} class="vela:font-mono vela:uppercase">{locale}</Tabs.Trigger>
131
+ {/each}
132
+ </Tabs.List>
133
+ </Tabs.Root>
134
+ {/if}
135
+
136
+ <div
137
+ class="vela:overflow-y-auto vela:max-h-[60vh] vela:px-4 vela:py-3 vela:flex vela:flex-col vela:gap-3"
138
+ >
139
+ {#if tab === defaultLocale || otherLocales.length === 0}
140
+ {@render editor(draft, update)}
141
+ {:else}
142
+ {#if fields.length === 0}
143
+ <p class="vela:text-[12px] vela:text-bar-text-tertiary vela:m-0">
144
+ Nothing to translate yet. Add content in
145
+ <span class="vela:font-mono vela:uppercase">{defaultLocale}</span> first.
146
+ </p>
147
+ {:else}
148
+ <p class="vela:text-[11px] vela:text-bar-text-tertiary vela:m-0">
149
+ Structure is shared with
150
+ <span class="vela:font-mono vela:uppercase">{defaultLocale}</span>; only the text
151
+ translates. Blank fields show the original.
152
+ </p>
153
+ {#each fields as f (`${f.id}.${f.field}`)}
154
+ <label class="vela:flex vela:flex-col vela:gap-1">
155
+ <span class="vela:text-[12px] vela:text-bar-text-secondary vela:truncate">
156
+ {f.source}
157
+ </span>
158
+ <Input
159
+ type="text"
160
+ value={translationValue(tab, f)}
161
+ placeholder={f.source}
162
+ oninput={(e) => setTranslation(tab, f, e.currentTarget.value)}
163
+ />
164
+ </label>
165
+ {/each}
166
+ {/if}
167
+ {/if}
168
+ </div>
169
+
170
+ <div
171
+ class="vela:flex vela:items-center vela:justify-between vela:px-4 vela:py-2.5 vela:border-t vela:border-[var(--cms-bar-divider)] vela:text-[12px] vela:text-bar-text-tertiary"
172
+ >
173
+ <Button variant="ghost" size="pill" onclick={clear}>Clear</Button>
174
+ <div class="vela:flex vela:items-center vela:gap-1.5">
175
+ <Button variant="ghost" size="pill" onclick={() => (open = false)}>Cancel</Button>
176
+ <Button size="pill" onclick={done}>Done</Button>
177
+ </div>
178
+ </div>
179
+ {/snippet}
180
+
181
+ <CssRoot>
182
+ <span class="cms-structured-edit" data-open={open ? '' : undefined} data-cms-name={field.name}>
183
+ <span class="cms-structured-edit__preview">{@render preview()}</span>
184
+ {#if isMobile}
185
+ <Sheet.Root bind:open>
186
+ <Sheet.Trigger class="cms-structured-edit__trigger" aria-label={`Edit ${label}`}>
187
+ <PencilIcon class="vela:size-3" />
188
+ {label}
189
+ </Sheet.Trigger>
190
+ <Sheet.Content side="bottom" class="vela:gap-0" showCloseButton={false}>
191
+ {@render body()}
192
+ </Sheet.Content>
193
+ </Sheet.Root>
194
+ {:else}
195
+ <Popover.Root bind:open>
196
+ <Popover.Trigger class="cms-structured-edit__trigger" aria-label={`Edit ${label}`}>
197
+ <PencilIcon class="vela:size-3" />
198
+ {label}
199
+ </Popover.Trigger>
200
+ <Popover.Content class="vela:w-[420px] vela:max-w-[calc(100vw-2rem)]">
201
+ {@render body()}
202
+ </Popover.Content>
203
+ </Popover.Root>
204
+ {/if}
205
+ </span>
206
+ </CssRoot>
207
+
208
+ <style>
209
+ .cms-structured-edit {
210
+ position: relative;
211
+ display: block;
212
+ border-radius: 0.125rem;
213
+ outline: 1px dashed rgba(127, 127, 127, 0.6);
214
+ outline-offset: 4px;
215
+ }
216
+ .cms-structured-edit:hover,
217
+ .cms-structured-edit:focus-within,
218
+ .cms-structured-edit[data-open] {
219
+ outline: 2px solid var(--cms-accent, #534ab7);
220
+ outline-offset: 4px;
221
+ }
222
+ .cms-structured-edit__preview {
223
+ display: contents;
224
+ }
225
+ :global(.cms-structured-edit__trigger) {
226
+ position: absolute;
227
+ top: -0.5rem;
228
+ right: -0.5rem;
229
+ z-index: 40;
230
+ display: none;
231
+ align-items: center;
232
+ gap: 0.25rem;
233
+ padding: 0.125rem 0.5rem;
234
+ background: var(--cms-bar-bg, #1f1f1f);
235
+ color: var(--cms-bar-text, #f5f5f5);
236
+ border: 1px solid var(--cms-bar-divider, #3a3a3a);
237
+ border-radius: 999px;
238
+ cursor: pointer;
239
+ font: inherit;
240
+ font-size: 0.6875rem;
241
+ font-family: ui-sans-serif, system-ui, sans-serif;
242
+ line-height: 1.4;
243
+ white-space: nowrap;
244
+ }
245
+ .cms-structured-edit:hover :global(.cms-structured-edit__trigger),
246
+ .cms-structured-edit:focus-within :global(.cms-structured-edit__trigger),
247
+ .cms-structured-edit[data-open] :global(.cms-structured-edit__trigger) {
248
+ display: inline-flex;
249
+ }
250
+ </style>
@@ -0,0 +1,48 @@
1
+ /**
2
+ * The editor every structured component opens: a popover anchored to the
3
+ * slot (a bottom sheet under 600px, per DESIGN.md §8.2) holding a form
4
+ * over a local draft, committed to the CMS draft on Done.
5
+ *
6
+ * Locales are tabs. The default locale's tab is the component's own form
7
+ * (`editor` snippet) and owns the structure; every other locale's tab
8
+ * lists the translatable strings with the default text as reference and
9
+ * writes only `<name>.$t.<id>.<field>` (see `core/structured.ts`). The
10
+ * popover opens on the locale the editor is previewing.
11
+ */
12
+ import { type Snippet } from 'svelte';
13
+ import type { CmsField } from '../cms/use-cms-field.svelte.js';
14
+ import { type Structured } from '../../core/structured.js';
15
+ declare function $$render<T extends Record<string, unknown>>(): {
16
+ props: {
17
+ field: CmsField<T>;
18
+ schema: Structured<T>;
19
+ /** Human label for the header, e.g. "Opening hours". */
20
+ label: string;
21
+ open?: boolean;
22
+ /** What the visitor sees; rendered in place with the edit affordance. */
23
+ preview: Snippet;
24
+ /** The default-locale form over a local draft. */
25
+ editor: Snippet<[T, (next: T) => void]>;
26
+ };
27
+ exports: {};
28
+ bindings: "open";
29
+ slots: {};
30
+ events: {};
31
+ };
32
+ declare class __sveltets_Render<T extends Record<string, unknown>> {
33
+ props(): ReturnType<typeof $$render<T>>['props'];
34
+ events(): ReturnType<typeof $$render<T>>['events'];
35
+ slots(): ReturnType<typeof $$render<T>>['slots'];
36
+ bindings(): "open";
37
+ exports(): {};
38
+ }
39
+ interface $$IsomorphicComponent {
40
+ new <T extends Record<string, unknown>>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
41
+ $$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
42
+ } & ReturnType<__sveltets_Render<T>['exports']>;
43
+ <T extends Record<string, unknown>>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
44
+ z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
45
+ }
46
+ declare const StructuredEditorPopover: $$IsomorphicComponent;
47
+ type StructuredEditorPopover<T extends Record<string, unknown>> = InstanceType<typeof StructuredEditorPopover<T>>;
48
+ export default StructuredEditorPopover;
@@ -0,0 +1,36 @@
1
+ <script lang="ts">
2
+ import { Checkbox as CheckboxPrimitive } from 'bits-ui';
3
+ import CheckIcon from '../../icons/check.svelte';
4
+ import MinusIcon from '../../icons/minus.svelte';
5
+ import { cn, type WithoutChildrenOrChild } from '../../utils.js';
6
+
7
+ let {
8
+ ref = $bindable(null),
9
+ checked = $bindable(false),
10
+ indeterminate = $bindable(false),
11
+ class: className,
12
+ ...restProps
13
+ }: WithoutChildrenOrChild<CheckboxPrimitive.RootProps> = $props();
14
+ </script>
15
+
16
+ <CheckboxPrimitive.Root
17
+ bind:ref
18
+ bind:checked
19
+ bind:indeterminate
20
+ data-slot="checkbox"
21
+ class={cn(
22
+ 'vela:peer vela:size-4 vela:shrink-0 vela:rounded-[4px] vela:border vela:border-[var(--cms-bar-divider)] vela:bg-transparent vela:cursor-pointer vela:transition-colors vela:focus-visible:outline-none vela:focus-visible:ring-2 vela:focus-visible:ring-[var(--cms-accent)] vela:disabled:cursor-not-allowed vela:disabled:opacity-50 vela:data-[state=checked]:bg-[var(--cms-accent)] vela:data-[state=checked]:border-[var(--cms-accent)] vela:data-[state=checked]:text-white vela:data-[state=indeterminate]:bg-[var(--cms-accent)] vela:data-[state=indeterminate]:text-white',
23
+ className
24
+ )}
25
+ {...restProps}
26
+ >
27
+ {#snippet children({ checked, indeterminate })}
28
+ <span class="vela:flex vela:size-full vela:items-center vela:justify-center vela:text-current">
29
+ {#if indeterminate}
30
+ <MinusIcon class="vela:size-3" />
31
+ {:else if checked}
32
+ <CheckIcon class="vela:size-3" />
33
+ {/if}
34
+ </span>
35
+ {/snippet}
36
+ </CheckboxPrimitive.Root>
@@ -0,0 +1,5 @@
1
+ import { Checkbox as CheckboxPrimitive } from 'bits-ui';
2
+ import { type WithoutChildrenOrChild } from '../../utils.js';
3
+ declare const Checkbox: import("svelte").Component<WithoutChildrenOrChild<CheckboxPrimitive.RootProps>, {}, "ref" | "checked" | "indeterminate">;
4
+ type Checkbox = ReturnType<typeof Checkbox>;
5
+ export default Checkbox;
@@ -0,0 +1,2 @@
1
+ import Root from './checkbox.svelte';
2
+ export { Root, Root as Checkbox };
@@ -0,0 +1,2 @@
1
+ import Root from './checkbox.svelte';
2
+ export { Root, Root as Checkbox };
@@ -0,0 +1,5 @@
1
+ import Root from './popover.svelte';
2
+ import Content from './popover-content.svelte';
3
+ import Trigger from './popover-trigger.svelte';
4
+ import Close from './popover-close.svelte';
5
+ export { Root, Content, Trigger, Close, Root as Popover, Content as PopoverContent, Trigger as PopoverTrigger, Close as PopoverClose };
@@ -0,0 +1,7 @@
1
+ import Root from './popover.svelte';
2
+ import Content from './popover-content.svelte';
3
+ import Trigger from './popover-trigger.svelte';
4
+ import Close from './popover-close.svelte';
5
+ export { Root, Content, Trigger, Close,
6
+ //
7
+ Root as Popover, Content as PopoverContent, Trigger as PopoverTrigger, Close as PopoverClose };
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { Popover as PopoverPrimitive } from 'bits-ui';
3
+
4
+ let { ref = $bindable(null), ...restProps }: PopoverPrimitive.CloseProps = $props();
5
+ </script>
6
+
7
+ <PopoverPrimitive.Close bind:ref data-slot="popover-close" {...restProps} />
@@ -0,0 +1,4 @@
1
+ import { Popover as PopoverPrimitive } from 'bits-ui';
2
+ declare const PopoverClose: import("svelte").Component<PopoverPrimitive.CloseProps, {}, "ref">;
3
+ type PopoverClose = ReturnType<typeof PopoverClose>;
4
+ export default PopoverClose;
@@ -0,0 +1,35 @@
1
+ <script lang="ts">
2
+ import { Popover as PopoverPrimitive } from 'bits-ui';
3
+ import { cn, type WithoutChildrenOrChild } from '../../utils.js';
4
+ import type { Snippet } from 'svelte';
5
+
6
+ let {
7
+ ref = $bindable(null),
8
+ class: className,
9
+ sideOffset = 6,
10
+ align = 'start',
11
+ portalProps,
12
+ children,
13
+ ...restProps
14
+ }: WithoutChildrenOrChild<PopoverPrimitive.ContentProps> & {
15
+ portalProps?: PopoverPrimitive.PortalProps;
16
+ children?: Snippet;
17
+ } = $props();
18
+ </script>
19
+
20
+ <!-- Portal targets `.vela-admin-bar` (not body) so the @scope-wrapped utilities apply. -->
21
+ <PopoverPrimitive.Portal to=".vela-admin-bar" {...portalProps}>
22
+ <PopoverPrimitive.Content
23
+ bind:ref
24
+ data-slot="popover-content"
25
+ {sideOffset}
26
+ {align}
27
+ class={cn(
28
+ 'vela:z-[9999] vela:w-80 vela:rounded-xl vela:border vela:border-[var(--cms-bar-divider)] vela:bg-bar-bg vela:text-bar-text vela:shadow-[0_12px_32px_rgba(0,0,0,0.45)] vela:outline-hidden vela:data-[state=open]:animate-in vela:data-[state=closed]:animate-out vela:data-[state=closed]:fade-out-0 vela:data-[state=open]:fade-in-0 vela:data-[state=closed]:zoom-out-95 vela:data-[state=open]:zoom-in-95 vela:duration-150',
29
+ className
30
+ )}
31
+ {...restProps}
32
+ >
33
+ {@render children?.()}
34
+ </PopoverPrimitive.Content>
35
+ </PopoverPrimitive.Portal>
@@ -0,0 +1,10 @@
1
+ import { Popover as PopoverPrimitive } from 'bits-ui';
2
+ import { type WithoutChildrenOrChild } from '../../utils.js';
3
+ import type { Snippet } from 'svelte';
4
+ type $$ComponentProps = WithoutChildrenOrChild<PopoverPrimitive.ContentProps> & {
5
+ portalProps?: PopoverPrimitive.PortalProps;
6
+ children?: Snippet;
7
+ };
8
+ declare const PopoverContent: import("svelte").Component<$$ComponentProps, {}, "ref">;
9
+ type PopoverContent = ReturnType<typeof PopoverContent>;
10
+ export default PopoverContent;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { Popover as PopoverPrimitive } from 'bits-ui';
3
+
4
+ let { ref = $bindable(null), ...restProps }: PopoverPrimitive.TriggerProps = $props();
5
+ </script>
6
+
7
+ <PopoverPrimitive.Trigger bind:ref data-slot="popover-trigger" {...restProps} />
@@ -0,0 +1,4 @@
1
+ import { Popover as PopoverPrimitive } from 'bits-ui';
2
+ declare const PopoverTrigger: import("svelte").Component<PopoverPrimitive.TriggerProps, {}, "ref">;
3
+ type PopoverTrigger = ReturnType<typeof PopoverTrigger>;
4
+ export default PopoverTrigger;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { Popover as PopoverPrimitive } from 'bits-ui';
3
+
4
+ let { open = $bindable(false), ...restProps }: PopoverPrimitive.RootProps = $props();
5
+ </script>
6
+
7
+ <PopoverPrimitive.Root bind:open {...restProps} />
@@ -0,0 +1,3 @@
1
+ declare const Popover: import("svelte").Component<import("bits-ui").PopoverRootPropsWithoutHTML, {}, "open">;
2
+ type Popover = ReturnType<typeof Popover>;
3
+ export default Popover;
@@ -0,0 +1,10 @@
1
+ import Root from './sheet.svelte';
2
+ import Close from './sheet-close.svelte';
3
+ import Trigger from './sheet-trigger.svelte';
4
+ import Overlay from './sheet-overlay.svelte';
5
+ import Content from './sheet-content.svelte';
6
+ import Header from './sheet-header.svelte';
7
+ import Footer from './sheet-footer.svelte';
8
+ import Title from './sheet-title.svelte';
9
+ import Description from './sheet-description.svelte';
10
+ export { Root, Close, Trigger, Overlay, Content, Header, Footer, Title, Description, Root as Sheet, Close as SheetClose, Trigger as SheetTrigger, Overlay as SheetOverlay, Content as SheetContent, Header as SheetHeader, Footer as SheetFooter, Title as SheetTitle, Description as SheetDescription };
@@ -0,0 +1,12 @@
1
+ import Root from './sheet.svelte';
2
+ import Close from './sheet-close.svelte';
3
+ import Trigger from './sheet-trigger.svelte';
4
+ import Overlay from './sheet-overlay.svelte';
5
+ import Content from './sheet-content.svelte';
6
+ import Header from './sheet-header.svelte';
7
+ import Footer from './sheet-footer.svelte';
8
+ import Title from './sheet-title.svelte';
9
+ import Description from './sheet-description.svelte';
10
+ export { Root, Close, Trigger, Overlay, Content, Header, Footer, Title, Description,
11
+ //
12
+ Root as Sheet, Close as SheetClose, Trigger as SheetTrigger, Overlay as SheetOverlay, Content as SheetContent, Header as SheetHeader, Footer as SheetFooter, Title as SheetTitle, Description as SheetDescription };
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { Dialog as SheetPrimitive } from 'bits-ui';
3
+
4
+ let { ref = $bindable(null), ...restProps }: SheetPrimitive.CloseProps = $props();
5
+ </script>
6
+
7
+ <SheetPrimitive.Close bind:ref data-slot="sheet-close" {...restProps} />
@@ -0,0 +1,4 @@
1
+ import { Dialog as SheetPrimitive } from 'bits-ui';
2
+ declare const SheetClose: import("svelte").Component<SheetPrimitive.TriggerProps, {}, "ref">;
3
+ type SheetClose = ReturnType<typeof SheetClose>;
4
+ export default SheetClose;
@@ -0,0 +1,64 @@
1
+ <script lang="ts" module>
2
+ import { variants, type VariantProps } from '../../variants.js';
3
+
4
+ export const sheetVariants = variants({
5
+ base: 'vela:fixed vela:z-[9999] vela:flex vela:flex-col vela:gap-4 vela:bg-bar-bg vela:text-bar-text vela:shadow-[0_12px_32px_rgba(0,0,0,0.45)] vela:transition vela:ease-in-out vela:data-[state=open]:animate-in vela:data-[state=closed]:animate-out vela:data-[state=closed]:duration-200 vela:data-[state=open]:duration-300',
6
+ variants: {
7
+ side: {
8
+ top: 'vela:inset-x-0 vela:top-0 vela:border-b vela:border-[var(--cms-bar-divider)] vela:data-[state=closed]:slide-out-to-top vela:data-[state=open]:slide-in-from-top',
9
+ bottom:
10
+ 'vela:inset-x-0 vela:bottom-0 vela:max-h-[85vh] vela:rounded-t-2xl vela:border-t vela:border-[var(--cms-bar-divider)] vela:data-[state=closed]:slide-out-to-bottom vela:data-[state=open]:slide-in-from-bottom',
11
+ left: 'vela:inset-y-0 vela:left-0 vela:h-full vela:w-3/4 vela:max-w-sm vela:border-r vela:border-[var(--cms-bar-divider)] vela:data-[state=closed]:slide-out-to-left vela:data-[state=open]:slide-in-from-left',
12
+ right:
13
+ 'vela:inset-y-0 vela:right-0 vela:h-full vela:w-3/4 vela:max-w-sm vela:border-l vela:border-[var(--cms-bar-divider)] vela:data-[state=closed]:slide-out-to-right vela:data-[state=open]:slide-in-from-right'
14
+ }
15
+ },
16
+ defaultVariants: { side: 'bottom' }
17
+ });
18
+
19
+ export type Side = VariantProps<typeof sheetVariants>['side'];
20
+ </script>
21
+
22
+ <script lang="ts">
23
+ import { Dialog as SheetPrimitive } from 'bits-ui';
24
+ import type { Snippet } from 'svelte';
25
+ import XIcon from '../../icons/x.svelte';
26
+ import { cn, type WithoutChildrenOrChild } from '../../utils.js';
27
+ import SheetOverlay from './sheet-overlay.svelte';
28
+
29
+ let {
30
+ ref = $bindable(null),
31
+ class: className,
32
+ side = 'bottom',
33
+ portalProps,
34
+ showCloseButton = true,
35
+ children,
36
+ ...restProps
37
+ }: WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
38
+ portalProps?: SheetPrimitive.PortalProps;
39
+ side?: Side;
40
+ showCloseButton?: boolean;
41
+ children: Snippet;
42
+ } = $props();
43
+ </script>
44
+
45
+ <SheetPrimitive.Portal to=".vela-admin-bar" {...portalProps}>
46
+ <SheetOverlay />
47
+ <SheetPrimitive.Content
48
+ bind:ref
49
+ data-slot="sheet-content"
50
+ class={cn(sheetVariants({ side }), className)}
51
+ {...restProps}
52
+ >
53
+ {@render children?.()}
54
+ {#if showCloseButton}
55
+ <SheetPrimitive.Close
56
+ data-slot="sheet-close"
57
+ class="vela:absolute vela:top-3 vela:right-3 vela:inline-flex vela:items-center vela:justify-center vela:w-7 vela:h-7 vela:rounded-full vela:text-bar-text-secondary vela:hover:text-bar-text vela:hover:bg-[var(--cms-bar-bg-hover)] vela:focus:outline-none vela:focus-visible:ring-2 vela:focus-visible:ring-[var(--cms-accent)] vela:cursor-pointer"
58
+ >
59
+ <XIcon class="vela:size-4" />
60
+ <span class="vela:sr-only">Close</span>
61
+ </SheetPrimitive.Close>
62
+ {/if}
63
+ </SheetPrimitive.Content>
64
+ </SheetPrimitive.Portal>
@@ -0,0 +1,17 @@
1
+ import { type VariantProps } from '../../variants.js';
2
+ export declare const sheetVariants: (props?: {
3
+ side?: "bottom" | "left" | "right" | "top" | undefined;
4
+ }) => string;
5
+ export type Side = VariantProps<typeof sheetVariants>['side'];
6
+ import { Dialog as SheetPrimitive } from 'bits-ui';
7
+ import type { Snippet } from 'svelte';
8
+ import { type WithoutChildrenOrChild } from '../../utils.js';
9
+ type $$ComponentProps = WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
10
+ portalProps?: SheetPrimitive.PortalProps;
11
+ side?: Side;
12
+ showCloseButton?: boolean;
13
+ children: Snippet;
14
+ };
15
+ declare const SheetContent: import("svelte").Component<$$ComponentProps, {}, "ref">;
16
+ type SheetContent = ReturnType<typeof SheetContent>;
17
+ export default SheetContent;
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import { Dialog as SheetPrimitive } from 'bits-ui';
3
+ import { cn } from '../../utils.js';
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ ...restProps
9
+ }: SheetPrimitive.DescriptionProps = $props();
10
+ </script>
11
+
12
+ <SheetPrimitive.Description
13
+ bind:ref
14
+ data-slot="sheet-description"
15
+ class={cn('vela:text-[12px] vela:text-bar-text-secondary vela:m-0', className)}
16
+ {...restProps}
17
+ />
@@ -0,0 +1,4 @@
1
+ import { Dialog as SheetPrimitive } from 'bits-ui';
2
+ declare const SheetDescription: import("svelte").Component<SheetPrimitive.DescriptionProps, {}, "ref">;
3
+ type SheetDescription = ReturnType<typeof SheetDescription>;
4
+ export default SheetDescription;
@@ -0,0 +1,23 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { cn, type WithElementRef } from '../../utils.js';
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+ </script>
12
+
13
+ <div
14
+ bind:this={ref}
15
+ data-slot="sheet-footer"
16
+ class={cn(
17
+ 'vela:mt-auto vela:flex vela:items-center vela:justify-end vela:gap-1.5 vela:px-4 vela:py-2.5 vela:border-t vela:border-[var(--cms-bar-divider)]',
18
+ className
19
+ )}
20
+ {...restProps}
21
+ >
22
+ {@render children?.()}
23
+ </div>
@@ -0,0 +1,5 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import { type WithElementRef } from '../../utils.js';
3
+ declare const SheetFooter: import("svelte").Component<WithElementRef<HTMLAttributes<HTMLDivElement>>, {}, "ref">;
4
+ type SheetFooter = ReturnType<typeof SheetFooter>;
5
+ export default SheetFooter;
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import type { HTMLAttributes } from 'svelte/elements';
3
+ import { cn, type WithElementRef } from '../../utils.js';
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ children,
9
+ ...restProps
10
+ }: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
11
+ </script>
12
+
13
+ <div
14
+ bind:this={ref}
15
+ data-slot="sheet-header"
16
+ class={cn('vela:flex vela:flex-col vela:gap-1 vela:px-4 vela:pt-3.5 vela:pb-3', className)}
17
+ {...restProps}
18
+ >
19
+ {@render children?.()}
20
+ </div>