@wix/himalaya-cli 0.1583.0 → 0.1585.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 (313) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-module.d.ts +7 -4
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/bindings.d.ts +7 -6
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/blog-v3/src/extensions.d.ts +2 -0
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/comments-v1/src/extensions.d.ts +2 -0
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/events/src/index.d.ts +3 -0
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/groups/src/extensions.d.ts +15 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/loyalty/src/extensions.d.ts +13 -0
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/members-v1/src/index.d.ts +19 -4
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +2 -2
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +8 -2
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-comments.mjs +3 -0
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-events.mjs +4 -2
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-groups.mjs +5 -0
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-loyalty.mjs +4 -0
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-members.mjs +10 -3
  16. package/dist/cli.mjs +2201 -1716
  17. package/dist/preview-assets.generated.bin +0 -0
  18. package/fixtures/wix-canned.json +25 -0
  19. package/guides/branded-lite-site-binding.md +7 -1
  20. package/guides/designing-himi-screens.md +47 -7
  21. package/guides/himi-skill.md +16 -0
  22. package/guides/index.json +1 -0
  23. package/guides/one-app-to-himi-app.md +52 -1
  24. package/guides/sdk-reference.json +37 -9
  25. package/guides/tier-5-add-a-screen.md +9 -0
  26. package/guides/wix-api-usage.md +9 -0
  27. package/package.json +2 -2
  28. package/templates/beauty-salon/config.ts +7 -0
  29. package/templates/beauty-salon/dev/index.ts +758 -352
  30. package/templates/beauty-salon/himalaya.content.json +3 -0
  31. package/templates/beauty-salon/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  32. package/templates/beauty-salon/tier5-src/_shared/collection-contract.ts +19 -3
  33. package/templates/beauty-salon/tier5-src/_shared/himi-restaurants.ts +2 -1
  34. package/templates/beauty-salon/tier5-src/_shared/owner-editor-value.ts +164 -0
  35. package/templates/beauty-salon/tier5-src/_shared/store-product-info.ts +50 -0
  36. package/templates/beauty-salon/tier5-src/himi-blog-post/index.ts +21 -8
  37. package/templates/beauty-salon/tier5-src/himi-branded-lite-category/index.ts +3 -2
  38. package/templates/beauty-salon/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  39. package/templates/beauty-salon/tier5-src/himi-branded-lite-plans/index.ts +2 -1
  40. package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +14 -3
  41. package/templates/beauty-salon/tier5-src/wix-spaces-plan-detail/index.ts +2 -1
  42. package/templates/beauty-salon/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  43. package/templates/beauty-salon-owner/dev/index.ts +129 -66
  44. package/templates/beauty-salon-owner/tier5-src/_shared/collection-contract.ts +19 -3
  45. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  46. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product/index.ts +39 -6
  47. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  48. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-products/index.ts +7 -4
  49. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-service/index.ts +38 -7
  50. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-service-form/index.ts +53 -7
  51. package/templates/beauty-salon-owner/tier5-src/himi-owner-lite-services/index.ts +4 -2
  52. package/templates/branded-lite/config.ts +9 -0
  53. package/templates/branded-lite/dev/index.ts +4988 -3304
  54. package/templates/branded-lite/himalaya.content.json +3 -0
  55. package/templates/branded-lite/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  56. package/templates/branded-lite/tier5-src/_shared/collection-contract.ts +19 -3
  57. package/templates/branded-lite/tier5-src/_shared/event-registration.ts +86 -0
  58. package/templates/branded-lite/tier5-src/_shared/himi-restaurants.ts +2 -1
  59. package/templates/branded-lite/tier5-src/_shared/owner-editor-value.ts +164 -0
  60. package/templates/branded-lite/tier5-src/_shared/store-product-info.ts +50 -0
  61. package/templates/branded-lite/tier5-src/himi-blog-post/index.ts +21 -8
  62. package/templates/branded-lite/tier5-src/himi-branded-lite-badges/index.ts +2 -1
  63. package/templates/branded-lite/tier5-src/himi-branded-lite-category/index.ts +3 -2
  64. package/templates/branded-lite/tier5-src/himi-branded-lite-feed/index.ts +4 -3
  65. package/templates/branded-lite/tier5-src/himi-branded-lite-group-about/index.ts +243 -0
  66. package/templates/branded-lite/tier5-src/himi-branded-lite-loyalty/index.ts +115 -49
  67. package/templates/branded-lite/tier5-src/himi-branded-lite-plans/index.ts +2 -1
  68. package/templates/branded-lite/tier5-src/himi-branded-lite-podcasts/index.ts +2 -1
  69. package/templates/branded-lite/tier5-src/himi-branded-lite-portfolio/index.ts +2 -1
  70. package/templates/branded-lite/tier5-src/himi-branded-lite-portfolio-project/index.ts +3 -2
  71. package/templates/branded-lite/tier5-src/himi-branded-lite-program/facts.ts +52 -0
  72. package/templates/branded-lite/tier5-src/himi-branded-lite-program/index.ts +21 -11
  73. package/templates/branded-lite/tier5-src/himi-branded-lite-video/index.ts +2 -1
  74. package/templates/branded-lite/tier5-src/himi-events-detail/index.ts +12 -86
  75. package/templates/branded-lite/tier5-src/himi-events-list/index.ts +47 -6
  76. package/templates/branded-lite/tier5-src/himi-store-product/index.ts +13 -3
  77. package/templates/branded-lite/tier5-src/wix-spaces-forum-post/index.ts +3 -2
  78. package/templates/branded-lite/tier5-src/wix-spaces-member-detail/index.ts +53 -37
  79. package/templates/branded-lite/tier5-src/wix-spaces-members/index.ts +100 -34
  80. package/templates/branded-lite/tier5-src/wix-spaces-plan-detail/index.ts +2 -1
  81. package/templates/branded-lite/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  82. package/templates/community-club/config.ts +16 -0
  83. package/templates/community-club/dev/index.ts +1930 -401
  84. package/templates/community-club/himalaya.content.json +6 -0
  85. package/templates/community-club/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  86. package/templates/community-club/tier5-src/_shared/collection-contract.ts +19 -3
  87. package/templates/community-club/tier5-src/_shared/event-registration.ts +86 -0
  88. package/templates/community-club/tier5-src/_shared/himi-restaurants.ts +2 -1
  89. package/templates/community-club/tier5-src/himi-blog-post/index.ts +21 -8
  90. package/templates/community-club/tier5-src/himi-branded-lite-feed/index.ts +4 -3
  91. package/templates/community-club/tier5-src/himi-branded-lite-group-about/index.ts +243 -0
  92. package/templates/community-club/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  93. package/templates/community-club/tier5-src/himi-events-detail/index.ts +12 -86
  94. package/templates/community-club/tier5-src/himi-events-list/index.ts +47 -6
  95. package/templates/community-club/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  96. package/templates/community-club-owner/dev/index.ts +53 -1
  97. package/templates/community-club-owner/tier5-src/_shared/collection-contract.ts +19 -3
  98. package/templates/community-club-owner/tier5-src/himi-owner-lite-event/index.ts +16 -8
  99. package/templates/community-club-owner/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  100. package/templates/community-club-owner/tier5-src/himi-owner-lite-events/index.ts +4 -2
  101. package/templates/community-club-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  102. package/templates/community-club-owner/tier5-src/himi-owner-lite-product/index.ts +39 -6
  103. package/templates/community-club-owner/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  104. package/templates/community-club-owner/tier5-src/himi-owner-lite-products/index.ts +7 -4
  105. package/templates/events-meetups/config.ts +16 -0
  106. package/templates/events-meetups/dev/index.ts +1930 -401
  107. package/templates/events-meetups/himalaya.content.json +6 -0
  108. package/templates/events-meetups/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  109. package/templates/events-meetups/tier5-src/_shared/collection-contract.ts +19 -3
  110. package/templates/events-meetups/tier5-src/_shared/event-registration.ts +86 -0
  111. package/templates/events-meetups/tier5-src/_shared/himi-restaurants.ts +2 -1
  112. package/templates/events-meetups/tier5-src/himi-blog-post/index.ts +21 -8
  113. package/templates/events-meetups/tier5-src/himi-branded-lite-feed/index.ts +4 -3
  114. package/templates/events-meetups/tier5-src/himi-branded-lite-group-about/index.ts +243 -0
  115. package/templates/events-meetups/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  116. package/templates/events-meetups/tier5-src/himi-events-detail/index.ts +12 -86
  117. package/templates/events-meetups/tier5-src/himi-events-list/index.ts +47 -6
  118. package/templates/events-meetups/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  119. package/templates/events-meetups-owner/dev/index.ts +6 -0
  120. package/templates/events-meetups-owner/tier5-src/_shared/collection-contract.ts +19 -3
  121. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event/index.ts +16 -8
  122. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  123. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-events/index.ts +4 -2
  124. package/templates/events-meetups-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  125. package/templates/gym-fitness/config.ts +7 -0
  126. package/templates/gym-fitness/dev/index.ts +1115 -278
  127. package/templates/gym-fitness/himalaya.content.json +3 -0
  128. package/templates/gym-fitness/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  129. package/templates/gym-fitness/tier5-src/_shared/collection-contract.ts +19 -3
  130. package/templates/gym-fitness/tier5-src/_shared/event-registration.ts +86 -0
  131. package/templates/gym-fitness/tier5-src/_shared/himi-restaurants.ts +2 -1
  132. package/templates/gym-fitness/tier5-src/_shared/owner-editor-value.ts +164 -0
  133. package/templates/gym-fitness/tier5-src/_shared/store-product-info.ts +50 -0
  134. package/templates/gym-fitness/tier5-src/himi-blog-post/index.ts +21 -8
  135. package/templates/gym-fitness/tier5-src/himi-branded-lite-category/index.ts +3 -2
  136. package/templates/gym-fitness/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  137. package/templates/gym-fitness/tier5-src/himi-branded-lite-plans/index.ts +2 -1
  138. package/templates/gym-fitness/tier5-src/himi-events-detail/index.ts +12 -86
  139. package/templates/gym-fitness/tier5-src/himi-events-list/index.ts +47 -6
  140. package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +14 -3
  141. package/templates/gym-fitness/tier5-src/wix-spaces-plan-detail/index.ts +2 -1
  142. package/templates/gym-fitness/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  143. package/templates/gym-fitness-owner/dev/index.ts +132 -66
  144. package/templates/gym-fitness-owner/tier5-src/_shared/collection-contract.ts +19 -3
  145. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event/index.ts +16 -8
  146. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  147. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-events/index.ts +4 -2
  148. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  149. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product/index.ts +39 -6
  150. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  151. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-products/index.ts +7 -4
  152. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-service/index.ts +38 -7
  153. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-service-form/index.ts +53 -7
  154. package/templates/gym-fitness-owner/tier5-src/himi-owner-lite-services/index.ts +4 -2
  155. package/templates/nonprofit-cause/config.ts +16 -0
  156. package/templates/nonprofit-cause/dev/index.ts +1925 -396
  157. package/templates/nonprofit-cause/himalaya.content.json +6 -0
  158. package/templates/nonprofit-cause/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  159. package/templates/nonprofit-cause/tier5-src/_shared/collection-contract.ts +19 -3
  160. package/templates/nonprofit-cause/tier5-src/_shared/event-registration.ts +86 -0
  161. package/templates/nonprofit-cause/tier5-src/_shared/himi-restaurants.ts +2 -1
  162. package/templates/nonprofit-cause/tier5-src/himi-blog-post/index.ts +21 -8
  163. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-feed/index.ts +4 -3
  164. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-group-about/index.ts +243 -0
  165. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  166. package/templates/nonprofit-cause/tier5-src/himi-branded-lite-plans/index.ts +2 -1
  167. package/templates/nonprofit-cause/tier5-src/himi-events-detail/index.ts +12 -86
  168. package/templates/nonprofit-cause/tier5-src/himi-events-list/index.ts +47 -6
  169. package/templates/nonprofit-cause/tier5-src/wix-spaces-plan-detail/index.ts +2 -1
  170. package/templates/nonprofit-cause/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  171. package/templates/nonprofit-cause-owner/dev/index.ts +85 -65
  172. package/templates/nonprofit-cause-owner/tier5-src/_shared/collection-contract.ts +19 -3
  173. package/templates/nonprofit-cause-owner/tier5-src/_shared/owner-rich-guard.ts +27 -0
  174. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event/index.ts +16 -8
  175. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  176. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-events/index.ts +4 -2
  177. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  178. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-service/index.ts +38 -7
  179. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-service-form/index.ts +53 -7
  180. package/templates/nonprofit-cause-owner/tier5-src/himi-owner-lite-services/index.ts +4 -2
  181. package/templates/owner-lite/dev/index.ts +132 -66
  182. package/templates/owner-lite/tier5-src/_shared/collection-contract.ts +19 -3
  183. package/templates/owner-lite/tier5-src/himi-owner-lite-event/index.ts +16 -8
  184. package/templates/owner-lite/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  185. package/templates/owner-lite/tier5-src/himi-owner-lite-events/index.ts +4 -2
  186. package/templates/owner-lite/tier5-src/himi-owner-lite-post/index.ts +7 -0
  187. package/templates/owner-lite/tier5-src/himi-owner-lite-product/index.ts +39 -6
  188. package/templates/owner-lite/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  189. package/templates/owner-lite/tier5-src/himi-owner-lite-products/index.ts +7 -4
  190. package/templates/owner-lite/tier5-src/himi-owner-lite-service/index.ts +38 -7
  191. package/templates/owner-lite/tier5-src/himi-owner-lite-service-form/index.ts +53 -7
  192. package/templates/owner-lite/tier5-src/himi-owner-lite-services/index.ts +4 -2
  193. package/templates/podcast-creator/config.ts +7 -0
  194. package/templates/podcast-creator/dev/index.ts +1051 -158
  195. package/templates/podcast-creator/himalaya.content.json +3 -0
  196. package/templates/podcast-creator/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  197. package/templates/podcast-creator/tier5-src/_shared/collection-contract.ts +19 -3
  198. package/templates/podcast-creator/tier5-src/_shared/event-registration.ts +86 -0
  199. package/templates/podcast-creator/tier5-src/_shared/himi-restaurants.ts +2 -1
  200. package/templates/podcast-creator/tier5-src/himi-blog-post/index.ts +21 -8
  201. package/templates/podcast-creator/tier5-src/himi-branded-lite-feed/index.ts +4 -3
  202. package/templates/podcast-creator/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  203. package/templates/podcast-creator/tier5-src/himi-branded-lite-plans/index.ts +2 -1
  204. package/templates/podcast-creator/tier5-src/himi-branded-lite-podcasts/index.ts +2 -1
  205. package/templates/podcast-creator/tier5-src/himi-events-detail/index.ts +12 -86
  206. package/templates/podcast-creator/tier5-src/himi-events-list/index.ts +47 -6
  207. package/templates/podcast-creator/tier5-src/wix-spaces-plan-detail/index.ts +2 -1
  208. package/templates/podcast-creator/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  209. package/templates/podcast-creator-owner/dev/index.ts +53 -1
  210. package/templates/podcast-creator-owner/tier5-src/_shared/collection-contract.ts +19 -3
  211. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event/index.ts +16 -8
  212. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  213. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-events/index.ts +4 -2
  214. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  215. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product/index.ts +39 -6
  216. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  217. package/templates/podcast-creator-owner/tier5-src/himi-owner-lite-products/index.ts +7 -4
  218. package/templates/portfolio-creative/config.ts +7 -0
  219. package/templates/portfolio-creative/dev/index.ts +1305 -468
  220. package/templates/portfolio-creative/himalaya.content.json +3 -0
  221. package/templates/portfolio-creative/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  222. package/templates/portfolio-creative/tier5-src/_shared/collection-contract.ts +19 -3
  223. package/templates/portfolio-creative/tier5-src/_shared/event-registration.ts +86 -0
  224. package/templates/portfolio-creative/tier5-src/_shared/himi-restaurants.ts +2 -1
  225. package/templates/portfolio-creative/tier5-src/_shared/owner-editor-value.ts +164 -0
  226. package/templates/portfolio-creative/tier5-src/_shared/store-product-info.ts +50 -0
  227. package/templates/portfolio-creative/tier5-src/himi-blog-post/index.ts +21 -8
  228. package/templates/portfolio-creative/tier5-src/himi-branded-lite-category/index.ts +3 -2
  229. package/templates/portfolio-creative/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  230. package/templates/portfolio-creative/tier5-src/himi-branded-lite-portfolio/index.ts +2 -1
  231. package/templates/portfolio-creative/tier5-src/himi-branded-lite-portfolio-project/index.ts +3 -2
  232. package/templates/portfolio-creative/tier5-src/himi-events-detail/index.ts +12 -86
  233. package/templates/portfolio-creative/tier5-src/himi-events-list/index.ts +47 -6
  234. package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +14 -3
  235. package/templates/portfolio-creative/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  236. package/templates/portfolio-creative-owner/dev/index.ts +129 -66
  237. package/templates/portfolio-creative-owner/tier5-src/_shared/collection-contract.ts +19 -3
  238. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  239. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product/index.ts +39 -6
  240. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  241. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-products/index.ts +7 -4
  242. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-service/index.ts +38 -7
  243. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-service-form/index.ts +53 -7
  244. package/templates/portfolio-creative-owner/tier5-src/himi-owner-lite-services/index.ts +4 -2
  245. package/templates/restaurant/config.ts +7 -0
  246. package/templates/restaurant/dev/index.ts +1051 -158
  247. package/templates/restaurant/himalaya.content.json +3 -0
  248. package/templates/restaurant/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  249. package/templates/restaurant/tier5-src/_shared/collection-contract.ts +19 -3
  250. package/templates/restaurant/tier5-src/_shared/event-registration.ts +86 -0
  251. package/templates/restaurant/tier5-src/_shared/himi-restaurants.ts +2 -1
  252. package/templates/restaurant/tier5-src/himi-blog-post/index.ts +21 -8
  253. package/templates/restaurant/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  254. package/templates/restaurant/tier5-src/himi-events-detail/index.ts +12 -86
  255. package/templates/restaurant/tier5-src/himi-events-list/index.ts +47 -6
  256. package/templates/restaurant/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  257. package/templates/restaurant-owner/dev/index.ts +132 -66
  258. package/templates/restaurant-owner/tier5-src/_shared/collection-contract.ts +19 -3
  259. package/templates/restaurant-owner/tier5-src/himi-owner-lite-event/index.ts +16 -8
  260. package/templates/restaurant-owner/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  261. package/templates/restaurant-owner/tier5-src/himi-owner-lite-events/index.ts +4 -2
  262. package/templates/restaurant-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  263. package/templates/restaurant-owner/tier5-src/himi-owner-lite-product/index.ts +39 -6
  264. package/templates/restaurant-owner/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  265. package/templates/restaurant-owner/tier5-src/himi-owner-lite-products/index.ts +7 -4
  266. package/templates/restaurant-owner/tier5-src/himi-owner-lite-service/index.ts +38 -7
  267. package/templates/restaurant-owner/tier5-src/himi-owner-lite-service-form/index.ts +53 -7
  268. package/templates/restaurant-owner/tier5-src/himi-owner-lite-services/index.ts +4 -2
  269. package/templates/retail-store/config.ts +7 -0
  270. package/templates/retail-store/dev/index.ts +597 -191
  271. package/templates/retail-store/himalaya.content.json +3 -0
  272. package/templates/retail-store/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  273. package/templates/retail-store/tier5-src/_shared/collection-contract.ts +19 -3
  274. package/templates/retail-store/tier5-src/_shared/himi-restaurants.ts +2 -1
  275. package/templates/retail-store/tier5-src/_shared/owner-editor-value.ts +164 -0
  276. package/templates/retail-store/tier5-src/_shared/store-product-info.ts +50 -0
  277. package/templates/retail-store/tier5-src/himi-blog-post/index.ts +21 -8
  278. package/templates/retail-store/tier5-src/himi-branded-lite-category/index.ts +3 -2
  279. package/templates/retail-store/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  280. package/templates/retail-store/tier5-src/himi-store-product/index.ts +13 -3
  281. package/templates/retail-store/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  282. package/templates/retail-store-owner/dev/index.ts +50 -1
  283. package/templates/retail-store-owner/tier5-src/_shared/collection-contract.ts +19 -3
  284. package/templates/retail-store-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  285. package/templates/retail-store-owner/tier5-src/himi-owner-lite-product/index.ts +39 -6
  286. package/templates/retail-store-owner/tier5-src/himi-owner-lite-product-form/index.ts +14 -8
  287. package/templates/retail-store-owner/tier5-src/himi-owner-lite-products/index.ts +7 -4
  288. package/templates/yoga-studio/config.ts +7 -0
  289. package/templates/yoga-studio/dev/index.ts +1107 -110
  290. package/templates/yoga-studio/himalaya.content.json +3 -0
  291. package/templates/yoga-studio/tier5-src/_shared/branded-lite-hosted.ts +1 -1
  292. package/templates/yoga-studio/tier5-src/_shared/collection-contract.ts +19 -3
  293. package/templates/yoga-studio/tier5-src/_shared/event-registration.ts +86 -0
  294. package/templates/yoga-studio/tier5-src/_shared/himi-restaurants.ts +2 -1
  295. package/templates/yoga-studio/tier5-src/himi-blog-post/index.ts +21 -8
  296. package/templates/yoga-studio/tier5-src/himi-branded-lite-notifsettings/index.ts +173 -0
  297. package/templates/yoga-studio/tier5-src/himi-branded-lite-plans/index.ts +2 -1
  298. package/templates/yoga-studio/tier5-src/himi-branded-lite-program/facts.ts +52 -0
  299. package/templates/yoga-studio/tier5-src/himi-branded-lite-program/index.ts +21 -11
  300. package/templates/yoga-studio/tier5-src/himi-events-detail/index.ts +12 -86
  301. package/templates/yoga-studio/tier5-src/himi-events-list/index.ts +47 -6
  302. package/templates/yoga-studio/tier5-src/wix-spaces-plan-detail/index.ts +2 -1
  303. package/templates/yoga-studio/tier5-src/wix-spaces-whats-new/index.ts +2 -1
  304. package/templates/yoga-studio-owner/dev/index.ts +85 -65
  305. package/templates/yoga-studio-owner/tier5-src/_shared/collection-contract.ts +19 -3
  306. package/templates/yoga-studio-owner/tier5-src/_shared/owner-rich-guard.ts +27 -0
  307. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event/index.ts +16 -8
  308. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-event-form/index.ts +16 -7
  309. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-events/index.ts +4 -2
  310. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-post/index.ts +7 -0
  311. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-service/index.ts +38 -7
  312. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-service-form/index.ts +53 -7
  313. package/templates/yoga-studio-owner/tier5-src/himi-owner-lite-services/index.ts +4 -2
@@ -76893,6 +76893,35 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
76893
76893
  }
76894
76894
  }
76895
76895
  },
76896
+ {
76897
+ "id": "service_form.description_note",
76898
+ "body": {
76899
+ "package": "himalaya",
76900
+ "type": "Text",
76901
+ "props": {
76902
+ "text": "$service:himiOwnerLiteServiceForm.descriptionNote",
76903
+ "style": "footnote",
76904
+ "color": "textSecondary",
76905
+ "collapseWhenEmpty": true
76906
+ }
76907
+ }
76908
+ },
76909
+ {
76910
+ "id": "service_form.description_preview",
76911
+ "body": {
76912
+ "package": "himalaya",
76913
+ "type": "Text",
76914
+ "props": {
76915
+ "text": "$service:himiOwnerLiteServiceForm.description",
76916
+ "style": "body",
76917
+ "maxLines": 8,
76918
+ "collapseWhenEmpty": true
76919
+ }
76920
+ },
76921
+ "modifiers": {
76922
+ "hiddenPath": "$service:himiOwnerLiteServiceForm.descriptionEditable"
76923
+ }
76924
+ },
76896
76925
  {
76897
76926
  "id": "service_form.form",
76898
76927
  "body": {
@@ -76937,6 +76966,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
76937
76966
  "multilineMaxLines": 3
76938
76967
  }
76939
76968
  }
76969
+ },
76970
+ "modifiers": {
76971
+ "hiddenPath": "$service:himiOwnerLiteServiceForm.descriptionProtected"
76940
76972
  }
76941
76973
  }
76942
76974
  ],
@@ -78253,6 +78285,51 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
78253
78285
  }
78254
78286
  }
78255
78287
  },
78288
+ {
78289
+ "id": "service_body",
78290
+ "body": {
78291
+ "package": "himalaya",
78292
+ "type": "RichContent",
78293
+ "props": {
78294
+ "documentJsonPath": "$service:himiOwnerLiteService.bodyJson",
78295
+ "onLink": {
78296
+ "actionId": "tier5.himiOwnerLiteService.openLink"
78297
+ },
78298
+ "fallback": {
78299
+ "id": "",
78300
+ "body": {
78301
+ "package": "himalaya",
78302
+ "type": "Text",
78303
+ "props": {
78304
+ "text": "$service:himiOwnerLiteService.bodyText",
78305
+ "style": "body",
78306
+ "color": "textPrimary",
78307
+ "collapseWhenEmpty": true
78308
+ }
78309
+ }
78310
+ }
78311
+ }
78312
+ },
78313
+ "modifiers": {
78314
+ "hiddenPath": "$service:himiOwnerLiteService.noBodyJson"
78315
+ }
78316
+ },
78317
+ {
78318
+ "id": "service_body_text",
78319
+ "body": {
78320
+ "package": "himalaya",
78321
+ "type": "Text",
78322
+ "props": {
78323
+ "text": "$service:himiOwnerLiteService.bodyText",
78324
+ "style": "body",
78325
+ "color": "textPrimary",
78326
+ "collapseWhenEmpty": true
78327
+ }
78328
+ },
78329
+ "modifiers": {
78330
+ "hiddenPath": "$service:himiOwnerLiteService.hasBodyJson"
78331
+ }
78332
+ },
78256
78333
  {
78257
78334
  "id": "service_info_card",
78258
78335
  "body": {
@@ -78440,70 +78517,6 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
78440
78517
  "modifiers": {
78441
78518
  "hiddenPath": "$service:himiOwnerLiteService.capacityBlank"
78442
78519
  }
78443
- },
78444
- {
78445
- "id": "",
78446
- "body": {
78447
- "package": "himalaya",
78448
- "type": "Divider",
78449
- "props": {}
78450
- },
78451
- "modifiers": {
78452
- "hiddenPath": "$service:himiOwnerLiteService.descriptionNoDivider"
78453
- }
78454
- },
78455
- {
78456
- "id": "service_row_description",
78457
- "body": {
78458
- "package": "himalaya",
78459
- "type": "HStack",
78460
- "props": {
78461
- "spacing": 0,
78462
- "children": [
78463
- {
78464
- "id": "",
78465
- "body": {
78466
- "package": "himalaya",
78467
- "type": "Text",
78468
- "props": {
78469
- "text": "What the role involves",
78470
- "style": "footnote",
78471
- "color": "textSecondary"
78472
- }
78473
- },
78474
- "modifiers": {
78475
- "padding": {
78476
- "trailing": 10
78477
- }
78478
- }
78479
- },
78480
- {
78481
- "id": "",
78482
- "body": {
78483
- "package": "himalaya",
78484
- "type": "Spacer",
78485
- "props": {}
78486
- }
78487
- },
78488
- {
78489
- "id": "",
78490
- "body": {
78491
- "package": "himalaya",
78492
- "type": "Text",
78493
- "props": {
78494
- "text": "$service:himiOwnerLiteService.description",
78495
- "style": "bodyEmphasis",
78496
- "maxLines": 1,
78497
- "collapseWhenEmpty": true
78498
- }
78499
- }
78500
- }
78501
- ]
78502
- }
78503
- },
78504
- "modifiers": {
78505
- "hiddenPath": "$service:himiOwnerLiteService.descriptionBlank"
78506
- }
78507
78520
  }
78508
78521
  ]
78509
78522
  }
@@ -78624,7 +78637,8 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
78624
78637
  "contentType": "application/javascript+ts-bundle",
78625
78638
  "declaredCapabilities": [
78626
78639
  "wix_api",
78627
- "local_database"
78640
+ "local_database",
78641
+ "open_url"
78628
78642
  ],
78629
78643
  "minBinaryVersion": "0.1.0",
78630
78644
  "bundleVersion": "0.0.1"
@@ -79089,6 +79103,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
79089
79103
  }
79090
79104
  }
79091
79105
  }
79106
+ },
79107
+ "modifiers": {
79108
+ "hiddenPath": "$service:himiOwnerLiteEvent.noBodyJson"
79092
79109
  }
79093
79110
  },
79094
79111
  {
@@ -80098,6 +80115,9 @@ const TEMPLATED: { pattern: string; display: string; liveSeed?: LiveSeed; static
80098
80115
  }
80099
80116
  }
80100
80117
  }
80118
+ },
80119
+ "modifiers": {
80120
+ "hiddenPath": "$service:himiOwnerLitePost.noBodyJson"
80101
80121
  }
80102
80122
  },
80103
80123
  {
@@ -19,6 +19,8 @@ export interface CollectionConfig {
19
19
  /** Numeric 0–5 row field rendered as a Rating (accessible "N out of 5") instead of
20
20
  * folding a "★★★★☆" glyph string into the metadata line, so screen readers get a value. */
21
21
  rating?: string;
22
+ /** Domain-provided calendar text and its unavailable flag, kept separate from media. */
23
+ dateBadge?: { text: string; hidden: string };
22
24
  sectioned?: boolean;
23
25
  view: 'list' | 'grid';
24
26
  backendQuery?: boolean;
@@ -38,7 +40,13 @@ export interface CollectionConfig {
38
40
  /** The card's primary verb, shown as a visible button beside the overflow.
39
41
  * `screenId` opens that screen with the row id; without it the verb reuses the
40
42
  * row's own tap action (the detail screen that owns the verb). */
41
- primaryVerb?: { label: string; screenId?: string };
43
+ primaryVerb?: { label: string; screenId?: string;
44
+ /** A row field holding THIS row's verb label (Register, RSVP, Buy Tickets…); `label` stays the fallback copy. */
45
+ labelPath?: string;
46
+ /** A row boolean that hides the verb on rows that offer no action (an event with no registration). */
47
+ hiddenPath?: string };
48
+ /** The worker action that shares a row (`tier5.<service>.<name>` with `{ id }`): adds Share to the card's overflow menu. */
49
+ shareAction?: string;
42
50
  /** A TIME-BOUND entity (an event, a booking, a reservation): the boolean row field the
43
51
  * DOMAIN sets once the record has finished — computed by the same rule as the row's own
44
52
  * "Past" label, in the same place, so the two cannot disagree. A finished
@@ -73,7 +81,7 @@ export const COLLECTIONS: Record<string, CollectionConfig> = {
73
81
  himiBookingBookings: { rows: 'rows', title: 'title', subtitle: 'subtitle', metadata: ['status'], view: 'list', backendQuery: true,
74
82
  defaultFilter: 'value:Upcoming', searchPlaceholder: 'Search by booking ID', countNoun: ['booking', 'bookings'], filterValues: ['Upcoming', 'Past', 'Cancelled'],
75
83
  sortLabels: { default: 'Soonest', az: 'Oldest', za: 'Latest' } },
76
- 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' }, endedWhen: 'isPast' },
84
+ himiEvents: { rows: 'results', title: 'title', subtitle: 'dateLine', image: 'image', dateBadge: { text: 'dateBadge', hidden: 'noDateBadge' }, gridColumns: 1, 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', labelPath: 'actionLabel', hiddenPath: 'noAction' }, shareAction: 'share', endedWhen: 'isPast' },
77
85
  himiBlogFeed: { rows: 'posts', title: 'title', subtitle: 'excerpt', image: 'image', filter: 'category', filterValuesFrom: 'categories', view: 'grid', narrowedBy: 'selectedCategoryId' },
78
86
  himiOwnerLiteProducts: { rows: 'products', title: 'name', subtitle: 'price', image: 'image', view: 'grid', backendQuery: true, countNoun: ['product', 'products'] },
79
87
  himiOwnerModules: { instanceInput: 'module', rows: 'rows', title: 'title', subtitle: 'subtitle', image: 'image', filter: 'statusLabel', view: 'list', paged: true, reviewAction: 'prepareRecord', reviewSelectedAction: 'prepareSelected' },
@@ -208,7 +216,15 @@ export function projectCollection(source: CollectionRow[], config: CollectionCon
208
216
  ...(config.endedWhen ? (() => {
209
217
  const ended = row[config.endedWhen] === true || (config.endedWhen === 'isPast' && row.statusLabel === 'Past');
210
218
  return { collectionEnded: ended, collectionNotEnded: !ended };
211
- })() : {}) })),
219
+ })() : {}),
220
+ // A row restored from state saved by an older build has no badge flag. An unset hidden flag
221
+ // fails open and would paint an empty chip, so it reads as "no badge" until a refresh.
222
+ ...(config.dateBadge && typeof row[config.dateBadge.hidden] !== 'boolean'
223
+ ? { [config.dateBadge.text]: '', [config.dateBadge.hidden]: true } : {}),
224
+ // Same for a per-row verb: an unset hidden flag fails open and would show a verb with an unresolved
225
+ // label, so a row without the flag offers no action until a refresh establishes one.
226
+ ...(config.primaryVerb?.hiddenPath && typeof row[config.primaryVerb.hiddenPath] !== 'boolean'
227
+ ? { ...(config.primaryVerb.labelPath ? { [config.primaryVerb.labelPath]: '' } : {}), [config.primaryVerb.hiddenPath]: true } : {}) })),
212
228
  filters, loaded: rows.length,
213
229
  };
214
230
  }
@@ -0,0 +1,27 @@
1
+ // May a plain owner form round-trip this body? The Ricos and HTML checks are @himalaya/wix-rich-content's;
2
+ // this file adds the read-only previews the forms show for a locked body, and the FAQ's legacy DraftJS answer.
3
+ // Inside the platform source this import is a relative path, so node test runs resolve it; an app's copy
4
+ // imports "@himalaya/wix-rich-content".
5
+ import { htmlIsTrivial } from "@himalaya/wix-rich-content";
6
+
7
+ export { htmlIsTrivial };
8
+
9
+ const ENTITIES: Record<string, string> = { "&nbsp;": " ", "&amp;": "&", "&lt;": "<", "&gt;": ">", "&quot;": "\"", "&#39;": "'" };
10
+
11
+ /** Read-only preview text for an HTML body: block closes become lines, tags are stripped (a bare
12
+ * `<` in prose is kept), the basic entities decode, and blank lines drop. */
13
+ export function htmlPreviewText(html: string | null | undefined): string {
14
+ return (html ?? "").replace(/<br\s*\/?>/gi, "\n").replace(/<\/(p|h[1-6]|li|div|blockquote|pre|tr)>/gi, "\n")
15
+ .replace(/<\/?[a-z!?][^>]*>/gi, "").replace(/&(nbsp|amp|lt|gt|quot|#39);/g, (m) => ENTITIES[m] ?? m)
16
+ .split("\n").map((l) => l.replace(/\s+/g, " ").trim()).filter(Boolean).join("\n");
17
+ }
18
+
19
+ /** Preview text for a legacy DraftJS document: its `blocks[].text` joined by a blank line, or ""
20
+ * when the payload is not DraftJS JSON (never a throw). */
21
+ export function draftjsText(raw: string | null | undefined): string {
22
+ try {
23
+ const doc = JSON.parse(raw ?? "") as { blocks?: Array<{ text?: unknown }> } | null;
24
+ const blocks = Array.isArray(doc?.blocks) ? doc.blocks : [];
25
+ return blocks.map((b) => (typeof b?.text === "string" ? b.text : "")).join("\n\n").trim();
26
+ } catch { return ""; }
27
+ }
@@ -12,7 +12,7 @@ import { ownerLoadError, isOwnerPreviewDemo, ownerDemoFallback, ownerWriteError,
12
12
  import { DEMO_EVENTS, DEMO_NOTE, DEMO_SAVE_NOTE } from "../_shared/owner-preview-demo.js";
13
13
  import { stashCopy, copyParam } from "../_shared/himi-copy.js";
14
14
  import { openRichLink } from "../_shared/rich-content-link.js";
15
- import { richBody } from "../_shared/rich-body.js";
15
+ import { descriptionBody } from "../_shared/rich-body.js";
16
16
  import { get as dbGet, upsert as dbUpsert, remove as dbRemove, type DbEntity } from "../_shared/owner-local-db.js";
17
17
  import { blankFlags } from "../_shared/detail-facts.js";
18
18
 
@@ -41,6 +41,7 @@ interface EventState {
41
41
  bodyJson: string;
42
42
  /** bodyJson !== "" — gates the plain text, because RichContent draws nothing for "". */
43
43
  hasBodyJson: boolean;
44
+ noBodyJson: boolean;
44
45
  /** The description's plain text (the document's own text, else the legacy description). */
45
46
  bodyText: string;
46
47
  initial: string;
@@ -68,15 +69,15 @@ interface EventState {
68
69
  }
69
70
 
70
71
  /* eslint-disable @typescript-eslint/no-explicit-any */
71
- /** [rico] #3499 — keep the description's plain text with the event's cached row, so the offline detail shows it.
72
+ /** [rico] #3499 — keep the description pair with the event's cached row, so the offline detail shows it.
72
73
  * Merged into the row the events list (or the form) wrote rather than replacing it; with no row yet, the
73
74
  * loaded detail's own fields become one. */
74
75
  async function cacheBodyText(s: EventState): Promise<void> {
75
76
  if (s.status !== "ready" || !s.id) return;
76
77
  const prev = await cacheGet(s.id);
77
- await cachePut(prev ? { ...prev, bodyText: s.bodyText } : {
78
+ await cachePut(prev ? { ...prev, bodyText: s.bodyText, bodyJson: s.bodyJson } : {
78
79
  id: s.id, title: s.title, subtitle: s.subtitle, image: s.image, dateLine: s.dateLine, location: s.location,
79
- statusLabel: s.statusLabel, registration: s.registration, bodyText: s.bodyText,
80
+ statusLabel: s.statusLabel, registration: s.registration, bodyText: s.bodyText, bodyJson: s.bodyJson,
80
81
  });
81
82
  }
82
83
  function idFrom(arg: unknown, fallback = ""): string {
@@ -132,6 +133,7 @@ function shapeFields(s: Partial<EventState>): EventState {
132
133
  summary: s.summary ?? "",
133
134
  bodyJson: s.bodyJson ?? "",
134
135
  hasBodyJson: !!s.bodyJson,
136
+ noBodyJson: !s.bodyJson,
135
137
  bodyText: s.bodyText ?? "",
136
138
  initial: s.initial ?? "?",
137
139
  image,
@@ -186,6 +188,7 @@ function cachedDetail(s: EventState, row: DbEntity): EventState {
186
188
  const title = String(row.title ?? row.name ?? "");
187
189
  const dateLine = String(row.dateLine ?? row.when ?? "");
188
190
  const location = String(row.location ?? "");
191
+ const body = descriptionBody(row.bodyJson || row.description, descriptionBody(row.bodyText ?? row.summary).bodyText);
189
192
  return shape({
190
193
  ...s,
191
194
  id: String(row.id),
@@ -193,8 +196,8 @@ function cachedDetail(s: EventState, row: DbEntity): EventState {
193
196
  title,
194
197
  subtitle: String(row.subtitle ?? [dateLine, location].filter((x) => x && x !== "—").join(" · ")),
195
198
  summary: "",
196
- bodyJson: "",
197
- bodyText: String(row.bodyText ?? row.summary ?? row.description ?? ""),
199
+ bodyJson: body.bodyJson,
200
+ bodyText: body.bodyText,
198
201
  initial: String(row.initial ?? (title[0] || "?")).slice(0, 1).toUpperCase(),
199
202
  image: String(row.image ?? ""),
200
203
  dateLine: dateLine || "—",
@@ -216,9 +219,9 @@ async function refresh(prev: EventState, id: string): Promise<EventState> {
216
219
  }
217
220
  const row = normalizeEvent(ev); // reuses date/location/status normalization
218
221
  const image = /^https?:\/\//.test(row.image) ? row.image : "";
219
- const { bodyJson, bodyText } = richBody((ev as unknown as { description?: unknown }).description, (eventDescription(ev) || "").trim());
222
+ const { bodyJson, bodyText } = descriptionBody((ev as unknown as { description?: unknown }).description, descriptionBody(eventDescription({ ...ev, description: undefined })).bodyText);
220
223
  // The teaser stays above the body only when it says something the body does not.
221
- const teaser = String((ev as any).shortDescription ?? "").trim();
224
+ const teaser = descriptionBody((ev as any).shortDescription).bodyText;
222
225
  return shape({
223
226
  ...prev,
224
227
  id,
@@ -358,4 +361,9 @@ if ((globalThis as { himalaya?: { hydrationOptOut?: unknown } }).himalaya?.hydra
358
361
  if (booted && typeof booted === "object") Object.assign(booted, { deletePending: false, noDeleteConfirmation: true });
359
362
  }
360
363
 
364
+ // Hydration shallow-merges older snapshots over defaults; derive both body gates from
365
+ // the restored document before the first paint, without waiting for a load action.
366
+ const bootedBody = svc.getState();
367
+ Object.assign(bootedBody, { hasBodyJson: !!bootedBody.bodyJson, noBodyJson: !bootedBody.bodyJson });
368
+
361
369
  export { svc };
@@ -1,3 +1,4 @@
1
+ import { descriptionBody } from "../_shared/rich-body.js";
1
2
  // Tier-5 bundle: __HIMI_APP_NAME__ — Events event EDIT form (the CRUD "U" only).
2
3
  // Modeled on himi-blog-owner-editor. Opened from the event detail ("Edit").
3
4
  //
@@ -222,12 +223,16 @@ const svc = defineService<EventFormState, {
222
223
  // this form never writes, so showing them here would invite an edit that lands elsewhere.
223
224
  ...(() => {
224
225
  const raw = (ev as unknown as { description?: unknown }).description;
225
- const doc = raw && typeof raw === "object" && Array.isArray((raw as { nodes?: unknown }).nodes) ? raw as Parameters<typeof postBodyText>[0] : null;
226
- const text = doc ? postBodyText(doc) : typeof raw === "string" ? raw.trim() : "";
226
+ const doc = parseRicosJson(raw);
227
+ const text = descriptionBody(raw).bodyText;
227
228
  // Edited in the RichContentEditor, seeded with the event's own document byte for byte (never
228
229
  // re-encoded); a legacy string seeds as paragraphs, and none seeds an empty editor.
229
- return { ...DESCRIPTION_LOADED, description: text, originalDescription: text, descriptionMode: "editor" as const,
230
- descriptionJson: doc ? JSON.stringify(raw) : text ? docJson(plainPostBody(text)) : "" };
230
+ // A description that looks like a serialized document but does not read as one (malformed JSON,
231
+ // or an object that is not a document) is locked, as on the Product form: an empty editor would
232
+ // let a save replace it. A blank or tag-only string stays editable so the owner can write the first one.
233
+ const unreadable = !doc && !text && raw != null && (typeof raw !== "string" || /^\s*[{[]/.test(raw));
234
+ return { ...DESCRIPTION_LOADED, description: text, originalDescription: text, descriptionMode: unreadable ? "locked" as const : "editor" as const,
235
+ descriptionJson: unreadable ? "" : doc ? JSON.stringify(doc) : text ? docJson(plainPostBody(text)) : "" };
231
236
  })(),
232
237
  when: row.dateLine || "—",
233
238
  location: row.location || "—",
@@ -239,14 +244,18 @@ const svc = defineService<EventFormState, {
239
244
  // Offline: prefill from the last-synced local cache before the demo/error fallbacks.
240
245
  const cached = await cacheGet(id);
241
246
  if (cached) {
247
+ // Only `descriptionJson` is the document as Wix returned it. The detail's `bodyJson` is the encoder's
248
+ // DISPLAY copy (media resized to urls), so it feeds the preview text and never seeds the editor.
249
+ const doc = parseRicosJson(cached.descriptionJson);
250
+ const description = descriptionBody(doc ?? cached.bodyJson, descriptionBody(cached.description ?? cached.bodyText ?? cached.summary).bodyText).bodyText;
242
251
  return shape({
243
252
  ...s, mode, id, heading: "Edit event",
244
253
  title: String(cached.title ?? cached.name ?? ""),
245
- description: String(cached.description ?? ""),
246
- originalDescription: String(cached.description ?? ""), ...DESCRIPTION_LOADED,
254
+ description,
255
+ originalDescription: description, ...DESCRIPTION_LOADED,
247
256
  // A row cached with its document reopens in the editor. An older row has none, so its verdict
248
257
  // decides: plain when it was plain, else locked (it carries no verdict either: fail closed).
249
- ...(cached.descriptionJson ? { descriptionMode: "editor" as const, descriptionJson: String(cached.descriptionJson) }
258
+ ...(doc ? { descriptionMode: "editor" as const, descriptionJson: JSON.stringify(doc) }
250
259
  : { descriptionMode: cached.descriptionProtected === "false" ? "plain" as const : "locked" as const, descriptionJson: "" }),
251
260
  when: String(cached.when ?? cached.dateLine ?? "—"),
252
261
  location: String(cached.location ?? "—"),
@@ -9,7 +9,7 @@ import { normalizeEvent, type EventRow } from "../_shared/himi-events.js";
9
9
  import { ownerLoadError, isOwnerPreviewDemo, ownerDemoFallback } from "../_shared/owner-load-error.js";
10
10
  import { DEMO_EVENTS, DEMO_NOTE } from "../_shared/owner-preview-demo.js";
11
11
  import { copyParam } from "../_shared/himi-copy.js";
12
- import { getAll, upsert, type DbEntity } from "../_shared/owner-local-db.js";
12
+ import { get, getAll, upsert, type DbEntity } from "../_shared/owner-local-db.js";
13
13
 
14
14
  // Last-synced rows are an explicitly incomplete fallback for an unfiltered
15
15
  // request during an outage. Filtered pages never claim this cache is complete.
@@ -19,7 +19,9 @@ async function readCachedRows(): Promise<EventRow[]> {
19
19
  try { return (await getAll(ENTITY)) as unknown as EventRow[]; } catch { return []; }
20
20
  }
21
21
  async function writeCachedRows(rows: EventRow[]): Promise<void> {
22
- try { for (const r of rows) await upsert(ENTITY, r as unknown as DbEntity); } catch { /* capability not granted → online-only */ }
22
+ try {
23
+ for (const r of rows) await upsert(ENTITY, { ...await get(ENTITY, r.id), ...r } as unknown as DbEntity);
24
+ } catch { /* capability not granted → online-only */ }
23
25
  }
24
26
 
25
27
  interface EventsState {
@@ -55,6 +55,7 @@ interface PostState {
55
55
  bodyJson: string;
56
56
  /** bodyJson !== "" — gates the plain text, because RichContent draws nothing for "". */
57
57
  hasBodyJson: boolean;
58
+ noBodyJson: boolean;
58
59
  /** Plain text of the body: RichContent's `fallback`, and the offline copy's body. */
59
60
  bodyText: string;
60
61
  // Info rows
@@ -151,6 +152,7 @@ function shapeFields(s: Partial<PostState>): PostState {
151
152
  image,
152
153
  bodyJson: s.bodyJson ?? "",
153
154
  hasBodyJson: !!s.bodyJson,
155
+ noBodyJson: !s.bodyJson,
154
156
  bodyText: s.bodyText ?? "",
155
157
  postStatus: s.postStatus ?? statusLabel(raw),
156
158
  category: s.category ?? "—",
@@ -485,4 +487,9 @@ if ((globalThis as { himalaya?: { hydrationOptOut?: unknown } }).himalaya?.hydra
485
487
  if (booted && typeof booted === "object") Object.assign(booted, { deletePending: false, noDeleteConfirmation: true });
486
488
  }
487
489
 
490
+ // Hydration shallow-merges older snapshots over defaults; derive both body gates from
491
+ // the restored document before the first paint, without waiting for a load action.
492
+ const bootedBody = svc.getState();
493
+ Object.assign(bootedBody, { hasBodyJson: !!bootedBody.bodyJson, noBodyJson: !bootedBody.bodyJson });
494
+
488
495
  export { svc };
@@ -1,3 +1,5 @@
1
+ import { descriptionBody } from "../_shared/rich-body.js";
2
+ import { openRichLink } from "../_shared/rich-content-link.js";
1
3
  // Tier-5 bundle: __HIMI_APP_NAME__ — Bookings service DETAIL (read view).
2
4
  // Inner admin page opened from the services list (himi_owner_lite_service_<id>).
3
5
  // Fetches the single Bookings v2 service and exposes a flat string state bound by
@@ -35,6 +37,10 @@ interface ServiceState {
35
37
  title: string;
36
38
  subtitle: string;
37
39
  summary: string;
40
+ bodyJson: string;
41
+ bodyText: string;
42
+ hasBodyJson: boolean;
43
+ noBodyJson: boolean;
38
44
  initial: string;
39
45
  image: string;
40
46
  typeLabel: string;
@@ -99,7 +105,7 @@ function imageOf(s: WixService): string {
99
105
 
100
106
  /** The fact rows this detail shows (the descriptor"s DETAIL_T5 rows): each publishes
101
107
  * `<key>Blank`, so a fact with no value hides instead of painting a dangling label. */
102
- const FACT_KEYS = ["typeLabel", "category", "capacity", "description"] as const;
108
+ const FACT_KEYS = ["typeLabel", "category", "capacity"] as const;
103
109
 
104
110
  function shape(s: Partial<ServiceState>): ServiceState {
105
111
  const out = shapeFields(s);
@@ -121,6 +127,10 @@ function shapeFields(s: Partial<ServiceState>): ServiceState {
121
127
  title: s.title ?? "",
122
128
  subtitle: s.subtitle ?? "",
123
129
  summary: s.summary ?? "",
130
+ bodyJson: s.bodyJson ?? "",
131
+ bodyText: s.bodyText ?? "",
132
+ hasBodyJson: !!s.bodyJson,
133
+ noBodyJson: !s.bodyJson,
124
134
  initial: s.initial ?? "?",
125
135
  image,
126
136
  typeLabel: s.typeLabel ?? "—",
@@ -152,7 +162,9 @@ function demoDetail(s: ServiceState, id: string): ServiceState | null {
152
162
  status: "ready",
153
163
  title: d.name,
154
164
  subtitle: [d.type, d.category].filter(Boolean).join(" · "),
155
- summary: d.description,
165
+ summary: "",
166
+ bodyText: d.description,
167
+ bodyJson: "",
156
168
  initial: (d.name[0] || "S").toUpperCase(),
157
169
  image: "",
158
170
  typeLabel: d.type,
@@ -169,20 +181,24 @@ function cachedDetail(s: ServiceState, row: DbEntity): ServiceState {
169
181
  const title = String(row.title ?? row.name ?? "");
170
182
  const type = String(row.typeLabel ?? "");
171
183
  const category = String(row.category ?? "");
184
+ const body = descriptionBody(row.bodyJson || row.description, descriptionBody(row.bodyText || row.summary).bodyText);
172
185
  return shape({
173
186
  ...s,
174
187
  id: String(row.id),
175
188
  status: "ready",
176
189
  title,
177
190
  subtitle: String(row.subtitle ?? [type, category].filter(Boolean).join(" · ")),
178
- summary: String(row.summary ?? row.description ?? ""),
191
+ summary: "",
192
+ bodyJson: body.bodyJson,
193
+ bodyText: body.bodyText,
179
194
  initial: String(row.initial ?? (title[0] || "S")).slice(0, 1).toUpperCase(),
180
195
  image: String(row.image ?? ""),
181
196
  typeLabel: type || "—",
182
197
  category: category || "—",
183
198
  capacity: String(row.capacity ?? "—"),
184
- description: String(row.description ?? "—"),
199
+ description: body.bodyText || "—",
185
200
  error: "",
201
+ actionMessage: "",
186
202
  demoNote: "",
187
203
  });
188
204
  }
@@ -197,21 +213,24 @@ async function refresh(prev: ServiceState, id: string): Promise<ServiceState> {
197
213
  const type = serviceTypeLabel((svc as any).type);
198
214
  const category = categoryName(svc) || "—";
199
215
  const cap = (svc as any).defaultCapacity;
200
- const desc = ((svc as any).description || (svc as any).tagLine || "").trim();
216
+ const body = descriptionBody((svc as any).description, descriptionBody((svc as any).tagLine).bodyText);
201
217
  return shape({
202
218
  ...prev,
203
219
  id,
204
220
  status: "ready",
205
221
  title: name,
206
222
  subtitle: [type, category !== "—" ? category : ""].filter(Boolean).join(" · "),
207
- summary: desc,
223
+ summary: "",
224
+ bodyJson: body.bodyJson,
225
+ bodyText: body.bodyText,
208
226
  initial: (name[0] || "S").toUpperCase(),
209
227
  image: imageOf(svc),
210
228
  typeLabel: type,
211
229
  category,
212
230
  capacity: cap != null ? `${cap} ${Number(cap) === 1 ? "guest" : "guests"}` : "—",
213
- description: desc || "—",
231
+ description: body.bodyText || "—",
214
232
  error: "",
233
+ actionMessage: "",
215
234
  demoNote: "",
216
235
  });
217
236
  }
@@ -220,9 +239,16 @@ const svc = defineService<ServiceState, {
220
239
  load: (s: ServiceState, arg?: unknown) => Promise<ServiceState>;
221
240
  retry: (s: ServiceState) => Promise<ServiceState>;
222
241
  delete: (s: ServiceState) => Promise<ServiceState>;
242
+ openLink: (s: ServiceState, arg?: unknown) => Promise<ServiceState>;
223
243
  }>("himiOwnerLiteService", {
224
244
  state: shape({ status: "loading" }),
225
245
  actions: {
246
+ openLink: async (_state, arg): Promise<ServiceState> => {
247
+ const opened = await openRichLink(arg);
248
+ const failed = copyParam("ownerService.linkOpenFailed", "This link could not be opened.");
249
+ const current = svc.getState();
250
+ return shape({ ...current, actionMessage: opened ? (current.actionMessage === failed ? "" : current.actionMessage) : failed });
251
+ },
226
252
  load: async (s, arg) => {
227
253
  stashCopy(arg); // absorb the descriptor's onAppear copy-pack param
228
254
  const id = idFrom(arg, s.id) || inputId();
@@ -284,4 +310,9 @@ const svc = defineService<ServiceState, {
284
310
  },
285
311
  });
286
312
 
313
+ // Hydration shallow-merges older snapshots over defaults; derive both body gates from
314
+ // the restored document before the first paint, without waiting for a load action.
315
+ const bootedBody = svc.getState();
316
+ Object.assign(bootedBody, { hasBodyJson: !!bootedBody.bodyJson, noBodyJson: !bootedBody.bodyJson });
317
+
287
318
  export { svc };