@wocart/theme 1.1.1 → 1.2.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 +8 -0
- package/README.md +1 -0
- package/dist/definitions.js +7 -1
- package/dist/index.d.ts +1 -1
- package/dist/instances.js +5 -1
- package/dist/manifest.d.ts +14 -0
- package/dist/manifest.js +5 -0
- package/dist/schemas.d.ts +1 -0
- package/dist/schemas.js +1 -0
- package/dist/types.d.ts +14 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,14 @@ All notable changes to `@wocart/theme` are recorded here. The package follows
|
|
|
5
5
|
major version, and an export is marked `@deprecated` for at least one minor
|
|
6
6
|
release before a major removes it.
|
|
7
7
|
|
|
8
|
+
## 1.2.0 — 2026-10-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Field kind `collection`: a collection handle (`best-sellers`), so the
|
|
13
|
+
merchant picks which curated list a section shows — Shopify's `collection`
|
|
14
|
+
setting. Type `CollectionFieldDefinition`.
|
|
15
|
+
|
|
8
16
|
## 1.1.1 — 2026-10-17
|
|
9
17
|
|
|
10
18
|
### Fixed
|
package/README.md
CHANGED
|
@@ -98,6 +98,7 @@ and, for page-data resolution issues, `path`.
|
|
|
98
98
|
| `boolean` | boolean | |
|
|
99
99
|
| `select` | one of `options` | `default` must be one of the options |
|
|
100
100
|
| `color` | `#rgb` or `#rrggbb` | anything else (a color name, `url(…)`) is rejected at assembly and reported on read |
|
|
101
|
+
| `collection` | a collection handle (`best-sellers`) | lowercase letters, digits and hyphens; its products are listed with `@wocart/storefront`'s `products.list({ collection })`, in the merchant's order |
|
|
101
102
|
| `menu` | a menu handle (`main-menu`) | lowercase letters, digits and hyphens; the store's menu is read with `@wocart/storefront`'s `menus.get(handle)` |
|
|
102
103
|
| `url` | a link target | a site path (`/products`), `#fragment`, `?query`, `http(s)://`, `mailto:` or `tel:`; `javascript:`, `data:`, `//host` and backslash tricks are rejected at assembly and reported on read |
|
|
103
104
|
|
package/dist/definitions.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* data — the validator exists so a theme's test suite fails loudly on catalog
|
|
5
5
|
* bugs when the catalog is assembled.
|
|
6
6
|
*/
|
|
7
|
-
import { COLOR_PATTERN, MENU_HANDLE_PATTERN, SURFACE_KEY_PATTERN, THEME_KEY_PATTERN, TYPE_KEY_PATTERN, isLocaleMap, isLocaleTag, isSafeLinkTarget, } from "./schemas.js";
|
|
7
|
+
import { COLOR_PATTERN, MENU_HANDLE_PATTERN, COLLECTION_HANDLE_PATTERN, SURFACE_KEY_PATTERN, THEME_KEY_PATTERN, TYPE_KEY_PATTERN, isLocaleMap, isLocaleTag, isSafeLinkTarget, } from "./schemas.js";
|
|
8
8
|
/** Identity helper: returns the definition unchanged so literal types survive. */
|
|
9
9
|
export function defineComponent(definition) {
|
|
10
10
|
return definition;
|
|
@@ -358,6 +358,12 @@ function inspectFields(fields, path, issues, rules) {
|
|
|
358
358
|
}
|
|
359
359
|
break;
|
|
360
360
|
}
|
|
361
|
+
case "collection": {
|
|
362
|
+
if (field.default !== undefined && (typeof field.default !== "string" || !COLLECTION_HANDLE_PATTERN.test(field.default))) {
|
|
363
|
+
addIssue(issues, `${fieldPath}.default`, "invalid-field", "`default` must be a collection handle: lowercase letters, digits and dashes");
|
|
364
|
+
}
|
|
365
|
+
break;
|
|
366
|
+
}
|
|
361
367
|
case "url": {
|
|
362
368
|
if (field.default !== undefined &&
|
|
363
369
|
(typeof field.default !== "string" || !isSafeLinkTarget(field.default))) {
|
package/dist/index.d.ts
CHANGED
|
@@ -17,4 +17,4 @@ export { localize } from "./locales.js";
|
|
|
17
17
|
export { PLURAL_CATEGORIES, formatMessage, messageForms, pluralFormIssues } from "./messages.js";
|
|
18
18
|
export type { MessageOptions, MessageValues, PluralCategory } from "./messages.js";
|
|
19
19
|
export { THEME_MANIFEST_CONTRACT_VERSION, themeManifest, validateThemeManifest, } from "./manifest.js";
|
|
20
|
-
export type { JsonValue, JsonObject, LocaleCode, LocalizedText, ResolutionScope, FieldKind, FieldDefinition, FieldValue, InferProps, SlotDefinition, ComponentCapabilities, ComponentDefinition, ComponentSpec, SurfaceSpec, ThemeDefinition, SettingsGroup, InferSettings, ThemeSettingsIssue, ThemeSettingsIssueCode, ThemeSettingsResult, ColorFieldDefinition, MenuFieldDefinition, ThemeManifest, ThemeManifestIssue, ThemeManifestIssueCode, ThemeManifestResult, ComponentInstance, PageData, ThemeRenderContext, LoadContext, LoadFn, ReadCache, PageDataIssue, PageDataIssueCode, PageDataResult, ResolvedInstance, ThemeDefinitionIssue, ThemeDefinitionIssueCode, ThemeValidationOptions, } from "./types.js";
|
|
20
|
+
export type { JsonValue, JsonObject, LocaleCode, LocalizedText, ResolutionScope, FieldKind, FieldDefinition, FieldValue, InferProps, SlotDefinition, ComponentCapabilities, ComponentDefinition, ComponentSpec, SurfaceSpec, ThemeDefinition, SettingsGroup, InferSettings, ThemeSettingsIssue, ThemeSettingsIssueCode, ThemeSettingsResult, ColorFieldDefinition, MenuFieldDefinition, CollectionFieldDefinition, ThemeManifest, ThemeManifestIssue, ThemeManifestIssueCode, ThemeManifestResult, ComponentInstance, PageData, ThemeRenderContext, LoadContext, LoadFn, ReadCache, PageDataIssue, PageDataIssueCode, PageDataResult, ResolvedInstance, ThemeDefinitionIssue, ThemeDefinitionIssueCode, ThemeValidationOptions, } from "./types.js";
|
package/dist/instances.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* default applies last).
|
|
10
10
|
*/
|
|
11
11
|
import { localize } from "./locales.js";
|
|
12
|
-
import { COLOR_PATTERN, MENU_HANDLE_PATTERN, isLocaleMap, isSafeLinkTarget } from "./schemas.js";
|
|
12
|
+
import { COLLECTION_HANDLE_PATTERN, COLOR_PATTERN, MENU_HANDLE_PATTERN, isLocaleMap, isSafeLinkTarget } from "./schemas.js";
|
|
13
13
|
/** Field kinds whose values may differ per language. Numbers, toggles and choices are shared. */
|
|
14
14
|
const TRANSLATABLE_KINDS = new Set(["text", "textarea", "url"]);
|
|
15
15
|
const isTranslatable = (field) => TRANSLATABLE_KINDS.has(field.kind);
|
|
@@ -211,6 +211,10 @@ function checkFieldValue(field, value) {
|
|
|
211
211
|
return typeof value === "string" && MENU_HANDLE_PATTERN.test(value)
|
|
212
212
|
? { ok: true, value }
|
|
213
213
|
: { ok: false, message: "must be a menu handle" };
|
|
214
|
+
case "collection":
|
|
215
|
+
return typeof value === "string" && COLLECTION_HANDLE_PATTERN.test(value)
|
|
216
|
+
? { ok: true, value }
|
|
217
|
+
: { ok: false, message: "must be a collection handle" };
|
|
214
218
|
case "select":
|
|
215
219
|
return typeof value === "string" && field.options.includes(value)
|
|
216
220
|
? { ok: true, value }
|
package/dist/manifest.d.ts
CHANGED
|
@@ -92,6 +92,13 @@ export declare const ThemeManifestSchema: z.ZodObject<{
|
|
|
92
92
|
required: z.ZodExactOptional<z.ZodBoolean>;
|
|
93
93
|
kind: z.ZodLiteral<"menu">;
|
|
94
94
|
default: z.ZodExactOptional<z.ZodString>;
|
|
95
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
96
|
+
key: z.ZodString;
|
|
97
|
+
label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
98
|
+
description: z.ZodExactOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
99
|
+
required: z.ZodExactOptional<z.ZodBoolean>;
|
|
100
|
+
kind: z.ZodLiteral<"collection">;
|
|
101
|
+
default: z.ZodExactOptional<z.ZodString>;
|
|
95
102
|
}, z.core.$strip>], "kind">>;
|
|
96
103
|
}, z.core.$strip>>>;
|
|
97
104
|
components: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -159,6 +166,13 @@ export declare const ThemeManifestSchema: z.ZodObject<{
|
|
|
159
166
|
required: z.ZodExactOptional<z.ZodBoolean>;
|
|
160
167
|
kind: z.ZodLiteral<"menu">;
|
|
161
168
|
default: z.ZodExactOptional<z.ZodString>;
|
|
169
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
170
|
+
key: z.ZodString;
|
|
171
|
+
label: z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>;
|
|
172
|
+
description: z.ZodExactOptional<z.ZodUnion<readonly [z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
|
|
173
|
+
required: z.ZodExactOptional<z.ZodBoolean>;
|
|
174
|
+
kind: z.ZodLiteral<"collection">;
|
|
175
|
+
default: z.ZodExactOptional<z.ZodString>;
|
|
162
176
|
}, z.core.$strip>], "kind">>>;
|
|
163
177
|
slots: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
164
178
|
name: z.ZodString;
|
package/dist/manifest.js
CHANGED
|
@@ -103,6 +103,11 @@ const FieldSchema = z.discriminatedUnion("kind", [
|
|
|
103
103
|
kind: z.literal("menu"),
|
|
104
104
|
default: z.exactOptional(z.string()),
|
|
105
105
|
}),
|
|
106
|
+
z.object({
|
|
107
|
+
...FieldCommonSchema,
|
|
108
|
+
kind: z.literal("collection"),
|
|
109
|
+
default: z.exactOptional(z.string()),
|
|
110
|
+
}),
|
|
106
111
|
]);
|
|
107
112
|
const ComponentSpecSchema = z.object({
|
|
108
113
|
type: z.string(),
|
package/dist/schemas.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ export declare const COLOR_PATTERN: RegExp;
|
|
|
29
29
|
* handles; a menu that does not exist reads as no menu.
|
|
30
30
|
*/
|
|
31
31
|
export declare const MENU_HANDLE_PATTERN: RegExp;
|
|
32
|
+
export declare const COLLECTION_HANDLE_PATTERN: RegExp;
|
|
32
33
|
export declare function isLocaleTag(value: string): boolean;
|
|
33
34
|
/**
|
|
34
35
|
* Whether `value` is a per-language map (`{ ar: "…", fr: "…" }`): a plain
|
package/dist/schemas.js
CHANGED
|
@@ -28,6 +28,7 @@ export const COLOR_PATTERN = /^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
|
|
|
28
28
|
* handles; a menu that does not exist reads as no menu.
|
|
29
29
|
*/
|
|
30
30
|
export const MENU_HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
31
|
+
export const COLLECTION_HANDLE_PATTERN = /^[a-z0-9][a-z0-9-]{0,63}$/;
|
|
31
32
|
/**
|
|
32
33
|
* A BCP 47 language tag in canonical case: a 2–3 letter language, an optional
|
|
33
34
|
* 4-letter script, an optional 2-letter or 3-digit region (`ar`, `zgh`,
|
package/dist/types.d.ts
CHANGED
|
@@ -36,8 +36,8 @@ export interface ResolutionScope {
|
|
|
36
36
|
content?: Record<string, string>;
|
|
37
37
|
locales?: readonly LocaleCode[];
|
|
38
38
|
}
|
|
39
|
-
/** The field kinds. `color` and `
|
|
40
|
-
export type FieldKind = "text" | "textarea" | "number" | "boolean" | "select" | "url" | "color" | "menu";
|
|
39
|
+
/** The field kinds. `color`, `menu` and `collection` were added after V1, additively. */
|
|
40
|
+
export type FieldKind = "text" | "textarea" | "number" | "boolean" | "select" | "url" | "color" | "menu" | "collection";
|
|
41
41
|
interface FieldDefinitionBase {
|
|
42
42
|
/** The exact prop name the component expects. */
|
|
43
43
|
key: string;
|
|
@@ -112,7 +112,18 @@ export interface MenuFieldDefinition extends FieldDefinitionBase {
|
|
|
112
112
|
kind: "menu";
|
|
113
113
|
default?: string;
|
|
114
114
|
}
|
|
115
|
-
|
|
115
|
+
/**
|
|
116
|
+
* `collection`: which of the store's collections to show here — Shopify's
|
|
117
|
+
* `collection` setting. The value is a collection handle (`best-sellers`); the
|
|
118
|
+
* theme lists its products with the storefront client's
|
|
119
|
+
* `products.list({ collection })`, in the merchant's order. An unknown handle
|
|
120
|
+
* lists nothing.
|
|
121
|
+
*/
|
|
122
|
+
export interface CollectionFieldDefinition extends FieldDefinitionBase {
|
|
123
|
+
kind: "collection";
|
|
124
|
+
default?: string;
|
|
125
|
+
}
|
|
126
|
+
export type FieldDefinition = TextFieldDefinition | NumberFieldDefinition | BooleanFieldDefinition | SelectFieldDefinition | UrlFieldDefinition | ColorFieldDefinition | MenuFieldDefinition | CollectionFieldDefinition;
|
|
116
127
|
/**
|
|
117
128
|
* One composition point a component declares (`"default"` = children).
|
|
118
129
|
*
|
package/package.json
CHANGED