smoodly 0.0.15 → 0.0.17
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 +238 -36
- package/dist/admin/auth.d.ts +7 -4
- package/dist/admin/auth.js +1 -1
- package/dist/admin/client-ops.js +3 -3
- package/dist/admin/custom-section.d.ts +10 -0
- package/dist/admin/custom-section.js +10 -0
- package/dist/admin/editor/CanvasOverlay.d.ts +6 -2
- package/dist/admin/editor/CanvasOverlay.js +6 -6
- package/dist/admin/editor/EditorView.d.ts +2 -0
- package/dist/admin/editor/EditorView.js +322 -62
- package/dist/admin/editor/GlobalInspector.d.ts +24 -0
- package/dist/admin/editor/GlobalInspector.js +13 -0
- package/dist/admin/editor/InsertPicker.d.ts +6 -5
- package/dist/admin/editor/InsertPicker.js +6 -4
- package/dist/admin/editor/InspectorFields.d.ts +21 -0
- package/dist/admin/editor/InspectorFields.js +22 -0
- package/dist/admin/editor/Outline.d.ts +0 -1
- package/dist/admin/editor/Outline.js +3 -3
- package/dist/admin/editor/PageSettings.js +3 -2
- package/dist/admin/editor/global-edit.d.ts +39 -0
- package/dist/admin/editor/global-edit.js +124 -0
- package/dist/admin/editor/useGlobalEdit.d.ts +6 -0
- package/dist/admin/editor/useGlobalEdit.js +18 -0
- package/dist/admin/forms/FieldWidget.d.ts +14 -1
- package/dist/admin/forms/FieldWidget.js +38 -11
- package/dist/admin/forms/ListField.d.ts +9 -1
- package/dist/admin/forms/ListField.js +16 -8
- package/dist/admin/forms/RichtextElementCard.js +11 -5
- package/dist/admin/forms/RowsWidget.d.ts +13 -0
- package/dist/admin/forms/RowsWidget.js +26 -0
- package/dist/admin/forms/SpanBar.d.ts +5 -0
- package/dist/admin/forms/SpanBar.js +37 -0
- package/dist/admin/forms/richtext-insert.d.ts +2 -2
- package/dist/admin/forms/richtext-insert.js +3 -3
- package/dist/admin/forms/richtext-nodes.js +1 -1
- package/dist/admin/forms/tabs.d.ts +20 -8
- package/dist/admin/forms/tabs.js +19 -23
- package/dist/admin/forms/useRichtextEditor.js +8 -1
- package/dist/admin/global-items.d.ts +9 -0
- package/dist/admin/{shared-items.js → global-items.js} +29 -14
- package/dist/admin/index.d.ts +3 -3
- package/dist/admin/index.js +1 -1
- package/dist/admin/next/op-handler.js +4 -3
- package/dist/admin/ops-impl.d.ts +3 -0
- package/dist/admin/ops-impl.js +242 -56
- package/dist/admin/ops.d.ts +38 -6
- package/dist/admin/serialize.d.ts +18 -7
- package/dist/admin/serialize.js +27 -5
- package/dist/admin/shell/AdminApp.js +7 -7
- package/dist/admin/shell/EntriesList.js +19 -3
- package/dist/admin/shell/EntryForm.js +183 -77
- package/dist/admin/shell/GlobalFields.d.ts +24 -0
- package/dist/admin/shell/GlobalFields.js +19 -0
- package/dist/admin/shell/{SharedForm.d.ts → GlobalForm.d.ts} +1 -1
- package/dist/admin/shell/GlobalForm.js +258 -0
- package/dist/admin/shell/{SharedList.d.ts → GlobalList.d.ts} +1 -1
- package/dist/admin/shell/{SharedList.js → GlobalList.js} +12 -11
- package/dist/admin/shell/IconRail.js +14 -7
- package/dist/admin/shell/PagesList.js +4 -8
- package/dist/admin/shell/entries-list.d.ts +2 -2
- package/dist/admin/shell/entries-list.js +3 -3
- package/dist/admin/shell/{shared-list.d.ts → global-list.d.ts} +3 -3
- package/dist/admin/shell/{shared-list.js → global-list.js} +2 -2
- package/dist/admin/supabase-auth.js +1 -1
- package/dist/admin/tree-ops.d.ts +10 -8
- package/dist/admin/tree-ops.js +28 -16
- package/dist/admin/ui/ActionMenu.d.ts +11 -0
- package/dist/admin/ui/ActionMenu.js +25 -0
- package/dist/admin/ui/HistoryModal.d.ts +23 -0
- package/dist/admin/ui/HistoryModal.js +40 -0
- package/dist/admin/ui/Modal.d.ts +5 -1
- package/dist/admin/ui/Modal.js +3 -3
- package/dist/admin/ui/PublishControl.d.ts +31 -0
- package/dist/admin/ui/PublishControl.js +24 -0
- package/dist/admin/ui/format.d.ts +4 -0
- package/dist/admin/ui/format.js +9 -0
- package/dist/admin/ui/primitives.d.ts +16 -1
- package/dist/admin/ui/primitives.js +20 -4
- package/dist/admin/ui/status-label.d.ts +10 -0
- package/dist/admin/ui/status-label.js +14 -0
- package/dist/admin/ui/theme.js +93 -13
- package/dist/admin/validate.d.ts +27 -2
- package/dist/admin/validate.js +47 -10
- package/dist/collections.d.ts +3 -9
- package/dist/collections.js +1 -2
- package/dist/conditions.d.ts +33 -0
- package/dist/conditions.js +79 -0
- package/dist/config.d.ts +26 -19
- package/dist/config.js +26 -25
- package/dist/css.d.ts +7 -0
- package/dist/css.js +57 -0
- package/dist/custom/CustomSection.d.ts +26 -0
- package/dist/custom/CustomSection.js +20 -0
- package/dist/custom/css.d.ts +3 -0
- package/dist/custom/css.js +28 -0
- package/dist/custom/index.d.ts +26 -0
- package/dist/custom/index.js +16 -0
- package/dist/custom/rows.d.ts +28 -0
- package/dist/custom/rows.js +129 -0
- package/dist/custom/schema.d.ts +32 -0
- package/dist/custom/schema.js +39 -0
- package/dist/entry-store.d.ts +42 -17
- package/dist/entry-store.js +107 -40
- package/dist/fields.d.ts +5 -2
- package/dist/fields.js +4 -2
- package/dist/{shared-id.d.ts → global-id.d.ts} +1 -1
- package/dist/{shared-id.js → global-id.js} +4 -4
- package/dist/global.d.ts +57 -0
- package/dist/global.js +51 -0
- package/dist/index.d.ts +28 -18
- package/dist/index.js +10 -5
- package/dist/media.js +1 -1
- package/dist/next/index.d.ts +1 -1
- package/dist/next/page-renderer.d.ts +4 -2
- package/dist/next/page-renderer.js +17 -13
- package/dist/next/queries.d.ts +6 -6
- package/dist/next/queries.js +7 -7
- package/dist/page.js +2 -2
- package/dist/pairing.d.ts +13 -7
- package/dist/pairing.js +4 -4
- package/dist/refs.d.ts +2 -2
- package/dist/refs.js +4 -4
- package/dist/render.d.ts +13 -1
- package/dist/render.js +10 -5
- package/dist/resolve.d.ts +11 -6
- package/dist/resolve.js +22 -12
- package/dist/revalidate.d.ts +4 -4
- package/dist/revalidate.js +4 -4
- package/dist/richtext-render.js +2 -2
- package/dist/richtext-walk.d.ts +5 -5
- package/dist/richtext-walk.js +4 -4
- package/dist/schema.d.ts +15 -10
- package/dist/schema.js +19 -7
- package/dist/section-wrapper.d.ts +18 -6
- package/dist/section-wrapper.js +24 -17
- package/dist/site.d.ts +17 -5
- package/dist/site.js +36 -12
- package/dist/sql-space.js +1 -1
- package/dist/sql.js +19 -16
- package/dist/store.d.ts +45 -13
- package/dist/store.js +88 -12
- package/dist/styles.d.ts +27 -0
- package/dist/styles.js +60 -0
- package/dist/supabase-entry-store.d.ts +11 -6
- package/dist/supabase-entry-store.js +115 -39
- package/dist/supabase-store.d.ts +13 -6
- package/dist/supabase-store.js +90 -20
- package/dist/zones.d.ts +9 -7
- package/dist/zones.js +5 -5
- package/package.json +1 -1
- package/dist/admin/shared-items.d.ts +0 -9
- package/dist/admin/shell/SharedForm.js +0 -134
- package/dist/shared.d.ts +0 -46
- package/dist/shared.js +0 -36
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { toolset } from "./toolset.ts";
|
|
|
4
4
|
import { Section } from "./section-wrapper.tsx";
|
|
5
5
|
import { page } from "./render.tsx";
|
|
6
6
|
import { entryPage } from "./entry-page.tsx";
|
|
7
|
-
import {
|
|
7
|
+
import { globalItem } from "./global.ts";
|
|
8
8
|
import { marks } from "./marks.ts";
|
|
9
9
|
export { Zone, renderPage, EMPTY_PAGE_CONTEXT } from "./render.tsx";
|
|
10
10
|
export type { PageTree, TreeNode, ZoneContent, PairedPage, Registry, PageContext, PageContextLink, PageLink, PageViewProps } from "./render.tsx";
|
|
@@ -14,6 +14,11 @@ export type { PageSchema } from "./page.ts";
|
|
|
14
14
|
export { fixedSlug } from "./page.ts";
|
|
15
15
|
export type { EntryPageSchema, PairedEntryPage, EntryPageProps } from "./entry-page.tsx";
|
|
16
16
|
export { f, normalizeOptions, optionsOf, optionValues } from "./fields.ts";
|
|
17
|
+
export { when, evaluate, isHidden, assertConditions, splitConditionPath } from "./conditions.ts";
|
|
18
|
+
export { DEFAULT_STYLE_VALUES, STYLE_KEYS, SPACING_NONE, resolveStyleValues, styleDescriptors, inlineStyles } from "./styles.ts";
|
|
19
|
+
export type { StyleValues, StyleValuesInput, StyleProps, StyleKey } from "./styles.ts";
|
|
20
|
+
export * from "./custom/index.ts";
|
|
21
|
+
export type { Condition, ConditionOp, ConditionScope } from "./conditions.ts";
|
|
17
22
|
export { defaultsOf, withDefaults } from "./field-defaults.ts";
|
|
18
23
|
export { filterPageTree } from "./page-tree.ts";
|
|
19
24
|
export { ASSET_COLLECTION, DEFAULT_MEDIA, MEDIA_TYPES, FULL_CROP, CENTER_HOTSPOT, parseAspect, cropAspect, clamp01, isMediaValue, collectAssetIds, applyAssets, } from "./media.ts";
|
|
@@ -39,7 +44,7 @@ export { SupabaseEntryStore } from "./supabase-entry-store.ts";
|
|
|
39
44
|
export { SupabasePathIndex } from "./supabase-path-index.ts";
|
|
40
45
|
export type { EntryStore, EntryRecord, EntryLocale, EntryVersion, EntryUsage, ListOptions, CreateEntryOptions, AddEntryLocaleOptions, EntryStoreOptions, Where, WhereValue, } from "./entry-store.ts";
|
|
41
46
|
export { entryErrors, compareEntries, DEFAULT_ENTRY_LOCALES, localizedKeys, splitFields, entryLocaleRow, entryFieldsIn, entryRefEdges, entryTitleIn, matchesWhere, } from "./entry-store.ts";
|
|
42
|
-
export { affectedTargets, pageTag, entryTag,
|
|
47
|
+
export { affectedTargets, pageTag, entryTag, globalTag, pagesTreeTag, collectionTag } from "./revalidate.ts";
|
|
43
48
|
export type { AffectedTargets } from "./revalidate.ts";
|
|
44
49
|
export { resolveTree, resolveFields, resolveMedia } from "./resolve.ts";
|
|
45
50
|
export type { EntryFetcher, ResolveFieldsOptions, AssetFetcher } from "./resolve.ts";
|
|
@@ -56,21 +61,28 @@ export type { CollectionSchema, EntryOrder } from "./collections.ts";
|
|
|
56
61
|
export { DEFAULT_TOOLSET, type Toolset, type ToolsetMark, type ToolsetNode } from "./toolset.ts";
|
|
57
62
|
export { collectionOrder, collectionDepth, DEFAULT_ORDER } from "./collections.ts";
|
|
58
63
|
export type { ZonePolicy } from "./zones.ts";
|
|
59
|
-
export {
|
|
60
|
-
export {
|
|
64
|
+
export { GLOBAL_NODE_TYPE, SETTINGS_KEY, STYLES_KEY, CSS_KEY, globalLink } from "./global.ts";
|
|
65
|
+
export { SMD_KEY } from "./section-wrapper.tsx";
|
|
66
|
+
export type { SmdInternal } from "./section-wrapper.tsx";
|
|
67
|
+
export { CSS_MAX, cssProblem, safeCss, scopedCss } from "./css.ts";
|
|
68
|
+
export { globalEntryId } from "./global-id.ts";
|
|
61
69
|
export { DEFAULT_SPACE_ID } from "./sql-space.ts";
|
|
62
|
-
export type {
|
|
70
|
+
export type { GlobalSchema, GlobalLink } from "./global.ts";
|
|
63
71
|
export declare const smoodly: {
|
|
64
72
|
schema: {
|
|
65
73
|
page: typeof import("./page.ts").pageSchema;
|
|
66
|
-
section<F extends import("./schema.ts").BuilderMap = {}, S extends import("./schema.ts").BuilderMap = {}
|
|
74
|
+
section<F extends import("./schema.ts").BuilderMap = {}, S extends import("./schema.ts").BuilderMap = {}>(input: {
|
|
67
75
|
name: string;
|
|
68
76
|
title: string;
|
|
69
77
|
icon?: string;
|
|
70
78
|
description?: string;
|
|
71
79
|
fields?: F | undefined;
|
|
72
|
-
|
|
73
|
-
meta?:
|
|
80
|
+
settings?: S | undefined;
|
|
81
|
+
meta?: never;
|
|
82
|
+
styles?: false | {
|
|
83
|
+
omit: string[];
|
|
84
|
+
};
|
|
85
|
+
css?: false;
|
|
74
86
|
sample?: Partial<{ [K_1 in Exclude<keyof F, { [K in keyof F]: F[K] extends {
|
|
75
87
|
__flags?: infer Fl;
|
|
76
88
|
} ? Fl extends {
|
|
@@ -88,18 +100,19 @@ export declare const smoodly: {
|
|
|
88
100
|
} ? Fl extends {
|
|
89
101
|
optional: true;
|
|
90
102
|
} ? K_3 : never : never; }[keyof S]]?: import("./fields.ts").ValueOf<S[K_5]> | undefined; }> | undefined;
|
|
91
|
-
styleDefaults?: false | {
|
|
92
|
-
omit: string[];
|
|
93
|
-
};
|
|
94
103
|
}): import("./schema.ts").SectionSchema<F, S>;
|
|
95
|
-
element<F extends import("./schema.ts").BuilderMap = {}, S extends import("./schema.ts").BuilderMap = {}
|
|
104
|
+
element<F extends import("./schema.ts").BuilderMap = {}, S extends import("./schema.ts").BuilderMap = {}>(input: {
|
|
96
105
|
name: string;
|
|
97
106
|
title: string;
|
|
98
107
|
icon?: string;
|
|
99
108
|
description?: string;
|
|
100
109
|
fields?: F | undefined;
|
|
101
|
-
|
|
102
|
-
meta?:
|
|
110
|
+
settings?: S | undefined;
|
|
111
|
+
meta?: never;
|
|
112
|
+
styles?: false | {
|
|
113
|
+
omit: string[];
|
|
114
|
+
};
|
|
115
|
+
css?: false;
|
|
103
116
|
sample?: Partial<{ [K_1 in Exclude<keyof F, { [K in keyof F]: F[K] extends {
|
|
104
117
|
__flags?: infer Fl;
|
|
105
118
|
} ? Fl extends {
|
|
@@ -117,9 +130,6 @@ export declare const smoodly: {
|
|
|
117
130
|
} ? Fl extends {
|
|
118
131
|
optional: true;
|
|
119
132
|
} ? K_3 : never : never; }[keyof S]]?: import("./fields.ts").ValueOf<S[K_5]> | undefined; }> | undefined;
|
|
120
|
-
styleDefaults?: false | {
|
|
121
|
-
omit: string[];
|
|
122
|
-
};
|
|
123
133
|
} & {
|
|
124
134
|
contexts: ("richtext" | "column")[];
|
|
125
135
|
}): import("./schema.ts").ElementSchema<F, S>;
|
|
@@ -130,7 +140,7 @@ export declare const smoodly: {
|
|
|
130
140
|
entryPage: typeof entryPage;
|
|
131
141
|
collection: typeof collection;
|
|
132
142
|
toolset: typeof toolset;
|
|
133
|
-
|
|
143
|
+
global: typeof globalItem;
|
|
134
144
|
Section: typeof Section;
|
|
135
145
|
marks: typeof marks;
|
|
136
146
|
};
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,15 @@ import { toolset } from "./toolset.js";
|
|
|
5
5
|
import { Section } from "./section-wrapper.js";
|
|
6
6
|
import { page } from "./render.js";
|
|
7
7
|
import { entryPage } from "./entry-page.js";
|
|
8
|
-
import {
|
|
8
|
+
import { globalItem } from "./global.js";
|
|
9
9
|
import { marks } from "./marks.js";
|
|
10
10
|
export { Zone, renderPage, EMPTY_PAGE_CONTEXT } from "./render.js";
|
|
11
11
|
export { RichText, defaultRichTextImage } from "./richtext-render.js";
|
|
12
12
|
export { fixedSlug } from "./page.js";
|
|
13
13
|
export { f, normalizeOptions, optionsOf, optionValues } from "./fields.js";
|
|
14
|
+
export { when, evaluate, isHidden, assertConditions, splitConditionPath } from "./conditions.js";
|
|
15
|
+
export { DEFAULT_STYLE_VALUES, STYLE_KEYS, SPACING_NONE, resolveStyleValues, styleDescriptors, inlineStyles } from "./styles.js";
|
|
16
|
+
export * from "./custom/index.js";
|
|
14
17
|
export { defaultsOf, withDefaults } from "./field-defaults.js";
|
|
15
18
|
export { filterPageTree } from "./page-tree.js";
|
|
16
19
|
export { ASSET_COLLECTION, DEFAULT_MEDIA, MEDIA_TYPES, FULL_CROP, CENTER_HOTSPOT, parseAspect, cropAspect, clamp01, isMediaValue, collectAssetIds, applyAssets, } from "./media.js";
|
|
@@ -30,15 +33,17 @@ export { MemoryEntryStore } from "./entry-store.js";
|
|
|
30
33
|
export { SupabaseEntryStore } from "./supabase-entry-store.js";
|
|
31
34
|
export { SupabasePathIndex } from "./supabase-path-index.js";
|
|
32
35
|
export { entryErrors, compareEntries, DEFAULT_ENTRY_LOCALES, localizedKeys, splitFields, entryLocaleRow, entryFieldsIn, entryRefEdges, entryTitleIn, matchesWhere, } from "./entry-store.js";
|
|
33
|
-
export { affectedTargets, pageTag, entryTag,
|
|
36
|
+
export { affectedTargets, pageTag, entryTag, globalTag, pagesTreeTag, collectionTag } from "./revalidate.js";
|
|
34
37
|
export { resolveTree, resolveFields, resolveMedia } from "./resolve.js";
|
|
35
38
|
export { SEGMENT_RE, isSegment, assertSegment, joinPath, splitPath, segmentFor, isHomeNode, pagePathIn, chainOf, assertDepth, pagePath, pagePathRows, entryPathRows, collectionSegment, buildPageTree, perLocaleSegments, assertSupportedLocale, unsupportedLocale, } from "./paths.js";
|
|
36
39
|
export { fixedPathFor } from "./localize.js";
|
|
37
40
|
export { pathOptions, pageErrors, localeRow, pageRefEdges, DEFAULT_LOCALES } from "./store.js";
|
|
38
41
|
export { DEFAULT_TOOLSET } from "./toolset.js";
|
|
39
42
|
export { collectionOrder, collectionDepth, DEFAULT_ORDER } from "./collections.js";
|
|
40
|
-
export {
|
|
41
|
-
export {
|
|
43
|
+
export { GLOBAL_NODE_TYPE, SETTINGS_KEY, STYLES_KEY, CSS_KEY, globalLink } from "./global.js";
|
|
44
|
+
export { SMD_KEY } from "./section-wrapper.js";
|
|
45
|
+
export { CSS_MAX, cssProblem, safeCss, scopedCss } from "./css.js";
|
|
46
|
+
export { globalEntryId } from "./global-id.js";
|
|
42
47
|
export { DEFAULT_SPACE_ID } from "./sql-space.js";
|
|
43
48
|
export const smoodly = {
|
|
44
49
|
schema,
|
|
@@ -48,7 +53,7 @@ export const smoodly = {
|
|
|
48
53
|
entryPage,
|
|
49
54
|
collection,
|
|
50
55
|
toolset,
|
|
51
|
-
|
|
56
|
+
global: globalItem,
|
|
52
57
|
Section,
|
|
53
58
|
marks,
|
|
54
59
|
};
|
package/dist/media.js
CHANGED
|
@@ -43,7 +43,7 @@ export function collectAssetIds(values, descriptors, out, elements = {}) {
|
|
|
43
43
|
out.add(value.asset);
|
|
44
44
|
}
|
|
45
45
|
else if (d.type === "richtext") {
|
|
46
|
-
// Block nodes (spec 2026-09-08 block nodes §2): image nodes, and media inside a known element's fields and
|
|
46
|
+
// Block nodes (spec 2026-09-08 block nodes §2): image nodes, and media inside a known element's fields and settings.
|
|
47
47
|
for (const node of richtextBlocks(value)) {
|
|
48
48
|
if (node.type === IMAGE_NODE) {
|
|
49
49
|
const image = node.attrs.image;
|
package/dist/next/index.d.ts
CHANGED
|
@@ -2,4 +2,4 @@ export { createPageRenderer } from "./page-renderer.tsx";
|
|
|
2
2
|
export type { PageRendererOptions, PathRenderOptions, PageRegistration } from "./page-renderer.tsx";
|
|
3
3
|
export { metadataFrom } from "./meta.ts";
|
|
4
4
|
export { createSmoodlyQueries } from "./queries.ts";
|
|
5
|
-
export type { SmoodlyQueries, QueryOptions, EntriesQuery, TypedEntryItem,
|
|
5
|
+
export type { SmoodlyQueries, QueryOptions, EntriesQuery, TypedEntryItem, GlobalValue } from "./queries.ts";
|
|
@@ -2,7 +2,7 @@ import type { ComponentType, ReactElement } from "react";
|
|
|
2
2
|
import type { Metadata } from "next";
|
|
3
3
|
import type { Descriptor } from "../fields.ts";
|
|
4
4
|
import { type PairedPage } from "../render.tsx";
|
|
5
|
-
import type {
|
|
5
|
+
import type { GlobalSchema } from "../global.ts";
|
|
6
6
|
import { type SmoodlySite } from "../site.ts";
|
|
7
7
|
/** A registered section, as renderPage's registry needs it. */
|
|
8
8
|
type SectionEntry = ComponentType<any> & {
|
|
@@ -22,6 +22,8 @@ export type PageRegistration = ((props: any) => ReactElement) & {
|
|
|
22
22
|
export type PageRendererOptions = {
|
|
23
23
|
site: SmoodlySite;
|
|
24
24
|
sections: SectionEntry[];
|
|
25
|
+
/** Registered Elements: what the custom section's default richtext renderer needs when no RichText is bound (spec 2026-09-14 §6). */
|
|
26
|
+
elements?: SectionEntry[];
|
|
25
27
|
pages: ReadonlyArray<PageRegistration>;
|
|
26
28
|
/** Locale-relative CMS path → site URL. Default: the path itself. With
|
|
27
29
|
* next-intl: `(path, locale) => getPathname({ locale, href: path })`. */
|
|
@@ -32,7 +34,7 @@ export type PathRenderOptions = {
|
|
|
32
34
|
searchParams?: Promise<Record<string, string | string[] | undefined>>;
|
|
33
35
|
};
|
|
34
36
|
export declare function createPageRenderer(options: PageRendererOptions): {
|
|
35
|
-
|
|
37
|
+
getSmoodlyGlobal: <V>(item: GlobalSchema<V>, opts?: {
|
|
36
38
|
locale?: string;
|
|
37
39
|
}) => Promise<V | null>;
|
|
38
40
|
renderSmoodlyPath: (segments: string[], opts?: PathRenderOptions) => Promise<ReactElement<unknown, string | import("react").JSXElementConstructor<any>>>;
|
|
@@ -7,7 +7,7 @@ import { EditorBridge } from "../admin/next/bridge.js";
|
|
|
7
7
|
import { fixedPathFor } from "../localize.js";
|
|
8
8
|
import { joinPath } from "../paths.js";
|
|
9
9
|
import { renderPage } from "../render.js";
|
|
10
|
-
import { entryTag, pageTag,
|
|
10
|
+
import { entryTag, pageTag, globalTag } from "../revalidate.js";
|
|
11
11
|
import { pageContextOf } from "../site.js";
|
|
12
12
|
import { metadataFrom } from "./meta.js";
|
|
13
13
|
export function createPageRenderer(options) {
|
|
@@ -17,12 +17,12 @@ export function createPageRenderer(options) {
|
|
|
17
17
|
const entryPages = new Map(options.pages.filter((p) => p.schema.kind === "entryPage" && p.schema.collection).map((p) => [p.schema.collection, p]));
|
|
18
18
|
/** locate (uncached: the id it returns IS the cache tag) then load —
|
|
19
19
|
* cached per (locale, path) outside draft mode. */
|
|
20
|
-
async function load(locale, path, draft) {
|
|
20
|
+
async function load(locale, path, draft, version) {
|
|
21
21
|
const target = await site.locate(locale, path);
|
|
22
22
|
if (!target)
|
|
23
23
|
return null;
|
|
24
24
|
if (draft)
|
|
25
|
-
return site.load(target, locale, path, { draft: true });
|
|
25
|
+
return site.load(target, locale, path, { draft: true, ...(version !== undefined ? { version } : {}) });
|
|
26
26
|
return unstable_cache(() => site.load(target, locale, path), ["smoodly-site", locale, path], {
|
|
27
27
|
tags: [target.kind === "page" ? pageTag(target.id) : entryTag(target.id)],
|
|
28
28
|
})();
|
|
@@ -35,7 +35,7 @@ export function createPageRenderer(options) {
|
|
|
35
35
|
notFound();
|
|
36
36
|
}
|
|
37
37
|
const page = pageContextOf(hit, (path) => href(path, locale));
|
|
38
|
-
return renderPage(Page, hit.tree, { sections: options.sections }, { editor, page });
|
|
38
|
+
return renderPage(Page, hit.tree, { sections: options.sections, elements: options.elements, styles: site.styles, custom: site.custom }, { editor, page });
|
|
39
39
|
}
|
|
40
40
|
const View = entryPages.get(hit.collection);
|
|
41
41
|
if (!View) {
|
|
@@ -58,10 +58,14 @@ export function createPageRenderer(options) {
|
|
|
58
58
|
const locale = opts?.locale ?? site.locales.default;
|
|
59
59
|
const path = pathFor(locale);
|
|
60
60
|
const { isEnabled: draft } = await draftMode();
|
|
61
|
-
const
|
|
61
|
+
const params = await opts?.searchParams;
|
|
62
|
+
// Both parameters exist only inside draft mode: the public site never sees an editor bridge or an old version.
|
|
63
|
+
const editor = draft && params?.["smoodly-editor"] === "1";
|
|
64
|
+
const versionParam = params?.["smoodly-version"];
|
|
65
|
+
const version = draft && typeof versionParam === "string" && versionParam !== "" ? versionParam : undefined;
|
|
66
|
+
const hit = await load(locale, path, draft, version);
|
|
62
67
|
if (!hit || !accept(hit))
|
|
63
68
|
notFound();
|
|
64
|
-
const editor = draft && (await opts?.searchParams)?.["smoodly-editor"] === "1";
|
|
65
69
|
return (_jsxs(_Fragment, { children: [editor ? _jsx(EditorBridge, {}) : null, render(hit, editor, locale)] }));
|
|
66
70
|
}
|
|
67
71
|
async function metadata(pathFor, opts, accept) {
|
|
@@ -82,20 +86,20 @@ export function createPageRenderer(options) {
|
|
|
82
86
|
* error surfaces as a rejected promise like every other failure. */
|
|
83
87
|
const fixedPath = (Page) => (locale) => fixedPathFor(Page.schema, locale, site.locales, site.homePageSlug);
|
|
84
88
|
const literal = (segments) => () => joinPath(segments);
|
|
85
|
-
/** A
|
|
86
|
-
*
|
|
87
|
-
async function
|
|
89
|
+
/** A global item for a layout: cached per (item, locale) under the
|
|
90
|
+
* global tag outside draft mode, the live draft inside it. */
|
|
91
|
+
async function getSmoodlyGlobal(item, opts) {
|
|
88
92
|
await connection();
|
|
89
93
|
const locale = opts?.locale ?? site.locales.default;
|
|
90
94
|
const { isEnabled: draft } = await draftMode();
|
|
91
95
|
if (draft)
|
|
92
|
-
return site.
|
|
93
|
-
return unstable_cache(() => site.
|
|
94
|
-
tags: [
|
|
96
|
+
return site.getGlobal(item, { locale, draft: true });
|
|
97
|
+
return unstable_cache(() => site.getGlobal(item, { locale }), ["smoodly-global", item.name, locale], {
|
|
98
|
+
tags: [globalTag(item.name)],
|
|
95
99
|
})();
|
|
96
100
|
}
|
|
97
101
|
return {
|
|
98
|
-
|
|
102
|
+
getSmoodlyGlobal,
|
|
99
103
|
renderSmoodlyPath: (segments, opts) => page(literal(segments), opts, any),
|
|
100
104
|
smoodlyMetadata: (segments, opts) => metadata(literal(segments), opts, any),
|
|
101
105
|
/** A fixed registration rendered from the developer's own route file. */
|
package/dist/next/queries.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CollectionSchema } from "../collections.ts";
|
|
2
2
|
import type { EntryRecord } from "../entry-store.ts";
|
|
3
|
-
import type {
|
|
3
|
+
import type { GlobalSchema } from "../global.ts";
|
|
4
4
|
import type { EntryQuery, PageTreeItem, SiteEntryItem, SitePage, SmoodlySite } from "../site.ts";
|
|
5
5
|
export type QueryOptions = {
|
|
6
6
|
locale?: string;
|
|
@@ -17,8 +17,8 @@ export type TypedEntryItem<C extends readonly CollectionSchema<any, string>[], N
|
|
|
17
17
|
fields: EntryFields<C, N>;
|
|
18
18
|
};
|
|
19
19
|
};
|
|
20
|
-
export type
|
|
21
|
-
export type SmoodlyQueries<C extends readonly CollectionSchema<any, string>[], S extends readonly
|
|
20
|
+
export type GlobalValue<S extends readonly GlobalSchema<any, string>[], N> = string extends S[number]["name"] ? Record<string, unknown> : NonNullable<ByName<S[number], N>["__value"]>;
|
|
21
|
+
export type SmoodlyQueries<C extends readonly CollectionSchema<any, string>[], S extends readonly GlobalSchema<any, string>[]> = {
|
|
22
22
|
/** The published page tree in a locale, every item with its page fields. */
|
|
23
23
|
getPageTree(options?: QueryOptions): Promise<PageTreeItem[]>;
|
|
24
24
|
/** A page by locale-relative path ("/company/about-us") or id. */
|
|
@@ -26,11 +26,11 @@ export type SmoodlyQueries<C extends readonly CollectionSchema<any, string>[], S
|
|
|
26
26
|
/** Published entries of a collection: `where` (shared fields), `order`, `limit`, `parent` run in the store. */
|
|
27
27
|
getEntries<N extends C[number]["name"]>(collection: N, options?: EntriesQuery): Promise<TypedEntryItem<C, N>[]>;
|
|
28
28
|
getEntry<N extends C[number]["name"]>(collection: N, idOrPath: string, options?: QueryOptions): Promise<TypedEntryItem<C, N> | null>;
|
|
29
|
-
|
|
29
|
+
getGlobal<N extends S[number]["name"]>(item: N, options?: QueryOptions): Promise<GlobalValue<S, N> | null>;
|
|
30
30
|
};
|
|
31
|
-
export declare function createSmoodlyQueries<const C extends readonly CollectionSchema<any, string>[], const S extends readonly
|
|
31
|
+
export declare function createSmoodlyQueries<const C extends readonly CollectionSchema<any, string>[], const S extends readonly GlobalSchema<any, string>[] = []>(options: {
|
|
32
32
|
site: SmoodlySite;
|
|
33
33
|
collections: C;
|
|
34
|
-
|
|
34
|
+
globals?: S;
|
|
35
35
|
}): SmoodlyQueries<C, S>;
|
|
36
36
|
export {};
|
package/dist/next/queries.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
// The in-app read API (spec 2026-09-11): five typed queries over the
|
|
2
2
|
// framework-free site layer, each draft-aware inside the editor preview
|
|
3
|
-
// and cached under a tag outside it — the pattern
|
|
3
|
+
// and cached under a tag outside it — the pattern getSmoodlyGlobal set.
|
|
4
4
|
// Lives in next/ because draftMode and unstable_cache are Next's; an
|
|
5
5
|
// Astro glue wraps the same site reads over its own cache seam.
|
|
6
6
|
import { unstable_cache } from "next/cache";
|
|
7
7
|
import { draftMode } from "next/headers";
|
|
8
8
|
import { connection } from "next/server";
|
|
9
|
-
import { collectionTag, entryTag, pageTag, pagesTreeTag,
|
|
9
|
+
import { collectionTag, entryTag, pageTag, pagesTreeTag, globalTag } from "../revalidate.js";
|
|
10
10
|
/** JSON with object keys sorted at every level and `undefined` dropped, so two spellings of one query share a unit. */
|
|
11
11
|
function stable(value) {
|
|
12
12
|
if (Array.isArray(value))
|
|
@@ -26,7 +26,7 @@ function entriesKey(o) {
|
|
|
26
26
|
}
|
|
27
27
|
export function createSmoodlyQueries(options) {
|
|
28
28
|
const { site } = options;
|
|
29
|
-
const
|
|
29
|
+
const globalByName = new Map((options.globals ?? []).map((s) => [s.name, s]));
|
|
30
30
|
const localeOf = (o) => o?.locale ?? site.locales.default;
|
|
31
31
|
/** Every query gates on the request (never a build prerender), then reads live in draft mode or cached under `tags`. */
|
|
32
32
|
async function run(key, tags, read) {
|
|
@@ -76,12 +76,12 @@ export function createSmoodlyQueries(options) {
|
|
|
76
76
|
return hit;
|
|
77
77
|
});
|
|
78
78
|
},
|
|
79
|
-
async
|
|
79
|
+
async getGlobal(name, o) {
|
|
80
80
|
const locale = localeOf(o);
|
|
81
|
-
const item =
|
|
81
|
+
const item = globalByName.get(name);
|
|
82
82
|
if (!item)
|
|
83
|
-
throw new Error(`smoodly: no
|
|
84
|
-
return run(["
|
|
83
|
+
throw new Error(`smoodly: no global item named "${name}".`);
|
|
84
|
+
return run(["global", name, locale], [globalTag(name)], (draft) => site.getGlobal(item, { locale, draft }));
|
|
85
85
|
},
|
|
86
86
|
};
|
|
87
87
|
}
|
package/dist/page.js
CHANGED
|
@@ -30,12 +30,12 @@ function normalizePolicy(p) {
|
|
|
30
30
|
return out;
|
|
31
31
|
}
|
|
32
32
|
case "freeform":
|
|
33
|
-
return { kind: "freeform", allow: p.allow,
|
|
33
|
+
return { kind: "freeform", allow: p.allow, custom: p.custom === true };
|
|
34
34
|
case "locked":
|
|
35
35
|
return {
|
|
36
36
|
kind: "locked",
|
|
37
37
|
component: p.component,
|
|
38
|
-
...(typeof p.
|
|
38
|
+
...(typeof p.global === "string" ? { global: p.global } : {}),
|
|
39
39
|
};
|
|
40
40
|
default:
|
|
41
41
|
throw new Error(`smoodly: unknown zone policy kind "${String(p.kind)}".`);
|
package/dist/pairing.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ComponentType, ReactElement } from "react";
|
|
2
2
|
import type { BuilderMap, ElementSchema, NamespaceValues, SectionSchema } from "./schema.ts";
|
|
3
3
|
import type { PageContext, ZoneContent } from "./render.tsx";
|
|
4
|
+
import type { StyleProps } from "./styles.ts";
|
|
4
5
|
/** What the view receives. A page view gets its zones and where it sits
|
|
5
|
-
* in the tree; a section/element view gets field values flat
|
|
6
|
-
* complete (defaults filled)
|
|
6
|
+
* in the tree; a section/element view gets field values flat, settings
|
|
7
|
+
* complete (defaults filled) and Smoodly's styles steps as stored (Default
|
|
8
|
+
* stores nothing — spec 2026-09-14 §2). The page branch keys on `kind` — an
|
|
7
9
|
* optional-only check would match section schemas too, since a type
|
|
8
10
|
* lacking `__zones` still extends `{ __zones?: X }`. */
|
|
9
11
|
export type Props<S> = S extends {
|
|
@@ -17,19 +19,23 @@ export type Props<S> = S extends {
|
|
|
17
19
|
__f?: infer F extends BuilderMap;
|
|
18
20
|
__s?: infer St extends BuilderMap;
|
|
19
21
|
} ? NamespaceValues<F> & {
|
|
20
|
-
|
|
22
|
+
settings: NamespaceValues<St>;
|
|
23
|
+
styles: StyleProps;
|
|
21
24
|
} : never;
|
|
22
|
-
/** What hard-coded JSX may pass: fields flat,
|
|
25
|
+
/** What hard-coded JSX may pass: fields flat, settings optional and partial, styles optional. */
|
|
23
26
|
type ExternalProps<F extends BuilderMap, St extends BuilderMap> = NamespaceValues<F> & {
|
|
24
|
-
|
|
27
|
+
settings?: Partial<NamespaceValues<St>>;
|
|
28
|
+
styles?: StyleProps;
|
|
25
29
|
};
|
|
26
30
|
export type PairedComponent<Schema, F extends BuilderMap, St extends BuilderMap> = ((props: ExternalProps<F, St>) => ReactElement) & {
|
|
27
31
|
schema: Schema;
|
|
28
32
|
};
|
|
29
33
|
export declare function section<F extends BuilderMap, St extends BuilderMap>(schema: SectionSchema<F, St>, View: ComponentType<NamespaceValues<F> & {
|
|
30
|
-
|
|
34
|
+
settings: NamespaceValues<St>;
|
|
35
|
+
styles: StyleProps;
|
|
31
36
|
}>): PairedComponent<SectionSchema<F, St>, F, St>;
|
|
32
37
|
export declare function element<F extends BuilderMap, St extends BuilderMap>(schema: ElementSchema<F, St>, View: ComponentType<NamespaceValues<F> & {
|
|
33
|
-
|
|
38
|
+
settings: NamespaceValues<St>;
|
|
39
|
+
styles: StyleProps;
|
|
34
40
|
}>): PairedComponent<ElementSchema<F, St>, F, St>;
|
|
35
41
|
export {};
|
package/dist/pairing.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { defaultsOf } from "./field-defaults.js";
|
|
3
3
|
function pair(schema, View) {
|
|
4
|
-
const defaults = defaultsOf(schema.
|
|
4
|
+
const defaults = defaultsOf(schema.settings);
|
|
5
5
|
const Component = (props) => {
|
|
6
|
-
const {
|
|
7
|
-
const
|
|
6
|
+
const { settings: overrides, styles, ...fields } = props ?? {};
|
|
7
|
+
const settings = { ...defaults, ...overrides };
|
|
8
8
|
const V = View;
|
|
9
|
-
return _jsx(V, { ...fields, styles: styles });
|
|
9
|
+
return _jsx(V, { ...fields, settings: settings, styles: styles ?? {} });
|
|
10
10
|
};
|
|
11
11
|
Component.schema = schema;
|
|
12
12
|
return Component;
|
package/dist/refs.d.ts
CHANGED
|
@@ -11,12 +11,12 @@ export declare function collectEntryRefs(fields: Record<string, unknown>, schema
|
|
|
11
11
|
export type SectionLike = {
|
|
12
12
|
name: string;
|
|
13
13
|
fields: Record<string, Descriptor>;
|
|
14
|
-
|
|
14
|
+
settings?: Record<string, Descriptor>;
|
|
15
15
|
} | {
|
|
16
16
|
schema: {
|
|
17
17
|
name: string;
|
|
18
18
|
fields: Record<string, Descriptor>;
|
|
19
|
-
|
|
19
|
+
settings?: Record<string, Descriptor>;
|
|
20
20
|
};
|
|
21
21
|
};
|
|
22
22
|
export declare function collectTreeRefs(tree: PageTree, sections: SectionLike[], elements?: SectionLike[]): RefEdge[];
|
package/dist/refs.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// and never the source of truth. Stores rewrite a source's edges on
|
|
5
5
|
// every save; `refs` answers only the REVERSE question (who depends on
|
|
6
6
|
// this?) — forward resolution stays resolveTree's job.
|
|
7
|
-
import {
|
|
7
|
+
import { globalLink } from "./global.js";
|
|
8
8
|
import { ASSET_COLLECTION, isMediaValue, MEDIA_TYPES } from "./media.js";
|
|
9
9
|
import { ELEMENT_NODE, IMAGE_NODE, elementOf, elementSchemas, elementSets, richtextBlocks } from "./richtext-walk.js";
|
|
10
10
|
function targetOf(d) {
|
|
@@ -87,7 +87,7 @@ export function collectTreeRefs(tree, sections, elements) {
|
|
|
87
87
|
for (const node of nodes) {
|
|
88
88
|
// A placement (spec 2026-09-07 §5): one edge, keyed by the node id
|
|
89
89
|
// so two placements of one item on one page stay distinct rows.
|
|
90
|
-
const link =
|
|
90
|
+
const link = globalLink(node);
|
|
91
91
|
if (link) {
|
|
92
92
|
out.push({ field: node.id, targetCollection: link.item, targetId: link.ref });
|
|
93
93
|
continue;
|
|
@@ -96,8 +96,8 @@ export function collectTreeRefs(tree, sections, elements) {
|
|
|
96
96
|
if (!schema)
|
|
97
97
|
continue; // fail-soft, same as renderPage
|
|
98
98
|
collectFrom(node.fields, schema.fields, out, els);
|
|
99
|
-
if (schema.
|
|
100
|
-
collectFrom(node.
|
|
99
|
+
if (schema.settings && node.settings)
|
|
100
|
+
collectFrom(node.settings, schema.settings, out, els);
|
|
101
101
|
}
|
|
102
102
|
}
|
|
103
103
|
return out;
|
package/dist/render.d.ts
CHANGED
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import type { ComponentType, ReactElement } from "react";
|
|
2
2
|
import type { PageSchema } from "./page.ts";
|
|
3
3
|
import type { BuilderMap, NamespaceValues } from "./schema.ts";
|
|
4
|
+
import { type StyleValues } from "./styles.ts";
|
|
5
|
+
import { type CustomOptions } from "./custom/index.ts";
|
|
4
6
|
export type TreeNode = {
|
|
5
7
|
id: string;
|
|
6
8
|
type: string;
|
|
7
9
|
fields: Record<string, unknown>;
|
|
10
|
+
/** The developer's knobs (spec 2026-09-14 §3). */
|
|
11
|
+
settings?: Record<string, unknown>;
|
|
12
|
+
/** Smoodly's styles steps (spec 2026-09-14 §2); absent keys are Default. */
|
|
8
13
|
styles?: Record<string, unknown>;
|
|
9
|
-
|
|
14
|
+
/** The custom-CSS snippet (spec 2026-09-14 §4), scoped by the wrapper. */
|
|
15
|
+
css?: string;
|
|
10
16
|
};
|
|
11
17
|
/** `meta` is the page's own metadata (SEO title, description, og image).
|
|
12
18
|
* It rides inside the tree deliberately: trees are already JSONB in
|
|
@@ -60,6 +66,8 @@ export type ZoneContent = {
|
|
|
60
66
|
readonly name: string;
|
|
61
67
|
readonly nodes: TreeNode[];
|
|
62
68
|
readonly components: ReadonlyMap<string, AnyPaired>;
|
|
69
|
+
/** The config's CSS values behind the styles set (spec 2026-09-14 §2). */
|
|
70
|
+
readonly styleValues: StyleValues;
|
|
63
71
|
readonly editor: boolean;
|
|
64
72
|
};
|
|
65
73
|
export declare function Zone({ of: content }: {
|
|
@@ -76,6 +84,10 @@ export declare function page<Zones extends Record<string, unknown>, F extends Bu
|
|
|
76
84
|
export type Registry = {
|
|
77
85
|
sections?: AnyPaired[];
|
|
78
86
|
elements?: AnyPaired[];
|
|
87
|
+
/** Resolved styles values; the package fallbacks when absent. */
|
|
88
|
+
styles?: StyleValues;
|
|
89
|
+
/** The custom section's bound RichText and breakpoint (spec 2026-09-14 §6); the defaults when absent. */
|
|
90
|
+
custom?: CustomOptions;
|
|
79
91
|
};
|
|
80
92
|
export declare function renderPage<Zones extends Record<string, unknown>>(Page: PairedPage<Zones>, tree: PageTree, registry: Registry, options?: {
|
|
81
93
|
editor?: boolean;
|
package/dist/render.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { EMPTY_ATTR, ZONE_ATTR } from "./marks.js";
|
|
3
|
+
import { SMD_KEY } from "./section-wrapper.js";
|
|
4
|
+
import { DEFAULT_STYLE_VALUES } from "./styles.js";
|
|
5
|
+
import { CUSTOM_NODE_TYPE, createCustomSection } from "./custom/index.js";
|
|
3
6
|
/** The `page` prop of a view rendered outside the site (a test, a preview
|
|
4
7
|
* of a shape): a real object, so a view never guards an optional prop, but
|
|
5
8
|
* no position in the tree. Frozen: one singleton shared by every such
|
|
@@ -22,10 +25,9 @@ export function Zone({ of: content }) {
|
|
|
22
25
|
console.warn(`smoodly: no registered component for node type "${node.type}" — skipping.`);
|
|
23
26
|
return null;
|
|
24
27
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return _jsx(Component, { ...node.fields, styles: styles }, node.id);
|
|
28
|
+
// The node id, the css and the values ride the styles under one reserved key; the wrapper reads and strips it.
|
|
29
|
+
const styles = { ...(node.styles ?? {}), [SMD_KEY]: { node: node.id, css: typeof node.css === "string" ? node.css : undefined, values: content.styleValues } };
|
|
30
|
+
return _jsx(Component, { ...node.fields, settings: node.settings ?? {}, styles: styles }, node.id);
|
|
29
31
|
}) }));
|
|
30
32
|
}
|
|
31
33
|
export function page(schema, View) {
|
|
@@ -41,9 +43,12 @@ export function renderPage(Page, tree, registry, options) {
|
|
|
41
43
|
for (const c of [...(registry.sections ?? []), ...(registry.elements ?? [])]) {
|
|
42
44
|
components.set(c.schema.name, c);
|
|
43
45
|
}
|
|
46
|
+
// The custom section (spec 2026-09-14 §6): Smoodly's own renderer under the reserved node type.
|
|
47
|
+
components.set(CUSTOM_NODE_TYPE, createCustomSection({ ...(registry.custom ?? {}), elements: (registry.elements ?? []) }));
|
|
48
|
+
const styleValues = registry.styles ?? DEFAULT_STYLE_VALUES;
|
|
44
49
|
const zones = Object.fromEntries(Object.keys(Page.schema.zones).map((zone) => [
|
|
45
50
|
zone,
|
|
46
|
-
{ name: zone, nodes: tree.zones?.[zone] ?? [], components, editor: options?.editor ?? false },
|
|
51
|
+
{ name: zone, nodes: tree.zones?.[zone] ?? [], components, styleValues, editor: options?.editor ?? false },
|
|
47
52
|
]));
|
|
48
53
|
return _jsx(Page, { zones: zones, page: (options?.page ?? EMPTY_PAGE_CONTEXT) });
|
|
49
54
|
}
|
package/dist/resolve.d.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import type { Descriptor } from "./fields.ts";
|
|
2
2
|
import type { CollectionSchema } from "./collections.ts";
|
|
3
3
|
import type { PageTree } from "./render.tsx";
|
|
4
|
-
import { type
|
|
4
|
+
import { type GlobalSchema } from "./global.ts";
|
|
5
5
|
import { type AssetRecord } from "./media.ts";
|
|
6
6
|
import { type ElementSchemas } from "./richtext-walk.ts";
|
|
7
7
|
import type { SectionLike } from "./refs.ts";
|
|
8
|
+
import type { Toolset } from "./toolset.ts";
|
|
8
9
|
export type EntryFetcher = (collection: string, ids: string[]) => Promise<Record<string, Record<string, unknown>>>;
|
|
9
10
|
export type AssetFetcher = (ids: string[]) => Promise<Record<string, AssetRecord>>;
|
|
10
11
|
type SchemaLike = {
|
|
11
12
|
name: string;
|
|
12
13
|
fields: Record<string, Descriptor>;
|
|
13
|
-
|
|
14
|
+
settings?: Record<string, Descriptor>;
|
|
14
15
|
};
|
|
15
|
-
/** One value set whose media resolves in place: a node's fields or
|
|
16
|
+
/** One value set whose media resolves in place: a node's fields or settings,
|
|
16
17
|
* an entry's fields, or an entry hydrated through a ref. */
|
|
17
18
|
export type MediaSet = {
|
|
18
19
|
values: Record<string, unknown> | undefined;
|
|
@@ -26,8 +27,8 @@ type ResolveOptions = {
|
|
|
26
27
|
fetch: EntryFetcher;
|
|
27
28
|
/** Media (spec 2026-09-08 §9): one batched asset fetch per page, values become resolved objects. */
|
|
28
29
|
assets?: AssetFetcher;
|
|
29
|
-
/** The registered
|
|
30
|
-
|
|
30
|
+
/** The registered global items a placement node may name (spec 2026-09-07 §4). */
|
|
31
|
+
globals?: GlobalSchema[];
|
|
31
32
|
/** Registered Elements a richtext document may embed (spec 2026-09-08 block nodes §2). */
|
|
32
33
|
elements?: SectionLike[];
|
|
33
34
|
/** Optional safety valve on chain length; unlimited by default. */
|
|
@@ -36,9 +37,13 @@ type ResolveOptions = {
|
|
|
36
37
|
page?: {
|
|
37
38
|
fields: Record<string, Descriptor>;
|
|
38
39
|
};
|
|
40
|
+
/** The custom section's columns toolset (spec 2026-09-14 §6); the default when absent. The schema is always in the map. */
|
|
41
|
+
custom?: {
|
|
42
|
+
toolset?: Toolset;
|
|
43
|
+
};
|
|
39
44
|
};
|
|
40
45
|
export declare function resolveTree(tree: PageTree, options: ResolveOptions): Promise<PageTree>;
|
|
41
|
-
/** One value set's media, resolved in place. Exported for the site layer's
|
|
46
|
+
/** One value set's media, resolved in place. Exported for the site layer's global-item settings. */
|
|
42
47
|
export declare function resolveMedia(values: Record<string, unknown>, descriptors: Record<string, Descriptor>, fetch: AssetFetcher, elements?: ElementSchemas): Promise<void>;
|
|
43
48
|
/** Many value sets, one asset round (plus one for posters): the tree's
|
|
44
49
|
* nodes and every entry hydrated through a ref, or a list page's items.
|