@wix/himalaya-cli 0.1029.0 → 0.1031.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 (185) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +7 -0
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-gateway.d.ts +32 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/wix-gateway.rules.d.ts +2 -1
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +7 -0
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/genie-chat/src/index.d.ts +64 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-genie-chat.mjs +41 -1
  7. package/dist/cli.mjs +298 -114
  8. package/dist/preview-assets.generated.bin +0 -0
  9. package/guides/component-reference.json +0 -7
  10. package/guides/component-reference.md +0 -2
  11. package/guides/sdk-reference.json +50 -2
  12. package/package.json +2 -2
  13. package/templates/beauty-salon/dev/index.ts +575 -214
  14. package/templates/beauty-salon/tier5-src/_shared/collection-contract.ts +4 -1
  15. package/templates/beauty-salon/tier5-src/_shared/owner-load-error.ts +7 -1
  16. package/templates/beauty-salon/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  17. package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +36 -5
  18. package/templates/beauty-salon/tier5-src/wix-spaces-app-language/index.ts +4 -2
  19. package/templates/beauty-salon-owner/config.ts +1 -1
  20. package/templates/beauty-salon-owner/dev/index.ts +247 -9
  21. package/templates/beauty-salon-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  22. package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +405 -20
  23. package/templates/beauty-salon-owner/tier5-src/_shared/collection-contract.ts +4 -1
  24. package/templates/beauty-salon-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  25. package/templates/beauty-salon-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  26. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  27. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  28. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  29. package/templates/branded-lite/dev/index.ts +699 -228
  30. package/templates/branded-lite/tier5-src/_shared/collection-contract.ts +4 -1
  31. package/templates/branded-lite/tier5-src/_shared/owner-load-error.ts +7 -1
  32. package/templates/branded-lite/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  33. package/templates/branded-lite/tier5-src/himi-branded-lite-notifsettings/index.ts +11 -6
  34. package/templates/branded-lite/tier5-src/himi-branded-lite-reviews/index.ts +11 -6
  35. package/templates/branded-lite/tier5-src/himi-store-product/index.ts +36 -5
  36. package/templates/branded-lite/tier5-src/wix-spaces-app-language/index.ts +4 -2
  37. package/templates/community-club/dev/index.ts +451 -204
  38. package/templates/community-club/tier5-src/_shared/collection-contract.ts +4 -1
  39. package/templates/community-club/tier5-src/_shared/owner-load-error.ts +7 -1
  40. package/templates/community-club/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  41. package/templates/community-club/tier5-src/wix-spaces-app-language/index.ts +4 -2
  42. package/templates/community-club-owner/config.ts +1 -1
  43. package/templates/community-club-owner/dev/index.ts +247 -9
  44. package/templates/community-club-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  45. package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +405 -20
  46. package/templates/community-club-owner/tier5-src/_shared/collection-contract.ts +4 -1
  47. package/templates/community-club-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  48. package/templates/community-club-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  49. package/templates/community-club-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  50. package/templates/community-club-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  51. package/templates/community-club-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  52. package/templates/events-meetups/dev/index.ts +451 -204
  53. package/templates/events-meetups/tier5-src/_shared/collection-contract.ts +4 -1
  54. package/templates/events-meetups/tier5-src/_shared/owner-load-error.ts +7 -1
  55. package/templates/events-meetups/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  56. package/templates/events-meetups/tier5-src/wix-spaces-app-language/index.ts +4 -2
  57. package/templates/events-meetups-owner/config.ts +1 -1
  58. package/templates/events-meetups-owner/dev/index.ts +247 -9
  59. package/templates/events-meetups-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  60. package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +405 -20
  61. package/templates/events-meetups-owner/tier5-src/_shared/collection-contract.ts +4 -1
  62. package/templates/events-meetups-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  63. package/templates/events-meetups-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  64. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  65. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  66. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  67. package/templates/gym-fitness/dev/index.ts +575 -214
  68. package/templates/gym-fitness/tier5-src/_shared/collection-contract.ts +4 -1
  69. package/templates/gym-fitness/tier5-src/_shared/owner-load-error.ts +7 -1
  70. package/templates/gym-fitness/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  71. package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +36 -5
  72. package/templates/gym-fitness/tier5-src/wix-spaces-app-language/index.ts +4 -2
  73. package/templates/gym-fitness-owner/config.ts +1 -1
  74. package/templates/gym-fitness-owner/dev/index.ts +247 -9
  75. package/templates/gym-fitness-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  76. package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +405 -20
  77. package/templates/gym-fitness-owner/tier5-src/_shared/collection-contract.ts +4 -1
  78. package/templates/gym-fitness-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  79. package/templates/gym-fitness-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  80. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  81. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  82. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  83. package/templates/himi-chat/tier5-src/_shared/owner-load-error.ts +7 -1
  84. package/templates/nonprofit-cause/dev/index.ts +451 -204
  85. package/templates/nonprofit-cause/tier5-src/_shared/collection-contract.ts +4 -1
  86. package/templates/nonprofit-cause/tier5-src/_shared/owner-load-error.ts +7 -1
  87. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  88. package/templates/nonprofit-cause/tier5-src/wix-spaces-app-language/index.ts +4 -2
  89. package/templates/nonprofit-cause-owner/config.ts +1 -1
  90. package/templates/nonprofit-cause-owner/dev/index.ts +247 -9
  91. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  92. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +405 -20
  93. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-contract.ts +4 -1
  94. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  95. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  96. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  97. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  98. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  99. package/templates/owner-lite/config.ts +1 -1
  100. package/templates/owner-lite/dev/index.ts +247 -9
  101. package/templates/owner-lite/tier5-src/_shared/aria-attachments.ts +179 -0
  102. package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +405 -20
  103. package/templates/owner-lite/tier5-src/_shared/collection-contract.ts +4 -1
  104. package/templates/owner-lite/tier5-src/_shared/owner-bookings.ts +20 -0
  105. package/templates/owner-lite/tier5-src/_shared/owner-load-error.ts +7 -1
  106. package/templates/owner-lite/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  107. package/templates/owner-lite/tier5-src/himi-owner-lite-home/index.ts +2 -12
  108. package/templates/owner-lite/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  109. package/templates/podcast-creator/dev/index.ts +451 -204
  110. package/templates/podcast-creator/tier5-src/_shared/collection-contract.ts +4 -1
  111. package/templates/podcast-creator/tier5-src/_shared/owner-load-error.ts +7 -1
  112. package/templates/podcast-creator/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  113. package/templates/podcast-creator/tier5-src/wix-spaces-app-language/index.ts +4 -2
  114. package/templates/podcast-creator-owner/config.ts +1 -1
  115. package/templates/podcast-creator-owner/dev/index.ts +247 -9
  116. package/templates/podcast-creator-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  117. package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +405 -20
  118. package/templates/podcast-creator-owner/tier5-src/_shared/collection-contract.ts +4 -1
  119. package/templates/podcast-creator-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  120. package/templates/podcast-creator-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  121. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  122. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  123. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  124. package/templates/portfolio-creative/dev/index.ts +575 -214
  125. package/templates/portfolio-creative/tier5-src/_shared/collection-contract.ts +4 -1
  126. package/templates/portfolio-creative/tier5-src/_shared/owner-load-error.ts +7 -1
  127. package/templates/portfolio-creative/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  128. package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +36 -5
  129. package/templates/portfolio-creative/tier5-src/wix-spaces-app-language/index.ts +4 -2
  130. package/templates/portfolio-creative-owner/config.ts +1 -1
  131. package/templates/portfolio-creative-owner/dev/index.ts +247 -9
  132. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  133. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +405 -20
  134. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-contract.ts +4 -1
  135. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  136. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  137. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  138. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  139. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  140. package/templates/restaurant/dev/index.ts +451 -204
  141. package/templates/restaurant/tier5-src/_shared/collection-contract.ts +4 -1
  142. package/templates/restaurant/tier5-src/_shared/owner-load-error.ts +7 -1
  143. package/templates/restaurant/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  144. package/templates/restaurant/tier5-src/wix-spaces-app-language/index.ts +4 -2
  145. package/templates/restaurant-owner/config.ts +1 -1
  146. package/templates/restaurant-owner/dev/index.ts +247 -9
  147. package/templates/restaurant-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  148. package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +405 -20
  149. package/templates/restaurant-owner/tier5-src/_shared/collection-contract.ts +4 -1
  150. package/templates/restaurant-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  151. package/templates/restaurant-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  152. package/templates/restaurant-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  153. package/templates/restaurant-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  154. package/templates/restaurant-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  155. package/templates/retail-store/dev/index.ts +575 -214
  156. package/templates/retail-store/tier5-src/_shared/collection-contract.ts +4 -1
  157. package/templates/retail-store/tier5-src/_shared/owner-load-error.ts +7 -1
  158. package/templates/retail-store/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  159. package/templates/retail-store/tier5-src/himi-store-product/index.ts +36 -5
  160. package/templates/retail-store/tier5-src/wix-spaces-app-language/index.ts +4 -2
  161. package/templates/retail-store-owner/config.ts +1 -1
  162. package/templates/retail-store-owner/dev/index.ts +247 -9
  163. package/templates/retail-store-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  164. package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +405 -20
  165. package/templates/retail-store-owner/tier5-src/_shared/collection-contract.ts +4 -1
  166. package/templates/retail-store-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  167. package/templates/retail-store-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  168. package/templates/retail-store-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  169. package/templates/retail-store-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  170. package/templates/retail-store-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
  171. package/templates/yoga-studio/dev/index.ts +451 -204
  172. package/templates/yoga-studio/tier5-src/_shared/collection-contract.ts +4 -1
  173. package/templates/yoga-studio/tier5-src/_shared/owner-load-error.ts +7 -1
  174. package/templates/yoga-studio/tier5-src/himi-branded-lite-appearance/index.ts +12 -1
  175. package/templates/yoga-studio/tier5-src/wix-spaces-app-language/index.ts +4 -2
  176. package/templates/yoga-studio-owner/config.ts +1 -1
  177. package/templates/yoga-studio-owner/dev/index.ts +247 -9
  178. package/templates/yoga-studio-owner/tier5-src/_shared/aria-attachments.ts +179 -0
  179. package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +405 -20
  180. package/templates/yoga-studio-owner/tier5-src/_shared/collection-contract.ts +4 -1
  181. package/templates/yoga-studio-owner/tier5-src/_shared/owner-bookings.ts +20 -0
  182. package/templates/yoga-studio-owner/tier5-src/_shared/owner-load-error.ts +7 -1
  183. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-aria/index.ts +40 -1
  184. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-home/index.ts +2 -12
  185. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-manage/index.ts +10 -4
@@ -14,6 +14,9 @@ export interface CollectionConfig {
14
14
  searchPlaceholder?: string;
15
15
  sortLabels?: { default: string; az: string; za: string };
16
16
  metadata?: string[];
17
+ /** Numeric 0–5 row field rendered as a Rating (accessible "N out of 5") instead of
18
+ * folding a "★★★★☆" glyph string into the metadata line, so screen readers get a value. */
19
+ rating?: string;
17
20
  sectioned?: boolean;
18
21
  view: 'list' | 'grid';
19
22
  backendQuery?: boolean;
@@ -58,7 +61,7 @@ export const COLLECTIONS: Record<string, CollectionConfig> = {
58
61
  himiBrandedCoupons: { rows: 'coupons', title: 'name', subtitle: 'subtitle', view: 'list', primaryVerb: { label: 'Get code' } },
59
62
  himiBrandedNotifications: { rows: 'items', title: 'name', subtitle: 'subtitle', image: 'photo', metadata: ['unreadDot'], view: 'list' },
60
63
  himiBrandedLoyalty: { rows: 'rewards', title: 'name', subtitle: 'description', view: 'grid', primaryVerb: { label: 'Redeem' } },
61
- himiBrandedReviews: { rows: 'reviews', title: 'title', subtitle: 'body', metadata: ['author', 'stars'], view: 'list' },
64
+ himiBrandedReviews: { rows: 'reviews', title: 'title', subtitle: 'body', metadata: ['author'], rating: 'rating', view: 'list' },
62
65
  himiBrandedPortfolio: { rows: 'projects', title: 'title', subtitle: 'subtitle', image: 'image', view: 'grid', gridImageHeight: 180 },
63
66
  himiBrandedInvoices: { rows: 'invoices', title: 'title', subtitle: 'subtitle', view: 'list' },
64
67
  himiBrandedBadges: { rows: 'badges', title: 'name', subtitle: 'description', view: 'grid' },
@@ -1,6 +1,12 @@
1
1
  import { copyParam } from "./himi-copy.js";
2
2
 
3
- /** Host-owned preview input. Absent on native and older hosts. */
3
+ /** Host-owned preview input. Absent on native and older hosts.
4
+ *
5
+ * `"sample"` — the built-in demo records; `"live"` — the viewer's own business over the
6
+ * owner rung; `"fixtures"` — a DEV web host over a sealed hermetic gateway, where
7
+ * the dev fixtures are the sample data. `"fixtures"` is neither live nor demo, so a
8
+ * worker READS through the bridge as it does on a device; it is still a preview host
9
+ * (`isOwnerPreviewHost`), so failure copy may name the web preview. */
4
10
  function ownerPreviewMode(): unknown {
5
11
  return (globalThis as unknown as { himalaya?: { input?: Record<string, unknown> } }).himalaya?.input?.__himiOwnerPreview;
6
12
  }
@@ -1,5 +1,6 @@
1
1
  import { defineService } from "@himalaya/state";
2
2
  import {
3
+ ACCENT_IDS,
3
4
  ACCENT_KEY,
4
5
  ACCENT_META,
5
6
  DEFAULT_ACCENT,
@@ -29,6 +30,10 @@ interface State {
29
30
  accentHex_sage: string;
30
31
  accentHex_plum: string;
31
32
  accentHex_ocean: string;
33
+ // Per-accent selection flags for the radio group (`selected_<id>`) and the
34
+ // check mark on the swatch (`notSelected_<id>`, hiddenWhen hides on TRUE). Flat
35
+ // fields for the same reason as the hex ones: the swatches are static nodes.
36
+ [flag: `selected_${string}` | `notSelected_${string}`]: boolean | string;
32
37
  }
33
38
 
34
39
  interface StorageLike {
@@ -50,7 +55,13 @@ function paramValue(arg: unknown, key: string): string {
50
55
  }
51
56
 
52
57
  function build(pendingAccent: string, brandAccent: string): State {
58
+ const flags: Record<string, boolean> = {};
59
+ for (const id of ACCENT_IDS) {
60
+ flags[`selected_${id}`] = id === pendingAccent;
61
+ flags[`notSelected_${id}`] = id !== pendingAccent;
62
+ }
53
63
  return {
64
+ ...flags,
54
65
  pendingAccent,
55
66
  brandAccent,
56
67
  accentHex_brand: brandAccent || ACCENT_META.amber.hex,
@@ -85,7 +96,7 @@ const svc = defineService<State, {
85
96
  selectAccent: (state, arg) => {
86
97
  const id = paramValue(arg, "id");
87
98
  if (!isAccentId(id)) return state;
88
- return { ...state, pendingAccent: id };
99
+ return build(id, state.brandAccent);
89
100
  },
90
101
  // Apply: persist the accent; the home worker re-reads it on launch.
91
102
  apply: (state) => {
@@ -55,6 +55,12 @@ interface S {
55
55
  shareUrl: string;
56
56
  cartHint: string;
57
57
  cartCount: number;
58
+ /** An add-to-cart write is in flight (pending line under the CTA). */
59
+ adding: boolean;
60
+ notAdding: boolean;
61
+ /** The last add succeeded (confirmation + View cart under the CTA). */
62
+ added: boolean;
63
+ notAdded: boolean;
58
64
  emptyText: string;
59
65
  isLoading: boolean;
60
66
  notLoading: boolean;
@@ -145,6 +151,8 @@ function derive(s: S): S {
145
151
  return {
146
152
  ...s,
147
153
  saveLabel: s.saved ? copyParam("product.saved", "Saved") : copyParam("product.save", "Save product"),
154
+ notAdding: !s.adding,
155
+ notAdded: !s.added,
148
156
  isLoading: s.status === "loading",
149
157
  notLoading: s.status !== "loading",
150
158
  isErrored: s.status === "error",
@@ -163,6 +171,7 @@ const svc = defineService<S, {
163
171
  load: (s: S, arg?: unknown) => Promise<S>;
164
172
  setQuantity: (s: S, arg?: unknown) => S;
165
173
  addToCart: (s: S) => Promise<S>;
174
+ beginAdd: (s: S, arg?: unknown) => S;
166
175
  share: (s: S) => Promise<S>;
167
176
  toggleSave: (s: S) => S;
168
177
  }>("himiStoreProduct", {
@@ -179,6 +188,10 @@ const svc = defineService<S, {
179
188
  shareUrl: "",
180
189
  cartHint: "",
181
190
  cartCount: 0,
191
+ adding: false,
192
+ notAdding: true,
193
+ added: false,
194
+ notAdded: true,
182
195
  emptyText: "",
183
196
  isLoading: true,
184
197
  notLoading: false,
@@ -201,7 +214,7 @@ const svc = defineService<S, {
201
214
  // Storage problems must not prevent browsing or buying a product.
202
215
  let saved = false;
203
216
  try { saved = isProductSaved(id); } catch { /* save action reports a retryable error */ }
204
- s = { ...s, saved, saveHint: "" };
217
+ s = { ...s, saved, saveHint: "", adding: false, added: false };
205
218
  // A fresh navigation into the product resets any quantity left over
206
219
  // from a previous visit to the same worker instance.
207
220
  if (!id) return derive({ ...s, status: "ready", quantity: 1, emptyText: copyParam("product.notFoundText", "Product not found.") });
@@ -254,25 +267,42 @@ const svc = defineService<S, {
254
267
  const quantity = parseQuantity(argValue(arg, "value"));
255
268
  return quantity ? derive({ ...s, quantity }) : s;
256
269
  },
270
+ // The pending half of addToCart, as its own reducer so it PUBLISHES before the
271
+ // network write starts: the pending line shows and the top-bar badge ticks up in the same
272
+ // interaction, instead of the tap looking dead until the round-trip (and the badge re-read)
273
+ // settle. Called from addToCart, not from the descriptor.
274
+ beginAdd: (s, arg) => {
275
+ const quantity = parseQuantity(argValue(arg, "quantity")) ?? 1;
276
+ return derive({ ...s, adding: true, added: false, cartHint: "", cartCount: s.cartCount + quantity });
277
+ },
257
278
  addToCart: async (s) => {
258
279
  const id = inputId();
259
280
  if (!id) return derive({ ...s, cartHint: copyParam("product.cartHintNoProduct", "No product to add.") });
281
+ // A second tap while the first write is in flight must not add the line twice.
282
+ if (s.adding) return s;
260
283
  const quantity = s.quantity > 0 ? s.quantity : 1;
284
+ const before = s.cartCount;
285
+ await svc.beginAdd({ quantity: String(quantity) });
286
+ s = svc.getState() as S;
261
287
  // Optimistic local cart line — the cart repaints from cache immediately (offline or not).
262
288
  const line: DbEntity = { id: `line-${id}`, productId: id, name: s.name || "product", title: s.name || "product", subtitle: `Qty ${quantity}`, quantity: String(quantity) };
263
289
  await cartPut(line);
264
290
  try {
265
291
  await addToCurrentCart(id, quantity);
266
- return derive({ ...s, cartHint: copyTemplate("product.cartHintAdded", "Added {name} to cart.", { name: s.name || "product" }), cartCount: await cartItemCount() });
267
292
  } catch (e) {
268
293
  if (isBridgeUnavailable(e)) {
269
294
  // Offline / no bridge: the optimistic cache line already shows; queue the
270
295
  // add to replay (WriteQueue, idempotent) when connectivity returns.
271
296
  await queueWrite("tier5.himiStoreProduct.addToCart", { id });
272
- return derive({ ...s, cartHint: copyTemplate("product.cartHintQueued", "Added {name} to cart. Will sync when you reconnect.", { name: s.name || "product" }) });
297
+ return derive({ ...s, adding: false, added: false, cartHint: copyTemplate("product.cartHintQueued", "Added {name} to cart. Will sync when you reconnect.", { name: s.name || "product" }) });
273
298
  }
274
- return derive({ ...s, cartHint: copyParam("product.cartHintFailed", "Could not add to cart. Try again.") });
299
+ // Roll the optimistic badge back — nothing was added.
300
+ return derive({ ...s, adding: false, added: false, cartCount: before, cartHint: copyParam("product.cartHintFailed", "Could not add to cart. Try again.") });
275
301
  }
302
+ // The write LANDED. The badge re-read is outside the write's try on purpose: a failed
303
+ // count must never be mistaken for a failed add. Server count wins; else keep optimistic.
304
+ const count = await cartItemCount().catch(() => 0);
305
+ return derive({ ...s, adding: false, added: true, cartHint: copyTemplate("product.cartHintAdded", "Added {name} to cart.", { name: s.name || "product" }), cartCount: count || s.cartCount });
276
306
  },
277
307
  toggleSave: (s) => {
278
308
  if (s.status !== "ready" || !s.name || !inputId()) return s;
@@ -291,7 +321,8 @@ const svc = defineService<S, {
291
321
  await shareSheet({ subject: s.name, text: s.name, ...(s.shareUrl ? { url: s.shareUrl } : {}) });
292
322
  return s;
293
323
  } catch {
294
- return derive({ ...s, cartHint: copyParam("product.shareUnavailable", "Sharing is not available on this device.") });
324
+ // `added: false` — this hint must not render inside the add-to-cart confirmation.
325
+ return derive({ ...s, added: false, cartHint: copyParam("product.shareUnavailable", "Sharing is not available on this device.") });
295
326
  }
296
327
  },
297
328
  },
@@ -5,11 +5,12 @@
5
5
  import { defineService } from "@himalaya/state";
6
6
  import { dispatch } from "@himalaya/dispatch";
7
7
 
8
- interface Row { id: string; name: string; subtitle: string }
8
+ /** `selected` drives the row's radio; `subtitle` stays for older descriptors. */
9
+ interface Row { id: string; name: string; subtitle: string; selected: boolean }
9
10
  interface S { status: "ready"; options: Row[] }
10
11
 
11
12
  /** Locales with catalogs (`tools/l10n/catalog.<tag>.json`) + LocaleStore support. */
12
- const LOCALE_OPTIONS: Omit<Row, "subtitle">[] = [
13
+ const LOCALE_OPTIONS: Omit<Row, "subtitle" | "selected">[] = [
13
14
  { id: "en", name: "English" },
14
15
  { id: "es", name: "Español" },
15
16
  { id: "he", name: "עברית" },
@@ -19,6 +20,7 @@ function withSelected(selected: string): Row[] {
19
20
  return LOCALE_OPTIONS.map((o) => ({
20
21
  ...o,
21
22
  subtitle: o.id === selected ? "Selected" : "",
23
+ selected: o.id === selected,
22
24
  }));
23
25
  }
24
26
 
@@ -37,7 +37,7 @@ export default defineApp({
37
37
  actions: "http://localhost:8190/v1/actions",
38
38
  sync: "http://localhost:8190/v1/sync",
39
39
  },
40
- capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui"],
40
+ capabilities: ["live_activity","push","share","secure_storage","open_url","local_database","clipboard","ui","camera","presigned_upload"],
41
41
  designTokensPath: "./tokens.json",
42
42
  navigation: {
43
43
  "navKind": "responsive",
@@ -50387,7 +50387,7 @@ const SCREENS = runtimeSetting({
50387
50387
  "itemsPath": "$service:himiOwnerLiteManage.recents",
50388
50388
  "items": [
50389
50389
  {
50390
- "id": "",
50390
+ "id": "himi_owner_lite.manage.recent.$item.id",
50391
50391
  "body": {
50392
50392
  "package": "himalaya",
50393
50393
  "type": "VStack",
@@ -50532,7 +50532,7 @@ const SCREENS = runtimeSetting({
50532
50532
  "spacing": 14,
50533
50533
  "children": [
50534
50534
  {
50535
- "id": "",
50535
+ "id": "himi_owner_lite.manage.recent.create.$item.id",
50536
50536
  "body": {
50537
50537
  "package": "himalaya",
50538
50538
  "type": "Text",
@@ -50557,7 +50557,7 @@ const SCREENS = runtimeSetting({
50557
50557
  }
50558
50558
  },
50559
50559
  {
50560
- "id": "",
50560
+ "id": "himi_owner_lite.manage.recent.handoff.$item.id",
50561
50561
  "body": {
50562
50562
  "package": "himalaya",
50563
50563
  "type": "Text",
@@ -50693,7 +50693,7 @@ const SCREENS = runtimeSetting({
50693
50693
  "itemsPath": "$item.areas",
50694
50694
  "items": [
50695
50695
  {
50696
- "id": "",
50696
+ "id": "himi_owner_lite.manage.area.$item.id",
50697
50697
  "body": {
50698
50698
  "package": "himalaya",
50699
50699
  "type": "VStack",
@@ -50838,7 +50838,7 @@ const SCREENS = runtimeSetting({
50838
50838
  "spacing": 14,
50839
50839
  "children": [
50840
50840
  {
50841
- "id": "",
50841
+ "id": "himi_owner_lite.manage.area.create.$item.id",
50842
50842
  "body": {
50843
50843
  "package": "himalaya",
50844
50844
  "type": "Text",
@@ -50863,7 +50863,7 @@ const SCREENS = runtimeSetting({
50863
50863
  }
50864
50864
  },
50865
50865
  {
50866
- "id": "",
50866
+ "id": "himi_owner_lite.manage.area.handoff.$item.id",
50867
50867
  "body": {
50868
50868
  "package": "himalaya",
50869
50869
  "type": "Text",
@@ -51643,7 +51643,7 @@ const SCREENS = runtimeSetting({
51643
51643
  "props": {
51644
51644
  "items": [
51645
51645
  {
51646
- "id": "",
51646
+ "id": "ol_drawer_nav.$item.id",
51647
51647
  "body": {
51648
51648
  "package": "himalaya",
51649
51649
  "type": "ListItem",
@@ -51695,7 +51695,7 @@ const SCREENS = runtimeSetting({
51695
51695
  "props": {
51696
51696
  "items": [
51697
51697
  {
51698
- "id": "",
51698
+ "id": "ol_drawer_attention.$item.id",
51699
51699
  "body": {
51700
51700
  "package": "himalaya",
51701
51701
  "type": "ListItem",
@@ -55256,6 +55256,45 @@ const SCREENS = runtimeSetting({
55256
55256
  }
55257
55257
  }
55258
55258
  },
55259
+ {
55260
+ "id": "himi_owner_lite_aria.msg_attach_$item.id",
55261
+ "body": {
55262
+ "package": "himalaya",
55263
+ "type": "HStack",
55264
+ "props": {
55265
+ "spacing": 0,
55266
+ "children": [
55267
+ {
55268
+ "id": "",
55269
+ "body": {
55270
+ "package": "himalaya",
55271
+ "type": "Spacer",
55272
+ "props": {}
55273
+ },
55274
+ "modifiers": {
55275
+ "hiddenPath": "$item.notUser"
55276
+ }
55277
+ },
55278
+ {
55279
+ "id": "",
55280
+ "body": {
55281
+ "package": "himalaya",
55282
+ "type": "Text",
55283
+ "props": {
55284
+ "text": "$item.attachText",
55285
+ "style": "footnote",
55286
+ "color": "textSecondary",
55287
+ "maxLines": 3
55288
+ }
55289
+ }
55290
+ }
55291
+ ]
55292
+ }
55293
+ },
55294
+ "modifiers": {
55295
+ "hiddenPath": "$item.attachHidden"
55296
+ }
55297
+ },
55259
55298
  {
55260
55299
  "id": "himi_owner_lite_aria.msg_$item.id.link1",
55261
55300
  "body": {
@@ -58836,6 +58875,203 @@ const SCREENS = runtimeSetting({
58836
58875
  }
58837
58876
  }
58838
58877
  },
58878
+ {
58879
+ "id": "himi_owner_lite_aria.attachments.bound",
58880
+ "body": {
58881
+ "package": "himalaya",
58882
+ "type": "LazyList",
58883
+ "props": {
58884
+ "itemsPath": "$service:himiOwnerLiteAria.attachments",
58885
+ "horizontal": true,
58886
+ "spacing": 8,
58887
+ "items": [
58888
+ {
58889
+ "id": "himi_owner_lite_aria.attachment_$item.id",
58890
+ "body": {
58891
+ "package": "himalaya",
58892
+ "type": "VStack",
58893
+ "props": {
58894
+ "spacing": 4,
58895
+ "children": [
58896
+ {
58897
+ "id": "himi_owner_lite_aria.attachment_thumb_$item.id",
58898
+ "body": {
58899
+ "package": "himalaya",
58900
+ "type": "Image",
58901
+ "props": {
58902
+ "url": "$item.thumbUrl",
58903
+ "width": 72,
58904
+ "height": 72,
58905
+ "contentMode": "fill",
58906
+ "shape": "rounded",
58907
+ "contentDescription": "$item.name"
58908
+ }
58909
+ },
58910
+ "modifiers": {
58911
+ "hiddenPath": "$item.thumbHidden"
58912
+ }
58913
+ },
58914
+ {
58915
+ "id": "",
58916
+ "body": {
58917
+ "package": "himalaya",
58918
+ "type": "Text",
58919
+ "props": {
58920
+ "text": "$item.statusText",
58921
+ "style": "caption",
58922
+ "color": "textSecondary",
58923
+ "maxLines": 2
58924
+ }
58925
+ },
58926
+ "modifiers": {
58927
+ "hiddenPath": "$item.statusHidden"
58928
+ }
58929
+ },
58930
+ {
58931
+ "id": "",
58932
+ "body": {
58933
+ "package": "himalaya",
58934
+ "type": "HStack",
58935
+ "props": {
58936
+ "spacing": 8,
58937
+ "children": [
58938
+ {
58939
+ "id": "himi_owner_lite_aria.attachment_retry_$item.id",
58940
+ "body": {
58941
+ "package": "himalaya",
58942
+ "type": "Text",
58943
+ "props": {
58944
+ "text": "Retry",
58945
+ "style": "caption",
58946
+ "color": "accentPrimary",
58947
+ "maxLines": 1
58948
+ }
58949
+ },
58950
+ "modifiers": {
58951
+ "onTap": {
58952
+ "actionId": "tier5.himiOwnerLiteAria.retryAttachment",
58953
+ "params": {
58954
+ "id": "$item.id"
58955
+ }
58956
+ },
58957
+ "hiddenPath": "$item.retryHidden"
58958
+ }
58959
+ },
58960
+ {
58961
+ "id": "himi_owner_lite_aria.attachment_remove_$item.id",
58962
+ "body": {
58963
+ "package": "himalaya",
58964
+ "type": "Icon",
58965
+ "props": {
58966
+ "name": "close",
58967
+ "size": 14,
58968
+ "tint": "textSecondary"
58969
+ }
58970
+ },
58971
+ "modifiers": {
58972
+ "onTap": {
58973
+ "actionId": "tier5.himiOwnerLiteAria.removeAttachment",
58974
+ "params": {
58975
+ "id": "$item.id"
58976
+ }
58977
+ },
58978
+ "accessibilityLabel": "Remove photo"
58979
+ }
58980
+ }
58981
+ ]
58982
+ }
58983
+ }
58984
+ }
58985
+ ]
58986
+ }
58987
+ },
58988
+ "modifiers": {
58989
+ "width": 72
58990
+ }
58991
+ }
58992
+ ]
58993
+ }
58994
+ },
58995
+ "modifiers": {
58996
+ "hiddenPath": "$service:himiOwnerLiteAria.attachmentsHidden",
58997
+ "padding": {
58998
+ "leading": 0,
58999
+ "trailing": 0,
59000
+ "top": 8,
59001
+ "bottom": 0
59002
+ }
59003
+ }
59004
+ },
59005
+ {
59006
+ "id": "",
59007
+ "body": {
59008
+ "package": "himalaya",
59009
+ "type": "HStack",
59010
+ "props": {
59011
+ "spacing": 16,
59012
+ "children": [
59013
+ {
59014
+ "id": "himi_owner_lite_aria.attach.library",
59015
+ "body": {
59016
+ "package": "himalaya",
59017
+ "type": "Icon",
59018
+ "props": {
59019
+ "name": "image",
59020
+ "size": 22,
59021
+ "tint": "accentPrimary"
59022
+ }
59023
+ },
59024
+ "modifiers": {
59025
+ "onTap": {
59026
+ "actionId": "tier5.himiOwnerLiteAria.attach",
59027
+ "params": {
59028
+ "source": "library"
59029
+ }
59030
+ },
59031
+ "accessibilityLabel": "Add a photo"
59032
+ }
59033
+ },
59034
+ {
59035
+ "id": "himi_owner_lite_aria.attach.camera",
59036
+ "body": {
59037
+ "package": "himalaya",
59038
+ "type": "Icon",
59039
+ "props": {
59040
+ "name": "camera",
59041
+ "size": 22,
59042
+ "tint": "accentPrimary"
59043
+ }
59044
+ },
59045
+ "modifiers": {
59046
+ "onTap": {
59047
+ "actionId": "tier5.himiOwnerLiteAria.attach",
59048
+ "params": {
59049
+ "source": "camera"
59050
+ }
59051
+ },
59052
+ "accessibilityLabel": "Take a photo"
59053
+ }
59054
+ },
59055
+ {
59056
+ "id": "",
59057
+ "body": {
59058
+ "package": "himalaya",
59059
+ "type": "Spacer",
59060
+ "props": {}
59061
+ }
59062
+ }
59063
+ ]
59064
+ }
59065
+ },
59066
+ "modifiers": {
59067
+ "padding": {
59068
+ "leading": 0,
59069
+ "trailing": 0,
59070
+ "top": 8,
59071
+ "bottom": 0
59072
+ }
59073
+ }
59074
+ },
58839
59075
  {
58840
59076
  "id": "form_aria",
58841
59077
  "body": {
@@ -58921,7 +59157,9 @@ const SCREENS = runtimeSetting({
58921
59157
  "wix_api",
58922
59158
  "open_url",
58923
59159
  "clipboard",
58924
- "ui"
59160
+ "ui",
59161
+ "camera",
59162
+ "presigned_upload"
58925
59163
  ],
58926
59164
  "minBinaryVersion": "0.1.0",
58927
59165
  "bundleVersion": "0.0.1"