@colixsystems/widget-sdk 0.164.0 → 0.165.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 +6 -2
- package/dist/linter.cjs +13 -6
- package/dist/linter.js +13 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -73,7 +73,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
|
|
|
73
73
|
|
|
74
74
|
## Status
|
|
75
75
|
|
|
76
|
-
`v0.
|
|
76
|
+
`v0.165.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**.
|
|
77
|
+
|
|
78
|
+
### What's new in 0.165.0 (contract 1.127.0 — unchanged)
|
|
79
|
+
|
|
80
|
+
**`no-hardcoded-design` flags a literal corner radius.** A radius is the app's shape: `theme.radii`, Theme Settings and the SDK's `Card` / `Button` / `ListRow` / `Tabs` all carry it, so a `borderRadius: 12` pinned in a widget is exactly where two widgets in one app stop matching. The rule now warns on a literal non-zero radius on any corner spelling; read it from `theme.radii.*` or a style field, or draw the surface with the SDK component. A computed radius (`size / 2` for a circle) and `0` are not flagged, and `// appstudio-design-ok: <reason>` licenses a genuine exception. Still a warning for a human author; like every linter finding it blocks the AI widget agent's publish, which is how generated widgets are held to it.
|
|
77
81
|
|
|
78
82
|
### What's new in 0.164.0 (contract 1.127.0)
|
|
79
83
|
|
|
@@ -827,7 +831,7 @@ Additive — one new hook, one new optional context-slice member; no existing ex
|
|
|
827
831
|
|
|
828
832
|
**Two linter rules make the styling contract checkable, and `lintStyleWiring` joins the linter export (sc-6455).** Every visual value a widget writes reaches the app's owner through one of exactly two channels — a **theme token** (`useTheme()`), which is the app-wide default and follows a look change, or a **`styleSchema` field** read off `props.style`, which the Studio offers per instance in the widget editor *and* app-wide under **Design → Widget appearance**. A literal reaches neither: it outranks the theme permanently and no control on either surface can move it, so the owner finds a corner of their app they cannot restyle. Until now that rule was documentation only.
|
|
829
833
|
|
|
830
|
-
- **`no-hardcoded-design`** flags a colour literal (`#rgb` / `#rrggbb` / `#rrggbbaa`, `rgb()`, `rgba()`, `hsl()`, `hsla()`), a `fontFamily` string literal,
|
|
834
|
+
- **`no-hardcoded-design`** flags a colour literal (`#rgb` / `#rrggbb` / `#rrggbbaa`, `rgb()`, `rgba()`, `hsl()`, `hsla()`), a `fontFamily` string literal, a numeric `fontSize`, or (since 0.165.0) a literal non-zero corner radius (`borderRadius: 12`, any per-corner spelling). A `fontSize` resolved off a theme token or a style field (`style.valueSize ?? 18`) is *not* flagged — a literal `default` beside a declared field is the contract working — and neither is a computed radius (`size / 2`) or `0`. Raw `padding` / `margin` numbers are deliberately out of scope: measured layout legitimately carries them, so a spacing rule would be noise.
|
|
831
835
|
- **`style-field-unread`** flags a `styleSchema` field whose name appears nowhere in the widget's source — a dead control the author moves to no effect. It runs over the WHOLE bundle, not per file, so a split-impl widget that reads a field in `widget.web.jsx` and not in `widget.native.jsx` is correctly counted as wired.
|
|
832
836
|
|
|
833
837
|
A value that genuinely cannot be a token — a categorical series palette, a video letterbox, a scannable QR plate — is licensed with a preceding comment. **The reason is mandatory**; a bare marker licenses nothing. A marker on its own line covers the whole statement below it (bracket-balanced, so one marker covers a multi-line palette); a trailing marker covers only its own line.
|
package/dist/linter.cjs
CHANGED
|
@@ -1337,16 +1337,20 @@ function narrowManifestForFile(manifest, filename) {
|
|
|
1337
1337
|
// colour or font pinned in the source outranks BOTH permanently, so neither
|
|
1338
1338
|
// the workspace theme nor Design -> Widget appearance can ever reach it.
|
|
1339
1339
|
//
|
|
1340
|
-
// Deliberately narrow: colour literals, a `fontFamily` string,
|
|
1341
|
-
//
|
|
1342
|
-
// —
|
|
1343
|
-
//
|
|
1344
|
-
//
|
|
1340
|
+
// Deliberately narrow: colour literals, a `fontFamily` string, a bare numeric
|
|
1341
|
+
// `fontSize`, and a literal non-zero corner radius. A radius is the app's
|
|
1342
|
+
// shape — `theme.radii`, Theme Settings, the SDK components all carry it — so
|
|
1343
|
+
// a pinned one is the mismatch between two widgets. Raw padding/margin numbers
|
|
1344
|
+
// are NOT flagged: measured layout legitimately carries them (a `flexBasis`
|
|
1345
|
+
// cell width the designer skill itself teaches), and a computed radius
|
|
1346
|
+
// (`size / 2`, a circle) is geometry, not a look.
|
|
1345
1347
|
const _DESIGN_HEX_RE =
|
|
1346
1348
|
/#(?:[0-9a-fA-F]{8}|[0-9a-fA-F]{6}|[0-9a-fA-F]{3,4})(?![0-9a-fA-F])/;
|
|
1347
1349
|
const _DESIGN_FUNC_COLOR_RE = /\b(?:rgba?|hsla?)\s*\(/;
|
|
1348
1350
|
const _DESIGN_FONT_FAMILY_RE = /\bfontFamily\s*:\s*["'`]\s*\S/;
|
|
1349
1351
|
const _DESIGN_FONT_SIZE_RE = /\bfontSize\s*:\s*-?\d/;
|
|
1352
|
+
const _DESIGN_RADIUS_RE =
|
|
1353
|
+
/\bborder(?:Top|Bottom|Start|End)?(?:Left|Right|Start|End)?Radius\s*:\s*(?:0*[1-9]\d*(?:\.\d+)?|0\.\d*[1-9]\d*)\s*(?=[,}]|$)/;
|
|
1350
1354
|
// A line that already reads the theme or the author's style object is
|
|
1351
1355
|
// resolving a DECLARED fallback, not pinning a look — `style.valueSize ?? 18`
|
|
1352
1356
|
// is exactly what a styleSchema `default` is for. Colour literals are held to
|
|
@@ -1411,6 +1415,8 @@ function _hardcodedDesignRules(source) {
|
|
|
1411
1415
|
!_DESIGN_TOKEN_REF_RE.test(line)
|
|
1412
1416
|
) {
|
|
1413
1417
|
what = "a pixel font size";
|
|
1418
|
+
} else if (_DESIGN_RADIUS_RE.test(line)) {
|
|
1419
|
+
what = "a pixel corner radius";
|
|
1414
1420
|
}
|
|
1415
1421
|
if (!what) continue;
|
|
1416
1422
|
findings.push({
|
|
@@ -1419,7 +1425,8 @@ function _hardcodedDesignRules(source) {
|
|
|
1419
1425
|
label:
|
|
1420
1426
|
`${what} pinned in the source is beyond the reach of BOTH the ` +
|
|
1421
1427
|
`workspace theme and the author's Style controls. Read it from ` +
|
|
1422
|
-
`useTheme() (theme.colors.* / theme.typography.*),
|
|
1428
|
+
`useTheme() (theme.colors.* / theme.typography.* / theme.radii.*), ` +
|
|
1429
|
+
`use the SDK's <Card> / <Button> / <ListRow>, or declare a ` +
|
|
1423
1430
|
`styleSchema field and apply props.style.<field>. License a value ` +
|
|
1424
1431
|
`that truly cannot be a token — a series palette, a video ` +
|
|
1425
1432
|
`letterbox, a QR plate — with a preceding ` +
|
package/dist/linter.js
CHANGED
|
@@ -1408,16 +1408,20 @@ export function narrowManifestForFile(manifest, filename) {
|
|
|
1408
1408
|
// colour or font pinned in the source outranks BOTH permanently, so neither
|
|
1409
1409
|
// the workspace theme nor Design -> Widget appearance can ever reach it.
|
|
1410
1410
|
//
|
|
1411
|
-
// Deliberately narrow: colour literals, a `fontFamily` string,
|
|
1412
|
-
//
|
|
1413
|
-
// —
|
|
1414
|
-
//
|
|
1415
|
-
//
|
|
1411
|
+
// Deliberately narrow: colour literals, a `fontFamily` string, a bare numeric
|
|
1412
|
+
// `fontSize`, and a literal non-zero corner radius. A radius is the app's
|
|
1413
|
+
// shape — `theme.radii`, Theme Settings, the SDK components all carry it — so
|
|
1414
|
+
// a pinned one is the mismatch between two widgets. Raw padding/margin numbers
|
|
1415
|
+
// are NOT flagged: measured layout legitimately carries them (a `flexBasis`
|
|
1416
|
+
// cell width the designer skill itself teaches), and a computed radius
|
|
1417
|
+
// (`size / 2`, a circle) is geometry, not a look.
|
|
1416
1418
|
const _DESIGN_HEX_RE =
|
|
1417
1419
|
/#(?:[0-9a-fA-F]{8}|[0-9a-fA-F]{6}|[0-9a-fA-F]{3,4})(?![0-9a-fA-F])/;
|
|
1418
1420
|
const _DESIGN_FUNC_COLOR_RE = /\b(?:rgba?|hsla?)\s*\(/;
|
|
1419
1421
|
const _DESIGN_FONT_FAMILY_RE = /\bfontFamily\s*:\s*["'`]\s*\S/;
|
|
1420
1422
|
const _DESIGN_FONT_SIZE_RE = /\bfontSize\s*:\s*-?\d/;
|
|
1423
|
+
const _DESIGN_RADIUS_RE =
|
|
1424
|
+
/\bborder(?:Top|Bottom|Start|End)?(?:Left|Right|Start|End)?Radius\s*:\s*(?:0*[1-9]\d*(?:\.\d+)?|0\.\d*[1-9]\d*)\s*(?=[,}]|$)/;
|
|
1421
1425
|
// A line that already reads the theme or the author's style object is
|
|
1422
1426
|
// resolving a DECLARED fallback, not pinning a look — `style.valueSize ?? 18`
|
|
1423
1427
|
// is exactly what a styleSchema `default` is for. Colour literals are held to
|
|
@@ -1482,6 +1486,8 @@ function _hardcodedDesignRules(source) {
|
|
|
1482
1486
|
!_DESIGN_TOKEN_REF_RE.test(line)
|
|
1483
1487
|
) {
|
|
1484
1488
|
what = "a pixel font size";
|
|
1489
|
+
} else if (_DESIGN_RADIUS_RE.test(line)) {
|
|
1490
|
+
what = "a pixel corner radius";
|
|
1485
1491
|
}
|
|
1486
1492
|
if (!what) continue;
|
|
1487
1493
|
findings.push({
|
|
@@ -1490,7 +1496,8 @@ function _hardcodedDesignRules(source) {
|
|
|
1490
1496
|
label:
|
|
1491
1497
|
`${what} pinned in the source is beyond the reach of BOTH the ` +
|
|
1492
1498
|
`workspace theme and the author's Style controls. Read it from ` +
|
|
1493
|
-
`useTheme() (theme.colors.* / theme.typography.*),
|
|
1499
|
+
`useTheme() (theme.colors.* / theme.typography.* / theme.radii.*), ` +
|
|
1500
|
+
`use the SDK's <Card> / <Button> / <ListRow>, or declare a ` +
|
|
1494
1501
|
`styleSchema field and apply props.style.<field>. License a value ` +
|
|
1495
1502
|
`that truly cannot be a token — a series palette, a video ` +
|
|
1496
1503
|
`letterbox, a QR plate — with a preceding ` +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.165.0",
|
|
4
4
|
"description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
|
|
5
5
|
"homepage": "https://github.com/Colix-AB/AppStudio",
|
|
6
6
|
"type": "module",
|