@velastack/cms 0.4.0 → 0.5.1
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.
- package/README.md +140 -28
- package/dist/backend/index.d.ts +1 -1
- package/dist/backend/routes/seed.d.ts +6 -0
- package/dist/backend/routes/seed.js +96 -0
- package/dist/backend/routes/table.js +3 -0
- package/dist/backend/store/queries.d.ts +6 -1
- package/dist/backend/store/queries.js +89 -0
- package/dist/cms.js +13 -16
- package/dist/components/admin-bar/admin-bar-internal.svelte +4 -4
- package/dist/components/admin-bar/admin-bar.css +1 -1
- package/dist/components/admin-bar/field-input.svelte +239 -0
- package/dist/components/admin-bar/field-input.svelte.d.ts +30 -0
- package/dist/components/admin-bar/fields-form.svelte +218 -0
- package/dist/components/admin-bar/fields-form.svelte.d.ts +16 -0
- package/dist/components/admin-bar/icons/pencil.svelte +19 -0
- package/dist/components/admin-bar/icons/pencil.svelte.d.ts +3 -0
- package/dist/components/admin-bar/keyboard-shortcuts-dialog.svelte +1 -1
- package/dist/components/admin-bar/link-input.svelte +102 -0
- package/dist/components/admin-bar/link-input.svelte.d.ts +9 -0
- package/dist/components/admin-bar/list-field.svelte +93 -0
- package/dist/components/admin-bar/list-field.svelte.d.ts +20 -0
- package/dist/components/admin-bar/locales-panel.svelte +42 -1
- package/dist/components/admin-bar/page-config.d.ts +8 -1
- package/dist/components/admin-bar/page-config.js +15 -2
- package/dist/components/admin-bar/page-options.d.ts +24 -0
- package/dist/components/admin-bar/page-options.js +53 -0
- package/dist/components/admin-bar/reorder-buttons.svelte +52 -0
- package/dist/components/admin-bar/reorder-buttons.svelte.d.ts +10 -0
- package/dist/components/admin-bar/rich-text-input.svelte +92 -0
- package/dist/components/admin-bar/rich-text-input.svelte.d.ts +9 -0
- package/dist/components/admin-bar/seo-panel.svelte +144 -189
- package/dist/components/admin-bar/site-options-panel.svelte +115 -0
- package/dist/components/admin-bar/site-options-panel.svelte.d.ts +7 -0
- package/dist/components/admin-bar/structured-editor-popover.svelte +259 -0
- package/dist/components/admin-bar/structured-editor-popover.svelte.d.ts +48 -0
- package/dist/components/admin-bar/ui/checkbox/checkbox.svelte +36 -0
- package/dist/components/admin-bar/ui/checkbox/checkbox.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/checkbox/index.d.ts +2 -0
- package/dist/components/admin-bar/ui/checkbox/index.js +2 -0
- package/dist/components/admin-bar/ui/popover/index.d.ts +5 -0
- package/dist/components/admin-bar/ui/popover/index.js +7 -0
- package/dist/components/admin-bar/ui/popover/popover-close.svelte +7 -0
- package/dist/components/admin-bar/ui/popover/popover-close.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/popover/popover-content.svelte +35 -0
- package/dist/components/admin-bar/ui/popover/popover-content.svelte.d.ts +10 -0
- package/dist/components/admin-bar/ui/popover/popover-trigger.svelte +7 -0
- package/dist/components/admin-bar/ui/popover/popover-trigger.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/popover/popover.svelte +7 -0
- package/dist/components/admin-bar/ui/popover/popover.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/sheet/index.d.ts +10 -0
- package/dist/components/admin-bar/ui/sheet/index.js +12 -0
- package/dist/components/admin-bar/ui/sheet/sheet-close.svelte +7 -0
- package/dist/components/admin-bar/ui/sheet/sheet-close.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/sheet/sheet-content.svelte +64 -0
- package/dist/components/admin-bar/ui/sheet/sheet-content.svelte.d.ts +17 -0
- package/dist/components/admin-bar/ui/sheet/sheet-description.svelte +17 -0
- package/dist/components/admin-bar/ui/sheet/sheet-description.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte +23 -0
- package/dist/components/admin-bar/ui/sheet/sheet-footer.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/sheet/sheet-header.svelte +20 -0
- package/dist/components/admin-bar/ui/sheet/sheet-header.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte +20 -0
- package/dist/components/admin-bar/ui/sheet/sheet-overlay.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/sheet/sheet-title.svelte +17 -0
- package/dist/components/admin-bar/ui/sheet/sheet-title.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte +7 -0
- package/dist/components/admin-bar/ui/sheet/sheet-trigger.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/sheet/sheet.svelte +7 -0
- package/dist/components/admin-bar/ui/sheet/sheet.svelte.d.ts +3 -0
- package/dist/components/admin-bar/ui/switch/index.d.ts +2 -0
- package/dist/components/admin-bar/ui/switch/index.js +2 -0
- package/dist/components/admin-bar/ui/switch/switch.svelte +27 -0
- package/dist/components/admin-bar/ui/switch/switch.svelte.d.ts +5 -0
- package/dist/components/admin-bar/ui/tabs/index.d.ts +5 -0
- package/dist/components/admin-bar/ui/tabs/index.js +7 -0
- package/dist/components/admin-bar/ui/tabs/tabs-content.svelte +17 -0
- package/dist/components/admin-bar/ui/tabs/tabs-content.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/tabs/tabs-list.svelte +16 -0
- package/dist/components/admin-bar/ui/tabs/tabs-list.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte +20 -0
- package/dist/components/admin-bar/ui/tabs/tabs-trigger.svelte.d.ts +4 -0
- package/dist/components/admin-bar/ui/tabs/tabs.svelte +19 -0
- package/dist/components/admin-bar/ui/tabs/tabs.svelte.d.ts +4 -0
- package/dist/components/cms/cms-boolean.svelte +9 -18
- package/dist/components/cms/cms-boolean.svelte.d.ts +1 -0
- package/dist/components/cms/cms-collection.svelte +46 -0
- package/dist/components/cms/cms-collection.svelte.d.ts +25 -0
- package/dist/components/cms/cms-contact.svelte +26 -0
- package/dist/components/cms/cms-contact.svelte.d.ts +14 -0
- package/dist/components/cms/cms-date-time-editable.svelte +3 -3
- package/dist/components/cms/cms-date-time.svelte +17 -17
- package/dist/components/cms/cms-date-time.svelte.d.ts +2 -1
- package/dist/components/cms/cms-faq.svelte +22 -0
- package/dist/components/cms/cms-faq.svelte.d.ts +15 -0
- package/dist/components/cms/cms-gallery.svelte +31 -0
- package/dist/components/cms/cms-gallery.svelte.d.ts +16 -0
- package/dist/components/cms/cms-hours-editable.svelte +160 -0
- package/dist/components/cms/cms-hours-editable.svelte.d.ts +17 -0
- package/dist/components/cms/cms-hours.svelte +42 -0
- package/dist/components/cms/cms-hours.svelte.d.ts +19 -0
- package/dist/components/cms/cms-image-editable.svelte +13 -4
- package/dist/components/cms/cms-image.svelte +19 -34
- package/dist/components/cms/cms-image.svelte.d.ts +7 -8
- package/dist/components/cms/cms-link-editable.svelte +4 -60
- package/dist/components/cms/cms-link.svelte +15 -28
- package/dist/components/cms/cms-link.svelte.d.ts +4 -9
- package/dist/components/cms/cms-logos.svelte +29 -0
- package/dist/components/cms/cms-logos.svelte.d.ts +16 -0
- package/dist/components/cms/cms-markdown.svelte +15 -16
- package/dist/components/cms/cms-markdown.svelte.d.ts +1 -0
- package/dist/components/cms/cms-nav.svelte +22 -0
- package/dist/components/cms/cms-nav.svelte.d.ts +15 -0
- package/dist/components/cms/cms-number-editable.svelte +4 -2
- package/dist/components/cms/cms-number.svelte +18 -17
- package/dist/components/cms/cms-number.svelte.d.ts +2 -1
- package/dist/components/cms/cms-pricing.svelte +36 -0
- package/dist/components/cms/cms-pricing.svelte.d.ts +14 -0
- package/dist/components/cms/cms-rich-text.svelte +17 -22
- package/dist/components/cms/cms-rich-text.svelte.d.ts +1 -0
- package/dist/components/cms/cms-schedule.svelte +35 -0
- package/dist/components/cms/cms-schedule.svelte.d.ts +16 -0
- package/dist/components/cms/cms-social-links.svelte +35 -0
- package/dist/components/cms/cms-social-links.svelte.d.ts +15 -0
- package/dist/components/cms/cms-stats.svelte +31 -0
- package/dist/components/cms/cms-stats.svelte.d.ts +16 -0
- package/dist/components/cms/cms-steps.svelte +31 -0
- package/dist/components/cms/cms-steps.svelte.d.ts +16 -0
- package/dist/components/cms/cms-store.svelte.d.ts +14 -0
- package/dist/components/cms/cms-store.svelte.js +39 -2
- package/dist/components/cms/cms-structured-editable.svelte +29 -0
- package/dist/components/cms/{cms-repeater-editable.svelte.d.ts → cms-structured-editable.svelte.d.ts} +12 -8
- package/dist/components/cms/cms-structured.svelte +50 -0
- package/dist/components/cms/cms-structured.svelte.d.ts +49 -0
- package/dist/components/cms/cms-team.svelte +22 -0
- package/dist/components/cms/cms-team.svelte.d.ts +15 -0
- package/dist/components/cms/cms-testimonials.svelte +36 -0
- package/dist/components/cms/cms-testimonials.svelte.d.ts +15 -0
- package/dist/components/cms/cms-text.svelte +23 -30
- package/dist/components/cms/cms-text.svelte.d.ts +3 -1
- package/dist/components/cms/cms-timeline.svelte +35 -0
- package/dist/components/cms/cms-timeline.svelte.d.ts +16 -0
- package/dist/components/cms/index.d.ts +15 -1
- package/dist/components/cms/index.js +15 -1
- package/dist/components/cms/scope.d.ts +25 -5
- package/dist/components/cms/use-cms-field.svelte.d.ts +54 -0
- package/dist/components/cms/use-cms-field.svelte.js +83 -0
- package/dist/core/metadata.d.ts +44 -0
- package/dist/core/metadata.js +59 -0
- package/dist/core/shapes/collection.d.ts +60 -0
- package/dist/core/shapes/collection.js +194 -0
- package/dist/core/shapes/contact.d.ts +70 -0
- package/dist/core/shapes/contact.js +214 -0
- package/dist/core/shapes/faq.d.ts +12 -0
- package/dist/core/shapes/faq.js +48 -0
- package/dist/core/shapes/form.d.ts +46 -0
- package/dist/core/shapes/form.js +7 -0
- package/dist/core/shapes/hours.d.ts +91 -0
- package/dist/core/shapes/hours.js +325 -0
- package/dist/core/shapes/image.d.ts +15 -0
- package/dist/core/shapes/image.js +27 -0
- package/dist/core/shapes/index.d.ts +31 -0
- package/dist/core/shapes/index.js +13 -0
- package/dist/core/shapes/link.d.ts +15 -0
- package/dist/core/shapes/link.js +42 -0
- package/dist/core/shapes/nav.d.ts +21 -0
- package/dist/core/shapes/nav.js +71 -0
- package/dist/core/shapes/presets.d.ts +65 -0
- package/dist/core/shapes/presets.js +152 -0
- package/dist/core/shapes/pricing.d.ts +40 -0
- package/dist/core/shapes/pricing.js +115 -0
- package/dist/core/shapes/social-links.d.ts +19 -0
- package/dist/core/shapes/social-links.js +83 -0
- package/dist/core/shapes/team.d.ts +22 -0
- package/dist/core/shapes/team.js +70 -0
- package/dist/core/shapes/testimonials.d.ts +24 -0
- package/dist/core/shapes/testimonials.js +86 -0
- package/dist/core/structured-registry.d.ts +10 -0
- package/dist/core/structured-registry.js +6 -0
- package/dist/core/structured.d.ts +131 -0
- package/dist/core/structured.js +235 -0
- package/dist/core/wire.d.ts +31 -1
- package/dist/editor.d.ts +26 -0
- package/dist/editor.js +25 -0
- package/dist/index.d.ts +26 -4
- package/dist/index.js +31 -2
- package/dist/server/load-cms.js +1 -0
- package/package.json +12 -3
- package/plugin/README.md +22 -2
- package/plugin/dist/build.d.ts +74 -0
- package/plugin/dist/build.js +210 -0
- package/plugin/dist/build.js.map +1 -0
- package/plugin/dist/index.d.ts +10 -1
- package/plugin/dist/index.js +63 -4
- package/plugin/dist/index.js.map +1 -1
- package/plugin/dist/manifest.d.ts +31 -0
- package/plugin/dist/manifest.js +146 -41
- package/plugin/dist/manifest.js.map +1 -1
- package/plugin/dist/parse-svelte.d.ts +15 -0
- package/plugin/dist/parse-svelte.js +26 -16
- package/plugin/dist/parse-svelte.js.map +1 -1
- package/dist/components/admin-bar/site-settings-panel.svelte +0 -225
- package/dist/components/admin-bar/site-settings-panel.svelte.d.ts +0 -7
- package/dist/components/cms/cms-repeater-editable.svelte +0 -137
- package/dist/components/cms/cms-repeater.svelte +0 -55
- package/dist/components/cms/cms-repeater.svelte.d.ts +0 -30
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured values: the shapes behind the editor components (hours, team,
|
|
3
|
+
* testimonials, …) and the two rules every one of them follows.
|
|
4
|
+
*
|
|
5
|
+
* 1. **Versioned shapes, whole-object writes.** A structured value is a plain
|
|
6
|
+
* object with a `v` version number. Components never patch a leaf inside
|
|
7
|
+
* it; they read the whole value through the schema's `normalize`, change
|
|
8
|
+
* it, and write the whole object back. A field the editor clears is
|
|
9
|
+
* written as `null`, never dropped: the draft and release trees deep-merge
|
|
10
|
+
* over the published tree, and a missing key merges to "unchanged" while
|
|
11
|
+
* `null` merges to "cleared". That is what stops a cleared field from
|
|
12
|
+
* reverting to the template's demo copy.
|
|
13
|
+
*
|
|
14
|
+
* 2. **Localisation is a string overlay, never a second structure.** The
|
|
15
|
+
* default locale stores the full value at `<name>`. Every other locale
|
|
16
|
+
* stores only strings, at `<name>.$t.<id>.<field>`, keyed by the stable
|
|
17
|
+
* `id` of the list item they translate (the reserved id `_` addresses the
|
|
18
|
+
* value's own root fields). Because objects deep-merge across locales,
|
|
19
|
+
* reading `es` yields the default structure plus the `es` overlay, and
|
|
20
|
+
* {@link applyTranslations} folds the strings in. Structure edits happen in
|
|
21
|
+
* the default locale only, so the item list can never fork between
|
|
22
|
+
* languages.
|
|
23
|
+
*/
|
|
24
|
+
import { type Tree } from './path.js';
|
|
25
|
+
/** Branch under a structured value that holds a locale's string overlay. */
|
|
26
|
+
export declare const TRANSLATIONS_KEY = "$t";
|
|
27
|
+
/** Overlay id that addresses the structured value's root fields. */
|
|
28
|
+
export declare const ROOT_ID = "_";
|
|
29
|
+
/** `{ [itemId]: { [field]: string } }` — what a non-default locale stores. */
|
|
30
|
+
export type TranslationOverlay = Record<string, Record<string, string>>;
|
|
31
|
+
export type StructuredItem = {
|
|
32
|
+
id: string;
|
|
33
|
+
} & Record<string, unknown>;
|
|
34
|
+
/**
|
|
35
|
+
* One list of items inside a structured value. `key` names the array field,
|
|
36
|
+
* `translatable` the item fields holding translatable text (a string, or an
|
|
37
|
+
* array of strings, translated per index as `<field>.<i>`), and `items` any
|
|
38
|
+
* lists nested inside each item (a collection item's `details`, a pricing
|
|
39
|
+
* tier's `features`). Every item at every level carries a stable `id`.
|
|
40
|
+
*/
|
|
41
|
+
export type ItemsSpec = {
|
|
42
|
+
key: string;
|
|
43
|
+
translatable: readonly string[];
|
|
44
|
+
items?: ItemsSpec | readonly ItemsSpec[];
|
|
45
|
+
};
|
|
46
|
+
export type StructuredSchema<T extends Tree> = {
|
|
47
|
+
/** Exported component name, e.g. `'CmsHours'`. Recorded in the manifest. */
|
|
48
|
+
component: string;
|
|
49
|
+
/** Current shape version, written as `v` on every value. */
|
|
50
|
+
version: number;
|
|
51
|
+
/** Root-level fields holding translatable strings, e.g. `['note']`. A
|
|
52
|
+
* dotted path addresses a nested field (`'labels.closed'`). */
|
|
53
|
+
translatable: readonly string[];
|
|
54
|
+
/** The value's item lists, when it has any, and the item fields that translate. */
|
|
55
|
+
items?: ItemsSpec | readonly ItemsSpec[];
|
|
56
|
+
/**
|
|
57
|
+
* Turn anything the store may hold — an older version, a hand-seeded
|
|
58
|
+
* partial object, garbage — into the current shape. Must never throw.
|
|
59
|
+
*/
|
|
60
|
+
normalize: (raw: unknown) => T;
|
|
61
|
+
/** The cleared value: what an editor gets after "Clear". */
|
|
62
|
+
empty: () => T;
|
|
63
|
+
};
|
|
64
|
+
export type Structured<T extends Tree> = StructuredSchema<T> & {
|
|
65
|
+
/**
|
|
66
|
+
* Resolve a stored value the way a display component reads it:
|
|
67
|
+
* `undefined` (nothing stored) → the fallback; `null` (cleared) → empty;
|
|
68
|
+
* anything else → normalized, with the locale overlay applied.
|
|
69
|
+
*/
|
|
70
|
+
read: (raw: unknown, fallback: T | undefined) => T;
|
|
71
|
+
};
|
|
72
|
+
export declare const isPlainObject: (v: unknown) => v is Tree;
|
|
73
|
+
export declare const defineStructured: <T extends Tree>(schema: StructuredSchema<T>) => Structured<T>;
|
|
74
|
+
/** Path of one translated string: `<name>.$t.<id>.<field>`. */
|
|
75
|
+
export declare const translationPath: (name: string, id: string, field: string) => string;
|
|
76
|
+
/** The `$t` branch of a stored value, when it is one. A dotted field
|
|
77
|
+
* (`labels.closed`, `tags.0`) is stored nested by the path-based writes and
|
|
78
|
+
* read back flat here. */
|
|
79
|
+
export declare const extractTranslations: (raw: unknown) => TranslationOverlay | undefined;
|
|
80
|
+
/** A copy of `raw` without its `$t` branch, so a whole-object write in the
|
|
81
|
+
* default locale never carries another locale's strings. */
|
|
82
|
+
export declare const stripTranslations: (raw: unknown) => unknown;
|
|
83
|
+
/** `set` that copies along the path instead of mutating shared branches. */
|
|
84
|
+
export declare const setIn: (obj: Tree, path: string, value: unknown) => Tree;
|
|
85
|
+
/**
|
|
86
|
+
* Fold a locale's string overlay into a normalized default-locale value.
|
|
87
|
+
* Root fields come from the `_` id; item fields from the item's own `id`,
|
|
88
|
+
* at every nesting level. Only non-empty strings override, so an
|
|
89
|
+
* untranslated field shows the default-locale text rather than a blank.
|
|
90
|
+
*/
|
|
91
|
+
export declare const applyTranslations: <T extends Tree>(value: T, overlay: TranslationOverlay | undefined, schema: Pick<StructuredSchema<T>, "translatable" | "items">) => T;
|
|
92
|
+
export type TranslatableField = {
|
|
93
|
+
/** Overlay id: an item id, or `_` for a root field. */
|
|
94
|
+
id: string;
|
|
95
|
+
/** Field path within the object the id addresses (`note`, `labels.closed`, `tags.0`). */
|
|
96
|
+
field: string;
|
|
97
|
+
/** The default-locale string being translated. */
|
|
98
|
+
source: string;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Every translatable, non-empty string in a normalized default-locale value.
|
|
102
|
+
* Drives the popover's translation tab and the Locales panel's counts.
|
|
103
|
+
*/
|
|
104
|
+
export declare const translatableFields: <T extends Tree>(value: T, schema: Pick<StructuredSchema<T>, "translatable" | "items">) => TranslatableField[];
|
|
105
|
+
/** How many translatable strings a locale's overlay still lacks. */
|
|
106
|
+
export declare const countTranslations: <T extends Tree>(value: T, overlay: TranslationOverlay | undefined, schema: Pick<StructuredSchema<T>, "translatable" | "items">) => {
|
|
107
|
+
total: number;
|
|
108
|
+
missing: number;
|
|
109
|
+
};
|
|
110
|
+
export declare const asString: (v: unknown, fallback?: string) => string;
|
|
111
|
+
export declare const asNumber: (v: unknown, fallback?: number | null) => number | null;
|
|
112
|
+
export declare const asBoolean: (v: unknown, fallback?: boolean) => boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Normalize a list of items, guaranteeing every item carries a string `id`.
|
|
115
|
+
* An item without one (a hand-written seed, say) gets a deterministic
|
|
116
|
+
* `item-<index>` so reads stay stable until the editor next writes the list,
|
|
117
|
+
* at which point the ids are persisted.
|
|
118
|
+
*/
|
|
119
|
+
export declare const asItems: <I extends StructuredItem>(raw: unknown, normalizeItem: (item: Tree, index: number) => Omit<I, "id">) => I[];
|
|
120
|
+
/** A short random id for a newly added item. Stable once written. */
|
|
121
|
+
export declare const newItemId: () => string;
|
|
122
|
+
/** Read a structured value's overlay for one locale out of a whole scope tree. */
|
|
123
|
+
export declare const overlayAt: (tree: Tree | undefined, name: string) => TranslationOverlay | undefined;
|
|
124
|
+
/** A list of strings; anything else is dropped. */
|
|
125
|
+
export declare const asStrings: (v: unknown) => string[];
|
|
126
|
+
/** A nullable string: `null` (cleared) stays `null`; anything else is a string. */
|
|
127
|
+
export declare const asOptionalString: (v: unknown) => string | null;
|
|
128
|
+
/** One of a fixed set of strings, else the fallback. */
|
|
129
|
+
export declare const asEnum: <E extends string>(v: unknown, values: readonly E[], fallback: E) => E;
|
|
130
|
+
/** Move an item within a list, returning a new list. */
|
|
131
|
+
export declare const moveItem: <I>(list: readonly I[], from: number, to: number) => I[];
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured values: the shapes behind the editor components (hours, team,
|
|
3
|
+
* testimonials, …) and the two rules every one of them follows.
|
|
4
|
+
*
|
|
5
|
+
* 1. **Versioned shapes, whole-object writes.** A structured value is a plain
|
|
6
|
+
* object with a `v` version number. Components never patch a leaf inside
|
|
7
|
+
* it; they read the whole value through the schema's `normalize`, change
|
|
8
|
+
* it, and write the whole object back. A field the editor clears is
|
|
9
|
+
* written as `null`, never dropped: the draft and release trees deep-merge
|
|
10
|
+
* over the published tree, and a missing key merges to "unchanged" while
|
|
11
|
+
* `null` merges to "cleared". That is what stops a cleared field from
|
|
12
|
+
* reverting to the template's demo copy.
|
|
13
|
+
*
|
|
14
|
+
* 2. **Localisation is a string overlay, never a second structure.** The
|
|
15
|
+
* default locale stores the full value at `<name>`. Every other locale
|
|
16
|
+
* stores only strings, at `<name>.$t.<id>.<field>`, keyed by the stable
|
|
17
|
+
* `id` of the list item they translate (the reserved id `_` addresses the
|
|
18
|
+
* value's own root fields). Because objects deep-merge across locales,
|
|
19
|
+
* reading `es` yields the default structure plus the `es` overlay, and
|
|
20
|
+
* {@link applyTranslations} folds the strings in. Structure edits happen in
|
|
21
|
+
* the default locale only, so the item list can never fork between
|
|
22
|
+
* languages.
|
|
23
|
+
*/
|
|
24
|
+
import { get, leafPaths } from './path.js';
|
|
25
|
+
/** Branch under a structured value that holds a locale's string overlay. */
|
|
26
|
+
export const TRANSLATIONS_KEY = '$t';
|
|
27
|
+
/** Overlay id that addresses the structured value's root fields. */
|
|
28
|
+
export const ROOT_ID = '_';
|
|
29
|
+
export const isPlainObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
30
|
+
export const defineStructured = (schema) => ({
|
|
31
|
+
...schema,
|
|
32
|
+
read: (raw, fallback) => {
|
|
33
|
+
if (raw === undefined)
|
|
34
|
+
return fallback === undefined ? schema.empty() : schema.normalize(fallback);
|
|
35
|
+
if (raw === null)
|
|
36
|
+
return schema.empty();
|
|
37
|
+
const overlay = extractTranslations(raw);
|
|
38
|
+
const value = schema.normalize(stripTranslations(raw));
|
|
39
|
+
return overlay ? applyTranslations(value, overlay, schema) : value;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
/** Path of one translated string: `<name>.$t.<id>.<field>`. */
|
|
43
|
+
export const translationPath = (name, id, field) => `${name}.${TRANSLATIONS_KEY}.${id}.${field}`;
|
|
44
|
+
/** The `$t` branch of a stored value, when it is one. A dotted field
|
|
45
|
+
* (`labels.closed`, `tags.0`) is stored nested by the path-based writes and
|
|
46
|
+
* read back flat here. */
|
|
47
|
+
export const extractTranslations = (raw) => {
|
|
48
|
+
if (!isPlainObject(raw))
|
|
49
|
+
return undefined;
|
|
50
|
+
const t = raw[TRANSLATIONS_KEY];
|
|
51
|
+
if (!isPlainObject(t))
|
|
52
|
+
return undefined;
|
|
53
|
+
const out = {};
|
|
54
|
+
for (const [id, fields] of Object.entries(t)) {
|
|
55
|
+
if (!isPlainObject(fields))
|
|
56
|
+
continue;
|
|
57
|
+
const strings = {};
|
|
58
|
+
for (const path of leafPaths(fields)) {
|
|
59
|
+
const v = get(fields, path);
|
|
60
|
+
if (typeof v === 'string')
|
|
61
|
+
strings[path] = v;
|
|
62
|
+
}
|
|
63
|
+
out[id] = strings;
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
};
|
|
67
|
+
/** A copy of `raw` without its `$t` branch, so a whole-object write in the
|
|
68
|
+
* default locale never carries another locale's strings. */
|
|
69
|
+
export const stripTranslations = (raw) => {
|
|
70
|
+
if (!isPlainObject(raw) || !(TRANSLATIONS_KEY in raw))
|
|
71
|
+
return raw;
|
|
72
|
+
const { [TRANSLATIONS_KEY]: _omit, ...rest } = raw;
|
|
73
|
+
return rest;
|
|
74
|
+
};
|
|
75
|
+
const overlayString = (overlay, id, field) => {
|
|
76
|
+
const v = overlay[id]?.[field];
|
|
77
|
+
return typeof v === 'string' && v !== '' ? v : undefined;
|
|
78
|
+
};
|
|
79
|
+
const specList = (items) => items === undefined ? [] : Array.isArray(items) ? items : [items];
|
|
80
|
+
const isStringArray = (v) => Array.isArray(v) && v.every((s) => typeof s === 'string');
|
|
81
|
+
/** `set` that copies along the path instead of mutating shared branches. */
|
|
82
|
+
export const setIn = (obj, path, value) => {
|
|
83
|
+
const [head, ...rest] = path.split('.');
|
|
84
|
+
const out = { ...obj };
|
|
85
|
+
if (rest.length === 0) {
|
|
86
|
+
out[head] = value;
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
const child = obj[head];
|
|
90
|
+
out[head] = setIn(isPlainObject(child) ? child : {}, rest.join('.'), value);
|
|
91
|
+
return out;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Fold a locale's string overlay into one object (the root value or an item)
|
|
95
|
+
* and, recursively, into the item lists it holds.
|
|
96
|
+
*/
|
|
97
|
+
const applyTo = (obj, id, translatable, items, overlay) => {
|
|
98
|
+
let out = { ...obj };
|
|
99
|
+
for (const field of translatable) {
|
|
100
|
+
const cur = get(obj, field);
|
|
101
|
+
if (typeof cur === 'string') {
|
|
102
|
+
const s = overlayString(overlay, id, field);
|
|
103
|
+
if (s !== undefined)
|
|
104
|
+
out = setIn(out, field, s);
|
|
105
|
+
}
|
|
106
|
+
else if (isStringArray(cur)) {
|
|
107
|
+
let changed = false;
|
|
108
|
+
const next = cur.map((v, i) => {
|
|
109
|
+
const s = overlayString(overlay, id, `${field}.${i}`);
|
|
110
|
+
if (s === undefined)
|
|
111
|
+
return v;
|
|
112
|
+
changed = true;
|
|
113
|
+
return s;
|
|
114
|
+
});
|
|
115
|
+
if (changed)
|
|
116
|
+
out = setIn(out, field, next);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
for (const spec of specList(items)) {
|
|
120
|
+
const list = obj[spec.key];
|
|
121
|
+
if (!Array.isArray(list))
|
|
122
|
+
continue;
|
|
123
|
+
out[spec.key] = list.map((item) => isPlainObject(item) && typeof item.id === 'string'
|
|
124
|
+
? applyTo(item, item.id, spec.translatable, spec.items, overlay)
|
|
125
|
+
: item);
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Fold a locale's string overlay into a normalized default-locale value.
|
|
131
|
+
* Root fields come from the `_` id; item fields from the item's own `id`,
|
|
132
|
+
* at every nesting level. Only non-empty strings override, so an
|
|
133
|
+
* untranslated field shows the default-locale text rather than a blank.
|
|
134
|
+
*/
|
|
135
|
+
export const applyTranslations = (value, overlay, schema) => {
|
|
136
|
+
if (!overlay)
|
|
137
|
+
return value;
|
|
138
|
+
return applyTo(value, ROOT_ID, schema.translatable, schema.items, overlay);
|
|
139
|
+
};
|
|
140
|
+
const collectFrom = (obj, id, translatable, items, out) => {
|
|
141
|
+
for (const field of translatable) {
|
|
142
|
+
const cur = get(obj, field);
|
|
143
|
+
if (typeof cur === 'string') {
|
|
144
|
+
if (cur !== '')
|
|
145
|
+
out.push({ id, field, source: cur });
|
|
146
|
+
}
|
|
147
|
+
else if (isStringArray(cur)) {
|
|
148
|
+
cur.forEach((s, i) => {
|
|
149
|
+
if (s !== '')
|
|
150
|
+
out.push({ id, field: `${field}.${i}`, source: s });
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
for (const spec of specList(items)) {
|
|
155
|
+
const list = obj[spec.key];
|
|
156
|
+
if (!Array.isArray(list))
|
|
157
|
+
continue;
|
|
158
|
+
for (const item of list) {
|
|
159
|
+
if (!isPlainObject(item) || typeof item.id !== 'string')
|
|
160
|
+
continue;
|
|
161
|
+
collectFrom(item, item.id, spec.translatable, spec.items, out);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
/**
|
|
166
|
+
* Every translatable, non-empty string in a normalized default-locale value.
|
|
167
|
+
* Drives the popover's translation tab and the Locales panel's counts.
|
|
168
|
+
*/
|
|
169
|
+
export const translatableFields = (value, schema) => {
|
|
170
|
+
const out = [];
|
|
171
|
+
collectFrom(value, ROOT_ID, schema.translatable, schema.items, out);
|
|
172
|
+
return out;
|
|
173
|
+
};
|
|
174
|
+
/** How many translatable strings a locale's overlay still lacks. */
|
|
175
|
+
export const countTranslations = (value, overlay, schema) => {
|
|
176
|
+
const fields = translatableFields(value, schema);
|
|
177
|
+
let missing = 0;
|
|
178
|
+
for (const f of fields) {
|
|
179
|
+
if (!overlay || overlayString(overlay, f.id, f.field) === undefined)
|
|
180
|
+
missing += 1;
|
|
181
|
+
}
|
|
182
|
+
return { total: fields.length, missing };
|
|
183
|
+
};
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
// Normalizer building blocks
|
|
186
|
+
// ---------------------------------------------------------------------------
|
|
187
|
+
export const asString = (v, fallback = '') => typeof v === 'string' ? v : fallback;
|
|
188
|
+
export const asNumber = (v, fallback = null) => typeof v === 'number' && Number.isFinite(v) ? v : fallback;
|
|
189
|
+
export const asBoolean = (v, fallback = false) => typeof v === 'boolean' ? v : fallback;
|
|
190
|
+
/**
|
|
191
|
+
* Normalize a list of items, guaranteeing every item carries a string `id`.
|
|
192
|
+
* An item without one (a hand-written seed, say) gets a deterministic
|
|
193
|
+
* `item-<index>` so reads stay stable until the editor next writes the list,
|
|
194
|
+
* at which point the ids are persisted.
|
|
195
|
+
*/
|
|
196
|
+
export const asItems = (raw, normalizeItem) => {
|
|
197
|
+
if (!Array.isArray(raw))
|
|
198
|
+
return [];
|
|
199
|
+
const out = [];
|
|
200
|
+
raw.forEach((entry, index) => {
|
|
201
|
+
if (!isPlainObject(entry))
|
|
202
|
+
return;
|
|
203
|
+
const id = typeof entry.id === 'string' && entry.id !== '' ? entry.id : `item-${index}`;
|
|
204
|
+
out.push({ id, ...normalizeItem(entry, index) });
|
|
205
|
+
});
|
|
206
|
+
return out;
|
|
207
|
+
};
|
|
208
|
+
/** A short random id for a newly added item. Stable once written. */
|
|
209
|
+
export const newItemId = () => {
|
|
210
|
+
const bytes = new Uint8Array(6);
|
|
211
|
+
if (typeof crypto !== 'undefined' && crypto.getRandomValues)
|
|
212
|
+
crypto.getRandomValues(bytes);
|
|
213
|
+
else
|
|
214
|
+
for (let i = 0; i < bytes.length; i++)
|
|
215
|
+
bytes[i] = Math.floor(Math.random() * 256);
|
|
216
|
+
let out = '';
|
|
217
|
+
for (const b of bytes)
|
|
218
|
+
out += b.toString(16).padStart(2, '0');
|
|
219
|
+
return out;
|
|
220
|
+
};
|
|
221
|
+
/** Read a structured value's overlay for one locale out of a whole scope tree. */
|
|
222
|
+
export const overlayAt = (tree, name) => extractTranslations(get(tree, name));
|
|
223
|
+
/** A list of strings; anything else is dropped. */
|
|
224
|
+
export const asStrings = (v) => Array.isArray(v) ? v.filter((s) => typeof s === 'string') : [];
|
|
225
|
+
/** A nullable string: `null` (cleared) stays `null`; anything else is a string. */
|
|
226
|
+
export const asOptionalString = (v) => typeof v === 'string' && v !== '' ? v : null;
|
|
227
|
+
/** One of a fixed set of strings, else the fallback. */
|
|
228
|
+
export const asEnum = (v, values, fallback) => typeof v === 'string' && values.includes(v) ? v : fallback;
|
|
229
|
+
/** Move an item within a list, returning a new list. */
|
|
230
|
+
export const moveItem = (list, from, to) => {
|
|
231
|
+
const next = [...list];
|
|
232
|
+
const [item] = next.splice(from, 1);
|
|
233
|
+
next.splice(to, 0, item);
|
|
234
|
+
return next;
|
|
235
|
+
};
|
package/dist/core/wire.d.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* `published_at` stay snake_case because that is what the JSON carries.
|
|
12
12
|
*/
|
|
13
13
|
import type { Tree } from './path.js';
|
|
14
|
-
import type { PageDeleteOutcome } from './page-entry.js';
|
|
14
|
+
import type { PageDeleteOutcome, PageEntry } from './page-entry.js';
|
|
15
15
|
export type { PageDeleteOutcome };
|
|
16
16
|
/** One pending change in a release, without the bookkeeping the store adds. */
|
|
17
17
|
export type ReleaseItemCore = {
|
|
@@ -182,6 +182,36 @@ export type CmsDeployState = {
|
|
|
182
182
|
};
|
|
183
183
|
latest?: CmsDeployRun | null;
|
|
184
184
|
};
|
|
185
|
+
/**
|
|
186
|
+
* A project's published content in one object: `layouts` and `pages` keyed
|
|
187
|
+
* `[locale][routeId]`, plus the non-localised `site` tree. `POST /seed`
|
|
188
|
+
* accepts it and `GET /export` returns it, so a template's published
|
|
189
|
+
* `content/` can seed a fresh project and a project can be dumped back into
|
|
190
|
+
* the same shape. A page keyed by route id may be a bare tree (a static page,
|
|
191
|
+
* `params: {}`) or a full `PageEntry[]`.
|
|
192
|
+
*/
|
|
193
|
+
export type CmsSeed = {
|
|
194
|
+
layouts?: Record<string, Record<string, Tree>>;
|
|
195
|
+
pages?: Record<string, Record<string, Tree | PageEntry[]>>;
|
|
196
|
+
site?: Tree;
|
|
197
|
+
};
|
|
198
|
+
export type SeedRequest = CmsSeed & {
|
|
199
|
+
/** Overwrite a project that already has published rows. */
|
|
200
|
+
force?: boolean;
|
|
201
|
+
};
|
|
202
|
+
export type SeedSummary = {
|
|
203
|
+
locales: string[];
|
|
204
|
+
layouts: number;
|
|
205
|
+
pages: number;
|
|
206
|
+
site: boolean;
|
|
207
|
+
};
|
|
208
|
+
export type SeedResponse = {
|
|
209
|
+
ok: true;
|
|
210
|
+
seeded: SeedSummary;
|
|
211
|
+
} | {
|
|
212
|
+
ok: false;
|
|
213
|
+
reason: 'already-seeded';
|
|
214
|
+
};
|
|
185
215
|
export type DocsResponse = {
|
|
186
216
|
contents: Tree;
|
|
187
217
|
} | PageDeleteOutcome;
|
package/dist/editor.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@velastack/cms/editor` — the editing chrome a structured component's
|
|
3
|
+
* editable sibling imports lazily, so none of it reaches the public bundle:
|
|
4
|
+
*
|
|
5
|
+
* ```svelte
|
|
6
|
+
* {#await import('@velastack/cms/editor') then { StructuredEditorPopover, FieldInput, ReorderButtons }}
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
export { default as StructuredEditorPopover } from './components/admin-bar/structured-editor-popover.svelte';
|
|
10
|
+
export { default as FieldInput } from './components/admin-bar/field-input.svelte';
|
|
11
|
+
export type { FieldInputType } from './components/admin-bar/field-input.svelte';
|
|
12
|
+
export { default as ReorderButtons } from './components/admin-bar/reorder-buttons.svelte';
|
|
13
|
+
export { default as FieldsForm } from './components/admin-bar/fields-form.svelte';
|
|
14
|
+
export { default as ListField } from './components/admin-bar/list-field.svelte';
|
|
15
|
+
export { default as LinkInput } from './components/admin-bar/link-input.svelte';
|
|
16
|
+
export { default as RichTextInput } from './components/admin-bar/rich-text-input.svelte';
|
|
17
|
+
export { default as CssRoot } from './components/admin-bar/css-root.svelte';
|
|
18
|
+
export { Button } from './components/admin-bar/ui/button/index.js';
|
|
19
|
+
export { Input } from './components/admin-bar/ui/input/index.js';
|
|
20
|
+
export { Textarea } from './components/admin-bar/ui/textarea/index.js';
|
|
21
|
+
export { Switch } from './components/admin-bar/ui/switch/index.js';
|
|
22
|
+
export { Checkbox } from './components/admin-bar/ui/checkbox/index.js';
|
|
23
|
+
export * as Popover from './components/admin-bar/ui/popover/index.js';
|
|
24
|
+
export * as Tabs from './components/admin-bar/ui/tabs/index.js';
|
|
25
|
+
export * as Sheet from './components/admin-bar/ui/sheet/index.js';
|
|
26
|
+
export { default as CmsMediaPicker } from './components/cms/cms-media-picker.svelte';
|
package/dist/editor.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@velastack/cms/editor` — the editing chrome a structured component's
|
|
3
|
+
* editable sibling imports lazily, so none of it reaches the public bundle:
|
|
4
|
+
*
|
|
5
|
+
* ```svelte
|
|
6
|
+
* {#await import('@velastack/cms/editor') then { StructuredEditorPopover, FieldInput, ReorderButtons }}
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
export { default as StructuredEditorPopover } from './components/admin-bar/structured-editor-popover.svelte';
|
|
10
|
+
export { default as FieldInput } from './components/admin-bar/field-input.svelte';
|
|
11
|
+
export { default as ReorderButtons } from './components/admin-bar/reorder-buttons.svelte';
|
|
12
|
+
export { default as FieldsForm } from './components/admin-bar/fields-form.svelte';
|
|
13
|
+
export { default as ListField } from './components/admin-bar/list-field.svelte';
|
|
14
|
+
export { default as LinkInput } from './components/admin-bar/link-input.svelte';
|
|
15
|
+
export { default as RichTextInput } from './components/admin-bar/rich-text-input.svelte';
|
|
16
|
+
export { default as CssRoot } from './components/admin-bar/css-root.svelte';
|
|
17
|
+
export { Button } from './components/admin-bar/ui/button/index.js';
|
|
18
|
+
export { Input } from './components/admin-bar/ui/input/index.js';
|
|
19
|
+
export { Textarea } from './components/admin-bar/ui/textarea/index.js';
|
|
20
|
+
export { Switch } from './components/admin-bar/ui/switch/index.js';
|
|
21
|
+
export { Checkbox } from './components/admin-bar/ui/checkbox/index.js';
|
|
22
|
+
export * as Popover from './components/admin-bar/ui/popover/index.js';
|
|
23
|
+
export * as Tabs from './components/admin-bar/ui/tabs/index.js';
|
|
24
|
+
export * as Sheet from './components/admin-bar/ui/sheet/index.js';
|
|
25
|
+
export { default as CmsMediaPicker } from './components/cms/cms-media-picker.svelte';
|
package/dist/index.d.ts
CHANGED
|
@@ -14,14 +14,36 @@ export type { CmsNumberProps } from './components/cms/cms-number.svelte';
|
|
|
14
14
|
export { default as CmsDateTime } from './components/cms/cms-date-time.svelte';
|
|
15
15
|
export type { CmsDateTimeMode, CmsDateTimeProps } from './components/cms/cms-date-time.svelte';
|
|
16
16
|
export { default as CmsLink } from './components/cms/cms-link.svelte';
|
|
17
|
-
export type {
|
|
18
|
-
export { default as CmsRepeater } from './components/cms/cms-repeater.svelte';
|
|
17
|
+
export type { CmsLinkRenderProps } from './components/cms/cms-link.svelte';
|
|
19
18
|
export { default as CmsEntries } from './components/cms/cms-entries.svelte';
|
|
19
|
+
export { default as CmsNav } from './components/cms/cms-nav.svelte';
|
|
20
|
+
export { default as CmsHours } from './components/cms/cms-hours.svelte';
|
|
21
|
+
export { default as CmsContact } from './components/cms/cms-contact.svelte';
|
|
22
|
+
export { default as CmsSocialLinks } from './components/cms/cms-social-links.svelte';
|
|
23
|
+
export { default as CmsCollection } from './components/cms/cms-collection.svelte';
|
|
24
|
+
export { default as CmsTeam } from './components/cms/cms-team.svelte';
|
|
25
|
+
export { default as CmsTestimonials } from './components/cms/cms-testimonials.svelte';
|
|
26
|
+
export { default as CmsPricing } from './components/cms/cms-pricing.svelte';
|
|
27
|
+
export { default as CmsFaq } from './components/cms/cms-faq.svelte';
|
|
28
|
+
export { default as CmsStats } from './components/cms/cms-stats.svelte';
|
|
29
|
+
export { default as CmsSteps } from './components/cms/cms-steps.svelte';
|
|
30
|
+
export { default as CmsTimeline } from './components/cms/cms-timeline.svelte';
|
|
31
|
+
export { default as CmsGallery } from './components/cms/cms-gallery.svelte';
|
|
32
|
+
export { default as CmsLogos } from './components/cms/cms-logos.svelte';
|
|
33
|
+
export { default as CmsSchedule } from './components/cms/cms-schedule.svelte';
|
|
34
|
+
export * from './core/shapes/index.js';
|
|
20
35
|
export { default as AdminBar } from './components/admin-bar/admin-bar.svelte';
|
|
21
|
-
export {
|
|
36
|
+
export { useCmsField, resolveScopeRef, ROOT_SCOPE_ID } from './components/cms/use-cms-field.svelte.js';
|
|
37
|
+
export type { CmsField, CmsFieldInput } from './components/cms/use-cms-field.svelte.js';
|
|
38
|
+
export { defineStructured, applyTranslations, countTranslations, extractTranslations, stripTranslations, translatableFields, translationPath, asBoolean, asEnum, asItems, asNumber, asOptionalString, asString, asStrings, moveItem, newItemId, setIn, ROOT_ID, TRANSLATIONS_KEY } from './core/structured.js';
|
|
39
|
+
export type { ItemsSpec, Structured, StructuredItem, StructuredSchema, TranslatableField, TranslationOverlay } from './core/structured.js';
|
|
40
|
+
export { registerStructured, getStructured } from './core/structured-registry.js';
|
|
41
|
+
export { toMetaTags } from './core/metadata.js';
|
|
42
|
+
export type { MetaTagsOptions, MetaTagsOutput } from './core/metadata.js';
|
|
43
|
+
export { definePage, DEFAULT_METADATA_SCHEMA, metadataSchemaFor } from './components/admin-bar/page-config.js';
|
|
22
44
|
export type { CmsPageConfig, CmsCreatablePageConfig, CmsStaticPageConfig, CmsPageField, CmsPageMetadataSchema, MetadataFieldSchema, MetadataPrimitive } from './components/admin-bar/page-config.js';
|
|
23
45
|
export { cmsStore } from './components/cms/cms-store.svelte.js';
|
|
24
46
|
export { cms } from './components/cms/cms-store.svelte.js';
|
|
25
47
|
export { CMS_SCOPE, getCmsScope, getCmsValue, getPageScope } from './components/cms/scope.js';
|
|
26
48
|
export { installCmsScope } from './components/cms/install-scope.svelte.js';
|
|
27
|
-
export type { CmsEntry, CmsManifest, CmsManifestRoute, CmsManifestScope, CmsPayload, CmsScope, CmsScopeEntry } from './components/cms/scope.js';
|
|
49
|
+
export type { CmsEntry, CmsManifest, CmsManifestRoute, CmsManifestScope, CmsManifestUsage, CmsPayload, CmsScope, CmsScopeEntry, SiteFieldSchema, SiteFieldType, SiteSchema } from './components/cms/scope.js';
|
package/dist/index.js
CHANGED
|
@@ -13,12 +13,41 @@ export { default as CmsBoolean } from './components/cms/cms-boolean.svelte';
|
|
|
13
13
|
export { default as CmsNumber } from './components/cms/cms-number.svelte';
|
|
14
14
|
export { default as CmsDateTime } from './components/cms/cms-date-time.svelte';
|
|
15
15
|
export { default as CmsLink } from './components/cms/cms-link.svelte';
|
|
16
|
-
export { default as CmsRepeater } from './components/cms/cms-repeater.svelte';
|
|
17
16
|
export { default as CmsEntries } from './components/cms/cms-entries.svelte';
|
|
17
|
+
// Structured editor components. Each reads one versioned value, opens a
|
|
18
|
+
// popover editor in edit mode and hands the typed view to `children`.
|
|
19
|
+
// Their value types, normalizers and JSON-LD helpers come from the shapes.
|
|
20
|
+
export { default as CmsNav } from './components/cms/cms-nav.svelte';
|
|
21
|
+
export { default as CmsHours } from './components/cms/cms-hours.svelte';
|
|
22
|
+
export { default as CmsContact } from './components/cms/cms-contact.svelte';
|
|
23
|
+
export { default as CmsSocialLinks } from './components/cms/cms-social-links.svelte';
|
|
24
|
+
export { default as CmsCollection } from './components/cms/cms-collection.svelte';
|
|
25
|
+
export { default as CmsTeam } from './components/cms/cms-team.svelte';
|
|
26
|
+
export { default as CmsTestimonials } from './components/cms/cms-testimonials.svelte';
|
|
27
|
+
export { default as CmsPricing } from './components/cms/cms-pricing.svelte';
|
|
28
|
+
export { default as CmsFaq } from './components/cms/cms-faq.svelte';
|
|
29
|
+
// List presets: fixed item shapes; a new shape is a new preset here.
|
|
30
|
+
export { default as CmsStats } from './components/cms/cms-stats.svelte';
|
|
31
|
+
export { default as CmsSteps } from './components/cms/cms-steps.svelte';
|
|
32
|
+
export { default as CmsTimeline } from './components/cms/cms-timeline.svelte';
|
|
33
|
+
export { default as CmsGallery } from './components/cms/cms-gallery.svelte';
|
|
34
|
+
export { default as CmsLogos } from './components/cms/cms-logos.svelte';
|
|
35
|
+
export { default as CmsSchedule } from './components/cms/cms-schedule.svelte';
|
|
36
|
+
export * from './core/shapes/index.js';
|
|
18
37
|
// Admin bar (sync wrapper; admin-bar-internal + seo-panel are async chunks)
|
|
19
38
|
export { default as AdminBar } from './components/admin-bar/admin-bar.svelte';
|
|
39
|
+
// Building blocks for structured components: the field hook, the value
|
|
40
|
+
// rules (versioned shapes, `$t` overlay) and the registry the Locales panel
|
|
41
|
+
// reads. The editor popover and field inputs are admin-bar chunks, imported
|
|
42
|
+
// lazily by editable siblings:
|
|
43
|
+
// `import('@velastack/cms/editor')`
|
|
44
|
+
export { useCmsField, resolveScopeRef, ROOT_SCOPE_ID } from './components/cms/use-cms-field.svelte.js';
|
|
45
|
+
export { defineStructured, applyTranslations, countTranslations, extractTranslations, stripTranslations, translatableFields, translationPath, asBoolean, asEnum, asItems, asNumber, asOptionalString, asString, asStrings, moveItem, newItemId, setIn, ROOT_ID, TRANSLATIONS_KEY } from './core/structured.js';
|
|
46
|
+
export { registerStructured, getStructured } from './core/structured-registry.js';
|
|
47
|
+
// Page metadata → svelte-meta-tags props.
|
|
48
|
+
export { toMetaTags } from './core/metadata.js';
|
|
20
49
|
// Per-route page configuration — declare in `page.cms.ts` next to `+page.svelte`.
|
|
21
|
-
export { definePage } from './components/admin-bar/page-config.js';
|
|
50
|
+
export { definePage, DEFAULT_METADATA_SCHEMA, metadataSchemaFor } from './components/admin-bar/page-config.js';
|
|
22
51
|
// Edit-mode store
|
|
23
52
|
export { cmsStore } from './components/cms/cms-store.svelte.js';
|
|
24
53
|
// Merged CMS read view (server payload + client overlay), shaped like CmsPayload
|
package/dist/server/load-cms.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velastack/cms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "A scope-aware CMS for SvelteKit, for static or dynamic sites.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
@@ -57,6 +57,11 @@
|
|
|
57
57
|
"svelte": "./dist/index.js",
|
|
58
58
|
"default": "./dist/index.js"
|
|
59
59
|
},
|
|
60
|
+
"./editor": {
|
|
61
|
+
"types": "./dist/editor.d.ts",
|
|
62
|
+
"svelte": "./dist/editor.js",
|
|
63
|
+
"default": "./dist/editor.js"
|
|
64
|
+
},
|
|
60
65
|
"./server": {
|
|
61
66
|
"types": "./dist/server/index.d.ts",
|
|
62
67
|
"default": "./dist/server/index.js"
|
|
@@ -72,6 +77,10 @@
|
|
|
72
77
|
"./adapter": {
|
|
73
78
|
"types": "./plugin/dist/adapter.d.ts",
|
|
74
79
|
"default": "./plugin/dist/adapter.js"
|
|
80
|
+
},
|
|
81
|
+
"./build": {
|
|
82
|
+
"types": "./plugin/dist/build.d.ts",
|
|
83
|
+
"default": "./plugin/dist/build.js"
|
|
75
84
|
}
|
|
76
85
|
},
|
|
77
86
|
"peerDependencies": {
|
|
@@ -110,7 +119,7 @@
|
|
|
110
119
|
"tw-animate-css": "^1.4.0",
|
|
111
120
|
"typescript": "^6.0.3",
|
|
112
121
|
"vite": "^8.2.2",
|
|
113
|
-
"vitest": "^
|
|
122
|
+
"vitest": "^5.0.1"
|
|
114
123
|
},
|
|
115
124
|
"dependencies": {
|
|
116
125
|
"@sveltejs/adapter-static": "^3.0.10",
|
|
@@ -119,7 +128,7 @@
|
|
|
119
128
|
"@tiptap/pm": "^3.30.6",
|
|
120
129
|
"@tiptap/starter-kit": "^3.30.6",
|
|
121
130
|
"bits-ui": "^2.19.0",
|
|
122
|
-
"devalue": "^
|
|
131
|
+
"devalue": "^6.0.0",
|
|
123
132
|
"tailwind-merge": "^3.6.0"
|
|
124
133
|
}
|
|
125
134
|
}
|