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/zones.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Zone policies — the freedom dial. Policies reference paired components
|
|
2
2
|
// directly; only their registered names are stored (plain data).
|
|
3
|
-
const
|
|
3
|
+
const isGlobal = (target) => "kind" in target && target.kind === "global";
|
|
4
4
|
const names = (components) => components.map((c) => c.schema.name);
|
|
5
5
|
export const z = {
|
|
6
6
|
sections(components) {
|
|
@@ -15,14 +15,14 @@ export const z = {
|
|
|
15
15
|
return {
|
|
16
16
|
kind: "freeform",
|
|
17
17
|
allow: opts.sections === "*" ? "*" : names(opts.sections),
|
|
18
|
-
|
|
18
|
+
custom: opts.custom ?? false,
|
|
19
19
|
};
|
|
20
20
|
},
|
|
21
21
|
locked(target) {
|
|
22
|
-
if (
|
|
22
|
+
if (isGlobal(target)) {
|
|
23
23
|
if (!target.section)
|
|
24
|
-
throw new Error(`smoodly:
|
|
25
|
-
return { kind: "locked", component: target.section,
|
|
24
|
+
throw new Error(`smoodly: global item "${target.name}" has no section — a locked zone needs a visual item.`);
|
|
25
|
+
return { kind: "locked", component: target.section, global: target.name };
|
|
26
26
|
}
|
|
27
27
|
return { kind: "locked", component: target.schema.name };
|
|
28
28
|
},
|
package/package.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ResolvedConfig } from "../config.ts";
|
|
2
|
-
import type { Descriptor } from "../fields.ts";
|
|
3
|
-
import type { EntryRecord, EntryStore } from "../entry-store.ts";
|
|
4
|
-
import { type SharedSchema } from "../shared.ts";
|
|
5
|
-
/** The merged fields a fresh item starts from: sampled field values, and
|
|
6
|
-
* for a visual item `$styles` = the resolved style defaults with the
|
|
7
|
-
* sample's style values on top. Unsampled fields stay absent. */
|
|
8
|
-
export declare function initialSharedFields(item: SharedSchema, resolvedStyles: Record<string, Descriptor>): Record<string, unknown>;
|
|
9
|
-
export declare function ensureSharedItems(entries: EntryStore, config: ResolvedConfig): Promise<Record<string, EntryRecord>>;
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
// One Globals item (shared content, spec 2026-09-07 §6), one locale: the
|
|
4
|
-
// entry form's shape without what a singleton never has — no slug, no
|
|
5
|
-
// "new", no delete, no add/remove locale (every supported locale exists
|
|
6
|
-
// by construction). The fields in schema order, a globe-off mark after
|
|
7
|
-
// the name of each that is not .localized(), and for a visual item a
|
|
8
|
-
// Styles group edited under the reserved `$styles` key.
|
|
9
|
-
// Status is per locale and immediate. "Used on N pages" is the refs
|
|
10
|
-
// index's answer.
|
|
11
|
-
import { useEffect, useMemo, useState } from "react";
|
|
12
|
-
import { STYLES_KEY } from "../../shared.js";
|
|
13
|
-
import { FieldWidget } from "../forms/FieldWidget.js";
|
|
14
|
-
import { relativeTime } from "../ui/format.js";
|
|
15
|
-
import { LocaleSwitcher } from "../ui/LocaleSwitcher.js";
|
|
16
|
-
import { Banner, Breadcrumb, Button, SectionLabel, Segmented, TopBar, UnlocalizedMark } from "../ui/primitives.js";
|
|
17
|
-
import { ResizeHandle } from "../ui/ResizeHandle.js";
|
|
18
|
-
import { entryTitle } from "./entries-list.js";
|
|
19
|
-
import { BASE } from "./base.js";
|
|
20
|
-
import { localeFromUrl, writeLocaleToUrl } from "../editor/locale-url.js";
|
|
21
|
-
import { useLeaveGuard } from "./router.js";
|
|
22
|
-
const STATUSES = ["Draft", "Published"];
|
|
23
|
-
export function SharedForm({ ops, registry, name }) {
|
|
24
|
-
const item = registry.shared.find((s) => s.name === name);
|
|
25
|
-
const multilingual = registry.locales.supported.length > 1;
|
|
26
|
-
const [locale, setLocale] = useState(() => localeFromUrl(registry));
|
|
27
|
-
const [record, setRecord] = useState(null);
|
|
28
|
-
const [fields, setFields] = useState(null);
|
|
29
|
-
const [usage, setUsage] = useState([]);
|
|
30
|
-
const [refOptions, setRefOptions] = useState({});
|
|
31
|
-
const [banner, setBanner] = useState(null);
|
|
32
|
-
const [fieldErrors, setFieldErrors] = useState({});
|
|
33
|
-
const [dirty, setDirty] = useState(false);
|
|
34
|
-
useLeaveGuard(dirty);
|
|
35
|
-
const refTargets = useMemo(() => {
|
|
36
|
-
const out = {};
|
|
37
|
-
for (const [key, d] of Object.entries(item?.fields ?? {})) {
|
|
38
|
-
if ((d.type === "ref" || d.type === "refList") && typeof d.target === "string")
|
|
39
|
-
out[key] = d.target;
|
|
40
|
-
}
|
|
41
|
-
return out;
|
|
42
|
-
}, [item]);
|
|
43
|
-
const localeKeys = useMemo(() => Object.entries(item?.fields ?? {}).filter(([, d]) => d.localized === true).map(([key]) => key), [item]);
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
let cancelled = false;
|
|
46
|
-
setFields(null);
|
|
47
|
-
setFieldErrors({});
|
|
48
|
-
ops.shared.get(name, locale).then((r) => {
|
|
49
|
-
if (cancelled)
|
|
50
|
-
return;
|
|
51
|
-
if (r.ok) {
|
|
52
|
-
setRecord(r.data.record);
|
|
53
|
-
setFields(r.data.fields);
|
|
54
|
-
setUsage(r.data.usage);
|
|
55
|
-
setDirty(false);
|
|
56
|
-
}
|
|
57
|
-
else
|
|
58
|
-
setBanner({ tone: "error", text: r.message });
|
|
59
|
-
}).catch(() => { if (!cancelled)
|
|
60
|
-
setBanner({ tone: "error", text: "Couldn't reach the server." }); });
|
|
61
|
-
return () => { cancelled = true; };
|
|
62
|
-
}, [ops, name, locale]);
|
|
63
|
-
// Ref options in the locale being edited — the entry form's rule.
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
let cancelled = false;
|
|
66
|
-
for (const target of new Set(Object.values(refTargets))) {
|
|
67
|
-
const targetMeta = registry.collections.find((c) => c.name === target);
|
|
68
|
-
ops.entries.list(target).then((r) => {
|
|
69
|
-
if (cancelled || !r.ok)
|
|
70
|
-
return;
|
|
71
|
-
const options = r.data
|
|
72
|
-
.filter((e) => e.locales[locale])
|
|
73
|
-
.map((e) => ({ id: e.id, title: targetMeta ? entryTitle(e, targetMeta, registry, locale) : e.id, status: e.locales[locale].status }));
|
|
74
|
-
setRefOptions((prev) => ({ ...prev, [target]: options }));
|
|
75
|
-
}).catch(console.error);
|
|
76
|
-
}
|
|
77
|
-
return () => { cancelled = true; };
|
|
78
|
-
}, [ops, refTargets, registry, locale]);
|
|
79
|
-
if (!item)
|
|
80
|
-
return _jsx("p", { style: { padding: 32 }, children: "No such shared item." });
|
|
81
|
-
const applyResult = (r, okText) => {
|
|
82
|
-
if (r.ok) {
|
|
83
|
-
setBanner({ tone: "ok", text: okText });
|
|
84
|
-
setFieldErrors({});
|
|
85
|
-
return true;
|
|
86
|
-
}
|
|
87
|
-
setBanner({ tone: "error", text: r.message });
|
|
88
|
-
setFieldErrors(Object.fromEntries((r.fields ?? []).map((f) => [f.field, f.message])));
|
|
89
|
-
return false;
|
|
90
|
-
};
|
|
91
|
-
const save = async () => {
|
|
92
|
-
if (!fields)
|
|
93
|
-
return;
|
|
94
|
-
const r = await ops.shared.save(name, locale, fields);
|
|
95
|
-
if (applyResult(r, "Saved.") && r.ok) {
|
|
96
|
-
setRecord(r.data);
|
|
97
|
-
setDirty(false);
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
const row = record?.locales[locale];
|
|
101
|
-
const status = row?.status ?? "draft";
|
|
102
|
-
const setPublished = async (next) => {
|
|
103
|
-
if (next === status)
|
|
104
|
-
return;
|
|
105
|
-
const r = await ops.shared.setStatus(name, locale, next);
|
|
106
|
-
if (applyResult(r, next === "published" ? "Published." : "Unpublished.") && r.ok)
|
|
107
|
-
setRecord(r.data);
|
|
108
|
-
};
|
|
109
|
-
const switchLocale = (next) => {
|
|
110
|
-
if (next === locale)
|
|
111
|
-
return;
|
|
112
|
-
if (dirty && !window.confirm("Discard unsaved changes?"))
|
|
113
|
-
return;
|
|
114
|
-
writeLocaleToUrl(next);
|
|
115
|
-
setBanner(null);
|
|
116
|
-
setLocale(next);
|
|
117
|
-
};
|
|
118
|
-
const styles = (fields?.[STYLES_KEY] ?? {});
|
|
119
|
-
const pages = new Set(usage.filter((u) => u.sourceKind === "page").map((u) => u.sourceId));
|
|
120
|
-
const widget = ([key, d]) => (_jsx(FieldWidget, { fieldKey: key, descriptor: d, value: fields?.[key], errors: fieldErrors, refOptions: refTargets[key] ? refOptions[refTargets[key]] ?? [] : undefined, mark: multilingual && !localeKeys.includes(key) ? _jsx(UnlocalizedMark, {}) : undefined, onChange: (value) => { setFields((f) => ({ ...(f ?? {}), [key]: value })); setDirty(true); } }, key));
|
|
121
|
-
return (_jsxs(_Fragment, { children: [_jsx(TopBar, { left: _jsx(_Fragment, { children: _jsx(Breadcrumb, { backHref: `${BASE}/shared`, items: [
|
|
122
|
-
{
|
|
123
|
-
label: "Globals", href: `${BASE}/shared`,
|
|
124
|
-
trailing: multilingual && (_jsx(LocaleSwitcher, { registry: registry, present: registry.locales.supported, parentLocales: [], value: locale, adding: false, onSwitch: switchLocale, onAdd: () => undefined })),
|
|
125
|
-
},
|
|
126
|
-
{ label: item.title },
|
|
127
|
-
] }) }), right: _jsx(Button, { onClick: save, disabled: fields === null, children: "Save" }) }), _jsxs("div", { className: "sm-editor", children: [_jsxs("div", { className: "sm-form", children: [banner && _jsx(Banner, { tone: banner.tone, onDismiss: () => setBanner(null), children: banner.text }), record && (_jsxs("p", { className: "sm-hint", children: [pages.size === 0 ? "Not placed on any page yet." : `Used on ${pages.size} page${pages.size === 1 ? "" : "s"}: `, [...pages].map((id, i) => (_jsxs("span", { children: [i > 0 && ", ", _jsx("a", { href: `${BASE}/pages/${encodeURIComponent(id)}?locale=${encodeURIComponent(locale)}`, children: id })] }, id)))] })), fields !== null ? (_jsxs(_Fragment, { children: [Object.entries(item.fields).map(widget), item.section !== undefined && Object.keys(item.styles).length > 0 && (_jsxs(_Fragment, { children: [_jsx(SectionLabel, { children: "Styles" }), Object.entries(item.styles).map(([key, d]) => (_jsx(FieldWidget, { fieldKey: key, descriptor: d, value: styles[key], onChange: (value) => {
|
|
128
|
-
setFields((f) => ({ ...(f ?? {}), [STYLES_KEY]: { ...(f?.[STYLES_KEY] ?? {}), [key]: value } }));
|
|
129
|
-
setDirty(true);
|
|
130
|
-
} }, key)))] }))] })) : !banner && _jsx("p", { style: { color: "var(--text-muted)" }, children: "Loading\u2026" })] }), _jsx(ResizeHandle, {}), _jsxs("aside", { className: "sm-inspector", children: [_jsxs("div", { className: "sm-card", children: [_jsxs(SectionLabel, { children: ["Status", multilingual ? ` · ${locale}` : ""] }), _jsx(Segmented, { options: STATUSES, stretch: true, disabled: !row, value: status === "published" ? "Published" : "Draft", onChange: (v) => { void setPublished(v === "Published" ? "published" : "draft"); } })] }), record && row && (_jsx(_Fragment, { children: _jsxs("div", { className: "sm-card", children: [_jsx(SectionLabel, { children: "Document info" }), _jsx(InfoRow, { label: "Kind", value: item.section !== undefined ? `Visual · ${item.section}` : "Fields" }), _jsx(InfoRow, { label: "Updated", value: relativeTime(row.updatedAt) }), _jsx(InfoRow, { label: "ID", value: record.id, mono: true })] }) }))] })] })] }));
|
|
131
|
-
}
|
|
132
|
-
function InfoRow({ label, value, mono }) {
|
|
133
|
-
return (_jsxs("div", { style: { display: "flex", justifyContent: "space-between", gap: 10, fontSize: "var(--text-sm)", color: "var(--text-muted)" }, children: [_jsx("span", { children: label }), _jsx("span", { style: { color: "var(--text)", fontFamily: mono ? "var(--font-mono)" : undefined, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: value })] }));
|
|
134
|
-
}
|
package/dist/shared.d.ts
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import type { CollectionSchema } from "./collections.ts";
|
|
2
|
-
import type { Descriptor } from "./fields.ts";
|
|
3
|
-
import type { PairedComponent } from "./pairing.tsx";
|
|
4
|
-
import type { BuilderMap, NamespaceValues, SectionSchema } from "./schema.ts";
|
|
5
|
-
/** The reserved tree node type of a placement. */
|
|
6
|
-
export declare const SHARED_NODE_TYPE = "shared";
|
|
7
|
-
/** The reserved key a visual item's styles live under in the node's shared JSONB. */
|
|
8
|
-
export declare const STYLES_KEY = "$styles";
|
|
9
|
-
export type SharedSchema<V = Record<string, unknown>, N extends string = string> = CollectionSchema<any, N> & {
|
|
10
|
-
kind: "shared";
|
|
11
|
-
/** The registered section a visual item renders through; absent = an object item. */
|
|
12
|
-
section?: string;
|
|
13
|
-
/** The section's style descriptors (empty for an object item). */
|
|
14
|
-
styles: Record<string, Descriptor>;
|
|
15
|
-
sample?: Record<string, unknown>;
|
|
16
|
-
/** phantom: what getShared returns */
|
|
17
|
-
readonly __value?: V;
|
|
18
|
-
};
|
|
19
|
-
export type SharedLink = {
|
|
20
|
-
item: string;
|
|
21
|
-
ref: string;
|
|
22
|
-
};
|
|
23
|
-
/** The placement a tree node is, or null for any other node. Accepts a
|
|
24
|
-
* bare `{ type, fields }` shape or a full tree node — `id` (and any
|
|
25
|
-
* other tree-node property) is ignored. */
|
|
26
|
-
export declare function sharedLink(node: {
|
|
27
|
-
id?: string;
|
|
28
|
-
type: string;
|
|
29
|
-
fields?: Record<string, unknown>;
|
|
30
|
-
}): SharedLink | null;
|
|
31
|
-
type SharedInput<N extends string = string> = {
|
|
32
|
-
name: N;
|
|
33
|
-
title: string;
|
|
34
|
-
versions?: boolean;
|
|
35
|
-
};
|
|
36
|
-
export declare function shared<F extends BuilderMap, const N extends string = string>(input: SharedInput<N> & {
|
|
37
|
-
fields: F;
|
|
38
|
-
section?: undefined;
|
|
39
|
-
}): SharedSchema<NamespaceValues<F>, N>;
|
|
40
|
-
export declare function shared<F extends BuilderMap, St extends BuilderMap, const N extends string = string>(input: SharedInput<N> & {
|
|
41
|
-
section: PairedComponent<SectionSchema<F, St>, F, St>;
|
|
42
|
-
fields?: undefined;
|
|
43
|
-
}): SharedSchema<NamespaceValues<F> & {
|
|
44
|
-
styles: NamespaceValues<St>;
|
|
45
|
-
}, N>;
|
|
46
|
-
export {};
|
package/dist/shared.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/** The reserved tree node type of a placement. */
|
|
2
|
-
export const SHARED_NODE_TYPE = "shared";
|
|
3
|
-
/** The reserved key a visual item's styles live under in the node's shared JSONB. */
|
|
4
|
-
export const STYLES_KEY = "$styles";
|
|
5
|
-
/** The placement a tree node is, or null for any other node. Accepts a
|
|
6
|
-
* bare `{ type, fields }` shape or a full tree node — `id` (and any
|
|
7
|
-
* other tree-node property) is ignored. */
|
|
8
|
-
export function sharedLink(node) {
|
|
9
|
-
if (node.type !== SHARED_NODE_TYPE)
|
|
10
|
-
return null;
|
|
11
|
-
const { item, ref } = node.fields ?? {};
|
|
12
|
-
return typeof item === "string" && typeof ref === "string" ? { item, ref } : null;
|
|
13
|
-
}
|
|
14
|
-
export function shared(input) {
|
|
15
|
-
if (!input?.name)
|
|
16
|
-
throw new Error("smoodly: a shared item requires a name.");
|
|
17
|
-
if ((input.fields === undefined) === (input.section === undefined)) {
|
|
18
|
-
throw new Error(`smoodly: shared item "${input.name}" must declare exactly one of \`section\` or \`fields\`.`);
|
|
19
|
-
}
|
|
20
|
-
const fields = input.section
|
|
21
|
-
? input.section.schema.fields
|
|
22
|
-
: Object.fromEntries(Object.entries(input.fields).map(([k, b]) => [k, b.descriptor]));
|
|
23
|
-
if (Object.prototype.hasOwnProperty.call(fields, STYLES_KEY)) {
|
|
24
|
-
throw new Error(`smoodly: shared item "${input.name}" has a field named "${STYLES_KEY}" — that key is reserved for a visual item's styles.`);
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
kind: "shared",
|
|
28
|
-
name: input.name,
|
|
29
|
-
title: input.title,
|
|
30
|
-
fields,
|
|
31
|
-
styles: input.section ? input.section.schema.styles : {},
|
|
32
|
-
...(input.section ? { section: input.section.schema.name } : {}),
|
|
33
|
-
...(input.section?.schema.sample ? { sample: input.section.schema.sample } : {}),
|
|
34
|
-
...(input.versions ? { versions: true } : {}),
|
|
35
|
-
};
|
|
36
|
-
}
|