@colixsystems/widget-sdk 0.70.0 → 0.71.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 +13 -1
- package/dist/contract.cjs +38 -7
- package/dist/contract.js +38 -7
- package/dist/theme-components.cjs +13 -0
- package/dist/theme-components.js +13 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,7 +54,19 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
54
54
|
|
|
55
55
|
## Status
|
|
56
56
|
|
|
57
|
-
`v0.
|
|
57
|
+
`v0.71.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
|
|
58
|
+
|
|
59
|
+
### What's new in 0.71.0
|
|
60
|
+
|
|
61
|
+
**A theme can set leading, tracking and case for text app-wide (sc-3857).** The `text` scope of `themeConfig.components` gains three tokens beside `color` and `fontSize`:
|
|
62
|
+
|
|
63
|
+
- **`lineHeight`** — leading as a MULTIPLE of the font size (0.8–3), so one app-wide value stays right at every size. Tight leading (1.0–1.15) is what makes a 32px+ headline read as a headline rather than as oversized body text.
|
|
64
|
+
- **`letterSpacing`** — tracking in pixels (−2 to 20). Wide positive tracking is what makes a small uppercase kicker read as a kicker.
|
|
65
|
+
- **`textTransform`** — `none` | `uppercase` | `capitalize`, published as `CONTRACT.themeComponentTextTransforms`.
|
|
66
|
+
|
|
67
|
+
Two new token value types back them: **`decimal`** (a clamped, 2-decimal number — `size` rounds, so it cannot carry a 1.05 multiplier) and **`textTransform`**. Each token binds to the identically named per-instance style field the target widgets read, so the author rule is unchanged: read `props.style` / `useWidgetStyle()`, and a per-instance value still wins over the app-wide token.
|
|
68
|
+
|
|
69
|
+
`CONTRACT.version` → `1.48.0`. Additive: no existing export changed signature, and a theme with none of the new tokens renders exactly as before.
|
|
58
70
|
|
|
59
71
|
### What's new in 0.70.0
|
|
60
72
|
|
package/dist/contract.cjs
CHANGED
|
@@ -107,6 +107,14 @@ const DEFAULT_THEME_TOKENS = Object.freeze({
|
|
|
107
107
|
// cannot drift between what Mason may emit and what a host actually applies.
|
|
108
108
|
const THEME_COMPONENT_SHADOWS = Object.freeze(["none", "sm", "md", "lg"]);
|
|
109
109
|
|
|
110
|
+
// sc-3857 — the `textTransform` token's closed enum, matching the per-instance
|
|
111
|
+
// Text/Label/Data Value style field and React Native's own vocabulary.
|
|
112
|
+
const THEME_COMPONENT_TEXT_TRANSFORMS = Object.freeze([
|
|
113
|
+
"none",
|
|
114
|
+
"uppercase",
|
|
115
|
+
"capitalize",
|
|
116
|
+
]);
|
|
117
|
+
|
|
110
118
|
// sc-3727 — the `gradient` token's value shape: two hex stops plus a CSS-degree
|
|
111
119
|
// angle, the same grammar as `themeConfig.backgroundGradient` minus the radial
|
|
112
120
|
// variant (a component fill projects through `<Gradient>`, which is linear-only
|
|
@@ -129,6 +137,16 @@ const CARD_SURFACE_FIELDS = Object.freeze({
|
|
|
129
137
|
gradient: "cardGradient",
|
|
130
138
|
});
|
|
131
139
|
|
|
140
|
+
// The text field names every text-bearing built-in reads
|
|
141
|
+
// (frontend/src/components/widgets/_shared/textStyle.js TYPOGRAPHY_STYLE_FIELDS).
|
|
142
|
+
const TEXT_TYPOGRAPHY_FIELDS = Object.freeze({
|
|
143
|
+
color: "color",
|
|
144
|
+
fontSize: "fontSize",
|
|
145
|
+
lineHeight: "lineHeight",
|
|
146
|
+
letterSpacing: "letterSpacing",
|
|
147
|
+
textTransform: "textTransform",
|
|
148
|
+
});
|
|
149
|
+
|
|
132
150
|
// A form widget's submit button — the `button` scope reaches it through the
|
|
133
151
|
// form's own submit* fields, so "make the buttons coral" does not skip forms.
|
|
134
152
|
const FORM_SUBMIT_FIELDS = Object.freeze({
|
|
@@ -190,14 +208,16 @@ const THEME_COMPONENTS = Object.freeze({
|
|
|
190
208
|
tokens: Object.freeze({
|
|
191
209
|
color: Object.freeze({ type: "color", uiDefault: "colors.onSurface" }),
|
|
192
210
|
fontSize: Object.freeze({ type: "size", min: 8, max: 96, uiDefault: "typography.sizes.md" }),
|
|
211
|
+
// sc-3857 — leading as a MULTIPLE of the font size, so one app-wide value
|
|
212
|
+
// is right at every size; `size` cannot carry it because it rounds.
|
|
213
|
+
lineHeight: Object.freeze({ type: "decimal", min: 0.8, max: 3, step: 0.05 }),
|
|
214
|
+
letterSpacing: Object.freeze({ type: "decimal", min: -2, max: 20, step: 0.1 }),
|
|
215
|
+
textTransform: Object.freeze({ type: "textTransform" }),
|
|
193
216
|
}),
|
|
194
217
|
targets: Object.freeze({
|
|
195
|
-
"appstudio.text":
|
|
196
|
-
"appstudio.label":
|
|
197
|
-
"appstudio.data-value":
|
|
198
|
-
color: "color",
|
|
199
|
-
fontSize: "fontSize",
|
|
200
|
-
}),
|
|
218
|
+
"appstudio.text": TEXT_TYPOGRAPHY_FIELDS,
|
|
219
|
+
"appstudio.label": TEXT_TYPOGRAPHY_FIELDS,
|
|
220
|
+
"appstudio.data-value": TEXT_TYPOGRAPHY_FIELDS,
|
|
201
221
|
}),
|
|
202
222
|
}),
|
|
203
223
|
});
|
|
@@ -2215,7 +2235,17 @@ const CONTRACT = deepFreeze({
|
|
|
2215
2235
|
// null, which is how one button stays flat while the rest are gradiented.
|
|
2216
2236
|
// Additive: no export changed signature and a theme with no gradient token
|
|
2217
2237
|
// renders exactly as before.
|
|
2218
|
-
|
|
2238
|
+
// 1.48.0: additive (sc-3857) — leading, tracking and case on the `text` scope.
|
|
2239
|
+
// `lineHeight` (a MULTIPLE of the font size), `letterSpacing` (pixels) and
|
|
2240
|
+
// `textTransform` join the existing `color` / `fontSize` tokens and bind to
|
|
2241
|
+
// the identically named per-instance style fields Text, Label and Data Value
|
|
2242
|
+
// now read, so a theme can set app-wide typography and an author still
|
|
2243
|
+
// overrides it per instance. Two new token value types back them: `decimal`
|
|
2244
|
+
// (a clamped 2-decimal number — `size` rounds, so it cannot carry a 1.05
|
|
2245
|
+
// multiplier) and `textTransform`, whose closed enum is published as
|
|
2246
|
+
// `themeComponentTextTransforms`. Additive: no export changed signature and
|
|
2247
|
+
// a theme with none of the new tokens renders exactly as before.
|
|
2248
|
+
version: "1.48.0",
|
|
2219
2249
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
2220
2250
|
hooks: HOOKS,
|
|
2221
2251
|
primitives: PRIMITIVES,
|
|
@@ -2228,6 +2258,7 @@ const CONTRACT = deepFreeze({
|
|
|
2228
2258
|
themeTokens: DEFAULT_THEME_TOKENS,
|
|
2229
2259
|
themeComponents: THEME_COMPONENTS,
|
|
2230
2260
|
themeComponentShadows: THEME_COMPONENT_SHADOWS,
|
|
2261
|
+
themeComponentTextTransforms: THEME_COMPONENT_TEXT_TRANSFORMS,
|
|
2231
2262
|
themeComponentGradient: THEME_COMPONENT_GRADIENT,
|
|
2232
2263
|
widgetContextShape: WIDGET_CONTEXT_SHAPE,
|
|
2233
2264
|
bundleExportContract: BUNDLE_EXPORT_CONTRACT,
|
package/dist/contract.js
CHANGED
|
@@ -107,6 +107,14 @@ const DEFAULT_THEME_TOKENS = Object.freeze({
|
|
|
107
107
|
// cannot drift between what Mason may emit and what a host actually applies.
|
|
108
108
|
const THEME_COMPONENT_SHADOWS = Object.freeze(["none", "sm", "md", "lg"]);
|
|
109
109
|
|
|
110
|
+
// sc-3857 — the `textTransform` token's closed enum, matching the per-instance
|
|
111
|
+
// Text/Label/Data Value style field and React Native's own vocabulary.
|
|
112
|
+
const THEME_COMPONENT_TEXT_TRANSFORMS = Object.freeze([
|
|
113
|
+
"none",
|
|
114
|
+
"uppercase",
|
|
115
|
+
"capitalize",
|
|
116
|
+
]);
|
|
117
|
+
|
|
110
118
|
// sc-3727 — the `gradient` token's value shape: two hex stops plus a CSS-degree
|
|
111
119
|
// angle, the same grammar as `themeConfig.backgroundGradient` minus the radial
|
|
112
120
|
// variant (a component fill projects through `<Gradient>`, which is linear-only
|
|
@@ -129,6 +137,16 @@ const CARD_SURFACE_FIELDS = Object.freeze({
|
|
|
129
137
|
gradient: "cardGradient",
|
|
130
138
|
});
|
|
131
139
|
|
|
140
|
+
// The text field names every text-bearing built-in reads
|
|
141
|
+
// (frontend/src/components/widgets/_shared/textStyle.js TYPOGRAPHY_STYLE_FIELDS).
|
|
142
|
+
const TEXT_TYPOGRAPHY_FIELDS = Object.freeze({
|
|
143
|
+
color: "color",
|
|
144
|
+
fontSize: "fontSize",
|
|
145
|
+
lineHeight: "lineHeight",
|
|
146
|
+
letterSpacing: "letterSpacing",
|
|
147
|
+
textTransform: "textTransform",
|
|
148
|
+
});
|
|
149
|
+
|
|
132
150
|
// A form widget's submit button — the `button` scope reaches it through the
|
|
133
151
|
// form's own submit* fields, so "make the buttons coral" does not skip forms.
|
|
134
152
|
const FORM_SUBMIT_FIELDS = Object.freeze({
|
|
@@ -190,14 +208,16 @@ const THEME_COMPONENTS = Object.freeze({
|
|
|
190
208
|
tokens: Object.freeze({
|
|
191
209
|
color: Object.freeze({ type: "color", uiDefault: "colors.onSurface" }),
|
|
192
210
|
fontSize: Object.freeze({ type: "size", min: 8, max: 96, uiDefault: "typography.sizes.md" }),
|
|
211
|
+
// sc-3857 — leading as a MULTIPLE of the font size, so one app-wide value
|
|
212
|
+
// is right at every size; `size` cannot carry it because it rounds.
|
|
213
|
+
lineHeight: Object.freeze({ type: "decimal", min: 0.8, max: 3, step: 0.05 }),
|
|
214
|
+
letterSpacing: Object.freeze({ type: "decimal", min: -2, max: 20, step: 0.1 }),
|
|
215
|
+
textTransform: Object.freeze({ type: "textTransform" }),
|
|
193
216
|
}),
|
|
194
217
|
targets: Object.freeze({
|
|
195
|
-
"appstudio.text":
|
|
196
|
-
"appstudio.label":
|
|
197
|
-
"appstudio.data-value":
|
|
198
|
-
color: "color",
|
|
199
|
-
fontSize: "fontSize",
|
|
200
|
-
}),
|
|
218
|
+
"appstudio.text": TEXT_TYPOGRAPHY_FIELDS,
|
|
219
|
+
"appstudio.label": TEXT_TYPOGRAPHY_FIELDS,
|
|
220
|
+
"appstudio.data-value": TEXT_TYPOGRAPHY_FIELDS,
|
|
201
221
|
}),
|
|
202
222
|
}),
|
|
203
223
|
});
|
|
@@ -2215,7 +2235,17 @@ const CONTRACT = deepFreeze({
|
|
|
2215
2235
|
// null, which is how one button stays flat while the rest are gradiented.
|
|
2216
2236
|
// Additive: no export changed signature and a theme with no gradient token
|
|
2217
2237
|
// renders exactly as before.
|
|
2218
|
-
|
|
2238
|
+
// 1.48.0: additive (sc-3857) — leading, tracking and case on the `text` scope.
|
|
2239
|
+
// `lineHeight` (a MULTIPLE of the font size), `letterSpacing` (pixels) and
|
|
2240
|
+
// `textTransform` join the existing `color` / `fontSize` tokens and bind to
|
|
2241
|
+
// the identically named per-instance style fields Text, Label and Data Value
|
|
2242
|
+
// now read, so a theme can set app-wide typography and an author still
|
|
2243
|
+
// overrides it per instance. Two new token value types back them: `decimal`
|
|
2244
|
+
// (a clamped 2-decimal number — `size` rounds, so it cannot carry a 1.05
|
|
2245
|
+
// multiplier) and `textTransform`, whose closed enum is published as
|
|
2246
|
+
// `themeComponentTextTransforms`. Additive: no export changed signature and
|
|
2247
|
+
// a theme with none of the new tokens renders exactly as before.
|
|
2248
|
+
version: "1.48.0",
|
|
2219
2249
|
sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
|
|
2220
2250
|
hooks: HOOKS,
|
|
2221
2251
|
primitives: PRIMITIVES,
|
|
@@ -2228,6 +2258,7 @@ const CONTRACT = deepFreeze({
|
|
|
2228
2258
|
themeTokens: DEFAULT_THEME_TOKENS,
|
|
2229
2259
|
themeComponents: THEME_COMPONENTS,
|
|
2230
2260
|
themeComponentShadows: THEME_COMPONENT_SHADOWS,
|
|
2261
|
+
themeComponentTextTransforms: THEME_COMPONENT_TEXT_TRANSFORMS,
|
|
2231
2262
|
themeComponentGradient: THEME_COMPONENT_GRADIENT,
|
|
2232
2263
|
widgetContextShape: WIDGET_CONTEXT_SHAPE,
|
|
2233
2264
|
bundleExportContract: BUNDLE_EXPORT_CONTRACT,
|
|
@@ -44,9 +44,22 @@ function coerceToken(def, value) {
|
|
|
44
44
|
if (!Number.isFinite(n)) return undefined;
|
|
45
45
|
return Math.min(def.max, Math.max(def.min, Math.round(n)));
|
|
46
46
|
}
|
|
47
|
+
// sc-3857: a leading multiplier / tracking value must survive the decimals
|
|
48
|
+
// `size` rounds away — 1.05 leading is the whole point of the token.
|
|
49
|
+
if (def.type === "decimal") {
|
|
50
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
51
|
+
if (!Number.isFinite(n)) return undefined;
|
|
52
|
+
const clamped = Math.min(def.max, Math.max(def.min, n));
|
|
53
|
+
return Math.round(clamped * 100) / 100;
|
|
54
|
+
}
|
|
47
55
|
if (def.type === "shadow") {
|
|
48
56
|
return CONTRACT.themeComponentShadows.includes(value) ? value : undefined;
|
|
49
57
|
}
|
|
58
|
+
if (def.type === "textTransform") {
|
|
59
|
+
return CONTRACT.themeComponentTextTransforms.includes(value)
|
|
60
|
+
? value
|
|
61
|
+
: undefined;
|
|
62
|
+
}
|
|
50
63
|
// sc-3727: the gradient value has its own normaliser on the contract, shared
|
|
51
64
|
// with the widget render path so both routes agree (CLAUDE.md §3).
|
|
52
65
|
if (def.type === "gradient") {
|
package/dist/theme-components.js
CHANGED
|
@@ -36,9 +36,22 @@ function coerceToken(def, value) {
|
|
|
36
36
|
if (!Number.isFinite(n)) return undefined;
|
|
37
37
|
return Math.min(def.max, Math.max(def.min, Math.round(n)));
|
|
38
38
|
}
|
|
39
|
+
// sc-3857: a leading multiplier / tracking value must survive the decimals
|
|
40
|
+
// `size` rounds away — 1.05 leading is the whole point of the token.
|
|
41
|
+
if (def.type === "decimal") {
|
|
42
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
43
|
+
if (!Number.isFinite(n)) return undefined;
|
|
44
|
+
const clamped = Math.min(def.max, Math.max(def.min, n));
|
|
45
|
+
return Math.round(clamped * 100) / 100;
|
|
46
|
+
}
|
|
39
47
|
if (def.type === "shadow") {
|
|
40
48
|
return CONTRACT.themeComponentShadows.includes(value) ? value : undefined;
|
|
41
49
|
}
|
|
50
|
+
if (def.type === "textTransform") {
|
|
51
|
+
return CONTRACT.themeComponentTextTransforms.includes(value)
|
|
52
|
+
? value
|
|
53
|
+
: undefined;
|
|
54
|
+
}
|
|
42
55
|
// sc-3727: the gradient value has its own normaliser on the contract, shared
|
|
43
56
|
// with the widget render path so both routes agree (CLAUDE.md §3).
|
|
44
57
|
if (def.type === "gradient") {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.71.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|