@sevenfold/setto-client 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -14
- package/dist/SettoAnimation.d.ts +22 -0
- package/dist/SettoForm.d.ts +18 -0
- package/dist/SettoVideo.d.ts +16 -0
- package/dist/block-tree/SettoBlockTree.d.ts +24 -0
- package/dist/block-tree/extract-keys.d.ts +30 -0
- package/dist/block-tree/registry.d.ts +24 -0
- package/dist/block-tree/schema.d.ts +120 -0
- package/dist/block-tree/validate.d.ts +28 -0
- package/dist/index.d.ts +13 -0
- package/dist/setto-client.js +715 -1
- package/dist/setto-client.js.map +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -8,19 +8,13 @@ Editors authenticate via Supabase, edit text inline on the live page, pick secti
|
|
|
8
8
|
|
|
9
9
|
## Install
|
|
10
10
|
|
|
11
|
-
Sevenfold sites pin
|
|
11
|
+
Sevenfold sites pin an npm version via alias:
|
|
12
12
|
|
|
13
13
|
```json
|
|
14
|
-
"@setto/client": "
|
|
14
|
+
"@setto/client": "npm:@sevenfold/setto-client@0.5.0"
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
The package is also still published to npm (`@sevenfold/setto-client`) for external consumers:
|
|
20
|
-
|
|
21
|
-
```bash
|
|
22
|
-
bun add @setto/client@npm:@sevenfold/setto-client
|
|
23
|
-
```
|
|
17
|
+
`bun install` pulls the prebuilt package from npm — no GitHub token required on Vercel.
|
|
24
18
|
|
|
25
19
|
Peer deps: `react`, `react-dom`, `react-i18next`, `i18next`.
|
|
26
20
|
|
|
@@ -29,13 +23,14 @@ For local monorepo development the consumer's `vite.config.ts` aliases `@setto/c
|
|
|
29
23
|
### Releasing a new version
|
|
30
24
|
|
|
31
25
|
1. Bump `version` in `package.json` following semver (patch / minor / major).
|
|
32
|
-
2. Commit and
|
|
33
|
-
3.
|
|
34
|
-
|
|
26
|
+
2. Commit and push to `main`. GitHub Actions publishes `@sevenfold/setto-client` to npm automatically (requires `NPM_TOKEN` secret in this repo).
|
|
27
|
+
3. Confirm the version is on npm: `npm view @sevenfold/setto-client@X.Y.Z version`.
|
|
28
|
+
4. In each consumer (`carryon.no`, `setto-site`):
|
|
29
|
+
- Update the pin in `package.json` (e.g. `@0.5.0` → `@0.5.1`).
|
|
35
30
|
- Run `bun install` to refresh the lockfile.
|
|
36
|
-
-
|
|
31
|
+
- Commit and push — Vercel installs the new npm version on the next deploy.
|
|
37
32
|
|
|
38
|
-
|
|
33
|
+
> **Why npm, not a git tag?** `nitech/setto-client` is private. Vercel cannot fetch `github:nitech/setto-client#v…` without a `GITHUB_TOKEN` with repo access. Public npm avoids that and ships a prebuilt `dist/`.
|
|
39
34
|
|
|
40
35
|
---
|
|
41
36
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { AnimationPreset } from './block-tree/schema';
|
|
3
|
+
export interface SettoAnimationProps {
|
|
4
|
+
preset: AnimationPreset;
|
|
5
|
+
/** Delay before play, in milliseconds. */
|
|
6
|
+
delay?: number;
|
|
7
|
+
/** Duration in milliseconds. Defaults per preset. */
|
|
8
|
+
duration?: number;
|
|
9
|
+
className?: string;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Lightweight, CSS-driven reveal wrapper. Triggers once when scrolled into
|
|
14
|
+
* view (or immediately, for non-scroll presets). Honors
|
|
15
|
+
* `prefers-reduced-motion`, falls back to plain children with no animation.
|
|
16
|
+
*
|
|
17
|
+
* Hosts that use GSAP (carryon.no, setto-site) should keep their own
|
|
18
|
+
* `data-reveal` system; this primitive exists so generated layout trees
|
|
19
|
+
* have a portable animation primitive without dragging GSAP into the
|
|
20
|
+
* setto-client bundle.
|
|
21
|
+
*/
|
|
22
|
+
export declare function SettoAnimation({ preset, delay, duration, className, children, }: SettoAnimationProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FormField } from './block-tree/schema';
|
|
2
|
+
export interface SettoFormProps {
|
|
3
|
+
/** Scopes i18n keys: `form.{formId}.submit`, `.success`, `.error`. */
|
|
4
|
+
formId: string;
|
|
5
|
+
fields: FormField[];
|
|
6
|
+
/** Static POST endpoint. Either this or `endpointKey` must be provided. */
|
|
7
|
+
endpoint?: string;
|
|
8
|
+
/** i18n key whose value is the runtime endpoint URL. */
|
|
9
|
+
endpointKey?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generic POST form whose copy lives in i18n. Field structure is fixed by
|
|
14
|
+
* the host (or by the block tree) — editors can change labels and copy but
|
|
15
|
+
* not the field set, matching the Setto product principle that the editor
|
|
16
|
+
* adjusts content, not structure.
|
|
17
|
+
*/
|
|
18
|
+
export declare function SettoForm({ formId, fields, endpoint, endpointKey, className, }: SettoFormProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface SettoVideoProps {
|
|
2
|
+
/** i18n key holding the video URL (YouTube, Vimeo, or direct MP4). */
|
|
3
|
+
srcKey: string;
|
|
4
|
+
/** Optional i18n key holding a poster image URL (HTML5 video only). */
|
|
5
|
+
posterKey?: string;
|
|
6
|
+
title?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Renders a video from a URL stored in i18n. YouTube and Vimeo URLs become
|
|
11
|
+
* iframe embeds; everything else renders as an HTML5 `<video>` element.
|
|
12
|
+
*
|
|
13
|
+
* Editors can change the URL via the i18n draft store (a dedicated picker
|
|
14
|
+
* UI may follow; until then it's swap-via-publish like other content).
|
|
15
|
+
*/
|
|
16
|
+
export declare function SettoVideo({ srcKey, posterKey, title, className }: SettoVideoProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ComponentType } from 'react';
|
|
2
|
+
import { type SettoIconRenderProps } from '../SettoIcon';
|
|
3
|
+
import type { BlockTree } from './schema';
|
|
4
|
+
export interface SettoBlockTreeProps {
|
|
5
|
+
/** Validated block tree, typically parsed from `home.layout.json`. */
|
|
6
|
+
tree: BlockTree;
|
|
7
|
+
/**
|
|
8
|
+
* Icon registry consumed by `SettoIcon` nodes — the same map a host would
|
|
9
|
+
* pass directly to `<SettoIcon icons={…}>`.
|
|
10
|
+
*/
|
|
11
|
+
icons: Record<string, ComponentType<SettoIconRenderProps>>;
|
|
12
|
+
/**
|
|
13
|
+
* When true (default), validates the tree and throws on schema errors.
|
|
14
|
+
* Disable in production after a one-time boot check.
|
|
15
|
+
*/
|
|
16
|
+
validate?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Renders a block tree by dispatching each node to the matching Setto
|
|
20
|
+
* primitive. Inside a `repeater`, leaf nodes use keys relative to the item;
|
|
21
|
+
* the renderer composes them with the active scope so the agent can author
|
|
22
|
+
* trees without knowing per-item suffixes.
|
|
23
|
+
*/
|
|
24
|
+
export declare function SettoBlockTree({ tree, icons, validate }: SettoBlockTreeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks a block tree and reports the i18n keys, theme ids, and required
|
|
3
|
+
* sample-locale entries it expects. The agent uses this output to validate
|
|
4
|
+
* that the generated `no.json` covers everything the tree references.
|
|
5
|
+
*/
|
|
6
|
+
import type { BlockTree } from './schema';
|
|
7
|
+
export interface ContentKeyRequirements {
|
|
8
|
+
/** Plain i18n keys that must exist with a string value. */
|
|
9
|
+
keys: Set<string>;
|
|
10
|
+
/**
|
|
11
|
+
* Section / block theme ids referenced by the tree. The deterministic
|
|
12
|
+
* sections.json overlay and section-schemas.ts must include each id.
|
|
13
|
+
*/
|
|
14
|
+
themeIds: Set<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Repeater requirements — at least one item entry must exist in the
|
|
17
|
+
* locale under `itemsKey`, with every field from `defaultItem`.
|
|
18
|
+
*/
|
|
19
|
+
repeaters: Array<{
|
|
20
|
+
itemsKey: string;
|
|
21
|
+
fields: string[];
|
|
22
|
+
/**
|
|
23
|
+
* Item-relative keys produced by walking the item template. The
|
|
24
|
+
* validator checks every existing locale item has these keys.
|
|
25
|
+
*/
|
|
26
|
+
itemKeys: string[];
|
|
27
|
+
}>;
|
|
28
|
+
}
|
|
29
|
+
/** Returns content requirements for an already-validated tree. */
|
|
30
|
+
export declare function extractContentKeys(tree: BlockTree): ContentKeyRequirements;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-type metadata for block-tree nodes.
|
|
3
|
+
*
|
|
4
|
+
* The renderer dispatches on node `type`; the validator and key extractor
|
|
5
|
+
* consult this registry for allowed children, required content keys, and
|
|
6
|
+
* whether a type carries a theme id.
|
|
7
|
+
*/
|
|
8
|
+
import type { BlockNode, BlockNodeType } from './schema';
|
|
9
|
+
export interface BlockTypeMeta {
|
|
10
|
+
/**
|
|
11
|
+
* Allowed child types. `null` means the node is a leaf; `'any'` means any
|
|
12
|
+
* other type may appear as a child.
|
|
13
|
+
*/
|
|
14
|
+
allowedChildren: BlockNodeType[] | 'any' | null;
|
|
15
|
+
/** True when the node has a theme id (used in `sections.json`). */
|
|
16
|
+
themed: boolean;
|
|
17
|
+
/** True when this node participates as a `SectionToolbar` target. */
|
|
18
|
+
selectable: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare const BLOCK_REGISTRY: Record<BlockNodeType, BlockTypeMeta>;
|
|
21
|
+
/** All known block types, kept in sync with `BLOCK_REGISTRY`. */
|
|
22
|
+
export declare const BLOCK_TYPES: readonly BlockNodeType[];
|
|
23
|
+
/** Returns the children of a node, or an empty array for leaves. */
|
|
24
|
+
export declare function nodeChildren(node: BlockNode): BlockNode[];
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Declarative page model rendered by `SettoBlockTree`.
|
|
3
|
+
*
|
|
4
|
+
* A site's layout is a tree of typed nodes. Each node maps to one of the
|
|
5
|
+
* existing editable primitives (T, SettoSection, SettoBlock, SettoRepeater,
|
|
6
|
+
* SettoImage, SettoIcon) or to a new composite primitive (SettoForm,
|
|
7
|
+
* SettoVideo, SettoAnimation). The tree is stored as JSON
|
|
8
|
+
* (`src/content/pages/home.layout.json`) and is what `setto-agent` generates
|
|
9
|
+
* during onboarding instead of writing TSX.
|
|
10
|
+
*/
|
|
11
|
+
export type BlockTreeVersion = '1';
|
|
12
|
+
export interface BlockTree {
|
|
13
|
+
version: BlockTreeVersion;
|
|
14
|
+
/** Top-level nodes rendered into `<main>` (or a host-provided wrapper). */
|
|
15
|
+
root: BlockNode[];
|
|
16
|
+
}
|
|
17
|
+
export type BlockNode = SectionNode | BlockBoxNode | ContainerNode | TextNode | ImageNode | IconNode | RepeaterNode | FormNode | VideoNode | AnimationNode;
|
|
18
|
+
export type BlockNodeType = BlockNode['type'];
|
|
19
|
+
interface BaseNode {
|
|
20
|
+
/** Stable id within the tree — used as React key and for diff/edit ops. */
|
|
21
|
+
id: string;
|
|
22
|
+
/** Optional Tailwind / CSS class string applied to the rendered element. */
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SectionNode extends BaseNode {
|
|
26
|
+
type: 'section';
|
|
27
|
+
/** Matches a key in `sections.json` / `sectionSchemas` for background theme. */
|
|
28
|
+
sectionId: string;
|
|
29
|
+
children: BlockNode[];
|
|
30
|
+
}
|
|
31
|
+
export interface BlockBoxNode extends BaseNode {
|
|
32
|
+
type: 'block';
|
|
33
|
+
blockId: string;
|
|
34
|
+
children: BlockNode[];
|
|
35
|
+
}
|
|
36
|
+
export type ContainerTag = 'div' | 'section' | 'header' | 'footer' | 'main' | 'aside' | 'nav' | 'article' | 'ul' | 'ol' | 'li' | 'p' | 'span';
|
|
37
|
+
export interface ContainerNode extends BaseNode {
|
|
38
|
+
type: 'container';
|
|
39
|
+
tag?: ContainerTag;
|
|
40
|
+
children: BlockNode[];
|
|
41
|
+
}
|
|
42
|
+
export type TextAs = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'p' | 'span' | 'div' | 'label' | 'em' | 'strong';
|
|
43
|
+
export interface TextNode extends BaseNode {
|
|
44
|
+
type: 'text';
|
|
45
|
+
/** i18n key, or a key relative to the surrounding repeater item. */
|
|
46
|
+
k: string;
|
|
47
|
+
/** Element tag to wrap the `<T>` in. Defaults to inline span. */
|
|
48
|
+
as?: TextAs;
|
|
49
|
+
}
|
|
50
|
+
export interface ImageNode extends BaseNode {
|
|
51
|
+
type: 'image';
|
|
52
|
+
/** i18n key holding the image src (resolved at runtime). */
|
|
53
|
+
srcKey: string;
|
|
54
|
+
alt?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface IconNode extends BaseNode {
|
|
57
|
+
type: 'icon';
|
|
58
|
+
/** i18n key holding the icon name from the host icon registry. */
|
|
59
|
+
k: string;
|
|
60
|
+
size?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface RepeaterNode extends BaseNode {
|
|
63
|
+
type: 'repeater';
|
|
64
|
+
/** i18n list prefix, e.g. 'faq.items'. */
|
|
65
|
+
itemsKey: string;
|
|
66
|
+
/** Norwegian label shown in the editor's add/remove controls. */
|
|
67
|
+
itemLabel?: string;
|
|
68
|
+
/** Field defaults seeded into i18n when an editor adds a new item. */
|
|
69
|
+
defaultItem: Record<string, string>;
|
|
70
|
+
/**
|
|
71
|
+
* Subtree rendered once per item. Text/image/icon nodes here may use
|
|
72
|
+
* keys relative to the item (e.g. `k: 'q'` resolves to
|
|
73
|
+
* `faq.items.{itemKey}.q` at render time).
|
|
74
|
+
*/
|
|
75
|
+
itemTemplate: BlockNode[];
|
|
76
|
+
}
|
|
77
|
+
export type FormFieldType = 'text' | 'email' | 'tel' | 'textarea';
|
|
78
|
+
export interface FormField {
|
|
79
|
+
/** Submitted form field name. */
|
|
80
|
+
name: string;
|
|
81
|
+
type: FormFieldType;
|
|
82
|
+
required?: boolean;
|
|
83
|
+
/** i18n key for the field label. */
|
|
84
|
+
labelKey: string;
|
|
85
|
+
/** i18n key for the placeholder text. */
|
|
86
|
+
placeholderKey?: string;
|
|
87
|
+
}
|
|
88
|
+
export interface FormNode extends BaseNode {
|
|
89
|
+
type: 'form';
|
|
90
|
+
/**
|
|
91
|
+
* Scopes all i18n keys for this form: `form.{formId}.submit`,
|
|
92
|
+
* `form.{formId}.success`, `form.{formId}.error`.
|
|
93
|
+
*/
|
|
94
|
+
formId: string;
|
|
95
|
+
/** Static POST endpoint. Use `endpointKey` to read from i18n instead. */
|
|
96
|
+
endpoint?: string;
|
|
97
|
+
/** i18n key whose value is the form POST endpoint. */
|
|
98
|
+
endpointKey?: string;
|
|
99
|
+
fields: FormField[];
|
|
100
|
+
}
|
|
101
|
+
export interface VideoNode extends BaseNode {
|
|
102
|
+
type: 'video';
|
|
103
|
+
/** i18n key holding the embed URL (YouTube, Vimeo, MP4, …). */
|
|
104
|
+
srcKey: string;
|
|
105
|
+
/** Optional i18n key for a poster image (HTML5 video only). */
|
|
106
|
+
posterKey?: string;
|
|
107
|
+
/** Iframe accessibility title. Not editable. */
|
|
108
|
+
title?: string;
|
|
109
|
+
}
|
|
110
|
+
export type AnimationPreset = 'fadeIn' | 'slideUp' | 'stagger' | 'scrollReveal';
|
|
111
|
+
export interface AnimationNode extends BaseNode {
|
|
112
|
+
type: 'animation';
|
|
113
|
+
preset: AnimationPreset;
|
|
114
|
+
/** Delay before play, in milliseconds. */
|
|
115
|
+
delay?: number;
|
|
116
|
+
/** Duration in milliseconds. Defaults to preset value. */
|
|
117
|
+
duration?: number;
|
|
118
|
+
children: BlockNode[];
|
|
119
|
+
}
|
|
120
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime validator for block trees.
|
|
3
|
+
*
|
|
4
|
+
* Used by both `setto-client` (when loading a `home.layout.json` at boot)
|
|
5
|
+
* and `setto-agent` (after generation, before sandbox build). No external
|
|
6
|
+
* dependencies so we can ship to host sites without bundle bloat.
|
|
7
|
+
*/
|
|
8
|
+
import type { BlockTree, FormField } from './schema';
|
|
9
|
+
export interface ValidationIssue {
|
|
10
|
+
/** Dotted path to the offending node, e.g. `root[2].children[0]`. */
|
|
11
|
+
path: string;
|
|
12
|
+
message: string;
|
|
13
|
+
}
|
|
14
|
+
export type ValidationResult = {
|
|
15
|
+
ok: true;
|
|
16
|
+
} | {
|
|
17
|
+
ok: false;
|
|
18
|
+
issues: ValidationIssue[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Validates a parsed block tree. Returns the first batch of issues found —
|
|
22
|
+
* the goal is enough detail for a fixer model to act on, not exhaustive
|
|
23
|
+
* reporting.
|
|
24
|
+
*/
|
|
25
|
+
export declare function validateBlockTree(input: unknown): ValidationResult;
|
|
26
|
+
/** Narrowing helper: validates and returns a typed tree, or throws. */
|
|
27
|
+
export declare function parseBlockTree(input: unknown): BlockTree;
|
|
28
|
+
export type { FormField };
|
package/dist/index.d.ts
CHANGED
|
@@ -9,9 +9,22 @@ export { SettoImage } from './SettoImage';
|
|
|
9
9
|
export type { SettoImageProps } from './SettoImage';
|
|
10
10
|
export { SettoRepeater } from './SettoRepeater';
|
|
11
11
|
export type { SettoRepeaterProps } from './SettoRepeater';
|
|
12
|
+
export { SettoForm } from './SettoForm';
|
|
13
|
+
export type { SettoFormProps } from './SettoForm';
|
|
14
|
+
export { SettoVideo } from './SettoVideo';
|
|
15
|
+
export type { SettoVideoProps } from './SettoVideo';
|
|
16
|
+
export { SettoAnimation } from './SettoAnimation';
|
|
17
|
+
export type { SettoAnimationProps } from './SettoAnimation';
|
|
12
18
|
export { useSectionTheme } from './use-section-theme';
|
|
13
19
|
export { SettoAdminApp } from './admin/App';
|
|
14
20
|
export { SETTO_BASE } from './lib/urls';
|
|
15
21
|
export { AuthGate } from './edit-mode/auth-gate';
|
|
16
22
|
export type { SettoConfig, BrandColor, DeploymentRow, SiteRow, ContentFile, PublishFile, PublishResult, } from './types';
|
|
17
23
|
export type { SectionSchema, SectionColorField } from './section-schema';
|
|
24
|
+
export { SettoBlockTree } from './block-tree/SettoBlockTree';
|
|
25
|
+
export type { SettoBlockTreeProps } from './block-tree/SettoBlockTree';
|
|
26
|
+
export type { BlockTree, BlockTreeVersion, BlockNode, BlockNodeType, SectionNode, BlockBoxNode, ContainerNode, ContainerTag, TextNode, TextAs, ImageNode, IconNode, RepeaterNode, FormNode, FormField, FormFieldType, VideoNode, AnimationNode, AnimationPreset, } from './block-tree/schema';
|
|
27
|
+
export { validateBlockTree, parseBlockTree, type ValidationIssue, type ValidationResult, } from './block-tree/validate';
|
|
28
|
+
export { extractContentKeys, type ContentKeyRequirements, } from './block-tree/extract-keys';
|
|
29
|
+
export { BLOCK_REGISTRY, BLOCK_TYPES, nodeChildren } from './block-tree/registry';
|
|
30
|
+
export type { BlockTypeMeta } from './block-tree/registry';
|