@wix/himalaya-cli 0.1512.0 → 0.1514.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.
@@ -56,6 +56,10 @@ export interface ScreenDescriptor {
56
56
  /** The page's title for a host that shows it in its own navigation bar. Mirror of
57
57
  * ScreenDescriptor.host_title in core.proto. */
58
58
  hostTitle?: import("@wix/himalaya/core").HostTitle;
59
+ /** RFC 0066 — "" / "visible" (default) | "hidden": hide the bottom tab bar while this screen
60
+ * is the visible top of its tab's stack. Mirror of ScreenDescriptor.tab_bar_visibility in
61
+ * core.proto. */
62
+ tabBarVisibility?: string;
59
63
  }
60
64
  /** Tier 3/4 + embeddable WebView behavior. Mirror of WebViewConfig in core.proto
61
65
  * (RFC 0038). All fields optional; zero values reproduce legacy behavior. */
@@ -3030,6 +3030,9 @@ export interface TopBarConfig {
3030
3030
  scrollBehavior?: string;
3031
3031
  /** RFC 0066 amendment — truthy ⇒ leaving the presentation asks to discard. Unset/unresolved ⇒ false. */
3032
3032
  dirtyPath?: string;
3033
+ /** RFC 0066 amendment — live `visibility` (`$service:`). Resolves to "visible" | "hidden";
3034
+ * anything else, or unresolved, falls back to `visibility`. Not a truthy boolean. */
3035
+ visibilityPath?: string;
3033
3036
  }
3034
3037
  /** RFC 0066 §1 (+ its "top-bar gap items" amendment) — one top-bar item. Test id `toolbar.<id>`
3035
3038
  * (`toolbar-<id>` on web and React Native). Every tap carries an existing `Action`
@@ -3057,6 +3060,9 @@ export interface ToolbarItem {
3057
3060
  avatar?: ToolbarAvatar;
3058
3061
  /** Live label; `label` is the fallback. */
3059
3062
  labelPath?: string;
3063
+ /** Long press (touch), secondary click (pointer) or the "More options" accessibility action.
3064
+ * Never also fires `onTap`; ignored while disabled or loading, in More Actions, and with a `menu`. */
3065
+ onLongPress?: Action;
3060
3066
  }
3061
3067
  /** RFC 0066 amendment — an avatar item. Images are absolute https URLs (resolve a Wix
3062
3068
  * media id with `wixMediaUrl` before publishing). */
@@ -3536,6 +3542,9 @@ export interface ScreenDescriptor {
3536
3542
  /** RFC 0010 (top-bar amendment) — per-screen top bar (trailing actions +
3537
3543
  * leading/style override). Fully replaces `NavigationConfig.topBarDefault`. */
3538
3544
  topBar?: TopBarConfig;
3545
+ /** "" / "visible" (default) | "hidden": hide the bottom tab bar while this screen is the
3546
+ * visible top of its tab's stack (RFC 0066). Static; no effect in a presentation. */
3547
+ tabBarVisibility?: string;
3539
3548
  etag?: string;
3540
3549
  cacheControl?: CacheControl;
3541
3550
  telemetryScreenName?: string;
@@ -151,6 +151,9 @@ export declare const screenDescriptorSchema: {
151
151
  readonly topBar: {
152
152
  readonly $ref: "#/$defs/topBarConfig";
153
153
  };
154
+ readonly tabBarVisibility: {
155
+ readonly type: "string";
156
+ };
154
157
  readonly logicBundle: {
155
158
  readonly type: "object";
156
159
  readonly additionalProperties: false;
@@ -410,6 +413,9 @@ export declare const screenDescriptorSchema: {
410
413
  readonly dirtyPath: {
411
414
  readonly type: "string";
412
415
  };
416
+ readonly visibilityPath: {
417
+ readonly type: "string";
418
+ };
413
419
  };
414
420
  };
415
421
  readonly searchableConfig: {
@@ -493,6 +499,9 @@ export declare const screenDescriptorSchema: {
493
499
  readonly labelPath: {
494
500
  readonly type: "string";
495
501
  };
502
+ readonly onLongPress: {
503
+ readonly $ref: "#/$defs/action";
504
+ };
496
505
  };
497
506
  };
498
507
  readonly toolbarAvatar: {
@@ -1742,6 +1751,9 @@ export declare const widgetSnapshotSchema: {
1742
1751
  readonly dirtyPath: {
1743
1752
  readonly type: "string";
1744
1753
  };
1754
+ readonly visibilityPath: {
1755
+ readonly type: "string";
1756
+ };
1745
1757
  };
1746
1758
  };
1747
1759
  readonly searchableConfig: {
@@ -1825,6 +1837,9 @@ export declare const widgetSnapshotSchema: {
1825
1837
  readonly labelPath: {
1826
1838
  readonly type: "string";
1827
1839
  };
1840
+ readonly onLongPress: {
1841
+ readonly $ref: "#/$defs/action";
1842
+ };
1828
1843
  };
1829
1844
  };
1830
1845
  readonly toolbarAvatar: {
@@ -8482,6 +8482,9 @@ var screenDescriptorSchema = {
8482
8482
  // in the schema, `additionalProperties:false` would reject EVERY descriptor
8483
8483
  // carrying a top bar (the same trap as logicBundle below).
8484
8484
  topBar: { $ref: "#/$defs/topBarConfig" },
8485
+ // RFC 0066 amendment — "" / "visible" (default) | "hidden". A free string like every
8486
+ // chrome discriminator: an unknown value coalesces to "visible" (invariant 6).
8487
+ tabBarVisibility: { type: "string" },
8485
8488
  // RFC 0002 — Tier-5 worker bundle reference (LogicBundleRef). Without this in
8486
8489
  // the schema, `additionalProperties:false` rejected EVERY T5 descriptor, so the
8487
8490
  // admin's pre-push validation 400'd any edit of a T5 screen.
@@ -8651,7 +8654,9 @@ var screenDescriptorSchema = {
8651
8654
  titleMenu: { $ref: "#/$defs/topBarTitleMenu" },
8652
8655
  subtitlePath: { type: "string" },
8653
8656
  scrollBehavior: { type: "string" },
8654
- dirtyPath: { type: "string" }
8657
+ dirtyPath: { type: "string" },
8658
+ // RFC 0066 amendment "long press, bar visibility, tab-bar visibility" (field 15).
8659
+ visibilityPath: { type: "string" }
8655
8660
  }
8656
8661
  },
8657
8662
  // RFC 0010 "Native top-bar search" (SearchableConfig fields 1–5, 12–15). `placement` stays a free string.
@@ -8687,7 +8692,8 @@ var screenDescriptorSchema = {
8687
8692
  content: { $ref: "#/$defs/component" },
8688
8693
  loadingPath: { type: "string" },
8689
8694
  avatar: { $ref: "#/$defs/toolbarAvatar" },
8690
- labelPath: { type: "string" }
8695
+ labelPath: { type: "string" },
8696
+ onLongPress: { $ref: "#/$defs/action" }
8691
8697
  }
8692
8698
  },
8693
8699
  toolbarAvatar: {
@@ -7054,6 +7054,9 @@ var screenDescriptorSchema = {
7054
7054
  // in the schema, `additionalProperties:false` would reject EVERY descriptor
7055
7055
  // carrying a top bar (the same trap as logicBundle below).
7056
7056
  topBar: { $ref: "#/$defs/topBarConfig" },
7057
+ // RFC 0066 amendment — "" / "visible" (default) | "hidden". A free string like every
7058
+ // chrome discriminator: an unknown value coalesces to "visible" (invariant 6).
7059
+ tabBarVisibility: { type: "string" },
7057
7060
  // RFC 0002 — Tier-5 worker bundle reference (LogicBundleRef). Without this in
7058
7061
  // the schema, `additionalProperties:false` rejected EVERY T5 descriptor, so the
7059
7062
  // admin's pre-push validation 400'd any edit of a T5 screen.
@@ -7223,7 +7226,9 @@ var screenDescriptorSchema = {
7223
7226
  titleMenu: { $ref: "#/$defs/topBarTitleMenu" },
7224
7227
  subtitlePath: { type: "string" },
7225
7228
  scrollBehavior: { type: "string" },
7226
- dirtyPath: { type: "string" }
7229
+ dirtyPath: { type: "string" },
7230
+ // RFC 0066 amendment "long press, bar visibility, tab-bar visibility" (field 15).
7231
+ visibilityPath: { type: "string" }
7227
7232
  }
7228
7233
  },
7229
7234
  // RFC 0010 "Native top-bar search" (SearchableConfig fields 1–5, 12–15). `placement` stays a free string.
@@ -7259,7 +7264,8 @@ var screenDescriptorSchema = {
7259
7264
  content: { $ref: "#/$defs/component" },
7260
7265
  loadingPath: { type: "string" },
7261
7266
  avatar: { $ref: "#/$defs/toolbarAvatar" },
7262
- labelPath: { type: "string" }
7267
+ labelPath: { type: "string" },
7268
+ onLongPress: { $ref: "#/$defs/action" }
7263
7269
  }
7264
7270
  },
7265
7271
  toolbarAvatar: {
package/dist/cli.mjs CHANGED
@@ -9823,6 +9823,9 @@ var init_validator = __esm({
9823
9823
  // in the schema, `additionalProperties:false` would reject EVERY descriptor
9824
9824
  // carrying a top bar (the same trap as logicBundle below).
9825
9825
  topBar: { $ref: "#/$defs/topBarConfig" },
9826
+ // RFC 0066 amendment — "" / "visible" (default) | "hidden". A free string like every
9827
+ // chrome discriminator: an unknown value coalesces to "visible" (invariant 6).
9828
+ tabBarVisibility: { type: "string" },
9826
9829
  // RFC 0002 — Tier-5 worker bundle reference (LogicBundleRef). Without this in
9827
9830
  // the schema, `additionalProperties:false` rejected EVERY T5 descriptor, so the
9828
9831
  // admin's pre-push validation 400'd any edit of a T5 screen.
@@ -9992,7 +9995,9 @@ var init_validator = __esm({
9992
9995
  titleMenu: { $ref: "#/$defs/topBarTitleMenu" },
9993
9996
  subtitlePath: { type: "string" },
9994
9997
  scrollBehavior: { type: "string" },
9995
- dirtyPath: { type: "string" }
9998
+ dirtyPath: { type: "string" },
9999
+ // RFC 0066 amendment "long press, bar visibility, tab-bar visibility" (field 15).
10000
+ visibilityPath: { type: "string" }
9996
10001
  }
9997
10002
  },
9998
10003
  // RFC 0010 "Native top-bar search" (SearchableConfig fields 1–5, 12–15). `placement` stays a free string.
@@ -10028,7 +10033,8 @@ var init_validator = __esm({
10028
10033
  content: { $ref: "#/$defs/component" },
10029
10034
  loadingPath: { type: "string" },
10030
10035
  avatar: { $ref: "#/$defs/toolbarAvatar" },
10031
- labelPath: { type: "string" }
10036
+ labelPath: { type: "string" },
10037
+ onLongPress: { $ref: "#/$defs/action" }
10032
10038
  }
10033
10039
  },
10034
10040
  toolbarAvatar: {
@@ -13052,6 +13058,7 @@ __export(validate_descriptor_core_exports, {
13052
13058
  validateAppServicesConfig: () => validateAppServicesConfig,
13053
13059
  validateAppWebViewInstances: () => validateAppWebViewInstances,
13054
13060
  validateScreenDescriptor: () => validateScreenDescriptor,
13061
+ validateTabBarVisibility: () => validateTabBarVisibility,
13055
13062
  webViewEmbeddedIssues: () => webViewEmbeddedIssues,
13056
13063
  workerSubtreeAllowed: () => workerSubtreeAllowed
13057
13064
  });
@@ -14659,6 +14666,16 @@ function topBarFindings(descriptor) {
14659
14666
  }
14660
14667
  });
14661
14668
  }
14669
+ const overSlots = legacy + trailingItems.length + (hasOverflow ? 1 : 0) > TOP_BAR_TRAILING_LIMIT;
14670
+ const movedByR2 = new Set(overSlots ? trailingItems.slice(Math.max(0, TOP_BAR_TRAILING_LIMIT - legacy - 1)) : []);
14671
+ items.forEach((i2, idx) => {
14672
+ if (!i2 || typeof i2 !== "object" || i2.onLongPress == null) return;
14673
+ if (i2.placement === "overflow" || movedByR2.has(i2)) {
14674
+ out2.push({ path: `topBar.items[${idx}].onLongPress`, message: `An item in More Actions (${i2.placement === "overflow" ? '`placement: "overflow"`' : "moved there because the bar has more than two trailing slots (R2)"}) has no long press: the menu row only taps, so \`onLongPress\` never fires. Move the action to its own menu row, or keep the item in a visible slot` });
14675
+ } else if (Array.isArray(i2.menu) && i2.menu.length > 0) {
14676
+ out2.push({ path: `topBar.items[${idx}].onLongPress`, message: "An item with a `menu` ignores `onLongPress`: the menu owns the press. Add the action to the menu, or remove the menu" });
14677
+ }
14678
+ });
14662
14679
  const notHttps = (v2) => {
14663
14680
  if (typeof v2 !== "string" || v2 === "") return false;
14664
14681
  if (!/^https:\/\/[^/?#\s]/i.test(v2)) return true;
@@ -14679,6 +14696,59 @@ function topBarFindings(descriptor) {
14679
14696
  }
14680
14697
  return out2;
14681
14698
  }
14699
+ function validateTabBarVisibility(screens, navigation) {
14700
+ const out2 = [];
14701
+ const items = navigation?.tabBar?.items;
14702
+ if (!Array.isArray(items)) return out2;
14703
+ const tabs = items.flatMap((item) => {
14704
+ const t2 = item;
14705
+ return t2 && typeof t2.screenId === "string" ? [{ id: typeof t2.id === "string" ? t2.id : t2.screenId, screenId: t2.screenId }] : [];
14706
+ });
14707
+ const hasBody = (block) => {
14708
+ const b2 = block;
14709
+ return !!b2 && (Array.isArray(b2.items) && b2.items.length > 0 || typeof b2.contentScreenId === "string" && b2.contentScreenId !== "");
14710
+ };
14711
+ const nav = navigation;
14712
+ const draws = (kind) => {
14713
+ if (kind === "drawer") return !hasBody(nav?.drawer);
14714
+ if (kind === "sidebar") return !hasBody(nav?.sidebar);
14715
+ return !(typeof kind === "string" && TAB_BAR_KINDS_WITHOUT_BOTTOM_TABS.has(kind));
14716
+ };
14717
+ const roots2 = /* @__PURE__ */ new Map();
14718
+ const addRoots = (surface, kind, destinations, screenIds) => {
14719
+ if (!draws(kind)) return;
14720
+ const wanted = Array.isArray(destinations) && destinations.length ? new Set(destinations.filter((d2) => typeof d2 === "string")) : null;
14721
+ const shown2 = wanted && tabs.some((t2) => wanted.has(t2.id)) ? tabs.filter((t2) => wanted.has(t2.id)) : tabs;
14722
+ const repoint = screenIds && typeof screenIds === "object" ? screenIds : {};
14723
+ for (const tab of shown2) {
14724
+ const root = typeof repoint[tab.id] === "string" && repoint[tab.id] ? repoint[tab.id] : tab.screenId;
14725
+ if (!roots2.has(root)) roots2.set(root, { tab: tab.id, surface });
14726
+ }
14727
+ };
14728
+ addRoots(null, navigation?.navKind);
14729
+ const surfaces = navigation?.surfaces;
14730
+ if (surfaces && typeof surfaces === "object" && !Array.isArray(surfaces)) {
14731
+ for (const [surface, entry] of Object.entries(surfaces)) {
14732
+ if (!entry || typeof entry !== "object") continue;
14733
+ const e2 = entry;
14734
+ addRoots(surface, typeof e2.navKind === "string" && e2.navKind ? e2.navKind : navigation?.navKind, e2.destinations, e2.screenIds);
14735
+ }
14736
+ }
14737
+ for (const { screenId, descriptor } of screens) {
14738
+ if (descriptor?.tabBarVisibility !== "hidden") continue;
14739
+ const root = roots2.get(screenId);
14740
+ if (!root) continue;
14741
+ const where = root.surface === null ? "" : ` on the "${root.surface}" surface`;
14742
+ out2.push({
14743
+ screenId,
14744
+ severity: "warning",
14745
+ pass: "top-bar",
14746
+ path: "tabBarVisibility",
14747
+ message: `"${screenId}" is the root of the "${root.tab}" tab${where} and sets \`tabBarVisibility: "hidden"\`, so the member has no way to switch tabs from it. Hide the tab bar only on screens pushed above a tab root`
14748
+ });
14749
+ }
14750
+ return out2;
14751
+ }
14682
14752
  function buttonVariantFindings(descriptor) {
14683
14753
  const out2 = [];
14684
14754
  const visit = (v2, path2, atRoot) => {
@@ -15453,7 +15523,7 @@ function validateAppWebViewInstances(screens) {
15453
15523
  const findings = webViewEmbeddedAppFindings(screens);
15454
15524
  return webViewEmbeddedIssues(findings).map((issue2, i2) => ({ ...issue2, screenId: findings[i2].screenId }));
15455
15525
  }
15456
- var CRAWL_BLOCKING_PASSES, BOOT_EVAL_TIMEOUT_MS, BUNDLE_FILENAME, DRIFT_PROBES, DEVICE_NETWORK_WITHHELD, DEVICE_STRIPPED_HOST_GLOBALS, DEVICE_WITHHELD, DEVICE_PARITY_CANDIDATES, DEVICE_PARITY_WITHHELD, defaultEvaluator, bootEvaluator, actionEvaluator, NATIVE_PROP_ENUMS, KNOWN_PROPS, IN_ARRAY_BINDING_PROPS, SERVICE_SIGIL, INTEGER_PROPS, NATIVE_REQUIRED_PROPS, bareNestedClass, NATIVE_NESTED_CLASSES, NATIVE_MODIFIERS_CLASS, NATIVE_NESTED_SCALARS, NATIVE_DESCRIPTOR_CLASS, NATIVE_DESCRIPTOR_NESTED, NATIVE_NESTED_PROPS, LENIENT_TOP_BAR_BLOCKS, MODIFIER_KEYS, INTEGER_MODIFIERS, MODIFIER_KINDS, SCHEMA_SCORED_NODES, CORE_PACKAGES, LEGACY_UNSCORED_KEYS, DYNAMIC_PLACEHOLDER, LITERAL_ONLY_PROPS, SERVICE_ONLY_BINDING_PROPS, WHOLE_VALUE_BINDING, EMBEDDED_BINDING, OPTIONS_BINDING_PROPS, EDITOR_SERVICE_NAME, SHEET_PLACEMENTS, UNSAFE_TO_RECURSE_DEPTH, TOP_BAR_TRAILING_LIMIT, TOP_BAR_NON_TRAILING, BUTTON_STYLES, EMPTY_STATE_ACTION_STYLES, EMPTY_STATE_ACTION_SIZES;
15526
+ var CRAWL_BLOCKING_PASSES, BOOT_EVAL_TIMEOUT_MS, BUNDLE_FILENAME, DRIFT_PROBES, DEVICE_NETWORK_WITHHELD, DEVICE_STRIPPED_HOST_GLOBALS, DEVICE_WITHHELD, DEVICE_PARITY_CANDIDATES, DEVICE_PARITY_WITHHELD, defaultEvaluator, bootEvaluator, actionEvaluator, NATIVE_PROP_ENUMS, KNOWN_PROPS, IN_ARRAY_BINDING_PROPS, SERVICE_SIGIL, INTEGER_PROPS, NATIVE_REQUIRED_PROPS, bareNestedClass, NATIVE_NESTED_CLASSES, NATIVE_MODIFIERS_CLASS, NATIVE_NESTED_SCALARS, NATIVE_DESCRIPTOR_CLASS, NATIVE_DESCRIPTOR_NESTED, NATIVE_NESTED_PROPS, LENIENT_TOP_BAR_BLOCKS, MODIFIER_KEYS, INTEGER_MODIFIERS, MODIFIER_KINDS, SCHEMA_SCORED_NODES, CORE_PACKAGES, LEGACY_UNSCORED_KEYS, DYNAMIC_PLACEHOLDER, LITERAL_ONLY_PROPS, SERVICE_ONLY_BINDING_PROPS, WHOLE_VALUE_BINDING, EMBEDDED_BINDING, OPTIONS_BINDING_PROPS, EDITOR_SERVICE_NAME, SHEET_PLACEMENTS, UNSAFE_TO_RECURSE_DEPTH, TOP_BAR_TRAILING_LIMIT, TOP_BAR_NON_TRAILING, TAB_BAR_KINDS_WITHOUT_BOTTOM_TABS, BUTTON_STYLES, EMPTY_STATE_ACTION_STYLES, EMPTY_STATE_ACTION_SIZES;
15457
15527
  var init_validate_descriptor_core = __esm({
15458
15528
  "../../core/dev-server/src/validate-descriptor.core.ts"() {
15459
15529
  init_validator();
@@ -16541,6 +16611,7 @@ var init_validate_descriptor_core = __esm({
16541
16611
  UNSAFE_TO_RECURSE_DEPTH = 128;
16542
16612
  TOP_BAR_TRAILING_LIMIT = 2;
16543
16613
  TOP_BAR_NON_TRAILING = /* @__PURE__ */ new Set(["leading", "principal", "bottom", "keyboard", "overflow"]);
16614
+ TAB_BAR_KINDS_WITHOUT_BOTTOM_TABS = /* @__PURE__ */ new Set(["single", "drawer", "sidebar"]);
16544
16615
  BUTTON_STYLES = /* @__PURE__ */ new Set(["filled", "tonal", "outlined", "text", "elevated", "bordered", "prominent", "plain", "glass", "primary", "secondary", "tertiary", "link", "destructive"]);
16545
16616
  EMPTY_STATE_ACTION_STYLES = /* @__PURE__ */ new Set(["primary", "secondary", "plain"]);
16546
16617
  EMPTY_STATE_ACTION_SIZES = /* @__PURE__ */ new Set(["sm", "md"]);
@@ -17692,6 +17763,7 @@ __export(validate_descriptor_exports, {
17692
17763
  validateAppServicesConfig: () => validateAppServicesConfig,
17693
17764
  validateAppWebViewInstances: () => validateAppWebViewInstances,
17694
17765
  validateScreenDescriptor: () => validateScreenDescriptor,
17766
+ validateTabBarVisibility: () => validateTabBarVisibility,
17695
17767
  webViewEmbeddedIssues: () => webViewEmbeddedIssues,
17696
17768
  workerSubtreeAllowed: () => workerSubtreeAllowed
17697
17769
  });
@@ -135131,6 +135203,7 @@ __export(build_exports2, {
135131
135203
  isMonorepoCheckout: () => isMonorepoCheckout,
135132
135204
  l10nLintOptions: () => l10nLintOptions,
135133
135205
  linkableScreenIdsFrom: () => linkableScreenIdsFrom,
135206
+ lintAppTabBarVisibility: () => lintAppTabBarVisibility,
135134
135207
  lintAppWebViewInstances: () => lintAppWebViewInstances,
135135
135208
  listBuildableApps: () => listBuildableApps,
135136
135209
  liveRenderServices: () => liveRenderServices,
@@ -135170,7 +135243,13 @@ function publishableFontFaces(fontFaces) {
135170
135243
  return kept.length > 0 ? Object.fromEntries(kept) : null;
135171
135244
  }
135172
135245
  function lintAppWebViewInstances(lint, screens) {
135173
- for (const { screenId, ...issue2 } of validateAppWebViewInstances(screens)) {
135246
+ attachAppIssues(lint, validateAppWebViewInstances(screens));
135247
+ }
135248
+ function lintAppTabBarVisibility(lint, screens, navigation) {
135249
+ attachAppIssues(lint, validateTabBarVisibility(screens, navigation));
135250
+ }
135251
+ function attachAppIssues(lint, issues) {
135252
+ for (const { screenId, ...issue2 } of issues) {
135174
135253
  const report3 = lint.find((l2) => l2.screenId === screenId);
135175
135254
  if (!report3) continue;
135176
135255
  report3.issues.push(issue2);
@@ -136124,6 +136203,7 @@ async function buildFromLoaded(preloaded, dest, opts = {}) {
136124
136203
  }
136125
136204
  }
136126
136205
  if (collect2?.lint) lintAppWebViewInstances(lint, lintScreens);
136206
+ if (collect2?.lint) lintAppTabBarVisibility(lint, lintScreens, preloaded.meta);
136127
136207
  if (collect2?.lint) {
136128
136208
  const issues = validateAppServicesConfig({
136129
136209
  config: preloaded.module.config,
@@ -154690,6 +154770,7 @@ __export(nav_lint_exports, {
154690
154770
  MISPLACED_TOP_LEVEL_KEYS: () => MISPLACED_TOP_LEVEL_KEYS,
154691
154771
  NAVIGATION_KEYS: () => NAVIGATION_KEYS,
154692
154772
  NAV_KINDS: () => NAV_KINDS,
154773
+ SCREEN_ONLY_TOP_BAR_KEYS: () => SCREEN_ONLY_TOP_BAR_KEYS,
154693
154774
  SERVED_ONLY_NAV_KEYS: () => SERVED_ONLY_NAV_KEYS,
154694
154775
  navIssues: () => navIssues,
154695
154776
  navSharedIdErrors: () => navSharedIdErrors,
@@ -154770,6 +154851,17 @@ async function navIssues(dir, strict) {
154770
154851
  error("nav-path-malformed", `navigation.${message}`);
154771
154852
  }
154772
154853
  for (const message of navSharedIdErrors(nav)) error("nav-row-id-shadows-tab", `navigation.${message}`);
154854
+ const topBarDefault = nav.topBarDefault;
154855
+ if (isPlainObject2(topBarDefault)) {
154856
+ for (const key3 of SCREEN_ONLY_TOP_BAR_KEYS) {
154857
+ const value = topBarDefault[key3];
154858
+ if (value === void 0 || value === null || value === "" || key3 === "scrollBehavior" && value === "pinned") continue;
154859
+ warn3(
154860
+ "nav-topbar-default-screen-field",
154861
+ key3 === "scrollBehavior" ? `navigation.topBarDefault.scrollBehavior ${JSON.stringify(value)} makes the bar of EVERY screen that sets no \`topBar\` hide on scroll, forms and presented screens included. Set \`topBar.scrollBehavior\` on the screens that scroll long content.` : `navigation.topBarDefault.${key3} is a binding to one screen's state: the default is copied onto every screen that sets no \`topBar\`, and each would resolve it against its own worker. Set \`topBar.${key3}\` on the screen that owns the value.`
154862
+ );
154863
+ }
154864
+ }
154773
154865
  const navKind = nav.navKind;
154774
154866
  const effectiveBottomTabs = navKind === void 0 || navKind === "bottomTabs" || typeof navKind !== "string" || !NAV_KINDS.has(navKind);
154775
154867
  const declaresOtherChrome = itemCount(nav.drawer) > 0 || itemCount(nav.sidebar) > 0;
@@ -154901,7 +154993,7 @@ function navSharedIdErrors(nav) {
154901
154993
  }
154902
154994
  return out2;
154903
154995
  }
154904
- var NAVIGATION_KEYS, NAV_KINDS, ITEMS_BLOCKS, SERVED_ONLY_NAV_KEYS, MISPLACED_TOP_LEVEL_KEYS, isPlainObject2, itemCount;
154996
+ var NAVIGATION_KEYS, NAV_KINDS, ITEMS_BLOCKS, SERVED_ONLY_NAV_KEYS, MISPLACED_TOP_LEVEL_KEYS, SCREEN_ONLY_TOP_BAR_KEYS, isPlainObject2, itemCount;
154905
154997
  var init_nav_lint = __esm({
154906
154998
  "src/nav-lint.ts"() {
154907
154999
  init_app_config_loader();
@@ -154954,6 +155046,7 @@ var init_nav_lint = __esm({
154954
155046
  "deepLinkPatterns",
154955
155047
  "linkableScreens"
154956
155048
  ];
155049
+ SCREEN_ONLY_TOP_BAR_KEYS = ["scrollBehavior", "dirtyPath", "visibilityPath"];
154957
155050
  isPlainObject2 = (v2) => typeof v2 === "object" && v2 !== null && !Array.isArray(v2);
154958
155051
  itemCount = (v2) => isPlainObject2(v2) && Array.isArray(v2.items) ? v2.items.length : 0;
154959
155052
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/himalaya-cli",
3
- "version": "0.1512.0",
3
+ "version": "0.1514.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": "b90f11814e5a926b40ad348a981b2d2a6c15445bfe39a6923a23c045"
74
+ "falconPackageHash": "b2ddd1eadb8b57663205c338a12cb5a71ac3af7098c1401e8a54ebb2"
75
75
  }
@@ -74,15 +74,24 @@ export function businessRealtimeStatusLabel(state: string, reason = ""): string
74
74
  const object = (value: unknown): RecordValue =>
75
75
  value !== null && typeof value === "object" && !Array.isArray(value) ? value as RecordValue : {};
76
76
 
77
- /** Return the only existing two-party business room; never create one or guess among matches. */
78
- export function selectExistingBusinessRoom(rooms: unknown[]): { id: string; participantId: string } | undefined {
79
- const candidates = rooms.filter((value) => {
77
+ /** Return a sole existing two-party business room, or a unique business-name match among several;
78
+ * never create a room or guess among remaining matches. */
79
+ export function selectExistingBusinessRoom(rooms: unknown[], businessName?: string): { id: string; participantId: string } | undefined {
80
+ let candidates = rooms.filter((value) => {
80
81
  const room = object(value);
81
82
  return typeof room.id === "string" && !!room.id &&
82
83
  typeof room.participantId === "string" && !!room.participantId &&
83
84
  room.participantCount === 2 && room.clientReferenceType === "contactId" &&
84
85
  Object.keys(object(room.businessContext)).length > 0;
85
86
  });
87
+ if (candidates.length > 1 && businessName?.trim()) {
88
+ // Keep case significant so differently named businesses are not conflated.
89
+ const name = businessName.trim();
90
+ candidates = candidates.filter((value) => {
91
+ const roomName = object(object(value).businessContext).name;
92
+ return typeof roomName === "string" && roomName.trim() === name;
93
+ });
94
+ }
86
95
  if (candidates.length !== 1) return undefined;
87
96
  const room = object(candidates[0]);
88
97
  return { id: room.id as string, participantId: room.participantId as string };
@@ -221,11 +221,11 @@ function me():ChatIdentity{
221
221
  return identity;
222
222
  }
223
223
  async function getCurrentMember():Promise<ChatIdentity>{return chat.chatIdentity();}
224
- async function resolveExistingBusinessRoom(startEpoch:number):Promise<{id:string;participantId:string}>{
224
+ async function resolveExistingBusinessRoom(startEpoch:number,businessName:string):Promise<{id:string;participantId:string}>{
225
225
  businessParticipantId='';
226
226
  const page=await chat.listRooms(me());
227
227
  if(startEpoch!==epoch)throw new Error('MemberAccessChanged');
228
- const room=selectExistingBusinessRoom(page.items);
228
+ const room=selectExistingBusinessRoom(page.items,businessName);
229
229
  if(!room)throw new Error('existing_business_conversation_unavailable');
230
230
  return room;
231
231
  }
@@ -359,7 +359,7 @@ const svc=defineService<State,Record<string,(s:State,a?:unknown)=>State|undefine
359
359
  if(oldPrincipal&&(oldPrincipal!==(identity.userId||identity.email)||s.scope!==identity.scope)){s=signed(clearPrivate(s,'guest'));myEpoch=epoch;reset=true;}
360
360
  currentIdentity=identity;
361
361
  s=shape({...s,phase:'loading',member:true,principal:identity.userId||identity.email,scope:identity.scope,error:'',notice:''});
362
- const existingRoom=await resolveExistingBusinessRoom(myEpoch);
362
+ const existingRoom=await resolveExistingBusinessRoom(myEpoch,signedBy);
363
363
  if(myEpoch!==epoch)return undefined;
364
364
  businessParticipantId=existingRoom.participantId;
365
365
  s=shape({...s,roomId:existingRoom.id});