@wix/himalaya-cli 0.1460.0 → 0.1462.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.
@@ -101,6 +101,8 @@ export interface NavToScreen {
101
101
  /** How to show it. Absent ⇒ `push`. */
102
102
  presentation?: "push" | "replace" | "sheet" | "full_screen";
103
103
  tab?: never;
104
+ /** Only a {@link NavToTab} resets; without a `tab` it would be ignored as a plain push. */
105
+ reset?: never;
104
106
  }
105
107
  /**
106
108
  * Leave the current screen. `back` pops the current stack. On iOS and Android, inside an
@@ -114,27 +116,57 @@ export interface NavBackOrDismiss {
114
116
  screenId?: never;
115
117
  args?: never;
116
118
  tab?: never;
119
+ reset?: never;
117
120
  }
118
121
  /**
119
122
  * Switch to the top-level destination with this id — a tab-bar item, or a sidebar-rail
120
123
  * item on a wide layout. The host closes any open sheet first. An id the app is not
121
- * showing right now (unknown, or hidden by the nav worker) is ignored, and so is the tab
122
- * the user is already on (their stack is kept — it is not a re-tap). A tab switch is not a
124
+ * showing right now (unknown, or hidden by the nav worker) is ignored — the whole
125
+ * directive, so nothing is pushed anywhere — and a bare `{ tab }` for the tab the user is
126
+ * already on does nothing (their stack is kept — it is not a re-tap). A tab switch is not a
123
127
  * stack operation: a later `back` pops the NEW tab's stack, not the switch.
128
+ *
129
+ * Two optional follow-ups act on THAT tab once it is selected, in this order:
130
+ * - `reset: true` pops the tab's stack to its root — even when it is the tab the user is
131
+ * already on, the one case a worker causes the pop a user's re-tap causes;
132
+ * - `screenId` (with `args`) is then pushed onto the tab's stack — never onto the tab the
133
+ * action ran on. Only push is defined: a `presentation` next to a `tab` is dropped.
134
+ *
135
+ * So `{ tab: "orders", screenId: "order_detail", args: { id } }` switches to Orders and
136
+ * opens the order there; `{ tab: "create", reset: true }` returns to a clean tab root.
137
+ * `args` without a `screenId` has nowhere to go: every host drops it as ambiguous, so the
138
+ * type does not admit it (a union — `args` only next to `screenId`). Binaries older than this
139
+ * form drop `{ tab, screenId }` / `{ tab, reset }` whole; a worker that must support them
140
+ * can return `{ tab }` and push on the next action.
124
141
  */
125
- export interface NavToTab {
142
+ export type NavToTab = {
143
+ tab: string;
144
+ /** Pop the tab to its root first. Literally `true` — anything else drops the directive. */
145
+ reset?: true;
146
+ /** Then push this screen onto the selected tab's stack. Must be linkable. */
147
+ screenId: string;
148
+ /** Nav params for the pushed screen. Strings only. */
149
+ args?: Record<string, string>;
150
+ presentation?: never;
151
+ } | {
126
152
  tab: string;
153
+ /** Pop the tab to its root. Literally `true` — anything else drops the directive. */
154
+ reset?: true;
127
155
  screenId?: never;
156
+ /** `args` needs a `screenId` to go to — every host drops `{ tab, args }` as ambiguous. */
128
157
  args?: never;
129
158
  presentation?: never;
130
- }
159
+ };
131
160
  /**
132
161
  * Attach a {@link NavDirective} to a state object an action returns. Sugar for
133
162
  * `{ ...state, _nav: target }` that keeps the field name in one place.
134
163
  *
135
164
  * `target` is exactly ONE of three forms — `{ screenId, args?, presentation? }`,
136
- * `{ presentation: "back" | "dismiss" }`, or `{ tab }`. A directive that mixes them
137
- * (a `tab` with a `screenId`, say) is dropped by every host.
165
+ * `{ presentation: "back" | "dismiss" }`, or `{ tab, reset?, screenId?, args? }`. In the
166
+ * tab form `reset: true` pops the selected tab to its root (even the current one) and
167
+ * `screenId` is pushed onto THAT tab's stack (see {@link NavToTab}). A directive that
168
+ * mixes the forms otherwise (a `tab` with a `presentation`, or `back` with `args`) is
169
+ * dropped by every host.
138
170
  */
139
171
  export declare function navigate<S extends object>(state: S, target: NavDirective): S & {
140
172
  _nav: NavDirective;
package/dist/cli.mjs CHANGED
@@ -7310,6 +7310,18 @@ function compileV2(html, profile, options) {
7310
7310
  mods[name2] = coerce(raw, field2);
7311
7311
  structured(el2, mods[name2]);
7312
7312
  }
7313
+ if (name2 === "onMeasure" && mods.onMeasure && typeof mods.onMeasure === "object") {
7314
+ for (const [key3, value] of Object.entries(mods.onMeasure)) {
7315
+ if (!key3.endsWith("Path") || typeof value !== "string") continue;
7316
+ if (value.startsWith("$service:") || info4?.paths.has(statePath(value))) {
7317
+ const axis = key3.replace(/Path$/, "");
7318
+ const taken = (k2) => !!info4?.paths.has(statePath(k2));
7319
+ let suggestion = taken(axis) ? `measured${axis[0].toUpperCase()}${axis.slice(1)}` : axis;
7320
+ for (let n2 = 2; taken(suggestion); n2++) suggestion = `measured${axis[0].toUpperCase()}${axis.slice(1)}${n2}`;
7321
+ error(el2, "HHP-MEASURE-TARGET", `onMeasure.${key3} ${value} names controller state; measurements publish only to the renderer's measure store.`, `Use a store key (e.g. "${suggestion}") and read it back with a $measure:<key> modifier path.`);
7322
+ }
7323
+ }
7324
+ }
7313
7325
  continue;
7314
7326
  }
7315
7327
  const name = nativeField(attr3.startsWith("data-prop-") ? attr3.slice(10) : attr3);
@@ -8115,7 +8127,6 @@ function resolveTranslation(value, catalog3, sourceCatalog) {
8115
8127
  var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
8116
8128
  var init_bindings = __esm({
8117
8129
  "../../core/ts/src/bindings.ts"() {
8118
- "use strict";
8119
8130
  BINDING_SIGILS = ["service", "flag", "item", "t"];
8120
8131
  BINDING_SIGIL_RE = new RegExp(
8121
8132
  `^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
@@ -162161,32 +162172,32 @@ var init_preview_assets_generated = __esm({
162161
162172
  "../../packages/serve/src/preview-assets.generated.ts"() {
162162
162173
  init_preview_assets_format();
162163
162174
  PREVIEW_ASSET_MANIFEST = [
162164
- { key: "assets/DashboardHost-C43Yf5i0.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 2916, sha256: "ed853f04eb950f074bb4b910d5b54777a593265eb3e9b6b69865a534afb4e367" },
162165
- { key: "assets/DevDrawer-Dtpdyj6s.js", contentType: "application/javascript; charset=utf-8", offset: 2924, length: 16744, sha256: "bd3f6e0dc4d77df24edc6945bc3a9d8271db4bb87b6d5504dbeac0c979fe97cc" },
162166
- { key: "assets/IdiomCompare-Q0N9nyRz.js", contentType: "application/javascript; charset=utf-8", offset: 19668, length: 1892, sha256: "f8c8dd05dd97b368107937763ce0713a6fd2a1dd8fbb443184e05fa8177b678c" },
162167
- { key: "assets/LightboxViewer-DXQZfuRl.js", contentType: "application/javascript; charset=utf-8", offset: 21560, length: 8132, sha256: "3b864e63b7d1edb62ae343113b949596a7db90cb85a598a778ee0e29a7bede10" },
162168
- { key: "assets/PhonePreviewControl-DNUNrsXI.js", contentType: "application/javascript; charset=utf-8", offset: 29692, length: 37729, sha256: "de870adf633b1f1075bb27f0cb75b3526b6409fc246d8ed8166e02c466004034" },
162169
- { key: "assets/SchemeCompare-nZarcCIk.js", contentType: "application/javascript; charset=utf-8", offset: 67421, length: 1824, sha256: "5f668d6a07cc16c4ba72d5867cb73f947f82a88abcb74aaefb2096ded87ffe88" },
162170
- { key: "assets/index-CkZmNXjh.js", contentType: "application/javascript; charset=utf-8", offset: 69245, length: 1274560, sha256: "12bd2fba7aa7c1bb8b01ca5a2fe87ebf6a1f33651e5e86b031f9205677408aad" },
162171
- { key: "assets/pdf-CGOkyAKC.js", contentType: "application/javascript; charset=utf-8", offset: 1343805, length: 488199, sha256: "25e2f49761cb2b6ffc967924e0aeea1225f60db8c80404928a4f6c20061aa6a8" },
162172
- { key: "assets/pdf.worker.min-BQa_JDET.js", contentType: "application/javascript; charset=utf-8", offset: 1832004, length: 73, sha256: "41bcfda4f3c8c0a81c785ea87c69afc8e7d0ed8c333324aee94c273d881bb6aa" },
162173
- { key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/javascript; charset=utf-8", offset: 1832077, length: 1317034, sha256: "a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e" },
162174
- { key: "assets/pdfDocument-lG038l52.js", contentType: "application/javascript; charset=utf-8", offset: 3149111, length: 2868, sha256: "2e062ad5b358932919bccd5594ece75c4e98f1a634811123cf334d791884663a" },
162175
- { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 3151979, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
162176
- { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 3156589, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
162177
- { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 3645173, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
162178
- { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 3736097, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
162179
- { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 3827081, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
162180
- { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 3918061, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
162181
- { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 4008933, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
162182
- { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 4099913, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
162183
- { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 4208549, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
162184
- { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 4317633, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
162185
- { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 4426681, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
162186
- { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 4534381, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
162187
- { key: "himi-sw.js", contentType: "application/javascript; charset=utf-8", offset: 4622489, length: 6748, sha256: "4a92459977d7cefa1a6a7e020c3a63509737f083b3f2773557c1a5771665811a" },
162188
- { key: "index.html", contentType: "text/html; charset=utf-8", offset: 4629237, length: 4947, sha256: "8f83cd54a8228dc903c5530de84080a2aff80f9ad4b7223985eb9da54f3a5c71" },
162189
- { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 4634184, length: 17786, sha256: "084107ca997628c248f1b0ba3a7494744850df39fad813546ab8bdb82a6058da" }
162175
+ { key: "assets/DashboardHost-LrGNV-jS.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 2916, sha256: "e3a905085f463d9b91582f0ce8de0fc30731d04b5d258d67d9adcc3286641e56" },
162176
+ { key: "assets/DevDrawer-C-C1YUSp.js", contentType: "application/javascript; charset=utf-8", offset: 2924, length: 16744, sha256: "4061f6ac1880864963f0934e3934c0a23c05c8a7cd707c90f39844475738ca47" },
162177
+ { key: "assets/IdiomCompare-B5V4qfEB.js", contentType: "application/javascript; charset=utf-8", offset: 19668, length: 1892, sha256: "eeed738d8a460b5b5b4d4d5ba34fa2ad7eb49fc107166620109975f0239f165e" },
162178
+ { key: "assets/LightboxViewer-E3ussy4X.js", contentType: "application/javascript; charset=utf-8", offset: 21560, length: 8132, sha256: "aec5fead81a6b3828fa1627e62a5cc0c7084fa6a59f17d1ee49fcab51e1d302a" },
162179
+ { key: "assets/PhonePreviewControl-C5EMlBne.js", contentType: "application/javascript; charset=utf-8", offset: 29692, length: 37729, sha256: "e7318bd350df6dcde05ba204ba7512f8d0c33f8f2d90071c484a673070d2a185" },
162180
+ { key: "assets/SchemeCompare-B4-6mjE4.js", contentType: "application/javascript; charset=utf-8", offset: 67421, length: 1824, sha256: "f237c7428db1d0078c3e0753f479dd3d925dcfd89377f0d4b6d757b6bb89df8f" },
162181
+ { key: "assets/index-C5tjmjTk.js", contentType: "application/javascript; charset=utf-8", offset: 69245, length: 1276300, sha256: "822ecae23245ff7a53ba1dbceb5112e5e0b2a3f2d6bc82fccd34d06394a0c8b0" },
162182
+ { key: "assets/pdf-BSJi7U_x.js", contentType: "application/javascript; charset=utf-8", offset: 1345545, length: 488199, sha256: "0f2d42d6e60dfa6bc4bca2d9123cd7e478cc714b9ec61acf87e36e63a07005b8" },
162183
+ { key: "assets/pdf.worker.min-BQa_JDET.js", contentType: "application/javascript; charset=utf-8", offset: 1833744, length: 73, sha256: "41bcfda4f3c8c0a81c785ea87c69afc8e7d0ed8c333324aee94c273d881bb6aa" },
162184
+ { key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/javascript; charset=utf-8", offset: 1833817, length: 1317034, sha256: "a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e" },
162185
+ { key: "assets/pdfDocument-DTMDemhm.js", contentType: "application/javascript; charset=utf-8", offset: 3150851, length: 2868, sha256: "a576fa3bb4a9cae01f3d29734ef1a6fd77945d40f97d956127e5b402412ad7c8" },
162186
+ { key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 3153719, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
162187
+ { key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 3158329, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
162188
+ { key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 3646913, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
162189
+ { key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 3737837, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
162190
+ { key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 3828821, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
162191
+ { key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 3919801, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
162192
+ { key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 4010673, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
162193
+ { key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 4101653, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
162194
+ { key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 4210289, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
162195
+ { key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 4319373, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
162196
+ { key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 4428421, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
162197
+ { key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 4536121, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
162198
+ { key: "himi-sw.js", contentType: "application/javascript; charset=utf-8", offset: 4624229, length: 6748, sha256: "4a92459977d7cefa1a6a7e020c3a63509737f083b3f2773557c1a5771665811a" },
162199
+ { key: "index.html", contentType: "text/html; charset=utf-8", offset: 4630977, length: 4947, sha256: "ecf082412df3339e5f9134136dce4c8a9436e95f35c2ed87eb8195f194b78eb9" },
162200
+ { key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 4635924, length: 17786, sha256: "084107ca997628c248f1b0ba3a7494744850df39fad813546ab8bdb82a6058da" }
162190
162201
  ];
162191
162202
  }
162192
162203
  });
Binary file
@@ -2814,9 +2814,9 @@ A worker moves the user by returning `_nav` from an action (`navigate()` from
2814
2814
  |---|---|
2815
2815
  | `{ screenId, args?, presentation? }` | Open a linkable screen. `presentation` is `push` (the default), `replace`, `sheet` or `full_screen`, as in the table above. |
2816
2816
  | `{ presentation: "back" }` / `{ presentation: "dismiss" }` | As in the table above. No target. |
2817
- | `{ tab: "<tabId>" }` | Switch to that tab: a `tabBar` item, or a sidebar-rail item on a wide layout. Any open sheet or cover closes first. An id the app is not showing (unknown, hidden, or no tab bar / rail at all) is ignored, and so is the tab the user is already on: its stack is kept, not popped to its root. |
2817
+ | `{ tab: "<tabId>", reset?: true, screenId?, args? }` | Switch to that tab: a `tabBar` item, or a sidebar-rail item on a wide layout. Any open sheet or cover closes first. An id the app is not showing (unknown, hidden, or no tab bar / rail at all) is ignored, whole. A bare `{ tab }` for the tab the user is already on does nothing: its stack is kept. Then, on THAT tab: `reset: true` pops its stack to its root (even on the current tab), and `screenId` (with `args`) is pushed onto it. |
2818
2818
 
2819
- A `_nav` that mixes forms (a `tab` with a `screenId`, `back` with a `screenId`) is ignored.
2819
+ A `_nav` that mixes forms otherwise (a `tab` with a `presentation`, `args` with a `tab` but no `screenId`, `back` with a `screenId`) is ignored.
2820
2820
 
2821
2821
  - **Switching tabs is a worker `_nav`.** A `himi.open` whose target is another tab's root
2822
2822
  screen does not select that tab: it PUSHES the screen onto the current tab's stack.
package/guides/hhp.md CHANGED
@@ -86,7 +86,9 @@ use a child `script type="application/himalaya-props"` containing JSON.
86
86
  ordinary-control aliases. Explicit modifiers use `data-mod-*` or `himi-mod-*`.
87
87
  A `…-path` modifier (`data-mod-hidden-path="full"`, `data-mod-background-color-path`)
88
88
  names controller state exactly like `bind:*`, or `$item.<field>` in a row; an unknown
89
- path is a lint error. `onMeasure` keys name the renderer's measure store instead.
89
+ path is a lint error. `onMeasure` keys name the renderer's measure store instead
90
+ (read back with a `$measure:<key>` path); no renderer writes a measurement into worker
91
+ state, so an `onMeasure` key that names controller state is an `HHP-MEASURE-TARGET` error.
90
92
  `style` and `title` are HTML globals: `style` is always CSS, so a native `style`
91
93
  variant uses `variant="primary"`; `title="…"` sets a component's `title` field. CSS
92
94
  `font` applies only to text components (Text, Label, Marquee). The profile's
@@ -44,24 +44,24 @@
44
44
  "name": "NavToScreen",
45
45
  "kind": "interface",
46
46
  "jsdoc": "/**\n * Open a screen. `presentation` picks how: `push` (the default) onto the current tab's\n * stack, `replace` to show it in place of the current screen, or present it as a\n * `sheet` / `full_screen` modal.\n */",
47
- "decl": "export interface NavToScreen {\n /** Screen to open. Must be linkable, or the host ignores the directive. */\n screenId: string;\n /** Nav params for the target (e.g. the record `id`). Strings only. */\n args?: Record<string, string>;\n /** How to show it. Absent ⇒ `push`. */\n presentation?: \"push\" | \"replace\" | \"sheet\" | \"full_screen\";\n tab?: never;\n}"
47
+ "decl": "export interface NavToScreen {\n /** Screen to open. Must be linkable, or the host ignores the directive. */\n screenId: string;\n /** Nav params for the target (e.g. the record `id`). Strings only. */\n args?: Record<string, string>;\n /** How to show it. Absent ⇒ `push`. */\n presentation?: \"push\" | \"replace\" | \"sheet\" | \"full_screen\";\n tab?: never;\n /** Only a {@link NavToTab} resets; without a `tab` it would be ignored as a plain push. */\n reset?: never;\n}"
48
48
  },
49
49
  {
50
50
  "name": "NavBackOrDismiss",
51
51
  "kind": "interface",
52
52
  "jsdoc": "/**\n * Leave the current screen. `back` pops the current stack. On iOS and Android, inside an\n * open sheet or cover it pops the modal's own stack and closes the modal at its root; on\n * web it pops the tab's stack, so close a modal with `dismiss`. `dismiss` closes the open\n * sheet / full-screen cover. Both are no-ops with nothing to leave. No target: the host\n * already knows where \"back\" is.\n */",
53
- "decl": "export interface NavBackOrDismiss {\n presentation: \"back\" | \"dismiss\";\n screenId?: never;\n args?: never;\n tab?: never;\n}"
53
+ "decl": "export interface NavBackOrDismiss {\n presentation: \"back\" | \"dismiss\";\n screenId?: never;\n args?: never;\n tab?: never;\n reset?: never;\n}"
54
54
  },
55
55
  {
56
56
  "name": "NavToTab",
57
- "kind": "interface",
58
- "jsdoc": "/**\n * Switch to the top-level destination with this id — a tab-bar item, or a sidebar-rail\n * item on a wide layout. The host closes any open sheet first. An id the app is not\n * showing right now (unknown, or hidden by the nav worker) is ignored, and so is the tab\n * the user is already on (their stack is kept — it is not a re-tap). A tab switch is not a\n * stack operation: a later `back` pops the NEW tab's stack, not the switch.\n */",
59
- "decl": "export interface NavToTab {\n tab: string;\n screenId?: never;\n args?: never;\n presentation?: never;\n}"
57
+ "kind": "type",
58
+ "jsdoc": "/**\n * Switch to the top-level destination with this id — a tab-bar item, or a sidebar-rail\n * item on a wide layout. The host closes any open sheet first. An id the app is not\n * showing right now (unknown, or hidden by the nav worker) is ignored — the whole\n * directive, so nothing is pushed anywhere — and a bare `{ tab }` for the tab the user is\n * already on does nothing (their stack is kept — it is not a re-tap). A tab switch is not a\n * stack operation: a later `back` pops the NEW tab's stack, not the switch.\n *\n * Two optional follow-ups act on THAT tab once it is selected, in this order:\n * - `reset: true` pops the tab's stack to its root — even when it is the tab the user is\n * already on, the one case a worker causes the pop a user's re-tap causes;\n * - `screenId` (with `args`) is then pushed onto the tab's stack — never onto the tab the\n * action ran on. Only push is defined: a `presentation` next to a `tab` is dropped.\n *\n * So `{ tab: \"orders\", screenId: \"order_detail\", args: { id } }` switches to Orders and\n * opens the order there; `{ tab: \"create\", reset: true }` returns to a clean tab root.\n * `args` without a `screenId` has nowhere to go: every host drops it as ambiguous, so the\n * type does not admit it (a union — `args` only next to `screenId`). Binaries older than this\n * form drop `{ tab, screenId }` / `{ tab, reset }` whole; a worker that must support them\n * can return `{ tab }` and push on the next action.\n */",
59
+ "decl": "export type NavToTab =\n | {\n tab: string;\n /** Pop the tab to its root first. Literally `true` — anything else drops the directive. */\n reset?: true;\n /** Then push this screen onto the selected tab's stack. Must be linkable. */\n screenId: string;\n /** Nav params for the pushed screen. Strings only. */\n args?: Record<string, string>;\n presentation?: never;\n }\n | {\n tab: string;\n /** Pop the tab to its root. Literally `true` — anything else drops the directive. */\n reset?: true;\n screenId?: never;\n /** `args` needs a `screenId` to go to — every host drops `{ tab, args }` as ambiguous. */\n args?: never;\n presentation?: never;\n };"
60
60
  },
61
61
  {
62
62
  "name": "navigate",
63
63
  "kind": "function",
64
- "jsdoc": "/**\n * Attach a {@link NavDirective} to a state object an action returns. Sugar for\n * `{ ...state, _nav: target }` that keeps the field name in one place.\n *\n * `target` is exactly ONE of three forms — `{ screenId, args?, presentation? }`,\n * `{ presentation: \"back\" | \"dismiss\" }`, or `{ tab }`. A directive that mixes them\n * (a `tab` with a `screenId`, say) is dropped by every host.\n */",
64
+ "jsdoc": "/**\n * Attach a {@link NavDirective} to a state object an action returns. Sugar for\n * `{ ...state, _nav: target }` that keeps the field name in one place.\n *\n * `target` is exactly ONE of three forms — `{ screenId, args?, presentation? }`,\n * `{ presentation: \"back\" | \"dismiss\" }`, or `{ tab, reset?, screenId?, args? }`. In the\n * tab form `reset: true` pops the selected tab to its root (even the current one) and\n * `screenId` is pushed onto THAT tab's stack (see {@link NavToTab}). A directive that\n * mixes the forms otherwise (a `tab` with a `presentation`, or `back` with `args`) is\n * dropped by every host.\n */",
65
65
  "decl": "export function navigate<S extends object>(\n state: S,\n target: NavDirective,\n): S & { _nav: NavDirective };"
66
66
  },
67
67
  {
@@ -714,11 +714,15 @@ a tapped `himi.open` would — including the `args` arriving as `himalaya.input`
714
714
  |---|---|
715
715
  | `{ screenId, args?, presentation? }` | Opens the screen. `presentation` is `push` (the default), `replace`, `sheet` or `full_screen` — the same verbs a descriptor action uses. |
716
716
  | `{ presentation: "back" }` or `{ presentation: "dismiss" }` | `back` pops the current screen; `dismiss` closes the open sheet or full-screen cover. No target. |
717
- | `{ tab: "<tabId>" }` | Switches to that tab — a `tabBar` item, or a sidebar-rail item on a wide layout. |
717
+ | `{ tab: "<tabId>", reset?: true, screenId?, args? }` | Switches to that tab — a `tabBar` item, or a sidebar-rail item on a wide layout. With `reset: true` it then pops that tab to its root. With `screenId` it then pushes that screen, with `args`, onto **that** tab's stack. |
718
718
 
719
719
  ```ts
720
720
  cancel: (s) => navigate({ ...s, draft: null }, { presentation: "dismiss" }),
721
721
  viewOrders: (s) => navigate(s, { tab: "orders" }),
722
+ // switch to Orders AND open order 42 there, in one result:
723
+ viewOrder: (s) => navigate(s, { tab: "orders", screenId: "order_detail", args: { id: "42" } }),
724
+ // return the user to a clean Create tab, even if they are already on it:
725
+ startOver: (s) => navigate({ ...s, draft: null }, { tab: "create", reset: true }),
722
726
  ```
723
727
 
724
728
  The rules:
@@ -726,9 +730,12 @@ The rules:
726
730
  - `screenId` must be a **linkable** screen (`navigation.linkableScreens`), or the host
727
731
  ignores the directive.
728
732
  - `args` values are **strings only**; anything else is dropped rather than coerced.
729
- - A directive that mixes forms — a `tab` with a `screenId`, `back` with a `screenId`, `back`
730
- with `args` — or names a verb outside its form (`alert`, `snackbar`) is **ignored** and
731
- logged as `nav_verb_dropped`.
733
+ - A directive that mixes forms — a `tab` with a `presentation`, a `tab` with `args` but no
734
+ `screenId`, `back` with a `screenId`, `back` with `args` — or names a verb outside its form
735
+ (`alert`, `snackbar`) is **ignored** and logged as `nav_verb_dropped`. Only push is defined
736
+ for a `screenId` next to a `tab`.
737
+ - `reset` must be literally `true`. `false`, `"true"` or `1` drops the whole directive
738
+ (`bad_reset`).
732
739
 
733
740
  Return `_nav` rather than calling `dispatch("himi.open", …)` from a worker. Current runtimes
734
741
  route a worker's `himi.open` dispatch on all three hosts, but older iOS and Android binaries
@@ -753,7 +760,18 @@ target is another tab's root screen does not select that tab — it pushes the s
753
760
  the app has no tab bar or sidebar rail (`single` / `drawer` navigation) — is ignored and
754
761
  logged as `nav_verb_dropped`. The user stays where they are.
755
762
  - Asking for the tab the user is already on does nothing. It does **not** pop that tab to its
756
- root the way a second tap on the tab bar does.
763
+ root the way a second tap on the tab bar does — unless you ask for it with `reset: true`.
764
+ - `reset: true` pops the selected tab to its root, even when it is the current tab. This is
765
+ the same pop as a second tap on the tab bar, and a tab already at its root does not move.
766
+ - A `screenId` next to the `tab` is pushed onto the **selected** tab's stack, after any reset,
767
+ never onto the tab the action ran on. `back` from it returns to that tab's root (or to
768
+ whatever the tab held before the push). If the tab id is ignored, nothing is pushed
769
+ anywhere.
770
+ - Runtimes older than this form ignore `{ tab, screenId }` and `{ tab, reset }` as mixed
771
+ forms. If your app must support them, return `{ tab }` and push from the next action.
772
+ - Only a returned `_nav` can reset or push on the tab. A `himi.tab` action written in a
773
+ descriptor, or sent with `dispatch("himi.tab", …)`, switches the tab and ignores any
774
+ `screenId` or `reset` it carries.
757
775
  - A tab switch is not a step on a stack: a later `back` pops the **new** tab's stack and does
758
776
  not return to the previous tab. On web the switch is also a browser-history entry, so the
759
777
  browser's own Back button returns to the previous tab; iOS and Android have no equivalent.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1460.0",
3
+ "version": "0.1462.0",
4
4
  "type": "module",
5
5
  "description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
6
6
  "keywords": [
@@ -71,5 +71,5 @@
71
71
  "artifactId": "himalaya-cli"
72
72
  }
73
73
  },
74
- "falconPackageHash": "671905888b8bae86b934860d075660df2589c4d9791b110e75cc5b8b"
74
+ "falconPackageHash": "d40739f8a350f4cf15d4ea5e3677bd4b4b29a3c9311c8e80752b9d3b"
75
75
  }