@numueg/theme-sdk 0.2.2 → 0.3.1
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 +29 -1
- package/README.md +8 -8
- package/dist/{entities-iiuRSPpk.d.mts → entities-6MGANln7.d.mts} +64 -1
- package/dist/{entities-iiuRSPpk.d.ts → entities-6MGANln7.d.ts} +64 -1
- package/dist/index.cjs +227 -66
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +221 -45
- package/dist/index.d.ts +221 -45
- package/dist/index.mjs +222 -68
- package/dist/index.mjs.map +1 -1
- package/dist/types.d.mts +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/v2-compat.d.mts +1 -1
- package/dist/v2-compat.d.ts +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -4,7 +4,35 @@ All notable changes to `@numueg/theme-sdk` are documented here. The format is ba
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
-
## [0.1
|
|
7
|
+
## [0.3.1] - 2026-06-17
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Size charts** — `useProductSizeChart()` hook + `resolveSizeChart()` pure
|
|
12
|
+
resolver. Resolves the per-product chart (`product.attributes.size_chart`)
|
|
13
|
+
against the store-wide default (`store.settings.size_chart`) using the same
|
|
14
|
+
precedence as the merchant hub + backend validator (`mode`:
|
|
15
|
+
`custom` → `default` → `off`, with a legacy no-mode fallback). New types
|
|
16
|
+
`SizeChart` / `SizeChartMode`.
|
|
17
|
+
- `Product.attributes` and `Store.settings` are now typed (optional
|
|
18
|
+
`Record<string, unknown>`) — the storefront already forwards these JSONB
|
|
19
|
+
blobs (also used by `useFieldTranslation`); they were previously untyped.
|
|
20
|
+
|
|
21
|
+
## [0.3.0] - 2026-06-10
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- **`defineThemeEntry`** — one-call theme entry that returns both `mount`
|
|
26
|
+
(client, hydration-aware via `hydrateRoot`) and `createApp` (server
|
|
27
|
+
`renderToString`), wiring `NuMuProvider` + page/product/collection context +
|
|
28
|
+
catalog forwarding + global style tokens + the customizer's live-preview
|
|
29
|
+
draft cycle. This is the SSR contract for federated themes.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- `mount()` adopts host-server-rendered HTML instead of re-rendering when the
|
|
34
|
+
host passes `hydrate: true`; pure, browser-free global-style-token compute so
|
|
35
|
+
the server render is deterministic.
|
|
8
36
|
|
|
9
37
|
First public release. Full surface documented at [numueg.app/docs/sdk/overview](https://numueg.app/docs/sdk/overview).
|
|
10
38
|
|
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://www.npmjs.com/package/@numueg/theme-sdk)
|
|
6
6
|
[](./LICENSE)
|
|
7
7
|
|
|
8
|
-
The SDK every NUMU theme consumes.
|
|
8
|
+
The SDK every NUMU theme consumes. The `mountTheme()` runtime helper, 27+ hooks (`useCart`, `useProduct`, `useCheckout`, `useVariantSelection`, `useCurrentTemplate`, `useResolvedSettings`, …), 15+ components (`AddToCartButton`, `ProductCard`, `Money`, `Section`, `EditableText`/`EditableImage`, `NuMuProvider`, …), and helpers for variant resolution, focal image crops (`focalSrc`), global style tokens, asset URLs, and federation singletons.
|
|
9
9
|
|
|
10
10
|
Themes import via the bare specifier `@numueg/theme-sdk` — at runtime the storefront's import map resolves it to the host-loaded singleton so every theme on the platform shares one React identity.
|
|
11
11
|
|
|
@@ -31,23 +31,23 @@ The `@numueg/theme-plugin` Vite plugin does this for you automatically.
|
|
|
31
31
|
|
|
32
32
|
## Usage
|
|
33
33
|
|
|
34
|
+
The host storefront calls your bundle's `mount(el, ctx)` where `ctx = { storeData, page, themeSettings, locale, … }`. Use `mountTheme()` — it wires catalog data, global style tokens, navigation, and live-edit updates for you and returns the `{ unmount, update }` contract the host expects:
|
|
35
|
+
|
|
34
36
|
```tsx
|
|
35
|
-
import {
|
|
36
|
-
import { NuMuProvider, useCart, AddToCartButton } from "@numueg/theme-sdk";
|
|
37
|
-
import type { MountContext } from "@numueg/theme-sdk";
|
|
37
|
+
import { mountTheme, useCart } from "@numueg/theme-sdk";
|
|
38
38
|
|
|
39
39
|
function App() {
|
|
40
40
|
const { cart } = useCart();
|
|
41
41
|
return <p>Items in cart: {cart.item_count}</p>;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
export function mount(ctx:
|
|
45
|
-
|
|
46
|
-
root.render(<NuMuProvider {...ctx}><App /></NuMuProvider>);
|
|
47
|
-
return () => root.unmount();
|
|
44
|
+
export function mount(el: HTMLElement, ctx: unknown) {
|
|
45
|
+
return mountTheme(el, ctx, () => <App />);
|
|
48
46
|
}
|
|
49
47
|
```
|
|
50
48
|
|
|
49
|
+
> The authoritative `ctx` shape is defined by the host's `ByotThemeBoundary` (numu-storefront), not by SDK types — accept it as opaque and let `mountTheme`/`NuMuProvider` normalize it.
|
|
50
|
+
|
|
51
51
|
## Docs
|
|
52
52
|
|
|
53
53
|
- [SDK Overview](https://numueg.app/docs/sdk/overview)
|
|
@@ -11,6 +11,14 @@ interface Store {
|
|
|
11
11
|
default_language: string;
|
|
12
12
|
use_nextjs_storefront: boolean;
|
|
13
13
|
social_links?: Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Store-level JSONB settings blob. Holds merchant-wide configuration the
|
|
16
|
+
* storefront forwards to themes — e.g. the store-wide default
|
|
17
|
+
* `size_chart` (see {@link SizeChart}) used when a product opts into
|
|
18
|
+
* `mode: "default"`. Untyped here because the shape grows independently
|
|
19
|
+
* of the SDK; narrow it at the read site.
|
|
20
|
+
*/
|
|
21
|
+
settings?: Record<string, unknown>;
|
|
14
22
|
}
|
|
15
23
|
/** Product entity */
|
|
16
24
|
interface Product {
|
|
@@ -30,6 +38,42 @@ interface Product {
|
|
|
30
38
|
in_stock: boolean;
|
|
31
39
|
seo_title?: string;
|
|
32
40
|
seo_description?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Per-product JSONB attribute blob the storefront forwards verbatim.
|
|
43
|
+
* Holds translated fields (`name_ar`, … — see `useFieldTranslation`) and
|
|
44
|
+
* the per-product `size_chart` ({@link SizeChart}). Untyped because the
|
|
45
|
+
* shape is open-ended; `useProductSizeChart` narrows the size-chart slot.
|
|
46
|
+
*/
|
|
47
|
+
attributes?: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Size-chart resolution mode (mirrors the merchant hub's editor).
|
|
51
|
+
*
|
|
52
|
+
* "custom" → use the product's own chart
|
|
53
|
+
* "default" → fall back to the store-wide chart (`store.settings.size_chart`)
|
|
54
|
+
* "off" → never show, even if a store default exists
|
|
55
|
+
*/
|
|
56
|
+
type SizeChartMode = "default" | "custom" | "off";
|
|
57
|
+
/**
|
|
58
|
+
* A size / measurement chart, stored per-product at
|
|
59
|
+
* `product.attributes.size_chart` and store-wide at
|
|
60
|
+
* `store.settings.size_chart`. Resolve the two with {@link useProductSizeChart}
|
|
61
|
+
* instead of reading the raw blobs.
|
|
62
|
+
*/
|
|
63
|
+
interface SizeChart {
|
|
64
|
+
/** Legacy boolean kept for charts written before `mode` existed. */
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
mode?: SizeChartMode;
|
|
67
|
+
/** Column labels, e.g. ["Chest", "Waist", "Hip"]. */
|
|
68
|
+
column_headers: string[];
|
|
69
|
+
/** One row per size; `values` aligns to `column_headers`. */
|
|
70
|
+
rows: Array<{
|
|
71
|
+
size: string;
|
|
72
|
+
values: string[];
|
|
73
|
+
}>;
|
|
74
|
+
unit?: "cm" | "in" | "kg";
|
|
75
|
+
notes?: string;
|
|
76
|
+
image_url?: string;
|
|
33
77
|
}
|
|
34
78
|
interface ProductImage {
|
|
35
79
|
id: string;
|
|
@@ -138,6 +182,25 @@ interface Order {
|
|
|
138
182
|
items: OrderItem[];
|
|
139
183
|
created_at: string;
|
|
140
184
|
shipping_address?: Address;
|
|
185
|
+
/**
|
|
186
|
+
* Discount code the customer applied at checkout, if any. Sourced from
|
|
187
|
+
* the backend order-detail (`GET /storefront/me/orders/{id}`). Themes
|
|
188
|
+
* render this on the order-confirmation / order-detail page.
|
|
189
|
+
*/
|
|
190
|
+
coupon_code?: string | null;
|
|
191
|
+
/**
|
|
192
|
+
* Automatic offers (offers-v2 promotions) applied to the order. Each
|
|
193
|
+
* entry carries the localized title and the discount it contributed.
|
|
194
|
+
* `amount` is in integer cents — divide by 100 (or pass through
|
|
195
|
+
* `<Money>`) before display, consistent with the rest of the order's
|
|
196
|
+
* money fields.
|
|
197
|
+
*/
|
|
198
|
+
applied_promotions?: {
|
|
199
|
+
id: string;
|
|
200
|
+
title: string;
|
|
201
|
+
title_ar?: string;
|
|
202
|
+
amount: number;
|
|
203
|
+
}[];
|
|
141
204
|
}
|
|
142
205
|
interface OrderItem {
|
|
143
206
|
product_id: string;
|
|
@@ -162,4 +225,4 @@ interface Page {
|
|
|
162
225
|
data?: Record<string, any>;
|
|
163
226
|
}
|
|
164
227
|
|
|
165
|
-
export type { Address as A, Cart as C, Order as O, Page as P,
|
|
228
|
+
export type { Address as A, Cart as C, Order as O, Page as P, SizeChart as S, CartItem as a, Collection as b, Customer as c, OrderItem as d, Product as e, ProductImage as f, ProductVariant as g, SizeChartMode as h, Store as i, ProductOption as j };
|
|
@@ -11,6 +11,14 @@ interface Store {
|
|
|
11
11
|
default_language: string;
|
|
12
12
|
use_nextjs_storefront: boolean;
|
|
13
13
|
social_links?: Record<string, string>;
|
|
14
|
+
/**
|
|
15
|
+
* Store-level JSONB settings blob. Holds merchant-wide configuration the
|
|
16
|
+
* storefront forwards to themes — e.g. the store-wide default
|
|
17
|
+
* `size_chart` (see {@link SizeChart}) used when a product opts into
|
|
18
|
+
* `mode: "default"`. Untyped here because the shape grows independently
|
|
19
|
+
* of the SDK; narrow it at the read site.
|
|
20
|
+
*/
|
|
21
|
+
settings?: Record<string, unknown>;
|
|
14
22
|
}
|
|
15
23
|
/** Product entity */
|
|
16
24
|
interface Product {
|
|
@@ -30,6 +38,42 @@ interface Product {
|
|
|
30
38
|
in_stock: boolean;
|
|
31
39
|
seo_title?: string;
|
|
32
40
|
seo_description?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Per-product JSONB attribute blob the storefront forwards verbatim.
|
|
43
|
+
* Holds translated fields (`name_ar`, … — see `useFieldTranslation`) and
|
|
44
|
+
* the per-product `size_chart` ({@link SizeChart}). Untyped because the
|
|
45
|
+
* shape is open-ended; `useProductSizeChart` narrows the size-chart slot.
|
|
46
|
+
*/
|
|
47
|
+
attributes?: Record<string, unknown>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Size-chart resolution mode (mirrors the merchant hub's editor).
|
|
51
|
+
*
|
|
52
|
+
* "custom" → use the product's own chart
|
|
53
|
+
* "default" → fall back to the store-wide chart (`store.settings.size_chart`)
|
|
54
|
+
* "off" → never show, even if a store default exists
|
|
55
|
+
*/
|
|
56
|
+
type SizeChartMode = "default" | "custom" | "off";
|
|
57
|
+
/**
|
|
58
|
+
* A size / measurement chart, stored per-product at
|
|
59
|
+
* `product.attributes.size_chart` and store-wide at
|
|
60
|
+
* `store.settings.size_chart`. Resolve the two with {@link useProductSizeChart}
|
|
61
|
+
* instead of reading the raw blobs.
|
|
62
|
+
*/
|
|
63
|
+
interface SizeChart {
|
|
64
|
+
/** Legacy boolean kept for charts written before `mode` existed. */
|
|
65
|
+
enabled?: boolean;
|
|
66
|
+
mode?: SizeChartMode;
|
|
67
|
+
/** Column labels, e.g. ["Chest", "Waist", "Hip"]. */
|
|
68
|
+
column_headers: string[];
|
|
69
|
+
/** One row per size; `values` aligns to `column_headers`. */
|
|
70
|
+
rows: Array<{
|
|
71
|
+
size: string;
|
|
72
|
+
values: string[];
|
|
73
|
+
}>;
|
|
74
|
+
unit?: "cm" | "in" | "kg";
|
|
75
|
+
notes?: string;
|
|
76
|
+
image_url?: string;
|
|
33
77
|
}
|
|
34
78
|
interface ProductImage {
|
|
35
79
|
id: string;
|
|
@@ -138,6 +182,25 @@ interface Order {
|
|
|
138
182
|
items: OrderItem[];
|
|
139
183
|
created_at: string;
|
|
140
184
|
shipping_address?: Address;
|
|
185
|
+
/**
|
|
186
|
+
* Discount code the customer applied at checkout, if any. Sourced from
|
|
187
|
+
* the backend order-detail (`GET /storefront/me/orders/{id}`). Themes
|
|
188
|
+
* render this on the order-confirmation / order-detail page.
|
|
189
|
+
*/
|
|
190
|
+
coupon_code?: string | null;
|
|
191
|
+
/**
|
|
192
|
+
* Automatic offers (offers-v2 promotions) applied to the order. Each
|
|
193
|
+
* entry carries the localized title and the discount it contributed.
|
|
194
|
+
* `amount` is in integer cents — divide by 100 (or pass through
|
|
195
|
+
* `<Money>`) before display, consistent with the rest of the order's
|
|
196
|
+
* money fields.
|
|
197
|
+
*/
|
|
198
|
+
applied_promotions?: {
|
|
199
|
+
id: string;
|
|
200
|
+
title: string;
|
|
201
|
+
title_ar?: string;
|
|
202
|
+
amount: number;
|
|
203
|
+
}[];
|
|
141
204
|
}
|
|
142
205
|
interface OrderItem {
|
|
143
206
|
product_id: string;
|
|
@@ -162,4 +225,4 @@ interface Page {
|
|
|
162
225
|
data?: Record<string, any>;
|
|
163
226
|
}
|
|
164
227
|
|
|
165
|
-
export type { Address as A, Cart as C, Order as O, Page as P,
|
|
228
|
+
export type { Address as A, Cart as C, Order as O, Page as P, SizeChart as S, CartItem as a, Collection as b, Customer as c, OrderItem as d, Product as e, ProductImage as f, ProductVariant as g, SizeChartMode as h, Store as i, ProductOption as j };
|