@colixsystems/widget-sdk 0.232.0 → 0.233.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 CHANGED
@@ -84,7 +84,11 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
84
84
 
85
85
  ## Status
86
86
 
87
- `v0.232.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**.
87
+ `v0.233.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**.
88
+
89
+ ### What's new in 0.233.0 (contract 1.188.0)
90
+
91
+ **A floating bottom navigation bar is frosted glass by default (host side only).** `resolveFooterTokens` from `@colixsystems/widget-sdk/host` now also resolves `glass`, true for a floating bar unless the theme's `footer.glass` is `false` (a docked bar is never frosted, as nothing scrolls behind it), and `glassTint`, the 8-digit hex surface laid over the blur: the bar's `backgroundColor` at 72%, or its own alpha when it already has one. Nothing a widget imports changes.
88
92
 
89
93
  ### What's new in 0.232.0 (contract 1.187.0)
90
94
 
package/dist/contract.cjs CHANGED
@@ -6044,7 +6044,9 @@ const CONTRACT = deepFreeze({
6044
6044
  // bar's `shape` (unset floats), `radius`, `itemRadius`, `sideMargin` and
6045
6045
  // `bottomSpacing`; host exports `FOOTER_SIZES`, `clampFooterSize` and
6046
6046
  // `FOOTER_HOME_LINE_CLEARANCE_PX`. No widget-facing surface changes.
6047
- version: "1.187.0",
6047
+ // 1.188.0: additive (sc-11692) — `resolveFooterTokens` gains `glass` (a
6048
+ // floating bar is frosted unless `footer.glass` is false) and `glassTint`.
6049
+ version: "1.188.0",
6048
6050
  sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
6049
6051
  hooks: HOOKS,
6050
6052
  primitives: PRIMITIVES,
package/dist/contract.js CHANGED
@@ -6040,7 +6040,9 @@ const CONTRACT = deepFreeze({
6040
6040
  // bar's `shape` (unset floats), `radius`, `itemRadius`, `sideMargin` and
6041
6041
  // `bottomSpacing`; host exports `FOOTER_SIZES`, `clampFooterSize` and
6042
6042
  // `FOOTER_HOME_LINE_CLEARANCE_PX`. No widget-facing surface changes.
6043
- version: "1.187.0",
6043
+ // 1.188.0: additive (sc-11692) — `resolveFooterTokens` gains `glass` (a
6044
+ // floating bar is frosted unless `footer.glass` is false) and `glassTint`.
6045
+ version: "1.188.0",
6044
6046
  sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
6045
6047
  hooks: HOOKS,
6046
6048
  primitives: PRIMITIVES,
package/dist/host.d.ts CHANGED
@@ -265,6 +265,11 @@ export interface FooterTokens {
265
265
  /** The active tab's surface, or `null` for none — which is what "accent"
266
266
  * resolves to unless the author names one. */
267
267
  activeSurface: string | null;
268
+ /** sc-11692: a floating bar's frosted glass, on unless `glass: false`. */
269
+ glass: boolean;
270
+ /** The see-through surface laid over the blur (8-digit hex), or `null`
271
+ * when the bar is not frosted. */
272
+ glassTint: string | null;
268
273
  /** sc-11678: a rounded bar inset from the screen's sides, the page showing
269
274
  * around and beneath it, or the edge-to-edge strip. Unset is "floating". */
270
275
  shape: "floating" | "docked";
@@ -86,7 +86,8 @@ function menuItemCap(menuType) {
86
86
  // The authorable keys are the controls the Design panel offers, one for one:
87
87
  // `backgroundColor`, `textColor`, `tabActiveBackgroundColor`,
88
88
  // `tabActiveTextColor`, `borderColor`, `borderWidth`, `activeStyle`,
89
- // `tabLayout`, and (sc-11678) `shape`, `radius`, `sideMargin`, `bottomSpacing`.
89
+ // `tabLayout`, (sc-11678) `shape`, `radius`, `sideMargin`, `bottomSpacing`
90
+ // and (sc-11692) `glass`.
90
91
  function resolveFooterTokens(theme) {
91
92
  const config = isPlainObject(theme) ? theme : {};
92
93
  const footer = isPlainObject(config.footer) ? config.footer : {};
@@ -105,8 +106,15 @@ function resolveFooterTokens(theme) {
105
106
  const divider = borderWidth > 0;
106
107
  const floats = footer.shape !== "docked";
107
108
  const radius = footerSizeOr(footer, "radius");
109
+ const backgroundColor = hexOr(footer.backgroundColor, DEFAULT_FOOTER_SURFACE);
110
+ // sc-11692: frosted unless switched off; only a floating bar has a page
111
+ // behind it to frost.
112
+ const glass = floats && footer.glass !== false;
108
113
  return {
109
- backgroundColor: hexOr(footer.backgroundColor, DEFAULT_FOOTER_SURFACE),
114
+ backgroundColor,
115
+ glass,
116
+ // The surface over the blur: the bar's colour, see-through.
117
+ glassTint: glass ? translucentHex(backgroundColor) : null,
110
118
  textColor: hexOr(footer.textColor, DEFAULT_CHROME_TEXT),
111
119
  borderColor: divider ? borderColor : null,
112
120
  borderWidth: divider ? borderWidth : null,
@@ -151,6 +159,16 @@ const FOOTER_SIZES = Object.freeze({
151
159
  bottomSpacing: Object.freeze({ max: 32, fallback: 8 }),
152
160
  });
153
161
  const DOCKED_TAB_RADIUS = 6;
162
+
163
+ // sc-11692: a colour that already carries its own alpha keeps it; an opaque
164
+ // one is laid over the blur at 72%.
165
+ const GLASS_TINT_ALPHA = "b8";
166
+ function translucentHex(hex) {
167
+ const digits = hex.slice(1);
168
+ if (digits.length === 8) return hex;
169
+ const six = digits.length === 3 ? digits.replace(/./g, (d) => d + d) : digits;
170
+ return `#${six}${GLASS_TINT_ALPHA}`;
171
+ }
154
172
  function clampFooterSize(value, key) {
155
173
  if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
156
174
  return Math.min(Math.max(Math.round(value), 0), FOOTER_SIZES[key].max);
@@ -77,7 +77,8 @@ export function menuItemCap(menuType) {
77
77
  // The authorable keys are the controls the Design panel offers, one for one:
78
78
  // `backgroundColor`, `textColor`, `tabActiveBackgroundColor`,
79
79
  // `tabActiveTextColor`, `borderColor`, `borderWidth`, `activeStyle`,
80
- // `tabLayout`, and (sc-11678) `shape`, `radius`, `sideMargin`, `bottomSpacing`.
80
+ // `tabLayout`, (sc-11678) `shape`, `radius`, `sideMargin`, `bottomSpacing`
81
+ // and (sc-11692) `glass`.
81
82
  export function resolveFooterTokens(theme) {
82
83
  const config = isPlainObject(theme) ? theme : {};
83
84
  const footer = isPlainObject(config.footer) ? config.footer : {};
@@ -96,8 +97,15 @@ export function resolveFooterTokens(theme) {
96
97
  const divider = borderWidth > 0;
97
98
  const floats = footer.shape !== "docked";
98
99
  const radius = footerSizeOr(footer, "radius");
100
+ const backgroundColor = hexOr(footer.backgroundColor, DEFAULT_FOOTER_SURFACE);
101
+ // sc-11692: frosted unless switched off; only a floating bar has a page
102
+ // behind it to frost.
103
+ const glass = floats && footer.glass !== false;
99
104
  return {
100
- backgroundColor: hexOr(footer.backgroundColor, DEFAULT_FOOTER_SURFACE),
105
+ backgroundColor,
106
+ glass,
107
+ // The surface over the blur: the bar's colour, see-through.
108
+ glassTint: glass ? translucentHex(backgroundColor) : null,
101
109
  textColor: hexOr(footer.textColor, DEFAULT_CHROME_TEXT),
102
110
  borderColor: divider ? borderColor : null,
103
111
  borderWidth: divider ? borderWidth : null,
@@ -142,6 +150,16 @@ export const FOOTER_SIZES = Object.freeze({
142
150
  bottomSpacing: Object.freeze({ max: 32, fallback: 8 }),
143
151
  });
144
152
  const DOCKED_TAB_RADIUS = 6;
153
+
154
+ // sc-11692: a colour that already carries its own alpha keeps it; an opaque
155
+ // one is laid over the blur at 72%.
156
+ const GLASS_TINT_ALPHA = "b8";
157
+ function translucentHex(hex) {
158
+ const digits = hex.slice(1);
159
+ if (digits.length === 8) return hex;
160
+ const six = digits.length === 3 ? digits.replace(/./g, (d) => d + d) : digits;
161
+ return `#${six}${GLASS_TINT_ALPHA}`;
162
+ }
145
163
  export function clampFooterSize(value, key) {
146
164
  if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
147
165
  return Math.min(Math.max(Math.round(value), 0), FOOTER_SIZES[key].max);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colixsystems/widget-sdk",
3
- "version": "0.232.0",
3
+ "version": "0.233.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",
package/src/contract.js CHANGED
@@ -6040,7 +6040,9 @@ const CONTRACT = deepFreeze({
6040
6040
  // bar's `shape` (unset floats), `radius`, `itemRadius`, `sideMargin` and
6041
6041
  // `bottomSpacing`; host exports `FOOTER_SIZES`, `clampFooterSize` and
6042
6042
  // `FOOTER_HOME_LINE_CLEARANCE_PX`. No widget-facing surface changes.
6043
- version: "1.187.0",
6043
+ // 1.188.0: additive (sc-11692) — `resolveFooterTokens` gains `glass` (a
6044
+ // floating bar is frosted unless `footer.glass` is false) and `glassTint`.
6045
+ version: "1.188.0",
6044
6046
  sharedTranslationKeys: SHARED_TRANSLATION_KEYS,
6045
6047
  hooks: HOOKS,
6046
6048
  primitives: PRIMITIVES,