@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
@@ -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>
@@ -0,0 +1,5 @@
1
+ import type { HTMLAttributes } from 'svelte/elements';
2
+ import { type WithElementRef } from '../../utils.js';
3
+ declare const SheetHeader: import("svelte").Component<WithElementRef<HTMLAttributes<HTMLDivElement>>, {}, "ref">;
4
+ type SheetHeader = ReturnType<typeof SheetHeader>;
5
+ export default SheetHeader;
@@ -0,0 +1,20 @@
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.OverlayProps = $props();
10
+ </script>
11
+
12
+ <SheetPrimitive.Overlay
13
+ bind:ref
14
+ data-slot="sheet-overlay"
15
+ class={cn(
16
+ 'vela:fixed vela:inset-0 vela:z-[9998] vela:bg-black/50 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',
17
+ className
18
+ )}
19
+ {...restProps}
20
+ />
@@ -0,0 +1,4 @@
1
+ import { Dialog as SheetPrimitive } from 'bits-ui';
2
+ declare const SheetOverlay: import("svelte").Component<SheetPrimitive.OverlayProps, {}, "ref">;
3
+ type SheetOverlay = ReturnType<typeof SheetOverlay>;
4
+ export default SheetOverlay;
@@ -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.TitleProps = $props();
10
+ </script>
11
+
12
+ <SheetPrimitive.Title
13
+ bind:ref
14
+ data-slot="sheet-title"
15
+ class={cn('vela:text-[15px] vela:font-semibold vela:m-0', className)}
16
+ {...restProps}
17
+ />
@@ -0,0 +1,4 @@
1
+ import { Dialog as SheetPrimitive } from 'bits-ui';
2
+ declare const SheetTitle: import("svelte").Component<SheetPrimitive.TitleProps, {}, "ref">;
3
+ type SheetTitle = ReturnType<typeof SheetTitle>;
4
+ export default SheetTitle;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { Dialog as SheetPrimitive } from 'bits-ui';
3
+
4
+ let { ref = $bindable(null), ...restProps }: SheetPrimitive.TriggerProps = $props();
5
+ </script>
6
+
7
+ <SheetPrimitive.Trigger bind:ref data-slot="sheet-trigger" {...restProps} />
@@ -0,0 +1,4 @@
1
+ import { Dialog as SheetPrimitive } from 'bits-ui';
2
+ declare const SheetTrigger: import("svelte").Component<SheetPrimitive.TriggerProps, {}, "ref">;
3
+ type SheetTrigger = ReturnType<typeof SheetTrigger>;
4
+ export default SheetTrigger;
@@ -0,0 +1,7 @@
1
+ <script lang="ts">
2
+ import { Dialog as SheetPrimitive } from 'bits-ui';
3
+
4
+ let { open = $bindable(false), ...restProps }: SheetPrimitive.RootProps = $props();
5
+ </script>
6
+
7
+ <SheetPrimitive.Root bind:open {...restProps} />
@@ -0,0 +1,3 @@
1
+ declare const Sheet: import("svelte").Component<import("bits-ui").AlertDialogRootPropsWithoutHTML, {}, "open">;
2
+ type Sheet = ReturnType<typeof Sheet>;
3
+ export default Sheet;
@@ -0,0 +1,2 @@
1
+ import Root from './switch.svelte';
2
+ export { Root, Root as Switch };
@@ -0,0 +1,2 @@
1
+ import Root from './switch.svelte';
2
+ export { Root, Root as Switch };
@@ -0,0 +1,27 @@
1
+ <script lang="ts">
2
+ import { Switch as SwitchPrimitive } from 'bits-ui';
3
+ import { cn, type WithoutChildrenOrChild } from '../../utils.js';
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ checked = $bindable(false),
8
+ class: className,
9
+ ...restProps
10
+ }: WithoutChildrenOrChild<SwitchPrimitive.RootProps> = $props();
11
+ </script>
12
+
13
+ <SwitchPrimitive.Root
14
+ bind:ref
15
+ bind:checked
16
+ data-slot="switch"
17
+ class={cn(
18
+ 'vela:peer vela:inline-flex vela:h-5 vela:w-9 vela:shrink-0 vela:items-center vela:rounded-full vela:border vela:border-transparent vela:transition-colors vela:cursor-pointer 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=unchecked]:bg-[var(--cms-bar-divider)]',
19
+ className
20
+ )}
21
+ {...restProps}
22
+ >
23
+ <SwitchPrimitive.Thumb
24
+ data-slot="switch-thumb"
25
+ class="vela:pointer-events-none vela:block vela:size-4 vela:rounded-full vela:bg-white vela:shadow vela:transition-transform vela:data-[state=checked]:translate-x-4 vela:data-[state=unchecked]:translate-x-0.5"
26
+ />
27
+ </SwitchPrimitive.Root>
@@ -0,0 +1,5 @@
1
+ import { Switch as SwitchPrimitive } from 'bits-ui';
2
+ import { type WithoutChildrenOrChild } from '../../utils.js';
3
+ declare const Switch: import("svelte").Component<WithoutChildrenOrChild<SwitchPrimitive.RootProps>, {}, "ref" | "checked">;
4
+ type Switch = ReturnType<typeof Switch>;
5
+ export default Switch;
@@ -0,0 +1,5 @@
1
+ import Root from './tabs.svelte';
2
+ import Content from './tabs-content.svelte';
3
+ import List from './tabs-list.svelte';
4
+ import Trigger from './tabs-trigger.svelte';
5
+ export { Root, Content, List, Trigger, Root as Tabs, Content as TabsContent, List as TabsList, Trigger as TabsTrigger };
@@ -0,0 +1,7 @@
1
+ import Root from './tabs.svelte';
2
+ import Content from './tabs-content.svelte';
3
+ import List from './tabs-list.svelte';
4
+ import Trigger from './tabs-trigger.svelte';
5
+ export { Root, Content, List, Trigger,
6
+ //
7
+ Root as Tabs, Content as TabsContent, List as TabsList, Trigger as TabsTrigger };
@@ -0,0 +1,17 @@
1
+ <script lang="ts">
2
+ import { Tabs as TabsPrimitive } from 'bits-ui';
3
+ import { cn } from '../../utils.js';
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ ...restProps
9
+ }: TabsPrimitive.ContentProps = $props();
10
+ </script>
11
+
12
+ <TabsPrimitive.Content
13
+ bind:ref
14
+ data-slot="tabs-content"
15
+ class={cn('vela:flex-1 vela:outline-none', className)}
16
+ {...restProps}
17
+ />
@@ -0,0 +1,4 @@
1
+ import { Tabs as TabsPrimitive } from 'bits-ui';
2
+ declare const TabsContent: import("svelte").Component<TabsPrimitive.ContentProps, {}, "ref">;
3
+ type TabsContent = ReturnType<typeof TabsContent>;
4
+ export default TabsContent;
@@ -0,0 +1,16 @@
1
+ <script lang="ts">
2
+ import { Tabs as TabsPrimitive } from 'bits-ui';
3
+ import { cn } from '../../utils.js';
4
+
5
+ let { ref = $bindable(null), class: className, ...restProps }: TabsPrimitive.ListProps = $props();
6
+ </script>
7
+
8
+ <TabsPrimitive.List
9
+ bind:ref
10
+ data-slot="tabs-list"
11
+ class={cn(
12
+ 'vela:inline-flex vela:self-start vela:items-center vela:justify-center vela:p-0.5 vela:rounded-md vela:bg-[var(--cms-bar-bg-hover)] vela:border vela:border-[var(--cms-bar-divider)]',
13
+ className
14
+ )}
15
+ {...restProps}
16
+ />
@@ -0,0 +1,4 @@
1
+ import { Tabs as TabsPrimitive } from 'bits-ui';
2
+ declare const TabsList: import("svelte").Component<TabsPrimitive.ListProps, {}, "ref">;
3
+ type TabsList = ReturnType<typeof TabsList>;
4
+ export default TabsList;
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import { Tabs as TabsPrimitive } from 'bits-ui';
3
+ import { cn } from '../../utils.js';
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ class: className,
8
+ ...restProps
9
+ }: TabsPrimitive.TriggerProps = $props();
10
+ </script>
11
+
12
+ <TabsPrimitive.Trigger
13
+ bind:ref
14
+ data-slot="tabs-trigger"
15
+ class={cn(
16
+ 'vela:inline-flex vela:items-center vela:justify-center vela:gap-1.5 vela:px-2.5 vela:py-1 vela:rounded vela:text-[11px] vela:font-medium vela:whitespace-nowrap vela:cursor-pointer vela:transition-colors vela:text-bar-text-secondary vela:hover:text-bar-text vela:data-[state=active]:bg-bar-bg vela:data-[state=active]:text-bar-text vela:focus-visible:outline-none vela:focus-visible:ring-2 vela:focus-visible:ring-[var(--cms-accent)] vela:disabled:pointer-events-none vela:disabled:opacity-50',
17
+ className
18
+ )}
19
+ {...restProps}
20
+ />
@@ -0,0 +1,4 @@
1
+ import { Tabs as TabsPrimitive } from 'bits-ui';
2
+ declare const TabsTrigger: import("svelte").Component<TabsPrimitive.TriggerProps, {}, "ref">;
3
+ type TabsTrigger = ReturnType<typeof TabsTrigger>;
4
+ export default TabsTrigger;
@@ -0,0 +1,19 @@
1
+ <script lang="ts">
2
+ import { Tabs as TabsPrimitive } from 'bits-ui';
3
+ import { cn } from '../../utils.js';
4
+
5
+ let {
6
+ ref = $bindable(null),
7
+ value = $bindable(),
8
+ class: className,
9
+ ...restProps
10
+ }: TabsPrimitive.RootProps = $props();
11
+ </script>
12
+
13
+ <TabsPrimitive.Root
14
+ bind:ref
15
+ bind:value
16
+ data-slot="tabs"
17
+ class={cn('vela:flex vela:flex-col vela:gap-2', className)}
18
+ {...restProps}
19
+ />
@@ -0,0 +1,4 @@
1
+ import { Tabs as TabsPrimitive } from 'bits-ui';
2
+ declare const Tabs: import("svelte").Component<TabsPrimitive.RootProps, {}, "value" | "ref">;
3
+ type Tabs = ReturnType<typeof Tabs>;
4
+ export default Tabs;
@@ -1,35 +1,26 @@
1
1
  <script lang="ts">
2
2
  import type { Snippet } from 'svelte';
3
- import { getCmsScope } from './scope.js';
4
- import { cmsStore, type CmsScopeRef } from './cms-store.svelte.js';
3
+ import { useCmsField } from './use-cms-field.svelte.js';
5
4
 
6
5
  type Props = {
7
6
  name: string;
7
+ scope?: string;
8
8
  initial?: boolean;
9
9
  value?: unknown;
10
10
  children?: Snippet<[boolean]>;
11
11
  };
12
- let { name, initial = false, value, children }: Props = $props();
12
+ let { name, scope, initial = false, value, children }: Props = $props();
13
13
 
14
- const scope = getCmsScope();
15
- const ref = $derived<CmsScopeRef | null>(
16
- scope ? { scopeId: scope.scopeId, routeId: scope.routeId, params: scope.params } : null
14
+ const field = useCmsField(
15
+ () => ({ name, scope, value }),
16
+ (raw): boolean => (typeof raw === 'boolean' ? raw : raw === null ? false : initial)
17
17
  );
18
18
 
19
- const resolved = $derived.by(() => {
20
- if (value !== undefined) return value;
21
- return ref ? cmsStore.getValue(ref, name) : undefined;
22
- });
23
-
24
- const current = $derived(typeof resolved === 'boolean' ? resolved : initial);
25
- const editable = $derived(cmsStore.isEditing && value === undefined && !!ref);
26
-
27
- const toggle = () => {
28
- if (ref) cmsStore.setValue(ref, name, !current);
29
- };
19
+ const current = $derived(field.current);
20
+ const toggle = () => field.set(!current);
30
21
  </script>
31
22
 
32
- {#if editable && ref}
23
+ {#if field.editable && field.ref}
33
24
  <span class="cms-boolean-edit">
34
25
  {@render children?.(current)}
35
26
  <button
@@ -1,6 +1,7 @@
1
1
  import type { Snippet } from 'svelte';
2
2
  type Props = {
3
3
  name: string;
4
+ scope?: string;
4
5
  initial?: boolean;
5
6
  value?: unknown;
6
7
  children?: Snippet<[boolean]>;
@@ -16,7 +16,7 @@
16
16
  );
17
17
 
18
18
  const live = $derived(cmsStore.getValue(scope, name));
19
- const display = $derived(typeof live === 'string' ? live : (initial ?? ''));
19
+ const display = $derived(typeof live === 'string' ? live : live === null ? '' : (initial ?? ''));
20
20
 
21
21
  let el = $state<HTMLInputElement>();
22
22
 
@@ -29,8 +29,8 @@
29
29
 
30
30
  const onInput = (e: Event) => {
31
31
  const raw = (e.currentTarget as HTMLInputElement).value;
32
- if (raw === '') return;
33
- cmsStore.setValue(scope, name, raw);
32
+ // An emptied input clears the field explicitly (`null`).
33
+ cmsStore.setValue(scope, name, raw === '' ? null : raw);
34
34
  };
35
35
  </script>
36
36
 
@@ -5,6 +5,7 @@
5
5
 
6
6
  export type CmsDateTimeProps = {
7
7
  name: string;
8
+ scope?: string;
8
9
  /**
9
10
  * `'datetime'` (default) → `<input type="datetime-local">`, stores
10
11
  * `YYYY-MM-DDTHH:MM`. `'date'` → `<input type="date">`, stores
@@ -13,44 +14,43 @@
13
14
  */
14
15
  mode?: CmsDateTimeMode;
15
16
  fallback?: string;
16
- /** Per-item override used by `CmsRepeater`. */
17
+ /** Per-item override used by structured components. */
17
18
  value?: unknown;
18
19
  children?: Snippet<[string]>;
19
20
  };
20
21
  </script>
21
22
 
22
23
  <script lang="ts">
23
- import { getCmsScope } from './scope.js';
24
- import { cmsStore, type CmsScopeRef } from './cms-store.svelte.js';
24
+ import { useCmsField } from './use-cms-field.svelte.js';
25
25
 
26
- let { name, mode = 'datetime', fallback, value, children }: CmsDateTimeProps = $props();
26
+ let { name, scope, mode = 'datetime', fallback, value, children }: CmsDateTimeProps = $props();
27
27
 
28
- const scope = getCmsScope();
29
- const ref = $derived<CmsScopeRef | null>(
30
- scope ? { scopeId: scope.scopeId, routeId: scope.routeId, params: scope.params } : null
28
+ const field = useCmsField(
29
+ () => ({ name, scope, value }),
30
+ (raw): string | undefined => {
31
+ if (raw === undefined) return fallback;
32
+ return typeof raw === 'string' ? raw : '';
33
+ }
31
34
  );
32
35
 
33
- const resolved = $derived.by(() => {
34
- if (value !== undefined) return value;
35
- return ref ? cmsStore.getValue(ref, name) : undefined;
36
- });
37
-
38
- const current = $derived(typeof resolved === 'string' ? resolved : fallback);
39
- const editable = $derived(cmsStore.isEditing && value === undefined && !!ref);
36
+ const current = $derived(field.current);
40
37
  </script>
41
38
 
42
- {#if editable && ref}
39
+ {#if field.editable && field.ref}
43
40
  {#await import('./cms-date-time-editable.svelte') then { default: Editable }}
44
- <Editable scope={ref} {name} {mode} initial={current} />
41
+ <Editable scope={field.ref} {name} {mode} initial={current} />
45
42
  {/await}
46
43
  {:else if current && children}
47
44
  {@render children(current)}
48
45
  {:else if current}
49
46
  {current}
47
+ {:else if field.raw === null}
48
+ <!-- cleared by the editor -->
50
49
  {:else if children}
51
50
  {@render children('')}
52
51
  {:else}
53
- <span class="cms-missing" data-cms-name={name} data-cms-scope={scope?.scopeId ?? '?'}>{name}</span
52
+ <span class="cms-missing" data-cms-name={name} data-cms-scope={field.ref?.scopeId ?? '?'}
53
+ >{name}</span
54
54
  >
55
55
  {/if}
56
56
 
@@ -2,6 +2,7 @@ import type { Snippet } from 'svelte';
2
2
  export type CmsDateTimeMode = 'datetime' | 'date' | 'time';
3
3
  export type CmsDateTimeProps = {
4
4
  name: string;
5
+ scope?: string;
5
6
  /**
6
7
  * `'datetime'` (default) → `<input type="datetime-local">`, stores
7
8
  * `YYYY-MM-DDTHH:MM`. `'date'` → `<input type="date">`, stores
@@ -10,7 +11,7 @@ export type CmsDateTimeProps = {
10
11
  */
11
12
  mode?: CmsDateTimeMode;
12
13
  fallback?: string;
13
- /** Per-item override used by `CmsRepeater`. */
14
+ /** Per-item override used by structured components. */
14
15
  value?: unknown;
15
16
  children?: Snippet<[string]>;
16
17
  };
@@ -29,13 +29,17 @@
29
29
  // Read leaves through `getValue` so live drafts reflect immediately. Fall
30
30
  // back to the snapshot the display passed in when nothing's been written.
31
31
  const currentUrl = $derived.by(() => {
32
- const v = pathGet(cmsStore.getValue(scope, name), 'url');
32
+ const stored = cmsStore.getValue(scope, name);
33
+ const v = pathGet(stored, 'url');
33
34
  if (typeof v === 'string') return v;
35
+ if (v === null || stored === null) return '';
34
36
  return initial.url ?? '';
35
37
  });
36
38
  const currentAlt = $derived.by(() => {
37
- const v = pathGet(cmsStore.getValue(scope, name), 'alt');
39
+ const stored = cmsStore.getValue(scope, name);
40
+ const v = pathGet(stored, 'alt');
38
41
  if (typeof v === 'string') return v;
42
+ if (v === null || stored === null) return '';
39
43
  return initial.alt ?? '';
40
44
  });
41
45
 
@@ -55,8 +59,13 @@
55
59
  let uploading = $state(false);
56
60
  let error: string | null = $state(null);
57
61
 
58
- const writeUrl = (v: string) => cmsStore.setValue(scope, `${name}.url`, v);
59
- const writeAlt = (v: string) => cmsStore.setValue(scope, `${name}.alt`, v);
62
+ // Whole-object writes (see `core/structured.ts`): a cleared image is
63
+ // `{ url: null }`, which merges over the published tree as "cleared"
64
+ // instead of falling back to the template's demo image.
65
+ const writeUrl = (v: string) =>
66
+ cmsStore.setValue(scope, name, { url: v || null, alt: currentAlt || null });
67
+ const writeAlt = (v: string) =>
68
+ cmsStore.setValue(scope, name, { url: currentUrl || null, alt: v || null });
60
69
 
61
70
  const upload = async (file: File) => {
62
71
  if (!file.type.startsWith('image/')) {