@colixsystems/widget-sdk 0.157.0 → 0.158.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
@@ -119,7 +119,7 @@ Behaviour: a bare date given to a `mode="datetime"` picker now shows local midni
119
119
 
120
120
  **The app header's row is arrangeable, and `./host` publishes the resolver both hosts read (sc-8023).** The row runs across the top of the content outside the side panel, and is drawn three times — as the phone header where the panel is a drawer, as the desktop strip, and as the full-width bar when one is switched on. Each surface hard-coded its own copy of it, so an author could colour the row but never move anything in it.
121
121
 
122
- - **`resolveTopStripeLayout(theme)`** reads `theme.sidebar.stripe` and returns the arrangement fully resolved: `slots` (already filtered and sequenced, so no host re-derives it), `order`, the box (`height`, `paddingX`, `contentOffsetY`), the resolved `backgroundColor` (joined in 0.155.0 by `tintColor` and `titleColor`), and `menuSide` — which edge the drawer must arrive from, since the brand grows and a burger ordered after it sits at the trailing edge. The web Player picks the drawer's side with it; the export makes it `drawerPosition`.
122
+ - **`resolveTopStripeLayout(theme)`** reads `theme.sidebar.stripe` and returns the arrangement fully resolved: `slots` (already filtered and sequenced, so no host re-derives it), `order`, the box (`height`, `paddingX`, `contentOffsetY`, and `barHeight` — the height once the nudge is held, since pushing the contents down grows the bar rather than letting them fall out of it), the resolved `backgroundColor` (joined in 0.155.0 by `tintColor` and `titleColor`), and `menuSide` — which edge the drawer must arrive from, since the brand grows and a burger ordered after it sits at the trailing edge. The web Player picks the drawer's side with it; the export makes it `drawerPosition`.
123
123
  - **`TOP_STRIPE_SLOTS`** is the vocabulary (`back`, `menu`, `brand`, `notifications`) and **`TOP_STRIPE_ALWAYS_SHOWN_SLOTS`** the slots that move but never hide. The burger is the only member: it is drawn only where the panel is a drawer, and there it is the sole route into the menu, so hiding it would strand the visitor. It keeps its place in `order` regardless.
124
124
  - **`topStripeShowKey(slot)`** derives the `theme_config` key that shows or hides one slot, in one place, so a control, the write path and the resolver cannot spell it differently.
125
125
  - **The bounds travel with the resolver** — `MIN`/`MAX_TOP_STRIPE_HEIGHT_PX`, `MIN`/`MAX_TOP_STRIPE_PADDING_X_PX`, `MAX_TOP_STRIPE_OFFSET_Y_PX` — so a control offers exactly the range the resolver clamps to. `DEFAULT_TOP_STRIPE_HEIGHT_PX` / `DEFAULT_TOP_STRIPE_PADDING_X_PX` are what the DESKTOP row measures with nothing stored, published so a control can show the number an author is departing from; the resolver still answers `null`, because each surface keeps its own box until one is named.
package/dist/host.d.ts CHANGED
@@ -332,8 +332,12 @@ export interface TopStripeLayout {
332
332
  * bar's 64px, the phone header's content-sized row. */
333
333
  height: number | null;
334
334
  paddingX: number | null;
335
- /** How far the row is pushed down, 0-60px. */
335
+ /** How far the row's contents are pushed down, 0-60px. */
336
336
  contentOffsetY: number;
337
+ /** The bar's total height once the nudge is held — its box plus
338
+ * `contentOffsetY`, so contents never fall out of the bottom. Null only
339
+ * while both are unset, where each surface keeps its own box. */
340
+ barHeight: number | null;
337
341
  /** Every slot in the author's sequence, hidden ones included. */
338
342
  order: TopStripeSlot[];
339
343
  /** What the bar actually SHOWS, already filtered and sequenced. A surface
@@ -405,6 +405,7 @@ function topStripeOrder(value) {
405
405
  * @param {unknown} theme — the whole `theme_config`.
406
406
  * @returns {{ backgroundColor: string, tintColor: string, titleColor: string,
407
407
  * height: number|null, paddingX: number|null, contentOffsetY: number,
408
+ * barHeight: number|null,
408
409
  * order: string[], slots: string[], menuSide: "start"|"end" }}
409
410
  */
410
411
  function resolveTopStripeLayout(theme) {
@@ -422,30 +423,40 @@ function resolveTopStripeLayout(theme) {
422
423
  : TOP_STRIPE_SLOT_SHOWN_BY_DEFAULT[slot];
423
424
  };
424
425
  const slots = order.filter(shown);
426
+ // Unset defers to each surface's own box — the desktop bar's fixed 64px, the
427
+ // phone header's content-sized row.
428
+ const height = topStripeClampedOr(
429
+ stripe.height,
430
+ MIN_TOP_STRIPE_HEIGHT_PX,
431
+ MAX_TOP_STRIPE_HEIGHT_PX,
432
+ null,
433
+ );
434
+ const contentOffsetY = topStripeClampedOr(
435
+ stripe.contentOffsetY,
436
+ 0,
437
+ MAX_TOP_STRIPE_OFFSET_Y_PX,
438
+ 0,
439
+ );
425
440
  return {
426
441
  // There is no alignment to resolve: the brand slot GROWS, so the row has no
427
442
  // free space for `justify-content` to distribute and every value looked
428
443
  // identical. The row spreads because the brand takes the slack.
429
- // Unset defers to each surface's own box — the desktop bar's fixed 64px,
430
- // the phone header's content-sized row.
431
- height: topStripeClampedOr(
432
- stripe.height,
433
- MIN_TOP_STRIPE_HEIGHT_PX,
434
- MAX_TOP_STRIPE_HEIGHT_PX,
435
- null,
436
- ),
444
+ height,
437
445
  paddingX: topStripeClampedOr(
438
446
  stripe.paddingX,
439
447
  MIN_TOP_STRIPE_PADDING_X_PX,
440
448
  MAX_TOP_STRIPE_PADDING_X_PX,
441
449
  null,
442
450
  ),
443
- contentOffsetY: topStripeClampedOr(
444
- stripe.contentOffsetY,
445
- 0,
446
- MAX_TOP_STRIPE_OFFSET_Y_PX,
447
- 0,
448
- ),
451
+ contentOffsetY,
452
+ // sc-8552: the bar GROWS by the nudge rather than letting its contents fall
453
+ // out of the bottom — the box the author sized, plus what they pushed into
454
+ // it. For a surface that must state a height (the desktop bar, the native
455
+ // header); the phone row is content-sized and grows on its padding alone.
456
+ barHeight:
457
+ height === null && contentOffsetY === 0
458
+ ? null
459
+ : (height ?? DEFAULT_TOP_STRIPE_HEIGHT_PX) + contentOffsetY,
449
460
  // sc-8023: the stripe's OWN surface, inheriting the app-header colour when
450
461
  // unset — so an untouched app is unmoved, and an author who dresses a
451
462
  // page's top navigation bar no longer repaints the stripe above the panel by
@@ -396,6 +396,7 @@ function topStripeOrder(value) {
396
396
  * @param {unknown} theme — the whole `theme_config`.
397
397
  * @returns {{ backgroundColor: string, tintColor: string, titleColor: string,
398
398
  * height: number|null, paddingX: number|null, contentOffsetY: number,
399
+ * barHeight: number|null,
399
400
  * order: string[], slots: string[], menuSide: "start"|"end" }}
400
401
  */
401
402
  export function resolveTopStripeLayout(theme) {
@@ -413,30 +414,40 @@ export function resolveTopStripeLayout(theme) {
413
414
  : TOP_STRIPE_SLOT_SHOWN_BY_DEFAULT[slot];
414
415
  };
415
416
  const slots = order.filter(shown);
417
+ // Unset defers to each surface's own box — the desktop bar's fixed 64px, the
418
+ // phone header's content-sized row.
419
+ const height = topStripeClampedOr(
420
+ stripe.height,
421
+ MIN_TOP_STRIPE_HEIGHT_PX,
422
+ MAX_TOP_STRIPE_HEIGHT_PX,
423
+ null,
424
+ );
425
+ const contentOffsetY = topStripeClampedOr(
426
+ stripe.contentOffsetY,
427
+ 0,
428
+ MAX_TOP_STRIPE_OFFSET_Y_PX,
429
+ 0,
430
+ );
416
431
  return {
417
432
  // There is no alignment to resolve: the brand slot GROWS, so the row has no
418
433
  // free space for `justify-content` to distribute and every value looked
419
434
  // identical. The row spreads because the brand takes the slack.
420
- // Unset defers to each surface's own box — the desktop bar's fixed 64px,
421
- // the phone header's content-sized row.
422
- height: topStripeClampedOr(
423
- stripe.height,
424
- MIN_TOP_STRIPE_HEIGHT_PX,
425
- MAX_TOP_STRIPE_HEIGHT_PX,
426
- null,
427
- ),
435
+ height,
428
436
  paddingX: topStripeClampedOr(
429
437
  stripe.paddingX,
430
438
  MIN_TOP_STRIPE_PADDING_X_PX,
431
439
  MAX_TOP_STRIPE_PADDING_X_PX,
432
440
  null,
433
441
  ),
434
- contentOffsetY: topStripeClampedOr(
435
- stripe.contentOffsetY,
436
- 0,
437
- MAX_TOP_STRIPE_OFFSET_Y_PX,
438
- 0,
439
- ),
442
+ contentOffsetY,
443
+ // sc-8552: the bar GROWS by the nudge rather than letting its contents fall
444
+ // out of the bottom — the box the author sized, plus what they pushed into
445
+ // it. For a surface that must state a height (the desktop bar, the native
446
+ // header); the phone row is content-sized and grows on its padding alone.
447
+ barHeight:
448
+ height === null && contentOffsetY === 0
449
+ ? null
450
+ : (height ?? DEFAULT_TOP_STRIPE_HEIGHT_PX) + contentOffsetY,
440
451
  // sc-8023: the stripe's OWN surface, inheriting the app-header colour when
441
452
  // unset — so an untouched app is unmoved, and an author who dresses a
442
453
  // page's top navigation bar no longer repaints the stripe above the panel by
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colixsystems/widget-sdk",
3
- "version": "0.157.0",
3
+ "version": "0.158.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",