@wix/himalaya-cli 0.1572.0 → 0.1574.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.
Files changed (103) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-module.d.ts +2 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/message-format.d.ts +59 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/checkout/src/index.d.ts +4 -0
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/apple-iap-contract.d.ts +1 -1
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/iap-checkout/src/commerce-contract.d.ts +2 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/index.d.ts +1 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/one-app-page.d.ts +61 -0
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/social-feed/src/index.d.ts +34 -9
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/checkout.mjs +28 -3
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +3 -3
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/iap-checkout.mjs +2 -1
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/l10n.mjs +8 -3
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +573 -73
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +3 -3
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-social-feed.mjs +24 -1
  16. package/dist/cli.mjs +2708 -1182
  17. package/dist/preview-assets.generated.bin +0 -0
  18. package/guides/himi-json-output.md +41 -2
  19. package/guides/himi-mcp.md +1 -1
  20. package/guides/himi-test.md +3 -2
  21. package/guides/iap-products.md +1 -1
  22. package/guides/importing-oneapp-translations.md +115 -0
  23. package/guides/index.json +6 -0
  24. package/guides/one-app-section-mappings.md +16 -4
  25. package/guides/one-app-to-himi-app.md +221 -10
  26. package/guides/qa-builds.md +21 -1
  27. package/guides/sdk-reference.json +28 -4
  28. package/guides/templates.md +3 -2
  29. package/guides/testing-himi-apps.md +1 -1
  30. package/guides/webview-page-sdk.md +68 -3
  31. package/package.json +3 -3
  32. package/templates/beauty-salon/dev/index.ts +22 -6
  33. package/templates/beauty-salon/tier5-src/_shared/iap-worker.ts +2 -0
  34. package/templates/beauty-salon/tier5-src/_shared/payment-setup.ts +6 -0
  35. package/templates/beauty-salon/tier5-src/himi-booking-time/index.ts +5 -2
  36. package/templates/beauty-salon/tier5-src/himi-branded-lite-cart/index.ts +5 -2
  37. package/templates/beauty-salon/tier5-src/himi-branded-lite-plans/index.ts +5 -2
  38. package/templates/beauty-salon-owner/dev/index.ts +22 -6
  39. package/templates/branded-lite/dev/index.ts +22 -6
  40. package/templates/branded-lite/tier5-src/_shared/iap-worker.ts +2 -0
  41. package/templates/branded-lite/tier5-src/_shared/payment-setup.ts +6 -0
  42. package/templates/branded-lite/tier5-src/himi-booking-time/index.ts +5 -2
  43. package/templates/branded-lite/tier5-src/himi-branded-lite-cart/index.ts +5 -2
  44. package/templates/branded-lite/tier5-src/himi-branded-lite-plans/index.ts +5 -2
  45. package/templates/branded-lite/tier5-src/himi-branded-lite-program/index.ts +5 -2
  46. package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +9 -4
  47. package/templates/community-club/dev/index.ts +22 -6
  48. package/templates/community-club/tier5-src/_shared/iap-worker.ts +2 -0
  49. package/templates/community-club/tier5-src/_shared/payment-setup.ts +6 -0
  50. package/templates/community-club/tier5-src/himi-events-detail/index.ts +9 -4
  51. package/templates/community-club-owner/dev/index.ts +22 -6
  52. package/templates/events-meetups/dev/index.ts +22 -6
  53. package/templates/events-meetups/tier5-src/_shared/iap-worker.ts +2 -0
  54. package/templates/events-meetups/tier5-src/_shared/payment-setup.ts +6 -0
  55. package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +9 -4
  56. package/templates/events-meetups-owner/dev/index.ts +22 -6
  57. package/templates/gym-fitness/dev/index.ts +22 -6
  58. package/templates/gym-fitness/tier5-src/_shared/iap-worker.ts +2 -0
  59. package/templates/gym-fitness/tier5-src/_shared/payment-setup.ts +6 -0
  60. package/templates/gym-fitness/tier5-src/himi-booking-time/index.ts +5 -2
  61. package/templates/gym-fitness/tier5-src/himi-branded-lite-cart/index.ts +5 -2
  62. package/templates/gym-fitness/tier5-src/himi-branded-lite-plans/index.ts +5 -2
  63. package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +9 -4
  64. package/templates/gym-fitness-owner/dev/index.ts +22 -6
  65. package/templates/himi-chat/dev/index.ts +22 -6
  66. package/templates/nonprofit-cause/dev/index.ts +22 -6
  67. package/templates/nonprofit-cause/tier5-src/_shared/iap-worker.ts +2 -0
  68. package/templates/nonprofit-cause/tier5-src/_shared/payment-setup.ts +6 -0
  69. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-plans/index.ts +5 -2
  70. package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +9 -4
  71. package/templates/nonprofit-cause-owner/dev/index.ts +22 -6
  72. package/templates/owner-lite/dev/index.ts +22 -6
  73. package/templates/podcast-creator/dev/index.ts +22 -6
  74. package/templates/podcast-creator/tier5-src/_shared/iap-worker.ts +2 -0
  75. package/templates/podcast-creator/tier5-src/_shared/payment-setup.ts +6 -0
  76. package/templates/podcast-creator/tier5-src/himi-branded-lite-plans/index.ts +5 -2
  77. package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +9 -4
  78. package/templates/podcast-creator-owner/dev/index.ts +22 -6
  79. package/templates/portfolio-creative/dev/index.ts +22 -6
  80. package/templates/portfolio-creative/tier5-src/_shared/iap-worker.ts +2 -0
  81. package/templates/portfolio-creative/tier5-src/_shared/payment-setup.ts +6 -0
  82. package/templates/portfolio-creative/tier5-src/himi-branded-lite-cart/index.ts +5 -2
  83. package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +9 -4
  84. package/templates/portfolio-creative-owner/dev/index.ts +22 -6
  85. package/templates/restaurant/dev/index.ts +22 -6
  86. package/templates/restaurant/tier5-src/_shared/iap-worker.ts +2 -0
  87. package/templates/restaurant/tier5-src/_shared/payment-setup.ts +6 -0
  88. package/templates/restaurant/tier5-src/himi-events-detail/index.ts +9 -4
  89. package/templates/restaurant-owner/dev/index.ts +22 -6
  90. package/templates/retail-store/dev/index.ts +22 -6
  91. package/templates/retail-store/tier5-src/_shared/iap-worker.ts +2 -0
  92. package/templates/retail-store/tier5-src/_shared/payment-setup.ts +6 -0
  93. package/templates/retail-store/tier5-src/himi-branded-lite-cart/index.ts +5 -2
  94. package/templates/retail-store-owner/dev/index.ts +22 -6
  95. package/templates/surface-showcase/dev/index.ts +22 -6
  96. package/templates/yoga-studio/dev/index.ts +22 -6
  97. package/templates/yoga-studio/tier5-src/_shared/iap-worker.ts +2 -0
  98. package/templates/yoga-studio/tier5-src/_shared/payment-setup.ts +6 -0
  99. package/templates/yoga-studio/tier5-src/himi-booking-time/index.ts +5 -2
  100. package/templates/yoga-studio/tier5-src/himi-branded-lite-plans/index.ts +5 -2
  101. package/templates/yoga-studio/tier5-src/himi-branded-lite-program/index.ts +5 -2
  102. package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +9 -4
  103. package/templates/yoga-studio-owner/dev/index.ts +22 -6
@@ -112,6 +112,8 @@ export interface BundleSource {
112
112
  * contract parity (spec invariants 18 + 19). OTA only revalidates the seed.
113
113
  */
114
114
  export interface AppSeed {
115
+ /** Live-only exact screens to omit from the generated binary seed. They remain in OTA releases. */
116
+ excludeScreens?: readonly string[];
115
117
  /** First-run screen descriptors, keyed by screenId. */
116
118
  screens: Record<string, ScreenDescriptor>;
117
119
  /** First-run entity snapshots (the per-app data substrate, e.g. data/*.json). */
@@ -18,6 +18,36 @@ export declare function pluralCategory(n: number, locale: string): PluralCategor
18
18
  * table arbitrarily wrong — which is how the obsolete Hebrew `many` rule nearly shipped.
19
19
  */
20
20
  export declare function pluralCategoryFallback(n: number, locale: string): PluralCategory;
21
+ /** Split the body of `{...}` on top-level commas into at most 3 parts.
22
+ *
23
+ * Exported for tools/l10n/import-oneapp.ts, which converts foreign catalogs with the SAME
24
+ * tokenizer `formatMessage` renders with — a second brace scanner would be free to disagree
25
+ * about what is an argument, and the disagreement would surface as a corrupted translation.
26
+ *
27
+ * @internal Tokenizer plumbing for the importer, not SDK surface — do not depend on it
28
+ * from app or worker code. */
29
+ export declare function splitArg(body: string): string[];
30
+ /** One parsed branch: its selector, its body, and where the body sits in the spec. */
31
+ export interface BranchEntry {
32
+ key: string;
33
+ body: string;
34
+ /** Offset of the body's first character in the spec (just past the opening brace). */
35
+ bodyStart: number;
36
+ /** Offset one past the body's last character (the closing brace's position). */
37
+ bodyEnd: number;
38
+ }
39
+ /** Parse `one {…} other {…}` into its branches IN SOURCE ORDER, preserving nested braces,
40
+ * with each body's offsets so a caller can rewrite a body in place.
41
+ *
42
+ * A `Record` cannot carry the order: `Object.entries` lists integer-like keys first, so a
43
+ * rebuild from one reorders `other {a} 1 {b}` — which changes the string, and with it any
44
+ * id derived from the string.
45
+ * @internal Tokenizer plumbing for the importer, not SDK surface. */
46
+ export declare function parseBranchEntries(spec: string): BranchEntry[];
47
+ /** Parse `one {…} other {…}` into its branches, preserving nested braces.
48
+ * Exported for the same reason as `splitArg`.
49
+ * @internal Tokenizer plumbing for the importer, not SDK surface. */
50
+ export declare function parseBranches(spec: string): Record<string, string>;
21
51
  /**
22
52
  * Format an ICU pattern.
23
53
  *
@@ -26,3 +56,32 @@ export declare function pluralCategoryFallback(n: number, locale: string): Plura
26
56
  * that makes a `$t:` miss fall back to its key.
27
57
  */
28
58
  export declare function formatMessage(pattern: string, args?: Record<string, unknown>, locale?: string): string;
59
+ /** Whether `formatMessage` can ever select a branch with this selector for a `plural` or
60
+ * `select` argument. Shared with the importer so "reported" and "kept verbatim" agree.
61
+ * @internal Importer plumbing, not SDK surface. */
62
+ export declare function isBranchSelector(kind: "plural" | "select", key: string): boolean;
63
+ /**
64
+ * Every construct in `pattern` that is OUTSIDE the subset `formatMessage` implements —
65
+ * i.e. everything that would hit one of its degradation branches (verbatim text, raw
66
+ * value, empty branch set) instead of being formatted.
67
+ *
68
+ * This exists for importers (RFC 0054, `himi l10n import`): a catalog converted from a
69
+ * richer MessageFormat dialect must KEEP such a message verbatim — degrading to visible
70
+ * text is this module's contract — but the import report has to NAME it, because "renders
71
+ * its raw ICU source to users" is a decision a human should get to veto. Scanning with the
72
+ * same tokenizer `formatMessage` uses (same quoting rules, same balanced-brace scan, same
73
+ * `splitArg`/`parseBranches`) is what keeps "unsupported" synonymous with "formatMessage
74
+ * would not format this", instead of a second opinion that drifts.
75
+ *
76
+ * Returns human-readable descriptions, one per finding, in source order. Empty = the whole
77
+ * pattern is inside the subset (simple arguments, `plural` with `=N`/`#`, `select`, and
78
+ * `select`/plural nesting that `formatMessage` renders correctly). Two shapes that look
79
+ * nested-and-fine are NOT: `formatMessage` replaces every `#` in a chosen plural branch
80
+ * with that plural's number BEFORE it handles quoting or recurses, so a plural nested in a
81
+ * plural has its own `#` clobbered by the outer one, and a quoted `'#'` renders as the
82
+ * number in quotes. Both are reported.
83
+ *
84
+ * @internal Importer plumbing, not SDK surface — a worker has no reason to ask this;
85
+ * `formatMessage` already degrades gracefully at runtime.
86
+ */
87
+ export declare function unsupportedConstructs(pattern: string): string[];
@@ -52,7 +52,11 @@ export type PayOutcome =
52
52
  | {
53
53
  kind: "failed";
54
54
  reason: string;
55
+ code?: "SITE_NOT_ACCEPTING_PAYMENTS";
55
56
  };
57
+ /** Match Wix's application code, including the native HTTP bridge frame and a
58
+ * complete web HTTP JSON envelope. Prose and truncated bodies are not evidence. */
59
+ export declare function isPaymentSetupFailure(error: unknown): boolean;
56
60
  export interface PayRequest {
57
61
  appId: string;
58
62
  /** Cashier order snapshot. May be empty — see `cashierUrl`. */
@@ -198,7 +198,7 @@ export interface OrderRefStore {
198
198
  siteId: string;
199
199
  }): boolean | null;
200
200
  }
201
- export type OrderFailureCode = "notEnabled" | "notConfigured" | "signInRequired" | "unsupportedItem" | "notAppleRoute" | "storageUnavailable" | "approvalRequired" | "orderClosed" | "orderRefused" | "chargeFailed" | "paymentRefused" | "paymentHeld" | "alreadyOwned" | "paymentInProgress" | "productChanged" | "invalidAssociation" | "needsSupport" | "unavailable" | "sessionChanged" | "outcomeUnknown";
201
+ export type OrderFailureCode = "notEnabled" | "notConfigured" | "signInRequired" | "unsupportedItem" | "notAppleRoute" | "storageUnavailable" | "approvalRequired" | "orderClosed" | "orderRefused" | "chargeFailed" | "paymentRefused" | "paymentHeld" | "alreadyOwned" | "paymentInProgress" | "productChanged" | "sitePaymentUnavailable" | "invalidAssociation" | "needsSupport" | "unavailable" | "sessionChanged" | "outcomeUnknown";
202
202
  /** Progress of a payment this device handed to wix-iap, tracked from its durable reference. */
203
203
  export type PaymentAccess = "processing" | "granted" | "accessUnknown" | "needsSupport";
204
204
  export interface PaymentProgress {
@@ -92,6 +92,8 @@ export interface IapPurchaseCopy {
92
92
  unavailable: string;
93
93
  signInRequired: string;
94
94
  retry: string;
95
+ /** Optional for existing SDK consumers; the app supplies a localized recovery message. */
96
+ sitePaymentUnavailable?: string;
95
97
  priceChanged: string;
96
98
  support: string;
97
99
  }
@@ -1,5 +1,6 @@
1
1
  export * from "./business-contact.js";
2
2
  export * from "./business-contact-service.js";
3
+ export * from "./one-app-page.js";
3
4
  export * from "./invite.js";
4
5
  import { entitlement } from "@wix/himalaya/checkout";
5
6
  type Node = Record<string, any>;
@@ -0,0 +1,61 @@
1
+ /** A decoded editorial document, suitable for copying into editable app source. Root editor metadata is omitted. */
2
+ export interface OneAppPage {
3
+ pageId: string;
4
+ title: string;
5
+ contentType: "RICH_CONTENT" | "DRAFTJS" | "PLAIN_TEXT";
6
+ documentJson: string;
7
+ plainText: string;
8
+ empty: boolean;
9
+ normalizedWebsiteLinks: number;
10
+ }
11
+ export type OneAppPageContentError = Error & {
12
+ code: "invalid" | "unsupported";
13
+ };
14
+ /** Stable parse failures without a subclass: worker bundles deliberately forbid class syntax. */
15
+ export declare function oneAppPageContentErrorCode(error: unknown): "invalid" | "unsupported" | undefined;
16
+ /** Validate a UUID source page selector before constructing a Pages read. */
17
+ export declare const isOneAppPageId: (value: unknown) => value is string;
18
+ /** Decode the exact Pages response; malformed, mismatched and unsupported documents throw.
19
+ * A real empty document succeeds with empty=true. Renderer media sizing and link sanitization
20
+ * use the existing bounded RichContent encoder on every format. */
21
+ export declare function decodeOneAppPage(response: unknown, expectedPageId: string): OneAppPage;
22
+ /** Editable native RichContent at one source placement. A document is literal data,
23
+ * including dollar-prefixed prose; it is never interpreted as service bindings.
24
+ * The standard RichContent link handler opens http(s), mailto and tel on each host. */
25
+ export declare function oneAppPageSection(page: OneAppPage, options: {
26
+ id: string;
27
+ emptyTitle?: string;
28
+ emptyDescription?: string;
29
+ }): {
30
+ id: string;
31
+ body: {
32
+ package: string;
33
+ type: string;
34
+ props: {
35
+ spacing: number;
36
+ children: {
37
+ id: string;
38
+ body: {
39
+ package: string;
40
+ type: string;
41
+ props: {
42
+ text: string;
43
+ style: string;
44
+ };
45
+ };
46
+ }[];
47
+ documentJson?: undefined;
48
+ };
49
+ };
50
+ } | {
51
+ id: string;
52
+ body: {
53
+ package: string;
54
+ type: string;
55
+ props: {
56
+ documentJson: string;
57
+ spacing?: undefined;
58
+ children?: undefined;
59
+ };
60
+ };
61
+ };
@@ -84,18 +84,43 @@ export interface WixListFeedItemsResponse {
84
84
  profiles?: WixFeedProfile[];
85
85
  nextPageCursor?: string;
86
86
  }
87
+ /** Read controls shared by the source's single-group and central feeds. */
88
+ export interface WixFeedPageOptions extends WixCallOptions {
89
+ /** Opaque server cursor; pass it back unchanged when loading the next page. */
90
+ cursor?: string;
91
+ invalidatePermissionsCache?: boolean;
92
+ }
93
+ export interface WixGroupFeedOptions extends WixFeedPageOptions {
94
+ topicId?: string;
95
+ }
96
+ export interface WixCentralFeedOptions extends WixFeedPageOptions {
97
+ withSuggestedPosts?: boolean;
98
+ /** Omit to use the central-feed service's default representation. */
99
+ contentType?: "DRAFTJS";
100
+ }
101
+ /**
102
+ * List one group's activity feed. Mirrors wix-one-app-feed getFeedPosts:
103
+ * containerId + Groups appDefId + feedType=all + contentType=DRAFTJS, with optional
104
+ * topic and opaque paging cursor. Existing site/cache options remain per-call.
105
+ * Reactions lists must not be treated as authoritative totals.
106
+ *
107
+ * @scope member — verified live with a signed-in member session; visitor readability
108
+ * depends on group permissions and is not established by the central-feed probe.
109
+ */
110
+ export declare function listFeedItems(groupId: string, limit?: number, options?: WixGroupFeedOptions): Promise<WixListFeedItemsResponse>;
87
111
  /**
88
- * List a group's activity feed — GET
89
- * https://social.wix.com/serverless/mobile/feed/v4/feedPosts (the ENRICHED read the
90
- * real mobile app uses). Each item carries content (Ricos blocks), commentsCount, and
91
- * reactionsList (count = length); the response's top-level `profiles[]` resolves each
92
- * item's author.id → userName + profileImage. Verified live (200). Replaces the lean
93
- * GET /api/v1/feed/items read, which omitted counts + author.
112
+ * List the site's combined feed, rather than substituting a selected group's feed.
113
+ * Mirrors wix-one-app-feed getCentralFeedPosts: there is no containerId or appDefId.
114
+ * Authentication and business selection belong to the bridge (or per-call `site`).
94
115
  *
95
- * @scope member — verified live with a signed-in member session; visitor/anonymous
96
- * readability of a public group's feed is unconfirmed.
116
+ * Source: wix-one-app-feed@6ef53170e94e27349d2a6c1cf08038b078d86228,
117
+ * src/services/feed-api.ts. A real Visitor read returned 200 with posts and a cursor.
118
+ * That establishes the server contract only: native consumers need a core release with the exact read-route guard, and
119
+ * production web still refuses social.wix.com. This SDK method does
120
+ * not change those policies or establish membership/write permission. Consumers must
121
+ * surface a transport refusal; they must not substitute a group directory or empty feed.
97
122
  */
98
- export declare function listFeedItems(groupId: string, limit?: number, options?: WixCallOptions): Promise<WixListFeedItemsResponse>;
123
+ export declare function listCentralFeedItems(limit?: number, options?: WixCentralFeedOptions): Promise<WixListFeedItemsResponse>;
99
124
  /**
100
125
  * Create a feed post in a group as the signed-in member — POST
101
126
  * https://social.wix.com/api/v1/feed/items. `content` is the post text (modern
@@ -146,6 +146,26 @@ async function entitlement(planId) {
146
146
  async function isEntitled() {
147
147
  return (await entitlement()).entitled;
148
148
  }
149
+ function isPaymentSetupFailure(error) {
150
+ if (!error || typeof error !== "object") return false;
151
+ const value = error;
152
+ if (value.code === "SITE_NOT_ACCEPTING_PAYMENTS" || value.applicationError?.code === "SITE_NOT_ACCEPTING_PAYMENTS" || value.details?.applicationError?.code === "SITE_NOT_ACCEPTING_PAYMENTS") return true;
153
+ if (typeof value.message !== "string") return false;
154
+ if (/^HTTP \d{3} \[SITE_NOT_ACCEPTING_PAYMENTS\]:/.test(value.message)) return true;
155
+ const web = /^HTTP \d{3}: (\{[\s\S]*\})$/.exec(value.message);
156
+ if (!web) return false;
157
+ try {
158
+ const body = JSON.parse(web[1]);
159
+ return body?.code === "SITE_NOT_ACCEPTING_PAYMENTS" || body?.applicationError?.code === "SITE_NOT_ACCEPTING_PAYMENTS" || body?.details?.applicationError?.code === "SITE_NOT_ACCEPTING_PAYMENTS";
160
+ } catch {
161
+ return false;
162
+ }
163
+ }
164
+ var PAYMENT_SETUP_FAILURE = {
165
+ kind: "failed",
166
+ code: "SITE_NOT_ACCEPTING_PAYMENTS",
167
+ reason: "the site is not accepting online payments"
168
+ };
149
169
  var WITHDRAWN = { kind: "failed", reason: "the caller withdrew the charge" };
150
170
  async function payOrder(req) {
151
171
  if (!req.snapshotId && !req.cashierUrl && !req.openCashier) {
@@ -160,7 +180,9 @@ async function payOrder(req) {
160
180
  msid: req.msid,
161
181
  amount: req.amount,
162
182
  currency: req.currency
163
- }).catch(() => ({ status: "failed" }));
183
+ }).catch((error) => ({ status: "failed", setupUnavailable: isPaymentSetupFailure(error) }));
184
+ if ("setupUnavailable" in r && r.setupUnavailable) return PAYMENT_SETUP_FAILURE;
185
+ if (r.status === "failed" && isPaymentSetupFailure({ message: "error" in r ? r.error : void 0 })) return PAYMENT_SETUP_FAILURE;
164
186
  if (r.status === "paid" || r.status === "pending") {
165
187
  const chargeId = r.chargeId;
166
188
  return {
@@ -173,11 +195,13 @@ async function payOrder(req) {
173
195
  }
174
196
  if (req.openCashier) {
175
197
  if (await req.mayCharge?.() === false) return WITHDRAWN;
176
- const opened = await req.openCashier(async () => await req.mayCharge?.() !== false).catch(() => false);
198
+ const opened = await req.openCashier(async () => await req.mayCharge?.() !== false).catch((error) => isPaymentSetupFailure(error) ? PAYMENT_SETUP_FAILURE : false);
199
+ if (typeof opened === "object") return opened;
177
200
  if (opened === "withdrawn") return WITHDRAWN;
178
201
  if (opened === true) return { kind: "handoff" };
179
202
  } else if (req.cashierUrl) {
180
- const url = await req.cashierUrl().catch(() => void 0);
203
+ const url = await req.cashierUrl().catch((error) => isPaymentSetupFailure(error) ? PAYMENT_SETUP_FAILURE : void 0);
204
+ if (typeof url === "object") return url;
181
205
  if (url) {
182
206
  if (await req.mayCharge?.() === false) return WITHDRAWN;
183
207
  const opened = await open(url, "in_app_browser").catch(() => ({ opened: false }));
@@ -194,6 +218,7 @@ export {
194
218
  activePlanIds,
195
219
  entitlement,
196
220
  isEntitled,
221
+ isPaymentSetupFailure,
197
222
  payOrder as payCashierOrder,
198
223
  payOrder
199
224
  };
@@ -10035,9 +10035,9 @@ var PREVIEW_SURFACES = [
10035
10035
  },
10036
10036
  {
10037
10037
  // NOTE: 834 is iPad portrait — six points UNDER the 840 `expanded`
10038
- // breakpoint, so an iPad in portrait resolves to `medium` and gets bottom
10039
- // tabs, becoming a sidebar only in landscape (1112). That is the shipped
10040
- // behaviour of the ladder, not a quirk of this registry.
10038
+ // breakpoint, so an iPad in portrait resolves to `medium`: full-bleed content
10039
+ // and, for responsive navigation, a sidebar (native wide starts at 600).
10040
+ // Landscape (1112) is expanded and applies the readable content measure.
10041
10041
  id: "tablet",
10042
10042
  label: "Tablet",
10043
10043
  chassis: "tablet",
@@ -2308,7 +2308,7 @@ var ITEM_REFUSALS = {
2308
2308
  PRODUCT_NOT_AVAILABLE: "paymentRefused",
2309
2309
  ALREADY_OWNED: "paymentRefused",
2310
2310
  ITEM_NOT_AVAILABLE: "orderRefused",
2311
- SITE_NOT_ACCEPTING_PAYMENTS: "orderRefused",
2311
+ SITE_NOT_ACCEPTING_PAYMENTS: "sitePaymentUnavailable",
2312
2312
  UNSUPPORTED_ORDER: "orderRefused"
2313
2313
  };
2314
2314
  var KIND_STOPS = {
@@ -2777,6 +2777,7 @@ function outcomeAction(state, copy) {
2777
2777
  }
2778
2778
  }
2779
2779
  function refusalAction(failure3, copy) {
2780
+ if (failure3 === "sitePaymentUnavailable") return action(copy, "enabled", copy.sitePaymentUnavailable ?? copy.retry);
2780
2781
  const [mode, note] = REFUSALS[failure3 ?? "unavailable"] ?? ["enabled", "retry"];
2781
2782
  return action(copy, mode, note ? copy[note] ?? "" : "");
2782
2783
  }
@@ -40,8 +40,8 @@ function splitArg(body) {
40
40
  out.push(body.slice(start));
41
41
  return out;
42
42
  }
43
- function parseBranches(spec) {
44
- const branches = {};
43
+ function parseBranchEntries(spec) {
44
+ const entries = [];
45
45
  let i = 0;
46
46
  while (i < spec.length) {
47
47
  while (i < spec.length && /\s/.test(spec[i])) i++;
@@ -59,9 +59,14 @@ function parseBranches(spec) {
59
59
  depth--;
60
60
  }
61
61
  }
62
- branches[key] = spec.slice(bodyStart, i);
62
+ entries.push({ key, body: spec.slice(bodyStart, i), bodyStart, bodyEnd: i });
63
63
  i++;
64
64
  }
65
+ return entries;
66
+ }
67
+ function parseBranches(spec) {
68
+ const branches = {};
69
+ for (const { key, body } of parseBranchEntries(spec)) branches[key] = body;
65
70
  return branches;
66
71
  }
67
72
  function formatMessage(pattern, args = {}, locale2 = "en") {