@wocart/theme 1.6.0 → 2.1.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/CHANGELOG.md +107 -0
- package/README.md +211 -9
- package/dist/astro/Block.astro +29 -0
- package/dist/astro/Blocks.astro +23 -0
- package/dist/astro/InstanceView.astro +34 -10
- package/dist/astro/ThemeStyles.astro +34 -0
- package/dist/astro/index.d.ts +49 -1
- package/dist/astro/index.js +43 -5
- package/dist/blocks.d.ts +61 -0
- package/dist/blocks.js +144 -0
- package/dist/conditions.d.ts +21 -0
- package/dist/conditions.js +65 -0
- package/dist/definitions.js +399 -29
- package/dist/index.d.ts +6 -1
- package/dist/index.js +4 -0
- package/dist/instances.d.ts +4 -0
- package/dist/instances.js +72 -4
- package/dist/manifest-diff.js +95 -2
- package/dist/manifest.d.ts +245 -13
- package/dist/manifest.js +64 -1
- package/dist/operations.d.ts +39 -13
- package/dist/operations.js +253 -55
- package/dist/page-data.js +63 -27
- package/dist/preview-bridge.js +10 -7
- package/dist/preview-protocol.d.ts +8 -3
- package/dist/rich-text.d.ts +2 -0
- package/dist/rich-text.js +4 -0
- package/dist/schemas.d.ts +2 -1
- package/dist/schemas.js +3 -1
- package/dist/settings.js +20 -1
- package/dist/style.d.ts +45 -0
- package/dist/style.js +248 -0
- package/dist/surface-document.d.ts +49 -0
- package/dist/surface-document.js +162 -0
- package/dist/types.d.ts +217 -7
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +4 -1
package/dist/manifest.js
CHANGED
|
@@ -35,9 +35,13 @@ export function themeManifest(theme) {
|
|
|
35
35
|
label: copyData(surface.label),
|
|
36
36
|
...(surface.pageType === undefined ? {} : { pageType: surface.pageType }),
|
|
37
37
|
...(surface.document === undefined ? {} : { document: copyData(surface.document) }),
|
|
38
|
+
...(surface.required === undefined ? {} : { required: copyData(surface.required) }),
|
|
39
|
+
...(surface.max === undefined ? {} : { max: surface.max }),
|
|
38
40
|
})),
|
|
41
|
+
areas: (theme.areas ?? []).map((area) => copyData(area)),
|
|
39
42
|
locales: [...(theme.locales ?? [])],
|
|
40
43
|
settings: (theme.settings ?? []).map((group) => copyData(group)),
|
|
44
|
+
...(theme.style === undefined ? {} : { style: copyData(theme.style) }),
|
|
41
45
|
content: copyData(theme.content ?? {}),
|
|
42
46
|
preview: theme.preview === true,
|
|
43
47
|
components: Object.fromEntries(Object.entries(theme.components).map(([key, definition]) => [
|
|
@@ -57,6 +61,9 @@ function componentSpec(definition) {
|
|
|
57
61
|
? {}
|
|
58
62
|
: { capabilities: copyData(definition.capabilities) }),
|
|
59
63
|
presets: (definition.presets ?? []).map((preset) => copyData(preset)),
|
|
64
|
+
...(definition.placement === undefined ? {} : { placement: definition.placement }),
|
|
65
|
+
...(definition.fixed === undefined ? {} : { fixed: copyData(definition.fixed) }),
|
|
66
|
+
...(definition.role === undefined ? {} : { role: definition.role }),
|
|
60
67
|
};
|
|
61
68
|
}
|
|
62
69
|
/**
|
|
@@ -75,6 +82,8 @@ const FieldCommonSchema = {
|
|
|
75
82
|
label: LocalizedTextSchema,
|
|
76
83
|
description: z.exactOptional(LocalizedTextSchema),
|
|
77
84
|
required: z.exactOptional(z.boolean()),
|
|
85
|
+
// A condition's own rules are relational; `validateThemeDefinition` checks them.
|
|
86
|
+
visibleIf: z.exactOptional(z.custom((value) => isRecord(value))),
|
|
78
87
|
};
|
|
79
88
|
const TextFieldSchema = z.object({
|
|
80
89
|
...FieldCommonSchema,
|
|
@@ -91,6 +100,7 @@ const ScalarFieldSchemas = [
|
|
|
91
100
|
min: z.exactOptional(z.number()),
|
|
92
101
|
max: z.exactOptional(z.number()),
|
|
93
102
|
step: z.exactOptional(z.number()),
|
|
103
|
+
display: z.exactOptional(z.enum(["input", "slider"])),
|
|
94
104
|
}),
|
|
95
105
|
z.object({
|
|
96
106
|
...FieldCommonSchema,
|
|
@@ -103,6 +113,7 @@ const ScalarFieldSchemas = [
|
|
|
103
113
|
options: z.array(z.string()),
|
|
104
114
|
optionLabels: z.exactOptional(z.record(z.string(), LocalizedTextSchema)),
|
|
105
115
|
default: z.exactOptional(z.string()),
|
|
116
|
+
display: z.exactOptional(z.enum(["dropdown", "radio", "segmented"])),
|
|
106
117
|
}),
|
|
107
118
|
...["url", "color", "menu", "collection", "product", "category"].map((kind) => z.object({
|
|
108
119
|
...FieldCommonSchema,
|
|
@@ -119,6 +130,26 @@ const ScalarFieldSchemas = [
|
|
|
119
130
|
formats: z.exactOptional(z.array(z.custom((value) => typeof value === "string"))),
|
|
120
131
|
// The document's own rules are relational; `validateThemeDefinition` checks them.
|
|
121
132
|
default: z.exactOptional(z.custom((value) => typeof value === "object" && value !== null)),
|
|
133
|
+
inline: z.exactOptional(z.boolean()),
|
|
134
|
+
}),
|
|
135
|
+
...["productList", "collectionList"].map((kind) => z.object({
|
|
136
|
+
...FieldCommonSchema,
|
|
137
|
+
kind: z.literal(kind),
|
|
138
|
+
min: z.exactOptional(z.number()),
|
|
139
|
+
max: z.exactOptional(z.number()),
|
|
140
|
+
default: z.exactOptional(z.array(z.string())),
|
|
141
|
+
})),
|
|
142
|
+
z.object({
|
|
143
|
+
...FieldCommonSchema,
|
|
144
|
+
kind: z.literal("style"),
|
|
145
|
+
panels: z.array(z.custom((value) => typeof value === "string")),
|
|
146
|
+
// Checked against the panels and the theme's sizes by `validateThemeDefinition`.
|
|
147
|
+
default: z.exactOptional(z.custom((value) => isRecord(value))),
|
|
148
|
+
}),
|
|
149
|
+
z.object({
|
|
150
|
+
...FieldCommonSchema,
|
|
151
|
+
kind: z.literal("colorScheme"),
|
|
152
|
+
default: z.exactOptional(z.string()),
|
|
122
153
|
}),
|
|
123
154
|
];
|
|
124
155
|
const ItemFieldSchema = z.discriminatedUnion("kind", [...ScalarFieldSchemas]);
|
|
@@ -133,6 +164,11 @@ const FieldSchema = z.discriminatedUnion("kind", [
|
|
|
133
164
|
default: z.exactOptional(z.array(z.object({ id: z.string(), props: z.exactOptional(z.record(z.string(), JsonValueSchema)) }))),
|
|
134
165
|
itemLabel: z.exactOptional(z.string()),
|
|
135
166
|
}),
|
|
167
|
+
z.object({
|
|
168
|
+
...FieldCommonSchema,
|
|
169
|
+
kind: z.literal("colorSchemes"),
|
|
170
|
+
default: z.array(z.custom((value) => isRecord(value))),
|
|
171
|
+
}),
|
|
136
172
|
]);
|
|
137
173
|
const PresetInstanceSchema = z.lazy(() => z.object({
|
|
138
174
|
type: z.string(),
|
|
@@ -140,6 +176,11 @@ const PresetInstanceSchema = z.lazy(() => z.object({
|
|
|
140
176
|
children: z.exactOptional(z.array(PresetInstanceSchema)),
|
|
141
177
|
slots: z.exactOptional(z.record(z.string(), z.array(PresetInstanceSchema))),
|
|
142
178
|
}));
|
|
179
|
+
const RequiredBlockSchema = z.object({
|
|
180
|
+
type: z.string(),
|
|
181
|
+
min: z.exactOptional(z.number()),
|
|
182
|
+
max: z.exactOptional(z.number()),
|
|
183
|
+
});
|
|
143
184
|
const ComponentSpecSchema = z.object({
|
|
144
185
|
type: z.string(),
|
|
145
186
|
label: LocalizedTextSchema,
|
|
@@ -150,8 +191,13 @@ const ComponentSpecSchema = z.object({
|
|
|
150
191
|
name: z.string(),
|
|
151
192
|
multiple: z.exactOptional(z.boolean()),
|
|
152
193
|
allow: z.exactOptional(z.array(z.string())),
|
|
194
|
+
max: z.exactOptional(z.number()),
|
|
195
|
+
required: z.exactOptional(z.array(RequiredBlockSchema)),
|
|
153
196
|
}))
|
|
154
197
|
.default([]),
|
|
198
|
+
placement: z.exactOptional(z.custom((value) => typeof value === "string")),
|
|
199
|
+
fixed: z.exactOptional(z.array(z.object({ name: z.string(), type: z.string(), label: z.exactOptional(LocalizedTextSchema) }))),
|
|
200
|
+
role: z.exactOptional(z.custom((value) => typeof value === "string")),
|
|
155
201
|
capabilities: z.exactOptional(z.object({
|
|
156
202
|
insertable: z.exactOptional(z.boolean()),
|
|
157
203
|
surfaces: z.exactOptional(z.array(z.string())),
|
|
@@ -184,12 +230,27 @@ export const ThemeManifestSchema = z.object({
|
|
|
184
230
|
pageType: z.exactOptional(z.custom((value) => typeof value === "string")),
|
|
185
231
|
// A page document's own rules are checked by `validateThemeDefinition` on the probe.
|
|
186
232
|
document: z.exactOptional(z.custom((value) => isRecord(value))),
|
|
233
|
+
required: z.exactOptional(z.array(RequiredBlockSchema)),
|
|
234
|
+
max: z.exactOptional(z.number()),
|
|
235
|
+
}))
|
|
236
|
+
.default([]),
|
|
237
|
+
areas: z
|
|
238
|
+
.array(z.object({
|
|
239
|
+
key: z.string(),
|
|
240
|
+
label: LocalizedTextSchema,
|
|
241
|
+
document: z.exactOptional(z.custom((value) => isRecord(value))),
|
|
242
|
+
required: z.exactOptional(z.array(RequiredBlockSchema)),
|
|
243
|
+
max: z.exactOptional(z.number()),
|
|
187
244
|
}))
|
|
188
245
|
.default([]),
|
|
189
246
|
locales: z.array(z.string()).default([]),
|
|
190
247
|
settings: z
|
|
191
248
|
.array(z.object({ key: z.string(), label: LocalizedTextSchema, fields: z.array(FieldSchema) }))
|
|
192
249
|
.default([]),
|
|
250
|
+
style: z.exactOptional(z.object({
|
|
251
|
+
spacing: z.exactOptional(z.record(z.string(), z.number())),
|
|
252
|
+
widths: z.exactOptional(z.record(z.string(), z.number())),
|
|
253
|
+
})),
|
|
193
254
|
content: z.record(z.string(), z.record(z.string(), z.string())).default({}),
|
|
194
255
|
preview: z.boolean().default(false),
|
|
195
256
|
components: z.record(z.string(), ComponentSpecSchema),
|
|
@@ -247,7 +308,7 @@ function codeAt(path) {
|
|
|
247
308
|
return "invalid-identity";
|
|
248
309
|
if (path === "version")
|
|
249
310
|
return "invalid-version";
|
|
250
|
-
if (path === "surfaces" || path.startsWith("surfaces["))
|
|
311
|
+
if (path === "surfaces" || path.startsWith("surfaces[") || path === "areas" || path.startsWith("areas["))
|
|
251
312
|
return "invalid-surface";
|
|
252
313
|
if (path === "settings" || path.startsWith("settings["))
|
|
253
314
|
return "invalid-settings";
|
|
@@ -278,8 +339,10 @@ export function manifestCatalog(manifest) {
|
|
|
278
339
|
key: manifest.key,
|
|
279
340
|
version: manifest.version,
|
|
280
341
|
surfaces: manifest.surfaces,
|
|
342
|
+
areas: manifest.areas,
|
|
281
343
|
locales: manifest.locales,
|
|
282
344
|
settings: manifest.settings,
|
|
345
|
+
...(manifest.style === undefined ? {} : { style: manifest.style }),
|
|
283
346
|
content: manifest.content,
|
|
284
347
|
preview: manifest.preview,
|
|
285
348
|
components: Object.fromEntries(Object.entries(manifest.components).map(([key, spec]) => [
|
package/dist/operations.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComponentInstance, JsonValue, PageData, ThemeDefinition } from "./types.js";
|
|
2
|
-
export type DocumentIssueCode = "invalid-document" | "invalid-instance" | "invalid-index" | "invalid-props" | "unknown-instance" | "unknown-type" | "unknown-slot" | "duplicate-id" | "not-insertable" | "not-available" | "not-allowed" | "slot-full" | "cycle";
|
|
2
|
+
export type DocumentIssueCode = "invalid-document" | "invalid-instance" | "invalid-index" | "invalid-props" | "unknown-instance" | "unknown-type" | "unknown-slot" | "duplicate-id" | "not-insertable" | "not-available" | "not-allowed" | "not-placeable" | "slot-full" | "fixed-block" | "required-block" | "limit-exceeded" | "cycle";
|
|
3
3
|
/** Why a document or a change is refused; `path` points into the document. */
|
|
4
4
|
export interface DocumentIssue {
|
|
5
5
|
path: string;
|
|
@@ -20,12 +20,19 @@ export interface InstancePlacement {
|
|
|
20
20
|
slot?: string;
|
|
21
21
|
index?: number;
|
|
22
22
|
}
|
|
23
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Where an instance is: its parent (`null` at the top level) and its slot and
|
|
25
|
+
* index there — or, for a fixed block, its owner and `fixed`, the name the
|
|
26
|
+
* owner's definition gives it (`slot` is then `null`).
|
|
27
|
+
*/
|
|
24
28
|
export interface InstanceLocation {
|
|
25
29
|
instance: ComponentInstance;
|
|
26
30
|
parent: string | null;
|
|
27
31
|
slot: string | null;
|
|
28
32
|
index: number;
|
|
33
|
+
fixed?: string;
|
|
34
|
+
/** Levels below the top-level sections (a section is at 0). */
|
|
35
|
+
depth: number;
|
|
29
36
|
}
|
|
30
37
|
/**
|
|
31
38
|
* A new instance id: `cmp_` and 16 random hex digits. Operations refuse an id
|
|
@@ -36,36 +43,55 @@ export declare function newInstanceId(): string;
|
|
|
36
43
|
export declare function findInstance(page: PageData, id: string): InstanceLocation | null;
|
|
37
44
|
/**
|
|
38
45
|
* Insert a new instance — from `createInstance` or `instantiatePreset` — at a
|
|
39
|
-
* placement
|
|
40
|
-
*
|
|
41
|
-
* already
|
|
46
|
+
* placement, completed with its fixed and required blocks. Refused when the
|
|
47
|
+
* component is not insertable, not available on the document's surface, not
|
|
48
|
+
* placeable there, when the list is full or already holds the most of its
|
|
49
|
+
* type, when the document would pass its caps, or when any id is already in
|
|
50
|
+
* the document.
|
|
42
51
|
*/
|
|
43
52
|
export declare function insertInstance(theme: ThemeDefinition, page: PageData, instance: ComponentInstance, placement?: InstancePlacement): DocumentEdit;
|
|
44
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Remove an instance and everything inside it. Refused for a fixed block and,
|
|
55
|
+
* given the theme, for the last required instance of its type in its list.
|
|
56
|
+
* The form without a theme is kept for writers that predate blocks: it still
|
|
57
|
+
* refuses a fixed block, but cannot know a slot's required types.
|
|
58
|
+
*/
|
|
59
|
+
export declare function removeInstance(theme: ThemeDefinition, page: PageData, id: string): DocumentEdit;
|
|
60
|
+
/** @deprecated Pass the theme first, so required blocks are kept. */
|
|
45
61
|
export declare function removeInstance(page: PageData, id: string): DocumentEdit;
|
|
46
62
|
/**
|
|
47
63
|
* Move an instance (with everything inside it) to a placement. `index` counts
|
|
48
64
|
* positions in the destination after the instance has left its old place.
|
|
65
|
+
* A fixed block never moves; a required one moves only within its own list,
|
|
66
|
+
* unless enough of its type stay behind.
|
|
49
67
|
*/
|
|
50
68
|
export declare function moveInstance(theme: ThemeDefinition, page: PageData, id: string, placement?: InstancePlacement): DocumentEdit;
|
|
51
69
|
/**
|
|
52
70
|
* Copy an instance and everything inside it right after the original, every
|
|
53
71
|
* copied instance with an id from `newId`. List items keep their ids: they
|
|
54
|
-
* are unique within their list, not the document.
|
|
72
|
+
* are unique within their list, not the document. A fixed block is never
|
|
73
|
+
* copied.
|
|
55
74
|
*/
|
|
56
75
|
export declare function duplicateInstance(theme: ThemeDefinition, page: PageData, id: string, newId: () => string): DocumentEdit;
|
|
57
76
|
/**
|
|
58
|
-
* Change an instance's props: each value is checked by
|
|
59
|
-
* `undefined` removes the stored value, so the field falls back to
|
|
60
|
-
* content-pack text or default.
|
|
77
|
+
* Change an instance's props — a fixed block's too: each value is checked by
|
|
78
|
+
* its field; `undefined` removes the stored value, so the field falls back to
|
|
79
|
+
* its content-pack text or default.
|
|
61
80
|
*/
|
|
62
81
|
export declare function setInstanceProps(theme: ThemeDefinition, page: PageData, id: string, changes: Readonly<Record<string, JsonValue | undefined>>): DocumentEdit;
|
|
63
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Switch an instance off (kept, not rendered) or back on. A fixed block is
|
|
84
|
+
* never hidden and, given the theme, neither is the last required instance of
|
|
85
|
+
* its type. The form without a theme refuses only a fixed block.
|
|
86
|
+
*/
|
|
87
|
+
export declare function setInstanceHidden(theme: ThemeDefinition, page: PageData, id: string, hidden: boolean): DocumentEdit;
|
|
88
|
+
/** @deprecated Pass the theme first, so required blocks stay shown. */
|
|
64
89
|
export declare function setInstanceHidden(page: PageData, id: string, hidden: boolean): DocumentEdit;
|
|
65
90
|
/**
|
|
66
91
|
* Everything a writer must fix before saving a document for this theme —
|
|
67
92
|
* the strict counterpart of `validatePageData`: an envelope for one of the
|
|
68
|
-
* theme's surfaces when it declares any,
|
|
69
|
-
*
|
|
93
|
+
* theme's surfaces when it declares any, the surface's required sections
|
|
94
|
+
* shown and its cap kept, and every section a tree the operations would have
|
|
95
|
+
* built. An empty list means the document may be saved.
|
|
70
96
|
*/
|
|
71
97
|
export declare function checkPageData(theme: ThemeDefinition, input: unknown): DocumentIssue[];
|