@colixsystems/widget-sdk 0.167.0 → 0.168.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 +1 -1
- package/dist/contract.cjs +3 -3
- package/dist/contract.js +3 -3
- package/dist/host.js +5 -0
- package/dist/navigation.cjs +59 -1
- package/dist/navigation.js +58 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,7 +93,7 @@ Render an **assistant** message with `<RichText value={m.content} stripLegacyHtm
|
|
|
93
93
|
A binding may now carry an opacity: `"theme:colors.primary/20"` is the primary brand colour at 20%.
|
|
94
94
|
|
|
95
95
|
- **`parseThemeColorTokenRef(value)` / `formatThemeColorTokenRef(path, percent)`** publish the grammar beside the existing `isThemeColorTokenRef` predicate. The BARE form inherits whatever opacity the token itself carries — a workspace may author a translucent brand colour — so `/100` is a real value, not a redundant spelling: it is how "opaque, whatever the brand does" is said. One opacity has one spelling otherwise (no leading zeros, nothing above 100).
|
|
96
|
-
- **`withHexAlpha(hex, percent)` / `hexAlphaPercent(hex)`** are the percent ↔ alpha-byte conversion the Studio's
|
|
96
|
+
- **`withHexAlpha(hex, percent)` / `hexAlphaPercent(hex)`** are the percent ↔ alpha-byte conversion, so the 20% a panel reads back is the 20% a render paints. The Studio's `frontend/src/utils/color.js` keeps its own copy of this maths rather than importing it — that module is reached by a `node --test` suite, and the SDK is a Vite alias with no node resolution — and the two are pinned equal by the SDK's suite.
|
|
97
97
|
- **An authored opacity replaces the token's.** With none authored the token is handed back verbatim, including a token that is itself translucent — reading the bare form as 100 would quietly paint a see-through brand colour solid.
|
|
98
98
|
- **A token resolving to a non-hex colour stays opaque** — alpha cannot be applied without rewriting the author's notation — and the Studio disables the opacity control for that case rather than lying about it.
|
|
99
99
|
- **Nothing changes for a widget author.** The host still hands your code an ordinary colour string; it is simply `#RRGGBBAA` when an opacity was authored.
|
package/dist/contract.cjs
CHANGED
|
@@ -4539,10 +4539,10 @@ const CONTRACT = deepFreeze({
|
|
|
4539
4539
|
// field bound, so "our brand colour at 20%" forced the author back to a
|
|
4540
4540
|
// frozen hex, which then stopped following a rebrand — the exact thing
|
|
4541
4541
|
// binding exists to prevent. `parseThemeColorTokenRef` /
|
|
4542
|
-
// `formatThemeColorTokenRef` publish the grammar and
|
|
4542
|
+
// `formatThemeColorTokenRef` publish the grammar, and
|
|
4543
4543
|
// `withHexAlpha` / `hexAlphaPercent` the percent-to-byte conversion the
|
|
4544
|
-
// Studio's control and both hosts' resolver
|
|
4545
|
-
// painted. The BARE form inherits the token's own opacity (a brand colour
|
|
4544
|
+
// Studio's control and both hosts' resolver answer alike, so 20% authored
|
|
4545
|
+
// is 20% painted. The BARE form inherits the token's own opacity (a brand colour
|
|
4546
4546
|
// may be authored translucent), which makes `/100` a real value rather
|
|
4547
4547
|
// than a redundant spelling: it is how "opaque, whatever the brand does"
|
|
4548
4548
|
// is said. Additive: an unsuffixed binding parses and resolves exactly as
|
package/dist/contract.js
CHANGED
|
@@ -4535,10 +4535,10 @@ const CONTRACT = deepFreeze({
|
|
|
4535
4535
|
// field bound, so "our brand colour at 20%" forced the author back to a
|
|
4536
4536
|
// frozen hex, which then stopped following a rebrand — the exact thing
|
|
4537
4537
|
// binding exists to prevent. `parseThemeColorTokenRef` /
|
|
4538
|
-
// `formatThemeColorTokenRef` publish the grammar and
|
|
4538
|
+
// `formatThemeColorTokenRef` publish the grammar, and
|
|
4539
4539
|
// `withHexAlpha` / `hexAlphaPercent` the percent-to-byte conversion the
|
|
4540
|
-
// Studio's control and both hosts' resolver
|
|
4541
|
-
// painted. The BARE form inherits the token's own opacity (a brand colour
|
|
4540
|
+
// Studio's control and both hosts' resolver answer alike, so 20% authored
|
|
4541
|
+
// is 20% painted. The BARE form inherits the token's own opacity (a brand colour
|
|
4542
4542
|
// may be authored translucent), which makes `/100` a real value rather
|
|
4543
4543
|
// than a redundant spelling: it is how "opaque, whatever the brand does"
|
|
4544
4544
|
// is said. Additive: an unsuffixed binding parses and resolves exactly as
|
package/dist/host.js
CHANGED
|
@@ -74,6 +74,9 @@ export {
|
|
|
74
74
|
// SIDEBAR local menu hangs in the rail and the drawer. The compiler asks it
|
|
75
75
|
// once per screen at build time and the Player once per render, so the two
|
|
76
76
|
// chromes derive the same tree from the same code.
|
|
77
|
+
// REQ-NAV-LOCAL (sc-8901): `resolveLocalNavModel` answers WHICH model a page
|
|
78
|
+
// wears in one device view, so the same menu can be a bottom bar on a phone and
|
|
79
|
+
// unfold in the rail on a desktop.
|
|
77
80
|
export {
|
|
78
81
|
normaliseNavigation,
|
|
79
82
|
menuItemCap,
|
|
@@ -94,6 +97,8 @@ export {
|
|
|
94
97
|
DEFAULT_TOP_STRIPE_HEIGHT_PX,
|
|
95
98
|
DEFAULT_TOP_STRIPE_PADDING_X_PX,
|
|
96
99
|
resolveSidebarUnfold,
|
|
100
|
+
resolveLocalNavModel,
|
|
101
|
+
drawsLocalNavAnywhere,
|
|
97
102
|
} from "./navigation.js";
|
|
98
103
|
|
|
99
104
|
// sc-5717: the codec behind `useWidgetRoute()` — how a widget's own internal
|
package/dist/navigation.cjs
CHANGED
|
@@ -675,6 +675,64 @@ function resolveSidebarUnfold(input) {
|
|
|
675
675
|
return { under: section.key, items: marked, standalone: true };
|
|
676
676
|
}
|
|
677
677
|
|
|
678
|
+
/**
|
|
679
|
+
* REQ-NAV-LOCAL (sc-8901) — which local-navigation model a page wears in ONE
|
|
680
|
+
* device view, so the same saved menu can be a bottom bar on a phone and unfold
|
|
681
|
+
* in the rail on a desktop.
|
|
682
|
+
*
|
|
683
|
+
* `local_nav` is the MOBILE value and the base of the cascade: a page authored
|
|
684
|
+
* before the wider views existed leaves both of them unset and therefore
|
|
685
|
+
* renders identically at every width. The cascade is REQ-LAY-07's — the one the
|
|
686
|
+
* layout grid and every responsive widget prop already use — because a page's
|
|
687
|
+
* chrome and its content must not disagree about what a tablet is.
|
|
688
|
+
*
|
|
689
|
+
* The vocabulary stays the API's: any non-empty string is a model and the
|
|
690
|
+
* host's own switch decides what it can draw, so a kind a newer backend allows
|
|
691
|
+
* cascades correctly here instead of being flattened to `NONE` on the way.
|
|
692
|
+
*
|
|
693
|
+
* @param {object|null|undefined} page — a page row carrying `local_nav` and,
|
|
694
|
+
* optionally, `local_nav_tablet` / `local_nav_desktop`.
|
|
695
|
+
* @param {"mobile"|"tablet"|"desktop"} view — the device view being drawn.
|
|
696
|
+
* @returns {string} the model for that view; `NONE` when the page sets none.
|
|
697
|
+
*/
|
|
698
|
+
function resolveLocalNavModel(page, view) {
|
|
699
|
+
const at = (key) => {
|
|
700
|
+
const value = isPlainObject(page) ? page[key] : null;
|
|
701
|
+
return typeof value === "string" && value ? value : null;
|
|
702
|
+
};
|
|
703
|
+
const mobile = at("local_nav") || "NONE";
|
|
704
|
+
if (view === "desktop") {
|
|
705
|
+
return at("local_nav_desktop") || at("local_nav_tablet") || mobile;
|
|
706
|
+
}
|
|
707
|
+
if (view === "tablet") return at("local_nav_tablet") || mobile;
|
|
708
|
+
return mobile;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// sc-8901: the three device views a local bar can differ across — REQ-LAY-07's
|
|
712
|
+
// own list, so a page's chrome and its content classify a width alike. Ordered
|
|
713
|
+
// narrowest first, which is also the cascade's direction.
|
|
714
|
+
const LOCAL_NAV_VIEWS = ["mobile", "tablet", "desktop"];
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* REQ-NAV-LOCAL (sc-8901) — does this page draw a local bar in ANY device view?
|
|
718
|
+
*
|
|
719
|
+
* The saved-menu reference is shared by all three views, so it is required — and
|
|
720
|
+
* resolved onto the wire — as soon as one of them draws. Asking
|
|
721
|
+
* `local_nav !== "NONE"` alone would miss a page that carries a bar only on the
|
|
722
|
+
* wider views.
|
|
723
|
+
*
|
|
724
|
+
* Beside the cascade it is derived from, so the API rule, the export's screen
|
|
725
|
+
* bake and Copy Workspace cannot disagree about which pages have a bar.
|
|
726
|
+
*
|
|
727
|
+
* @param {object|null|undefined} page — a page row.
|
|
728
|
+
* @returns {boolean}
|
|
729
|
+
*/
|
|
730
|
+
function drawsLocalNavAnywhere(page) {
|
|
731
|
+
return LOCAL_NAV_VIEWS.some(
|
|
732
|
+
(view) => resolveLocalNavModel(page, view) !== "NONE",
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
|
|
678
736
|
// REQ-THEME-LOOK: the divider's width in px, bounded HERE so both hosts inherit
|
|
679
737
|
// one range. The export clamped it on its way into the StyleSheet
|
|
680
738
|
// (`coerceBorderWidth(...) ?? 1`) where the Player passed any finite number
|
|
@@ -711,4 +769,4 @@ function borderWidthOr(...values) {
|
|
|
711
769
|
return BORDER_WIDTH_MIN;
|
|
712
770
|
}
|
|
713
771
|
|
|
714
|
-
module.exports = { normaliseNavigation, menuItemCap, resolveFooterTokens, resolveSidebarTokens, resolveTopStripeLayout, resolveTopBarTokens, topStripeShowKey, TOP_STRIPE_ALWAYS_SHOWN_SLOTS, TOP_STRIPE_SLOTS, MIN_TOP_STRIPE_HEIGHT_PX, MAX_TOP_STRIPE_HEIGHT_PX, MIN_TOP_STRIPE_PADDING_X_PX, MAX_TOP_STRIPE_PADDING_X_PX, MAX_TOP_STRIPE_OFFSET_Y_PX, DEFAULT_TOP_STRIPE_HEIGHT_PX, DEFAULT_TOP_STRIPE_PADDING_X_PX, resolveSidebarUnfold };
|
|
772
|
+
module.exports = { normaliseNavigation, menuItemCap, resolveFooterTokens, resolveSidebarTokens, resolveTopStripeLayout, resolveTopBarTokens, topStripeShowKey, TOP_STRIPE_ALWAYS_SHOWN_SLOTS, TOP_STRIPE_SLOTS, MIN_TOP_STRIPE_HEIGHT_PX, MAX_TOP_STRIPE_HEIGHT_PX, MIN_TOP_STRIPE_PADDING_X_PX, MAX_TOP_STRIPE_PADDING_X_PX, MAX_TOP_STRIPE_OFFSET_Y_PX, DEFAULT_TOP_STRIPE_HEIGHT_PX, DEFAULT_TOP_STRIPE_PADDING_X_PX, resolveSidebarUnfold, resolveLocalNavModel, drawsLocalNavAnywhere };
|
package/dist/navigation.js
CHANGED
|
@@ -666,6 +666,64 @@ export function resolveSidebarUnfold(input) {
|
|
|
666
666
|
return { under: section.key, items: marked, standalone: true };
|
|
667
667
|
}
|
|
668
668
|
|
|
669
|
+
/**
|
|
670
|
+
* REQ-NAV-LOCAL (sc-8901) — which local-navigation model a page wears in ONE
|
|
671
|
+
* device view, so the same saved menu can be a bottom bar on a phone and unfold
|
|
672
|
+
* in the rail on a desktop.
|
|
673
|
+
*
|
|
674
|
+
* `local_nav` is the MOBILE value and the base of the cascade: a page authored
|
|
675
|
+
* before the wider views existed leaves both of them unset and therefore
|
|
676
|
+
* renders identically at every width. The cascade is REQ-LAY-07's — the one the
|
|
677
|
+
* layout grid and every responsive widget prop already use — because a page's
|
|
678
|
+
* chrome and its content must not disagree about what a tablet is.
|
|
679
|
+
*
|
|
680
|
+
* The vocabulary stays the API's: any non-empty string is a model and the
|
|
681
|
+
* host's own switch decides what it can draw, so a kind a newer backend allows
|
|
682
|
+
* cascades correctly here instead of being flattened to `NONE` on the way.
|
|
683
|
+
*
|
|
684
|
+
* @param {object|null|undefined} page — a page row carrying `local_nav` and,
|
|
685
|
+
* optionally, `local_nav_tablet` / `local_nav_desktop`.
|
|
686
|
+
* @param {"mobile"|"tablet"|"desktop"} view — the device view being drawn.
|
|
687
|
+
* @returns {string} the model for that view; `NONE` when the page sets none.
|
|
688
|
+
*/
|
|
689
|
+
export function resolveLocalNavModel(page, view) {
|
|
690
|
+
const at = (key) => {
|
|
691
|
+
const value = isPlainObject(page) ? page[key] : null;
|
|
692
|
+
return typeof value === "string" && value ? value : null;
|
|
693
|
+
};
|
|
694
|
+
const mobile = at("local_nav") || "NONE";
|
|
695
|
+
if (view === "desktop") {
|
|
696
|
+
return at("local_nav_desktop") || at("local_nav_tablet") || mobile;
|
|
697
|
+
}
|
|
698
|
+
if (view === "tablet") return at("local_nav_tablet") || mobile;
|
|
699
|
+
return mobile;
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// sc-8901: the three device views a local bar can differ across — REQ-LAY-07's
|
|
703
|
+
// own list, so a page's chrome and its content classify a width alike. Ordered
|
|
704
|
+
// narrowest first, which is also the cascade's direction.
|
|
705
|
+
const LOCAL_NAV_VIEWS = ["mobile", "tablet", "desktop"];
|
|
706
|
+
|
|
707
|
+
/**
|
|
708
|
+
* REQ-NAV-LOCAL (sc-8901) — does this page draw a local bar in ANY device view?
|
|
709
|
+
*
|
|
710
|
+
* The saved-menu reference is shared by all three views, so it is required — and
|
|
711
|
+
* resolved onto the wire — as soon as one of them draws. Asking
|
|
712
|
+
* `local_nav !== "NONE"` alone would miss a page that carries a bar only on the
|
|
713
|
+
* wider views.
|
|
714
|
+
*
|
|
715
|
+
* Beside the cascade it is derived from, so the API rule, the export's screen
|
|
716
|
+
* bake and Copy Workspace cannot disagree about which pages have a bar.
|
|
717
|
+
*
|
|
718
|
+
* @param {object|null|undefined} page — a page row.
|
|
719
|
+
* @returns {boolean}
|
|
720
|
+
*/
|
|
721
|
+
export function drawsLocalNavAnywhere(page) {
|
|
722
|
+
return LOCAL_NAV_VIEWS.some(
|
|
723
|
+
(view) => resolveLocalNavModel(page, view) !== "NONE",
|
|
724
|
+
);
|
|
725
|
+
}
|
|
726
|
+
|
|
669
727
|
// REQ-THEME-LOOK: the divider's width in px, bounded HERE so both hosts inherit
|
|
670
728
|
// one range. The export clamped it on its way into the StyleSheet
|
|
671
729
|
// (`coerceBorderWidth(...) ?? 1`) where the Player passed any finite number
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@colixsystems/widget-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.168.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",
|