@wix/himalaya-cli 0.1034.0 → 0.1036.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 (234) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/builder.d.ts +7 -1
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/display.d.ts +13 -1
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +28 -6
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-stores-collections.mjs +1 -1
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-stores.mjs +7 -1
  6. package/dist/cli.mjs +25 -19
  7. package/dist/preview-assets.generated.bin +0 -0
  8. package/guides/sdk-reference.json +16 -4
  9. package/package.json +2 -2
  10. package/templates/beauty-salon/dev/index.ts +72 -175
  11. package/templates/beauty-salon/tier5-src/_shared/collection-contract.ts +16 -9
  12. package/templates/beauty-salon/tier5-src/_shared/collection-service.ts +19 -5
  13. package/templates/beauty-salon/tier5-src/_shared/engine-intl.ts +51 -0
  14. package/templates/beauty-salon/tier5-src/_shared/himi-restaurants.ts +4 -4
  15. package/templates/beauty-salon/tier5-src/_shared/owner-load-error.ts +49 -0
  16. package/templates/beauty-salon/tier5-src/_shared/wix-service-price.ts +1 -1
  17. package/templates/beauty-salon/tier5-src/himi-branded-lite-info/index.ts +5 -2
  18. package/templates/beauty-salon/tier5-src/himi-branded-lite-plans/index.ts +1 -1
  19. package/templates/beauty-salon/tier5-src/wix-spaces-collections/index.ts +1 -1
  20. package/templates/beauty-salon/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  21. package/templates/beauty-salon-owner/dev/index.ts +84 -599
  22. package/templates/beauty-salon-owner/tier5-src/_shared/aria-chat.ts +22 -6
  23. package/templates/beauty-salon-owner/tier5-src/_shared/collection-contract.ts +16 -9
  24. package/templates/beauty-salon-owner/tier5-src/_shared/collection-service.ts +19 -5
  25. package/templates/beauty-salon-owner/tier5-src/_shared/engine-intl.ts +51 -0
  26. package/templates/beauty-salon-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  27. package/templates/branded-lite/dev/index.ts +178 -264
  28. package/templates/branded-lite/tier5-src/_shared/collection-contract.ts +16 -9
  29. package/templates/branded-lite/tier5-src/_shared/collection-service.ts +19 -5
  30. package/templates/branded-lite/tier5-src/_shared/engine-intl.ts +51 -0
  31. package/templates/branded-lite/tier5-src/_shared/himi-restaurants.ts +4 -4
  32. package/templates/branded-lite/tier5-src/_shared/owner-load-error.ts +49 -0
  33. package/templates/branded-lite/tier5-src/_shared/wix-service-price.ts +1 -1
  34. package/templates/branded-lite/tier5-src/himi-branded-lite-cms/index.ts +5 -5
  35. package/templates/branded-lite/tier5-src/himi-branded-lite-coupons/index.ts +33 -7
  36. package/templates/branded-lite/tier5-src/himi-branded-lite-donations/index.ts +3 -3
  37. package/templates/branded-lite/tier5-src/himi-branded-lite-forms/index.ts +11 -10
  38. package/templates/branded-lite/tier5-src/himi-branded-lite-giftcards/index.ts +3 -3
  39. package/templates/branded-lite/tier5-src/himi-branded-lite-info/index.ts +5 -2
  40. package/templates/branded-lite/tier5-src/himi-branded-lite-invoices/index.ts +3 -3
  41. package/templates/branded-lite/tier5-src/himi-branded-lite-loyalty/index.ts +1 -1
  42. package/templates/branded-lite/tier5-src/himi-branded-lite-plans/index.ts +1 -1
  43. package/templates/branded-lite/tier5-src/himi-branded-lite-program/index.ts +1 -1
  44. package/templates/branded-lite/tier5-src/himi-branded-lite-reserve/index.ts +5 -3
  45. package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +1 -1
  46. package/templates/branded-lite/tier5-src/himi-events-list/index.ts +20 -4
  47. package/templates/branded-lite/tier5-src/himi-events-my-events/index.ts +2 -2
  48. package/templates/branded-lite/tier5-src/wix-spaces-collections/index.ts +1 -1
  49. package/templates/branded-lite/tier5-src/wix-spaces-forum/index.ts +7 -1
  50. package/templates/branded-lite/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  51. package/templates/community-club/dev/index.ts +62 -81
  52. package/templates/community-club/tier5-src/_shared/collection-contract.ts +16 -9
  53. package/templates/community-club/tier5-src/_shared/collection-service.ts +19 -5
  54. package/templates/community-club/tier5-src/_shared/engine-intl.ts +51 -0
  55. package/templates/community-club/tier5-src/_shared/himi-restaurants.ts +4 -4
  56. package/templates/community-club/tier5-src/_shared/owner-load-error.ts +49 -0
  57. package/templates/community-club/tier5-src/_shared/wix-service-price.ts +1 -1
  58. package/templates/community-club/tier5-src/himi-branded-lite-cms/index.ts +5 -5
  59. package/templates/community-club/tier5-src/himi-branded-lite-info/index.ts +5 -2
  60. package/templates/community-club/tier5-src/himi-events-detail/index.ts +1 -1
  61. package/templates/community-club/tier5-src/himi-events-list/index.ts +20 -4
  62. package/templates/community-club/tier5-src/himi-events-my-events/index.ts +2 -2
  63. package/templates/community-club/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  64. package/templates/community-club-owner/dev/index.ts +84 -599
  65. package/templates/community-club-owner/tier5-src/_shared/aria-chat.ts +22 -6
  66. package/templates/community-club-owner/tier5-src/_shared/collection-contract.ts +16 -9
  67. package/templates/community-club-owner/tier5-src/_shared/collection-service.ts +19 -5
  68. package/templates/community-club-owner/tier5-src/_shared/engine-intl.ts +51 -0
  69. package/templates/community-club-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  70. package/templates/community-club-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
  71. package/templates/events-meetups/dev/index.ts +60 -79
  72. package/templates/events-meetups/tier5-src/_shared/collection-contract.ts +16 -9
  73. package/templates/events-meetups/tier5-src/_shared/collection-service.ts +19 -5
  74. package/templates/events-meetups/tier5-src/_shared/engine-intl.ts +51 -0
  75. package/templates/events-meetups/tier5-src/_shared/himi-restaurants.ts +4 -4
  76. package/templates/events-meetups/tier5-src/_shared/owner-load-error.ts +49 -0
  77. package/templates/events-meetups/tier5-src/_shared/wix-service-price.ts +1 -1
  78. package/templates/events-meetups/tier5-src/himi-branded-lite-info/index.ts +5 -2
  79. package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +1 -1
  80. package/templates/events-meetups/tier5-src/himi-events-list/index.ts +20 -4
  81. package/templates/events-meetups/tier5-src/himi-events-my-events/index.ts +2 -2
  82. package/templates/events-meetups/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  83. package/templates/events-meetups-owner/dev/index.ts +84 -543
  84. package/templates/events-meetups-owner/tier5-src/_shared/aria-chat.ts +22 -6
  85. package/templates/events-meetups-owner/tier5-src/_shared/collection-contract.ts +16 -9
  86. package/templates/events-meetups-owner/tier5-src/_shared/collection-service.ts +19 -5
  87. package/templates/events-meetups-owner/tier5-src/_shared/engine-intl.ts +51 -0
  88. package/templates/events-meetups-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  89. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
  90. package/templates/gym-fitness/dev/index.ts +73 -204
  91. package/templates/gym-fitness/tier5-src/_shared/collection-contract.ts +16 -9
  92. package/templates/gym-fitness/tier5-src/_shared/collection-service.ts +19 -5
  93. package/templates/gym-fitness/tier5-src/_shared/engine-intl.ts +51 -0
  94. package/templates/gym-fitness/tier5-src/_shared/himi-restaurants.ts +4 -4
  95. package/templates/gym-fitness/tier5-src/_shared/owner-load-error.ts +49 -0
  96. package/templates/gym-fitness/tier5-src/_shared/wix-service-price.ts +1 -1
  97. package/templates/gym-fitness/tier5-src/himi-branded-lite-info/index.ts +5 -2
  98. package/templates/gym-fitness/tier5-src/himi-branded-lite-plans/index.ts +1 -1
  99. package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +1 -1
  100. package/templates/gym-fitness/tier5-src/himi-events-list/index.ts +20 -4
  101. package/templates/gym-fitness/tier5-src/himi-events-my-events/index.ts +2 -2
  102. package/templates/gym-fitness/tier5-src/wix-spaces-collections/index.ts +1 -1
  103. package/templates/gym-fitness/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  104. package/templates/gym-fitness-owner/dev/index.ts +84 -627
  105. package/templates/gym-fitness-owner/tier5-src/_shared/aria-chat.ts +22 -6
  106. package/templates/gym-fitness-owner/tier5-src/_shared/collection-contract.ts +16 -9
  107. package/templates/gym-fitness-owner/tier5-src/_shared/collection-service.ts +19 -5
  108. package/templates/gym-fitness-owner/tier5-src/_shared/engine-intl.ts +51 -0
  109. package/templates/gym-fitness-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  110. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
  111. package/templates/himi-chat/tier5-src/_shared/owner-load-error.ts +49 -0
  112. package/templates/nonprofit-cause/dev/index.ts +71 -90
  113. package/templates/nonprofit-cause/tier5-src/_shared/collection-contract.ts +16 -9
  114. package/templates/nonprofit-cause/tier5-src/_shared/collection-service.ts +19 -5
  115. package/templates/nonprofit-cause/tier5-src/_shared/engine-intl.ts +51 -0
  116. package/templates/nonprofit-cause/tier5-src/_shared/himi-restaurants.ts +4 -4
  117. package/templates/nonprofit-cause/tier5-src/_shared/owner-load-error.ts +49 -0
  118. package/templates/nonprofit-cause/tier5-src/_shared/wix-service-price.ts +1 -1
  119. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-info/index.ts +5 -2
  120. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-plans/index.ts +1 -1
  121. package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +1 -1
  122. package/templates/nonprofit-cause/tier5-src/himi-events-list/index.ts +20 -4
  123. package/templates/nonprofit-cause/tier5-src/himi-events-my-events/index.ts +2 -2
  124. package/templates/nonprofit-cause/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  125. package/templates/nonprofit-cause-owner/dev/index.ts +84 -571
  126. package/templates/nonprofit-cause-owner/tier5-src/_shared/aria-chat.ts +22 -6
  127. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-contract.ts +16 -9
  128. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-service.ts +19 -5
  129. package/templates/nonprofit-cause-owner/tier5-src/_shared/engine-intl.ts +51 -0
  130. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  131. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
  132. package/templates/owner-lite/dev/index.ts +84 -627
  133. package/templates/owner-lite/tier5-src/_shared/aria-chat.ts +22 -6
  134. package/templates/owner-lite/tier5-src/_shared/collection-contract.ts +16 -9
  135. package/templates/owner-lite/tier5-src/_shared/collection-service.ts +19 -5
  136. package/templates/owner-lite/tier5-src/_shared/engine-intl.ts +51 -0
  137. package/templates/owner-lite/tier5-src/_shared/owner-load-error.ts +49 -0
  138. package/templates/owner-lite/tier5-src/himi-owner-lite-events/index.ts +1 -0
  139. package/templates/podcast-creator/dev/index.ts +71 -90
  140. package/templates/podcast-creator/tier5-src/_shared/collection-contract.ts +16 -9
  141. package/templates/podcast-creator/tier5-src/_shared/collection-service.ts +19 -5
  142. package/templates/podcast-creator/tier5-src/_shared/engine-intl.ts +51 -0
  143. package/templates/podcast-creator/tier5-src/_shared/himi-restaurants.ts +4 -4
  144. package/templates/podcast-creator/tier5-src/_shared/owner-load-error.ts +49 -0
  145. package/templates/podcast-creator/tier5-src/_shared/wix-service-price.ts +1 -1
  146. package/templates/podcast-creator/tier5-src/himi-branded-lite-info/index.ts +5 -2
  147. package/templates/podcast-creator/tier5-src/himi-branded-lite-plans/index.ts +1 -1
  148. package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +1 -1
  149. package/templates/podcast-creator/tier5-src/himi-events-list/index.ts +20 -4
  150. package/templates/podcast-creator/tier5-src/himi-events-my-events/index.ts +2 -2
  151. package/templates/podcast-creator/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  152. package/templates/podcast-creator-owner/dev/index.ts +84 -599
  153. package/templates/podcast-creator-owner/tier5-src/_shared/aria-chat.ts +22 -6
  154. package/templates/podcast-creator-owner/tier5-src/_shared/collection-contract.ts +16 -9
  155. package/templates/podcast-creator-owner/tier5-src/_shared/collection-service.ts +19 -5
  156. package/templates/podcast-creator-owner/tier5-src/_shared/engine-intl.ts +51 -0
  157. package/templates/podcast-creator-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  158. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
  159. package/templates/portfolio-creative/dev/index.ts +62 -137
  160. package/templates/portfolio-creative/tier5-src/_shared/collection-contract.ts +16 -9
  161. package/templates/portfolio-creative/tier5-src/_shared/collection-service.ts +19 -5
  162. package/templates/portfolio-creative/tier5-src/_shared/engine-intl.ts +51 -0
  163. package/templates/portfolio-creative/tier5-src/_shared/himi-restaurants.ts +4 -4
  164. package/templates/portfolio-creative/tier5-src/_shared/owner-load-error.ts +49 -0
  165. package/templates/portfolio-creative/tier5-src/_shared/wix-service-price.ts +1 -1
  166. package/templates/portfolio-creative/tier5-src/himi-branded-lite-info/index.ts +5 -2
  167. package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +1 -1
  168. package/templates/portfolio-creative/tier5-src/himi-events-list/index.ts +20 -4
  169. package/templates/portfolio-creative/tier5-src/himi-events-my-events/index.ts +2 -2
  170. package/templates/portfolio-creative/tier5-src/wix-spaces-collections/index.ts +1 -1
  171. package/templates/portfolio-creative/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  172. package/templates/portfolio-creative-owner/dev/index.ts +84 -599
  173. package/templates/portfolio-creative-owner/tier5-src/_shared/aria-chat.ts +22 -6
  174. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-contract.ts +16 -9
  175. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-service.ts +19 -5
  176. package/templates/portfolio-creative-owner/tier5-src/_shared/engine-intl.ts +51 -0
  177. package/templates/portfolio-creative-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  178. package/templates/restaurant/dev/index.ts +124 -101
  179. package/templates/restaurant/tier5-src/_shared/collection-contract.ts +16 -9
  180. package/templates/restaurant/tier5-src/_shared/collection-service.ts +19 -5
  181. package/templates/restaurant/tier5-src/_shared/engine-intl.ts +51 -0
  182. package/templates/restaurant/tier5-src/_shared/himi-restaurants.ts +4 -4
  183. package/templates/restaurant/tier5-src/_shared/owner-load-error.ts +49 -0
  184. package/templates/restaurant/tier5-src/_shared/wix-service-price.ts +1 -1
  185. package/templates/restaurant/tier5-src/himi-branded-lite-info/index.ts +5 -2
  186. package/templates/restaurant/tier5-src/himi-branded-lite-reserve/index.ts +5 -3
  187. package/templates/restaurant/tier5-src/himi-events-detail/index.ts +1 -1
  188. package/templates/restaurant/tier5-src/himi-events-list/index.ts +20 -4
  189. package/templates/restaurant/tier5-src/himi-events-my-events/index.ts +2 -2
  190. package/templates/restaurant/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  191. package/templates/restaurant-owner/dev/index.ts +84 -627
  192. package/templates/restaurant-owner/tier5-src/_shared/aria-chat.ts +22 -6
  193. package/templates/restaurant-owner/tier5-src/_shared/collection-contract.ts +16 -9
  194. package/templates/restaurant-owner/tier5-src/_shared/collection-service.ts +19 -5
  195. package/templates/restaurant-owner/tier5-src/_shared/engine-intl.ts +51 -0
  196. package/templates/restaurant-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  197. package/templates/restaurant-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
  198. package/templates/retail-store/dev/index.ts +59 -106
  199. package/templates/retail-store/tier5-src/_shared/collection-contract.ts +16 -9
  200. package/templates/retail-store/tier5-src/_shared/collection-service.ts +19 -5
  201. package/templates/retail-store/tier5-src/_shared/engine-intl.ts +51 -0
  202. package/templates/retail-store/tier5-src/_shared/himi-restaurants.ts +4 -4
  203. package/templates/retail-store/tier5-src/_shared/owner-load-error.ts +49 -0
  204. package/templates/retail-store/tier5-src/_shared/wix-service-price.ts +1 -1
  205. package/templates/retail-store/tier5-src/himi-branded-lite-info/index.ts +5 -2
  206. package/templates/retail-store/tier5-src/wix-spaces-collections/index.ts +1 -1
  207. package/templates/retail-store/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  208. package/templates/retail-store-owner/dev/index.ts +84 -571
  209. package/templates/retail-store-owner/tier5-src/_shared/aria-chat.ts +22 -6
  210. package/templates/retail-store-owner/tier5-src/_shared/collection-contract.ts +16 -9
  211. package/templates/retail-store-owner/tier5-src/_shared/collection-service.ts +19 -5
  212. package/templates/retail-store-owner/tier5-src/_shared/engine-intl.ts +51 -0
  213. package/templates/retail-store-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  214. package/templates/yoga-studio/dev/index.ts +73 -148
  215. package/templates/yoga-studio/tier5-src/_shared/collection-contract.ts +16 -9
  216. package/templates/yoga-studio/tier5-src/_shared/collection-service.ts +19 -5
  217. package/templates/yoga-studio/tier5-src/_shared/engine-intl.ts +51 -0
  218. package/templates/yoga-studio/tier5-src/_shared/himi-restaurants.ts +4 -4
  219. package/templates/yoga-studio/tier5-src/_shared/owner-load-error.ts +49 -0
  220. package/templates/yoga-studio/tier5-src/_shared/wix-service-price.ts +1 -1
  221. package/templates/yoga-studio/tier5-src/himi-branded-lite-info/index.ts +5 -2
  222. package/templates/yoga-studio/tier5-src/himi-branded-lite-plans/index.ts +1 -1
  223. package/templates/yoga-studio/tier5-src/himi-branded-lite-program/index.ts +1 -1
  224. package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +1 -1
  225. package/templates/yoga-studio/tier5-src/himi-events-list/index.ts +20 -4
  226. package/templates/yoga-studio/tier5-src/himi-events-my-events/index.ts +2 -2
  227. package/templates/yoga-studio/tier5-src/wix-spaces-whats-new/index.ts +4 -4
  228. package/templates/yoga-studio-owner/dev/index.ts +84 -571
  229. package/templates/yoga-studio-owner/tier5-src/_shared/aria-chat.ts +22 -6
  230. package/templates/yoga-studio-owner/tier5-src/_shared/collection-contract.ts +16 -9
  231. package/templates/yoga-studio-owner/tier5-src/_shared/collection-service.ts +19 -5
  232. package/templates/yoga-studio-owner/tier5-src/_shared/engine-intl.ts +51 -0
  233. package/templates/yoga-studio-owner/tier5-src/_shared/owner-load-error.ts +49 -0
  234. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-events/index.ts +1 -0
@@ -3881,17 +3881,6 @@ const SCREENS = runtimeSetting({
3881
3881
  }
3882
3882
  }
3883
3883
  },
3884
- {
3885
- "id": "",
3886
- "body": {
3887
- "package": "himalaya",
3888
- "type": "Text",
3889
- "props": {
3890
- "text": "__HIMI_APP_NAME__",
3891
- "style": "bodyEmphasis"
3892
- }
3893
- }
3894
- },
3895
3884
  {
3896
3885
  "id": "",
3897
3886
  "body": {
@@ -5525,16 +5514,64 @@ const SCREENS = runtimeSetting({
5525
5514
  }
5526
5515
  },
5527
5516
  {
5528
- "id": "",
5517
+ "id": "himi_whats_new.empty",
5529
5518
  "body": {
5530
5519
  "package": "himalaya",
5531
- "type": "Text",
5520
+ "type": "VStack",
5532
5521
  "props": {
5533
- "text": "$service:spacesWhatsNew.emptyText",
5534
- "style": "body",
5535
- "color": "textSecondary",
5536
- "collapseWhenEmpty": true
5522
+ "spacing": 8,
5523
+ "alignment": "leading",
5524
+ "children": [
5525
+ {
5526
+ "id": "",
5527
+ "body": {
5528
+ "package": "himalaya",
5529
+ "type": "Icon",
5530
+ "props": {
5531
+ "name": "newspaper",
5532
+ "size": 28,
5533
+ "tint": "textTertiary"
5534
+ }
5535
+ },
5536
+ "modifiers": {
5537
+ "accessibilityRole": "decorative"
5538
+ }
5539
+ },
5540
+ {
5541
+ "id": "",
5542
+ "body": {
5543
+ "package": "himalaya",
5544
+ "type": "Text",
5545
+ "props": {
5546
+ "text": "$service:spacesWhatsNew.emptyText",
5547
+ "style": "body",
5548
+ "color": "textSecondary",
5549
+ "collapseWhenEmpty": true
5550
+ }
5551
+ }
5552
+ }
5553
+ ]
5537
5554
  }
5555
+ },
5556
+ "modifiers": {
5557
+ "background": {
5558
+ "token": "surfaceElevated"
5559
+ },
5560
+ "border": {
5561
+ "width": 1,
5562
+ "color": {
5563
+ "token": "border"
5564
+ }
5565
+ },
5566
+ "cornerRadius": 16,
5567
+ "padding": {
5568
+ "leading": 16,
5569
+ "trailing": 16,
5570
+ "top": 16,
5571
+ "bottom": 16
5572
+ },
5573
+ "fillMaxWidth": true,
5574
+ "hiddenPath": "$service:spacesWhatsNew.noEmpty"
5538
5575
  }
5539
5576
  }
5540
5577
  ]
@@ -5626,7 +5663,7 @@ const SCREENS = runtimeSetting({
5626
5663
  "package": "himalaya",
5627
5664
  "type": "SearchField",
5628
5665
  "props": {
5629
- "placeholder": "Service name starts with…",
5666
+ "placeholder": "Search services",
5630
5667
  "debounceMs": 200,
5631
5668
  "onChange": {
5632
5669
  "actionId": "tier5.himiBookingServices.collectionSearch"
@@ -6818,20 +6855,6 @@ const SCREENS = runtimeSetting({
6818
6855
  }
6819
6856
  }
6820
6857
  },
6821
- {
6822
- "id": "btn_tier5_himibookingservices_refresh",
6823
- "body": {
6824
- "package": "himalaya",
6825
- "type": "Button",
6826
- "props": {
6827
- "title": "Refresh",
6828
- "style": "plain",
6829
- "action": {
6830
- "actionId": "tier5.himiBookingServices.refresh"
6831
- }
6832
- }
6833
- }
6834
- },
6835
6858
  {
6836
6859
  "id": "himi_services.list.collection.more",
6837
6860
  "body": {
@@ -7507,20 +7530,6 @@ const SCREENS = runtimeSetting({
7507
7530
  }
7508
7531
  }
7509
7532
  },
7510
- {
7511
- "id": "btn_tier5_himibookingservices_refresh",
7512
- "body": {
7513
- "package": "himalaya",
7514
- "type": "Button",
7515
- "props": {
7516
- "title": "Refresh",
7517
- "style": "plain",
7518
- "action": {
7519
- "actionId": "tier5.himiBookingServices.refresh"
7520
- }
7521
- }
7522
- }
7523
- },
7524
7533
  {
7525
7534
  "id": "himi_services.list.collection.compact-more",
7526
7535
  "body": {
@@ -8805,7 +8814,7 @@ const SCREENS = runtimeSetting({
8805
8814
  "package": "himalaya",
8806
8815
  "type": "SearchField",
8807
8816
  "props": {
8808
- "placeholder": "Exact booking ID",
8817
+ "placeholder": "Search by booking ID",
8809
8818
  "value": "$service:himiBookingBookings.collection.query",
8810
8819
  "debounceMs": 200,
8811
8820
  "onChange": {
@@ -9720,20 +9729,6 @@ const SCREENS = runtimeSetting({
9720
9729
  }
9721
9730
  }
9722
9731
  },
9723
- {
9724
- "id": "btn_tier5_himibookingbookings_refresh",
9725
- "body": {
9726
- "package": "himalaya",
9727
- "type": "Button",
9728
- "props": {
9729
- "title": "Refresh",
9730
- "style": "plain",
9731
- "action": {
9732
- "actionId": "tier5.himiBookingBookings.refresh"
9733
- }
9734
- }
9735
- }
9736
- },
9737
9732
  {
9738
9733
  "id": "himi_bookings.list.collection.more",
9739
9734
  "body": {
@@ -10346,20 +10341,6 @@ const SCREENS = runtimeSetting({
10346
10341
  }
10347
10342
  }
10348
10343
  },
10349
- {
10350
- "id": "btn_tier5_himibookingbookings_refresh",
10351
- "body": {
10352
- "package": "himalaya",
10353
- "type": "Button",
10354
- "props": {
10355
- "title": "Refresh",
10356
- "style": "plain",
10357
- "action": {
10358
- "actionId": "tier5.himiBookingBookings.refresh"
10359
- }
10360
- }
10361
- }
10362
- },
10363
10344
  {
10364
10345
  "id": "himi_bookings.list.collection.compact-more",
10365
10346
  "body": {
@@ -11649,7 +11630,7 @@ const SCREENS = runtimeSetting({
11649
11630
  "package": "himalaya",
11650
11631
  "type": "SearchField",
11651
11632
  "props": {
11652
- "placeholder": "Search loaded items",
11633
+ "placeholder": "Search",
11653
11634
  "value": "$service:himiBrandedPrograms.collection.query",
11654
11635
  "debounceMs": 200,
11655
11636
  "onChange": {
@@ -13333,7 +13314,7 @@ const SCREENS = runtimeSetting({
13333
13314
  "package": "himalaya",
13334
13315
  "type": "Text",
13335
13316
  "props": {
13336
- "text": "Sort loaded items",
13317
+ "text": "Sort",
13337
13318
  "style": "bodyEmphasis"
13338
13319
  }
13339
13320
  }
@@ -14183,7 +14164,7 @@ const SCREENS = runtimeSetting({
14183
14164
  "package": "himalaya",
14184
14165
  "type": "SearchField",
14185
14166
  "props": {
14186
- "placeholder": "Search loaded items",
14167
+ "placeholder": "Search",
14187
14168
  "value": "$service:himiBrandedPlans.collection.query",
14188
14169
  "debounceMs": 200,
14189
14170
  "onChange": {
@@ -14573,7 +14554,7 @@ const SCREENS = runtimeSetting({
14573
14554
  "text": "$item.collectionMeta",
14574
14555
  "style": "caption",
14575
14556
  "color": "textSecondary",
14576
- "maxLines": 2,
14557
+ "maxLines": 8,
14577
14558
  "collapseWhenEmpty": true
14578
14559
  }
14579
14560
  }
@@ -14821,9 +14802,9 @@ const SCREENS = runtimeSetting({
14821
14802
  "package": "himalaya",
14822
14803
  "type": "Grid",
14823
14804
  "props": {
14824
- "columns": 2,
14825
- "columnsMedium": 3,
14826
- "columnsExpanded": 4,
14805
+ "columns": 1,
14806
+ "columnsMedium": 2,
14807
+ "columnsExpanded": 3,
14827
14808
  "spacing": 12,
14828
14809
  "itemsPath": "$service:himiBrandedPlans.collection.items",
14829
14810
  "items": [
@@ -14880,7 +14861,7 @@ const SCREENS = runtimeSetting({
14880
14861
  "text": "$item.collectionMeta",
14881
14862
  "style": "caption",
14882
14863
  "color": "textSecondary",
14883
- "maxLines": 2,
14864
+ "maxLines": 8,
14884
14865
  "collapseWhenEmpty": true
14885
14866
  }
14886
14867
  }
@@ -15449,9 +15430,9 @@ const SCREENS = runtimeSetting({
15449
15430
  "package": "himalaya",
15450
15431
  "type": "Grid",
15451
15432
  "props": {
15452
- "columns": 2,
15453
- "columnsMedium": 3,
15454
- "columnsExpanded": 4,
15433
+ "columns": 1,
15434
+ "columnsMedium": 2,
15435
+ "columnsExpanded": 3,
15455
15436
  "spacing": 8,
15456
15437
  "itemsPath": "$service:himiBrandedPlans.collection.items",
15457
15438
  "items": [
@@ -15825,7 +15806,7 @@ const SCREENS = runtimeSetting({
15825
15806
  "package": "himalaya",
15826
15807
  "type": "Text",
15827
15808
  "props": {
15828
- "text": "Sort loaded items",
15809
+ "text": "Sort",
15829
15810
  "style": "bodyEmphasis"
15830
15811
  }
15831
15812
  }
@@ -16107,7 +16088,7 @@ const SCREENS = runtimeSetting({
16107
16088
  "text": "$item.collectionMeta",
16108
16089
  "style": "caption",
16109
16090
  "color": "textSecondary",
16110
- "maxLines": 2,
16091
+ "maxLines": 8,
16111
16092
  "collapseWhenEmpty": true
16112
16093
  }
16113
16094
  }
@@ -17438,7 +17419,7 @@ const SCREENS = runtimeSetting({
17438
17419
  "package": "himalaya",
17439
17420
  "type": "SearchField",
17440
17421
  "props": {
17441
- "placeholder": "Exact event title",
17422
+ "placeholder": "Search events",
17442
17423
  "debounceMs": 200,
17443
17424
  "onChange": {
17444
17425
  "actionId": "tier5.himiEvents.collectionSearch"
@@ -18631,20 +18612,6 @@ const SCREENS = runtimeSetting({
18631
18612
  }
18632
18613
  }
18633
18614
  },
18634
- {
18635
- "id": "btn_tier5_himievents_refresh",
18636
- "body": {
18637
- "package": "himalaya",
18638
- "type": "Button",
18639
- "props": {
18640
- "title": "Refresh",
18641
- "style": "plain",
18642
- "action": {
18643
- "actionId": "tier5.himiEvents.refresh"
18644
- }
18645
- }
18646
- }
18647
- },
18648
18615
  {
18649
18616
  "id": "himi_events.list.collection.more",
18650
18617
  "body": {
@@ -19320,20 +19287,6 @@ const SCREENS = runtimeSetting({
19320
19287
  }
19321
19288
  }
19322
19289
  },
19323
- {
19324
- "id": "btn_tier5_himievents_refresh",
19325
- "body": {
19326
- "package": "himalaya",
19327
- "type": "Button",
19328
- "props": {
19329
- "title": "Refresh",
19330
- "style": "plain",
19331
- "action": {
19332
- "actionId": "tier5.himiEvents.refresh"
19333
- }
19334
- }
19335
- }
19336
- },
19337
19290
  {
19338
19291
  "id": "himi_events.list.collection.compact-more",
19339
19292
  "body": {
@@ -20806,7 +20759,7 @@ const SCREENS = runtimeSetting({
20806
20759
  "package": "himalaya",
20807
20760
  "type": "SearchField",
20808
20761
  "props": {
20809
- "placeholder": "Search loaded items",
20762
+ "placeholder": "Search",
20810
20763
  "debounceMs": 200,
20811
20764
  "onChange": {
20812
20765
  "actionId": "tier5.himiBlogFeed.collectionSearch"
@@ -21918,20 +21871,6 @@ const SCREENS = runtimeSetting({
21918
21871
  }
21919
21872
  }
21920
21873
  },
21921
- {
21922
- "id": "btn_tier5_himiblogfeed_retry",
21923
- "body": {
21924
- "package": "himalaya",
21925
- "type": "Button",
21926
- "props": {
21927
- "title": "Refresh",
21928
- "style": "plain",
21929
- "action": {
21930
- "actionId": "tier5.himiBlogFeed.retry"
21931
- }
21932
- }
21933
- }
21934
- },
21935
21874
  {
21936
21875
  "id": "himi_blog.list.collection.more",
21937
21876
  "body": {
@@ -22569,20 +22508,6 @@ const SCREENS = runtimeSetting({
22569
22508
  }
22570
22509
  }
22571
22510
  },
22572
- {
22573
- "id": "btn_tier5_himiblogfeed_retry",
22574
- "body": {
22575
- "package": "himalaya",
22576
- "type": "Button",
22577
- "props": {
22578
- "title": "Refresh",
22579
- "style": "plain",
22580
- "action": {
22581
- "actionId": "tier5.himiBlogFeed.retry"
22582
- }
22583
- }
22584
- }
22585
- },
22586
22511
  {
22587
22512
  "id": "himi_blog.list.collection.compact-more",
22588
22513
  "body": {
@@ -22709,7 +22634,7 @@ const SCREENS = runtimeSetting({
22709
22634
  "package": "himalaya",
22710
22635
  "type": "Text",
22711
22636
  "props": {
22712
- "text": "Sort loaded items",
22637
+ "text": "Sort",
22713
22638
  "style": "bodyEmphasis"
22714
22639
  }
22715
22640
  }
@@ -23413,7 +23338,7 @@ const SCREENS = runtimeSetting({
23413
23338
  "package": "himalaya",
23414
23339
  "type": "Text",
23415
23340
  "props": {
23416
- "text": "Posts saved on this member device.",
23341
+ "text": "Posts you have saved to read later.",
23417
23342
  "style": "body",
23418
23343
  "color": "textSecondary"
23419
23344
  }
@@ -26,6 +26,13 @@ export interface CollectionConfig {
26
26
  reviewSelectedAction?: string;
27
27
  /** Optional comfortable grid media height for immersive visual catalogs. */
28
28
  gridImageHeight?: number;
29
+ /** What the count summary counts — ["dish", "dishes"] reads "12 dishes". Default "item(s)". */
30
+ countNoun?: [string, string];
31
+ /** Phone grid columns (default 2). A card carrying a paragraph of benefits and a CTA — a
32
+ * pricing plan — is unreadable at half width, so it opts into one. */
33
+ gridColumns?: number;
34
+ /** Lines of the meta caption a comfortable row may use (default 2). */
35
+ metaMaxLines?: number;
29
36
  /** The card's primary verb, shown as a visible button beside the overflow.
30
37
  * `screenId` opens that screen with the row id; without it the verb reuses the
31
38
  * row's own tap action (the detail screen that owns the verb). */
@@ -38,28 +45,28 @@ export interface CollectionConfig {
38
45
  * page, the list/grid toggle, Refine, chips, search and count are noise. */
39
46
  export const COLLECTION_CHROME_MIN_ITEMS = 4;
40
47
  export const COLLECTIONS: Record<string, CollectionConfig> = {
41
- himiStoreShop: { rows: 'results', title: 'name', subtitle: 'subtitle', image: 'image', view: 'grid', backendQuery: true },
42
- himiBookingServices: { rows: 'results', title: 'name', subtitle: 'subtitle', image: 'image', filter: 'category', view: 'grid', backendQuery: true, searchPlaceholder: 'Service name starts with…', primaryVerb: { label: 'Book', screenId: 'himi_time' } },
48
+ himiStoreShop: { rows: 'results', title: 'name', subtitle: 'subtitle', image: 'image', view: 'grid', backendQuery: true, countNoun: ['product', 'products'] },
49
+ himiBookingServices: { rows: 'results', title: 'name', subtitle: 'subtitle', image: 'image', filter: 'category', view: 'grid', backendQuery: true, searchPlaceholder: 'Search services', countNoun: ['service', 'services'], primaryVerb: { label: 'Book', screenId: 'himi_time' } },
43
50
  himiBookingBookings: { rows: 'rows', title: 'title', subtitle: 'subtitle', metadata: ['status'], view: 'list', backendQuery: true,
44
- defaultFilter: 'value:Upcoming', searchPlaceholder: 'Exact booking ID', filterValues: ['Upcoming', 'Past', 'Cancelled'],
51
+ defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search by booking ID', countNoun: ['booking', 'bookings'], filterValues: ['Upcoming', 'Past', 'Cancelled'],
45
52
  sortLabels: { default: 'Soonest', az: 'Oldest', za: 'Latest' } },
46
- himiEvents: { rows: 'results', title: 'title', subtitle: 'dateLine', image: 'image', view: 'grid', backendQuery: true, searchPlaceholder: 'Exact event title', filterValues: ['Upcoming', 'Past'], sortLabels: { default: 'Date', az: 'Title A–Z', za: 'Title Z–A' }, primaryVerb: { label: 'Register' } },
53
+ himiEvents: { rows: 'results', title: 'title', subtitle: 'dateLine', image: 'image', view: 'grid', backendQuery: true, defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search events', countNoun: ['event', 'events'], filterValues: ['Upcoming', 'Past'], sortLabels: { default: 'Date', az: 'Title A–Z', za: 'Title Z–A' }, primaryVerb: { label: 'Register' } },
47
54
  himiBlogFeed: { rows: 'posts', title: 'title', subtitle: 'excerpt', image: 'image', filter: 'category', filterValuesFrom: 'categories', view: 'grid', narrowedBy: 'selectedCategoryId' },
48
- himiOwnerLiteProducts: { rows: 'products', title: 'name', subtitle: 'price', image: 'image', view: 'grid', backendQuery: true },
55
+ himiOwnerLiteProducts: { rows: 'products', title: 'name', subtitle: 'price', image: 'image', view: 'grid', backendQuery: true, countNoun: ['product', 'products'] },
49
56
  himiOwnerModules: { instanceInput: 'module', rows: 'rows', title: 'title', subtitle: 'subtitle', image: 'image', filter: 'statusLabel', view: 'list', paged: true, reviewAction: 'prepareRecord', reviewSelectedAction: 'prepareSelected' },
50
57
  himiOwnerLiteServices: { rows: 'services', title: 'name', subtitle: 'subtitle', view: 'list', backendQuery: true, searchPlaceholder: 'Service name starts with…' },
51
58
  himiOwnerLiteEvents: { rows: 'events', title: 'title', subtitle: 'dateLine', view: 'grid', backendQuery: true, searchPlaceholder: 'Exact event title', filterValues: ['Upcoming'], sortLabels: { default: 'Date', az: 'Title A–Z', za: 'Title Z–A' } },
52
59
  himiOwnerLitePosts: { rows: 'posts', title: 'title', subtitle: 'excerpt', image: 'image', view: 'grid' },
53
- himiOwnerLiteOrders: { rows: 'orders', title: 'buyer', subtitle: 'meta', filter: 'statusLabel', view: 'list', backendQuery: true,
60
+ himiOwnerLiteOrders: { rows: 'orders', title: 'buyer', subtitle: 'meta', filter: 'statusLabel', view: 'list', backendQuery: true, countNoun: ['order', 'orders'],
54
61
  searchPlaceholder: 'Customer name, email or order #', sortLabels: { default: 'Newest', az: 'Customer A–Z', za: 'Customer Z–A' },
55
62
  filterValues: ['Recent 7 days', 'Paid', 'Unpaid', 'Partially paid', 'Pending', 'Refunded', 'Partly refunded'] },
56
63
  himiBrandedGroups: { rows: 'rows', title: 'name', subtitle: 'description', image: 'image', view: 'grid' },
57
64
  himiBrandedCms: { rows: 'rows', title: 'name', subtitle: 'subtitle', view: 'grid' },
58
65
  himiBrandedCmsCollection: { instanceInput: 'collection', rows: 'rows', title: 'title', subtitle: 'subtitle', view: 'list' },
59
66
  himiBrandedOrders: { rows: 'rows', title: 'title', subtitle: 'subtitle', view: 'list', backendQuery: true,
60
- searchPlaceholder: 'Exact order number', filterValues: ['Not fulfilled', 'Partially fulfilled', 'Fulfilled'],
67
+ searchPlaceholder: 'Search by order number', countNoun: ['order', 'orders'], filterValues: ['Not fulfilled', 'Partially fulfilled', 'Fulfilled'],
61
68
  sortLabels: { default: 'Newest', az: 'Oldest', za: 'Order # ↓' } },
62
- himiBrandedPlans: { rows: 'rows', title: 'name', subtitle: 'description', metadata: ['priceLine', 'periodLine', 'trialBadge', 'perk1', 'perk2', 'perk3'], view: 'grid' },
69
+ himiBrandedPlans: { rows: 'rows', title: 'name', subtitle: 'description', metadata: ['badge', 'priceLine', 'periodLine', 'trialBadge', 'perk1', 'perk2', 'perk3'], view: 'grid', gridColumns: 1, metaMaxLines: 8, countNoun: ['plan', 'plans'] },
63
70
  himiBrandedPrograms: { rows: 'rows', title: 'name', subtitle: 'description', image: 'image', view: 'grid' },
64
71
  himiBrandedCoupons: { rows: 'coupons', title: 'name', subtitle: 'subtitle', view: 'list', primaryVerb: { label: 'Get code' } },
65
72
  himiBrandedNotifications: { rows: 'items', title: 'name', subtitle: 'subtitle', image: 'photo', metadata: ['unreadDot'], view: 'list' },
@@ -75,7 +82,7 @@ export const COLLECTIONS: Record<string, CollectionConfig> = {
75
82
  himiBrandedForms: { rows: 'forms', title: 'name', subtitle: 'description', view: 'list' },
76
83
  himiBrandedGalleries: { rows: 'galleries', title: 'name', subtitle: 'description', image: 'image', view: 'grid' },
77
84
  himiBrandedInbox: { rows: 'conversations', title: 'title', subtitle: 'preview', view: 'list' },
78
- himiBrandedMenus: { rows: 'rows', title: 'name', subtitle: 'description', image: 'image', sectioned: true, filter: 'collectionCategory', metadata: ['collectionCategory', 'priceLine', 'label1', 'label2', 'label3'], view: 'grid' },
85
+ himiBrandedMenus: { rows: 'rows', title: 'name', subtitle: 'description', image: 'image', sectioned: true, filter: 'collectionCategory', metadata: ['collectionCategory', 'priceLine', 'label1', 'label2', 'label3'], view: 'grid', searchPlaceholder: 'Search the menu', countNoun: ['dish', 'dishes'] },
79
86
  };
80
87
  export interface CollectionPreferences {
81
88
  view: 'list' | 'grid';
@@ -18,6 +18,20 @@ type Reducer = (s: State, ...args: unknown[]) => State | undefined | Promise<Sta
18
18
  const object = (x: unknown): State => x && typeof x === 'object' && !Array.isArray(x) ? x as State : {};
19
19
  const str = (arg: unknown, key: string): string => typeof arg === 'string' ? arg : String(object(arg)[key] ?? '');
20
20
 
21
+ /** The toolbar count line — "12 dishes", or "3 of 12 dishes" while a filter narrows the list.
22
+ *
23
+ * It used to read "12 / 12 loaded" and "2 / 2 results" ([branded-lite-qa] #3002): the numbers
24
+ * described the implementation (a client-side filter over a fetched page) rather than what the
25
+ * customer is looking at, and the slash-and-suffix wrapped onto two lines on web. When the
26
+ * backend total is unknown the count shown is simply what is shown; the "Load more" button is
27
+ * what says there is more. */
28
+ export function collectionSummary(o: { shown: number; loaded: number; total?: number; backend?: boolean; noun?: [string, string] }): string {
29
+ const [one, many] = o.noun ?? [copyParam('collection.itemOne', 'item'), copyParam('collection.itemMany', 'items')];
30
+ const whole = o.backend ? (typeof o.total === 'number' ? o.total : o.shown) : o.loaded;
31
+ const noun = (whole === 1 ? one : many);
32
+ return o.shown < whole ? `${o.shown} ${copyParam('collection.of', 'of')} ${whole} ${noun}` : `${o.shown} ${o.shown === 1 ? one : many}`;
33
+ }
34
+
21
35
  /** Opt-in decorator. Domain reducers remain authoritative; collection preferences
22
36
  * survive reducers which replace their entire state, including async refreshes. */
23
37
  export function decorateCollection(name: string, def: { state: State; actions?: Record<string, Reducer> }, saving?: CollectionSaving, backend?: BackendCollection) {
@@ -179,11 +193,11 @@ export function decorateCollection(name: string, def: { state: State; actions?:
179
193
  filtersPresented, previewPresented: !!previewId, preview: projected.items.filter(row => row.collectionId === previewId),
180
194
  persistenceLabel: persisted.available ? copyParam('collection.onDevice', 'Saved on this device') : copyParam('collection.sessionOnly', 'Choices last for this session'),
181
195
  noEmpty: loading || errored || sourceEmpty || domainNarrowed || projected.items.length > 0,
182
- summary: backend && config.backendQuery
183
- ? (s.fromCache ? copyParam('collection.cached', 'Saved offline · may be outdated')
184
- : typeof s.total === 'number' ? `${projected.items.length} / ${s.total} ${copyParam('collection.results', 'results')}`
185
- : `${projected.items.length} ${s.complete ? copyParam('collection.results', 'results') : copyParam('collection.loaded', 'loaded')}`)
186
- : `${projected.items.length} / ${projected.loaded} ${copyParam('collection.loaded', 'loaded')}`,
196
+ summary: backend && config.backendQuery && s.fromCache
197
+ ? copyParam('collection.cached', 'Saved offline · may be outdated')
198
+ : collectionSummary({ shown: projected.items.length, loaded: projected.loaded, backend: !!(backend && config.backendQuery),
199
+ total: typeof s.total === 'number' ? s.total : undefined, noun: config.countNoun
200
+ ? [copyParam(`collection.${name}.countOne`, config.countNoun[0]), copyParam(`collection.${name}.countMany`, config.countNoun[1])] : undefined }),
187
201
  selectedSummary: `${prefs.selectedIds.length} ${copyParam('collection.selected', 'selected')}`,
188
202
  filterChoices,
189
203
  chips: config.filterValues ? filterChoices.filter(choice => ['all', 'saved', prefs.filter].includes(choice.id)) : filterChoices,
@@ -352,3 +352,54 @@ export function compareDateDesc(a: string, b: string): number {
352
352
  if (bBad) return -1;
353
353
  return tb - ta;
354
354
  }
355
+
356
+ // --- [branded-lite-qa] #3079: one pattern per fact ---------------------------------------
357
+ //
358
+ // Before these existed, four screens formatted the same money four ways — Shop "69.00 ₪" (Wix's
359
+ // pre-formatted string), Services "₪70" (0 decimals), Menu "₪32.00", Plans "$24" — and two
360
+ // screens formatted the same clock two ways (Events "9:00 PM-11:00 PM", Reserve "20:00").
361
+ // Customers read that as sloppiness, and a whole "₪70" beside "₪69.50" reads as a different
362
+ // kind of number. So: one money pattern, one clock, one range.
363
+
364
+ // Money uses `formatCurrency(amount, currency, "en")` — the currency's NATURAL decimals
365
+ // ("₪70.00", "¥500"). Passing 0 fraction digits for whole amounts is what made a list read
366
+ // "₪70 · ₪69.50".
367
+
368
+ const KNOWN_SYMBOLS = new Set(Object.values(CURRENCY_SYMBOL));
369
+
370
+ /** Wix hands some prices over PRE-formatted in the site's regional style — "69.00 ₪" with the
371
+ * symbol trailing, often wrapped in bidi marks. Reorder those to the house pattern ("₪69.00") so
372
+ * they match every price we format ourselves. Only an en-shaped number ("69.00", "1,234.50") with
373
+ * a known trailing symbol is reordered: a comma-decimal or space-grouped string ("69,00 €",
374
+ * "1 234,56 €") is kept as Wix wrote it, because half-converting it would be worse. Anything else
375
+ * ("Market price") is returned trimmed. The store SDK's product price applies the same rule. */
376
+ export function normalizeFormattedPrice(formatted: string): string {
377
+ const raw = (formatted || "").replace(/[‎‏]/g, "").trim();
378
+ const m = /^(-?)(\d{1,3}(?:,\d{3})*(?:\.\d+)?|\d+(?:\.\d+)?)[\s  ]*(\S+)$/.exec(raw);
379
+ if (!m || !KNOWN_SYMBOLS.has(m[3])) return raw;
380
+ return `${m[1]}${m[3]}${m[2]}`;
381
+ }
382
+
383
+ function clockParts(d: Date, locale: string): { time: string; meridiem: string } {
384
+ const full = hasIntl()
385
+ ? new Intl.DateTimeFormat(locale, { hour: "numeric", minute: "2-digit", hour12: true }).format(d)
386
+ : clock12(d);
387
+ // ICU puts a narrow no-break space before the meridiem; normalize so callers can split on it.
388
+ const clean = full.replace(/[  ]/g, " ");
389
+ const m = /^(.*?)\s*([AP]\.?M\.?)$/i.exec(clean);
390
+ return m ? { time: m[1], meridiem: m[2] } : { time: clean, meridiem: "" };
391
+ }
392
+
393
+ /** "8:00 PM" — the one clock every customer screen uses (12-hour, en-US shape). */
394
+ export function formatClock(date: Date, locale = "en-US"): string {
395
+ const { time, meridiem } = clockParts(date, locale);
396
+ return meridiem ? `${time} ${meridiem}` : time;
397
+ }
398
+
399
+ /** Is this ISO instant before `now`? A missing or unparseable value is NOT past — "no expiry"
400
+ * must never classify an offer as expired. */
401
+ export function isPastDate(iso: string | undefined | null, now: number = Date.now()): boolean {
402
+ if (!iso) return false;
403
+ const t = Date.parse(iso);
404
+ return !Number.isNaN(t) && t < now;
405
+ }
@@ -11,7 +11,7 @@ import { wixMediaUrl, type WixImageSize } from "@himalaya/wix-media";
11
11
  // copier recognizes + carries the dependency; resolves to the same file here
12
12
  // and in the scaffolded tier5-src/_shared/ layout.
13
13
  import { cleanTitle, initials } from "../_shared/himi-text.js";
14
- import { formatCurrency } from "../_shared/engine-intl.js";
14
+ import { formatCurrency, normalizeFormattedPrice } from "../_shared/engine-intl.js";
15
15
 
16
16
  /** One dish tile/row: the media-XOR-initials card contract every himi list
17
17
  * uses, plus a formatted price line and the templated detail screen id. */
@@ -97,13 +97,13 @@ export function itemPriceLine(item: WixItem): string {
97
97
  | { price?: unknown; currency?: unknown; formattedPrice?: unknown }
98
98
  | undefined;
99
99
  const formatted = typeof info?.formattedPrice === "string" ? info.formattedPrice.trim() : "";
100
- if (formatted) return formatted;
100
+ if (formatted) return normalizeFormattedPrice(formatted);
101
101
  const price = info?.price;
102
102
  if (price == null || price === "" || Number.isNaN(Number(price))) return "";
103
103
  const currency = typeof info?.currency === "string" ? info.currency : "";
104
104
  if (!currency) return `${price}`;
105
105
  try {
106
- return formatCurrency(Number(price), currency, "en", Number(price) % 1 === 0 ? 0 : 2);
106
+ return formatCurrency(Number(price), currency, "en");
107
107
  } catch {
108
108
  return `${price}`;
109
109
  }
@@ -149,7 +149,7 @@ export function itemPriceVariants(item: WixItem): Array<{ id: string; name: stri
149
149
  let priceLine = `${price}`;
150
150
  if (currency) {
151
151
  try {
152
- priceLine = formatCurrency(Number(price), currency, "en", Number(price) % 1 === 0 ? 0 : 2);
152
+ priceLine = formatCurrency(Number(price), currency, "en");
153
153
  } catch { /* keep the bare amount */ }
154
154
  }
155
155
  rows.push({ id: typeof node.id === "string" && node.id ? node.id : `variant-${index}`, name: name || "Option", priceLine });