@wix/himalaya-cli 0.1579.0 → 0.1581.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 (54) hide show
  1. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +18 -3
  2. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/builder.d.ts +3 -0
  3. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/motion/src/index.d.ts +51 -5
  4. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/network/src/index.d.ts +39 -0
  5. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +2 -1
  6. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview-page/src/capabilities.generated.d.ts +2 -0
  7. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +1 -1
  8. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +12 -0
  9. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/validator.d.ts +6 -0
  10. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/media/src/index.d.ts +1 -0
  11. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/wix-sdk/media/src/rendition.d.ts +42 -0
  12. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -0
  13. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -0
  14. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -0
  15. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -0
  16. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +1 -0
  17. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -0
  18. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +23 -2
  19. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/network.mjs +45 -0
  20. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -0
  21. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -0
  22. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +1 -0
  23. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -0
  24. package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/wix-media.mjs +78 -0
  25. package/dist/authoring-runtime/node_modules/@wix/himalaya/package.json +4 -0
  26. package/dist/cli.mjs +9144 -7459
  27. package/dist/preview-assets.generated.bin +0 -0
  28. package/dist/quickjs-intl.js +462 -0
  29. package/dist/quickjs-web-globals.js +540 -0
  30. package/dist/quickjs-worker-entry.js +313 -0
  31. package/guides/app-config.md +1 -1
  32. package/guides/component-reference.json +5 -3
  33. package/guides/component-reference.md +10 -2
  34. package/guides/designing-himi-screens.md +24 -0
  35. package/guides/himi-json-output.md +30 -1
  36. package/guides/importable-sdks.md +1 -0
  37. package/guides/one-app-section-mappings.md +4 -5
  38. package/guides/one-app-to-himi-app.md +214 -6
  39. package/guides/one-app-viewer.md +2 -2
  40. package/guides/sdk-reference.json +74 -7
  41. package/guides/tier-5-add-a-screen.md +32 -0
  42. package/guides/web-page-sdk-reference.md +1 -0
  43. package/package.json +3 -2
  44. package/templates/beauty-salon/dev/index.ts +197 -304
  45. package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +44 -13
  46. package/templates/branded-lite/dev/index.ts +197 -304
  47. package/templates/branded-lite/l10n/en.json +2 -2
  48. package/templates/branded-lite/tier5-src/himi-store-product/index.ts +49 -17
  49. package/templates/gym-fitness/dev/index.ts +197 -304
  50. package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +44 -13
  51. package/templates/portfolio-creative/dev/index.ts +197 -304
  52. package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +44 -13
  53. package/templates/retail-store/dev/index.ts +197 -304
  54. package/templates/retail-store/tier5-src/himi-store-product/index.ts +49 -17
@@ -44,6 +44,7 @@ async function cartItemCount(): Promise<number> {
44
44
  }
45
45
 
46
46
  interface GalleryItem {
47
+ id: string;
47
48
  url: string;
48
49
  }
49
50
 
@@ -134,8 +135,8 @@ function slotsOf(groups: StoreOption[], selection: StoreOptionSelection, showErr
134
135
  out[`opt${n}Chips`] = (g?.choices ?? []).map((c) => ({ id: c.id, label: c.label, ...(g.kind === "color" && c.colorCode ? { swatch: c.colorCode } : {}), disabled: c.inStock === false }));
135
136
  out[`opt${n}Selected`] = chosen ? [chosen] : [];
136
137
  out[`opt${n}SelectedId`] = chosen;
137
- out[`opt${n}Placeholder`] = g?.choices.find(c => c.id === chosen)?.label ?? copyTemplate("product.optionPlaceholder", "Choose {option}", { option: displayName || "option" });
138
- const error = showErrors && g && !chosen ? copyTemplate("product.optionRequired", "Choose a {option}", { option: g.name.toLowerCase() }) : "";
138
+ out[`opt${n}Placeholder`] = g?.choices.find(c => c.id === chosen)?.label ?? copyTemplate("product.optionPlaceholder", "Select {option}", { option: displayName || "option" });
139
+ const error = showErrors && g && !chosen ? copyTemplate("product.optionRequired", "Select a {option}", { option: g.name.toLowerCase() }) : "";
139
140
  out[`opt${n}Error`] = error;
140
141
  out[`noOpt${n}Error`] = !error;
141
142
  out[`hasOpt${n}Error`] = !!error;
@@ -261,6 +262,11 @@ interface S {
261
262
  /** FULL media gallery (media.items[] with the main image first) — the detail
262
263
  * screen renders a Carousel over it when 2+ images exist. */
263
264
  gallery: GalleryItem[];
265
+ galleryIndex: number;
266
+ galleryLabel: string;
267
+ opt1ScrollRequest: string;
268
+ opt2ScrollRequest: string;
269
+ opt3ScrollRequest: string;
264
270
  hasGallery: boolean;
265
271
  noGallery: boolean;
266
272
  initial: string;
@@ -270,6 +276,7 @@ interface S {
270
276
  cartCount: number;
271
277
  /** An add-to-cart write is in flight (pending line under the CTA). */
272
278
  adding: boolean;
279
+ addLabel: string;
273
280
  notAdding: boolean;
274
281
  /** The last add succeeded (confirmation + View cart under the CTA). */
275
282
  added: boolean;
@@ -305,6 +312,8 @@ interface S {
305
312
  /** Add to cart is blocked: this product has options and they are not all chosen. */
306
313
  optionsIncomplete: boolean;
307
314
  showOptionErrors: boolean;
315
+ optionValidationRequest: number;
316
+ optionValidationTarget: string;
308
317
  addDisabled: boolean;
309
318
  /** The product was served from the offline cache, which carries no option groups.
310
319
  * "No groups" here means UNKNOWN, not "none" — so the CTA must stay blocked rather
@@ -352,7 +361,8 @@ export function productGallery(p: StoreProduct): GalleryItem[] {
352
361
  // image no matter what the read asked for. One reader, not a private copy per
353
362
  // worker — that is how the two layouts drifted apart in the first place.
354
363
  for (const url of sdkProductGallery(p, WIX_DETAIL_IMAGE)) push(url);
355
- return urls.map((url) => ({ url }));
364
+ for (const group of productOptions(p, WIX_DETAIL_IMAGE)) for (const choice of group.choices) push(choice.image);
365
+ return urls.map((url) => ({ id: url, url }));
356
366
  }
357
367
 
358
368
  /** The product's public page URL when the payload carries one ("" otherwise) —
@@ -390,6 +400,7 @@ function parseQuantity(raw: string): number | undefined {
390
400
 
391
401
  function derive(s: S): S {
392
402
  const empty = s.status === "ready" && !s.name;
403
+ const galleryIndex = Math.min(Math.max(0, Math.floor(Number(s.galleryIndex) || 0)), Math.max(0, s.gallery.length - 1));
393
404
  const hasGallery = s.gallery.length > 1;
394
405
  const hasSingleImage = !!s.image && !hasGallery;
395
406
  const groups = s.optionGroups;
@@ -397,6 +408,8 @@ function derive(s: S): S {
397
408
  const optionsIncomplete = s.optionsUnknown || !!outOfStockPick(groups, s.selection) || (groups.length > 0 && (overflow || !isSelectionComplete(groups, s.selection)));
398
409
  return {
399
410
  ...s,
411
+ galleryIndex,
412
+ galleryLabel: s.gallery.length ? copyTemplate("product.galleryPage", "Image {index} of {count}", { index: String(galleryIndex + 1), count: String(s.gallery.length) }) : "",
400
413
  notOnSale: !s.wasPrice,
401
414
  wasPriceEmpty: !!s.wasPrice,
402
415
  noSku: !s.skuLabel,
@@ -425,9 +438,12 @@ function derive(s: S): S {
425
438
  // indistinguishable from one with none, and adding it would post the variant-less
426
439
  // line this whole feature exists to prevent.
427
440
  optionsIncomplete,
428
- addDisabled: optionsIncomplete,
441
+ ...Object.fromEntries([1, 2, 3].map(n => [`opt${n}ScrollRequest`,
442
+ s.showOptionErrors && groups[n - 1]?.id === s.optionValidationTarget && !s.selection[groups[n - 1].id] ? String(s.optionValidationRequest || "") : ""])),
443
+ addDisabled: s.adding || s.optionsUnknown || overflow || !!outOfStockPick(groups, s.selection),
429
444
  optionsHint: groups.length ? optionsHint(groups, s.selection) : "",
430
445
  saveLabel: s.saved ? copyParam("savedProducts.removeLabel", "Remove from wishlist") : copyParam("savedProducts.addLabel", "Add to wishlist"),
446
+ addLabel: s.adding ? copyParam("product.adding", "Adding to cart…") : copyParam("product.addToCart", "Add to cart"),
431
447
  notAdding: !s.adding,
432
448
  notAdded: !s.added,
433
449
  isLoading: s.status === "loading",
@@ -461,7 +477,7 @@ const defineService = withIapPresentation<S>({
461
477
  register: withOnlineWrites(registerState, ["beginAdd", "addToCart", "buy"], { derive, messageFields: action => action === "buy" ? ["buyNote"] : ["cartHint"] }),
462
478
  adapters: SELLS_THROUGH_APPLE ? [storesProductOrders] : [],
463
479
  onCreate: commerce => { productPricing = commerce; }, prefix: "product",
464
- transientKeys: ["price", "optionsIncomplete", "cartHint", "cartHidden", "buyHidden", "buyLabel", "buyDisabled", "buyNote", "purchasedNote", "addedSheetPresented", "shareHint"], contentActions: ["load", "paintCached"], concurrentPublishActions: ["buy"],
480
+ transientKeys: ["optionValidationTarget", "optionValidationRequest", "opt1ScrollRequest", "opt2ScrollRequest", "opt3ScrollRequest", "galleryIndex", "price", "optionsIncomplete", "cartHint", "cartHidden", "buyHidden", "buyLabel", "buyDisabled", "buyNote", "purchasedNote", "addedSheetPresented", "shareHint"], contentActions: ["load", "paintCached"], concurrentPublishActions: ["buy"],
465
481
  items: state => inputId() ? [{ reference: { kind: "storesProduct", id: inputId() }, commerceDisplayPrice: state.price }] : [],
466
482
  present: (state, price, allowed) => {
467
483
  const purchase = applePurchase(state);
@@ -469,9 +485,10 @@ const defineService = withIapPresentation<S>({
469
485
  const blocked = lastProduct?.productType?.toLowerCase() === "digital" || (!state.optionsUnknown && !allowed(inputId()));
470
486
  const cartHint = state.cartHint === offlineWriteMessage ? state.cartHint
471
487
  : !purchase.appleRoute && blocked ? unavailable : state.cartHint === unavailable ? "" : state.cartHint;
488
+ const productState = derive(state);
472
489
  return {
473
- ...state, price: price(inputId()), ...(purchase.appleRoute ? { wasPrice: "", wasPriceEmpty: false, notOnSale: true } : {}), optionsIncomplete: derive(state).optionsIncomplete || !allowed(inputId()) || lastProduct?.productType?.toLowerCase() === "digital",
474
- cartHint, noCartHint: !cartHint || state.added, addDisabled: state.addDisabled || blocked,
490
+ ...state, price: price(inputId()), ...(purchase.appleRoute ? { wasPrice: "", wasPriceEmpty: false, notOnSale: true } : {}), optionsIncomplete: productState.optionsIncomplete || !allowed(inputId()) || lastProduct?.productType?.toLowerCase() === "digital",
491
+ cartHint, noCartHint: !cartHint || state.added, addDisabled: productState.addDisabled || blocked,
475
492
  cartHidden: purchase.appleRoute,
476
493
  buyHidden: !purchase.appleRoute || purchase.accessReady, buyLabel: purchase.buyLabel, buyDisabled: purchase.buyDisabled,
477
494
  buyNote: state.buyNote === offlineWriteMessage ? state.buyNote : purchase.buyNote,
@@ -505,6 +522,7 @@ const svc = defineService<S, {
505
522
  toggleReturnPolicy: (s: S) => S;
506
523
  toggleShippingInfo: (s: S) => S;
507
524
  selectOption: (s: S, arg?: unknown) => S;
525
+ setGalleryIndex: (s: S, arg?: unknown) => S;
508
526
  addToCart: (s: S) => Promise<S>;
509
527
  beginAdd: (s: S, arg?: unknown) => S;
510
528
  paintCached: (s: S, arg?: unknown) => S;
@@ -550,6 +568,9 @@ const svc = defineService<S, {
550
568
  shippingInfoExpanded: false,
551
569
  image: "",
552
570
  gallery: [],
571
+ galleryIndex: 0,
572
+ opt1ScrollRequest: "", opt2ScrollRequest: "", opt3ScrollRequest: "",
573
+ galleryLabel: "",
553
574
  hasGallery: false,
554
575
  noGallery: true,
555
576
  initial: "",
@@ -557,6 +578,7 @@ const svc = defineService<S, {
557
578
  cartHint: "",
558
579
  cartCount: 0,
559
580
  adding: false,
581
+ addLabel: "",
560
582
  notAdding: true,
561
583
  added: false,
562
584
  notAdded: true,
@@ -582,6 +604,8 @@ const svc = defineService<S, {
582
604
  noOptionsOverflow: true,
583
605
  optionsIncomplete: false,
584
606
  showOptionErrors: false,
607
+ optionValidationRequest: 0,
608
+ optionValidationTarget: "",
585
609
  addDisabled: false,
586
610
  optionsUnknown: false,
587
611
  optionsHint: "",
@@ -607,7 +631,7 @@ const svc = defineService<S, {
607
631
  // Storage problems must not prevent browsing or buying a product.
608
632
  let saved = false;
609
633
  try { saved = isProductSaved(id); } catch { /* save action reports a retryable error */ }
610
- s = { ...s, saved, saveHint: "", shareHint: "", adding: false, added: false, addedSheetPresented: false, quantity: 1, showOptionErrors: false, returnPolicyExpanded: false, shippingInfoExpanded: false };
634
+ s = { ...s, saved, saveHint: "", shareHint: "", adding: false, added: false, addedSheetPresented: false, quantity: 1, showOptionErrors: false, optionValidationRequest: 0, optionValidationTarget: "", galleryIndex: 0, returnPolicyExpanded: false, shippingInfoExpanded: false };
611
635
  // A fresh navigation into the product resets any quantity left over
612
636
  // from a previous visit to the same worker instance.
613
637
  if (!id) {
@@ -625,7 +649,7 @@ const svc = defineService<S, {
625
649
  // The live product read goes out FIRST too — the local-db read below must never delay it.
626
650
  // Settled into a value so a failure is handled where it is awaited, never unhandled.
627
651
  // DESCRIPTION widens the default fieldset with the V3 Ricos description (a V1 catalog ignores it).
628
- const live = getStoreProduct(id, ["DESCRIPTION"]).then(
652
+ const live = getStoreProduct(id, ["DESCRIPTION", "PRODUCT_CHOICES_DISPLAY_IMAGE"]).then(
629
653
  (r) => ({ ok: true as const, r }),
630
654
  () => ({ ok: false as const }),
631
655
  );
@@ -658,11 +682,11 @@ const svc = defineService<S, {
658
682
  if (outcome.ok) {
659
683
  const p = (outcome.r.product ?? (outcome.r as unknown as StoreProduct)) as StoreProduct;
660
684
  const name = cleanTitle(p.name) || "Product";
661
- const image = productImage(p, WIX_DETAIL_IMAGE);
685
+ const image = productImage(p, WIX_DETAIL_IMAGE) || productGallery(p)[0]?.url || "";
662
686
  lastProduct = p;
663
687
  // A group with exactly one choice is chosen for the shopper; a real choice
664
688
  // is left blank so the pick is deliberate.
665
- const optionGroups = productOptions(p);
689
+ const optionGroups = productOptions(p, WIX_DETAIL_IMAGE);
666
690
  const sale = productSale(p);
667
691
  // A pooled screen re-appearing re-runs `load`. Wiping `selection` there means a
668
692
  // trip to the cart and back silently clears the size the shopper picked and
@@ -749,6 +773,11 @@ const svc = defineService<S, {
749
773
  // One chip row per option group. `group` is the descriptor slot ("1".."3");
750
774
  // FilterChips sends back the WHOLE selected set, which for a single-select row
751
775
  // is either one id or none (re-tapping the active chip clears it).
776
+ setGalleryIndex: (s, arg) => {
777
+ const raw = argValue(arg, "index") || argValue(arg, "value");
778
+ const index = raw.trim() ? Number(raw) : NaN;
779
+ return Number.isInteger(index) && index >= 0 && index < s.gallery.length ? derive({ ...s, galleryIndex: index }) : s;
780
+ },
752
781
  selectOption: (s, arg) => {
753
782
  const slot = Math.floor(Number(argValue(arg, "group")));
754
783
  const group = s.optionGroups[slot - 1];
@@ -763,7 +792,9 @@ const svc = defineService<S, {
763
792
  if (choice) selection[group.id] = choice; else delete selection[group.id];
764
793
  // A new choice invalidates the last add's confirmation — it was for the
765
794
  // previous variant.
766
- return derive({ ...s, selection, added: false, addedSheetPresented: false, cartHint: "" });
795
+ const image = group.choices.find(c => c.id === choice)?.image;
796
+ const imageIndex = image ? s.gallery.findIndex(page => page.url === image) : -1;
797
+ return derive({ ...s, selection, optionValidationTarget: "", ...(imageIndex >= 0 ? { galleryIndex: imageIndex } : {}), added: false, addedSheetPresented: false, cartHint: "" });
767
798
  },
768
799
  // The pending half of addToCart, as its own reducer so it PUBLISHES before the
769
800
  // network write starts: the pending line shows and the top-bar badge ticks up in the same
@@ -819,7 +850,7 @@ const svc = defineService<S, {
819
850
  if (s.optionsIncomplete) {
820
851
  // With no groups in hand there is nothing for `optionsHint` to name, so the
821
852
  // offline case needs its own reason rather than an empty string.
822
- return derive({ ...s, showOptionErrors: true, cartHint: s.optionsUnknown
853
+ return derive({ ...s, showOptionErrors: true, optionValidationTarget: s.optionGroups.find(g => !s.selection[g.id])?.id ?? "", optionValidationRequest: (s.optionValidationRequest || 0) + 1, cartHint: s.optionsUnknown
823
854
  ? copyParam("product.cartHintOffline", "Reconnect to choose options and add this to your cart.")
824
855
  : optionsHint(s.optionGroups, s.selection) || copyParam("product.cartHintNoVariant", "That combination is not available. Try another.") });
825
856
  }