@wix/himalaya-cli 0.1580.0 → 0.1582.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.
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +18 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/builder.d.ts +3 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/network/src/index.d.ts +39 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview-page/src/capabilities.generated.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +12 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/validator.d.ts +6 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/network.mjs +45 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/package.json +4 -0
- package/dist/cli.mjs +16481 -16739
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/app-config.md +1 -1
- package/guides/component-reference.json +5 -3
- package/guides/component-reference.md +10 -2
- package/guides/designing-himi-screens.md +24 -0
- package/guides/importable-sdks.md +1 -0
- package/guides/sdk-reference.json +38 -1
- package/guides/tier-5-add-a-screen.md +32 -0
- package/guides/web-page-sdk-reference.md +1 -0
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +197 -304
- package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +44 -13
- package/templates/branded-lite/dev/index.ts +197 -304
- package/templates/branded-lite/l10n/en.json +2 -2
- package/templates/branded-lite/tier5-src/himi-store-product/index.ts +49 -17
- package/templates/gym-fitness/dev/index.ts +197 -304
- package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +44 -13
- package/templates/portfolio-creative/dev/index.ts +197 -304
- package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +44 -13
- package/templates/retail-store/dev/index.ts +197 -304
- package/templates/retail-store/tier5-src/himi-store-product/index.ts +49 -17
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$source": "en",
|
|
3
|
-
"$generated": "2026-11-
|
|
3
|
+
"$generated": "2026-11-05T19:49:25.752Z",
|
|
4
4
|
"messages": {
|
|
5
5
|
"h_042c862e4467": {
|
|
6
6
|
"source": "Try again",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"occurrences": [
|
|
9
9
|
"himi_branded_home#payload.body.props.children[0].body.props.children[1].body.props.title",
|
|
10
10
|
"himi_account_settings#payload.body.props.children[3].body.props.children[1].body.props.title",
|
|
11
|
-
"himi_shop#payload.body.props.children[
|
|
11
|
+
"himi_shop#payload.body.props.children[6].body.props.children[3].body.props.title",
|
|
12
12
|
"himi_saved_products#payload.body.props.children[3].body.props.children[2].body.props.title",
|
|
13
13
|
"himi_collections#payload.body.props.children[4].body.props.ctaLabel",
|
|
14
14
|
"himi_collection#payload.body.props.children[0].body.props.children[8].body.props.ctaLabel",
|
|
@@ -33,6 +33,7 @@ async function cartItemCount(): Promise<number> {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
interface GalleryItem {
|
|
36
|
+
id: string;
|
|
36
37
|
url: string;
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -104,8 +105,8 @@ function slotsOf(groups: StoreOption[], selection: StoreOptionSelection, showErr
|
|
|
104
105
|
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 }));
|
|
105
106
|
out[`opt${n}Selected`] = chosen ? [chosen] : [];
|
|
106
107
|
out[`opt${n}SelectedId`] = chosen;
|
|
107
|
-
out[`opt${n}Placeholder`] = g?.choices.find(c => c.id === chosen)?.label ?? copyTemplate("product.optionPlaceholder", "
|
|
108
|
-
const error = showErrors && g && !chosen ? copyTemplate("product.optionRequired", "
|
|
108
|
+
out[`opt${n}Placeholder`] = g?.choices.find(c => c.id === chosen)?.label ?? copyTemplate("product.optionPlaceholder", "Select {option}", { option: displayName || "option" });
|
|
109
|
+
const error = showErrors && g && !chosen ? copyTemplate("product.optionRequired", "Select a {option}", { option: g.name.toLowerCase() }) : "";
|
|
109
110
|
out[`opt${n}Error`] = error;
|
|
110
111
|
out[`noOpt${n}Error`] = !error;
|
|
111
112
|
out[`hasOpt${n}Error`] = !!error;
|
|
@@ -231,6 +232,8 @@ interface S {
|
|
|
231
232
|
/** FULL media gallery (media.items[] with the main image first) — the detail
|
|
232
233
|
* screen renders a Carousel over it when 2+ images exist. */
|
|
233
234
|
gallery: GalleryItem[];
|
|
235
|
+
galleryIndex: number;
|
|
236
|
+
galleryLabel: string;
|
|
234
237
|
hasGallery: boolean;
|
|
235
238
|
noGallery: boolean;
|
|
236
239
|
initial: string;
|
|
@@ -240,6 +243,7 @@ interface S {
|
|
|
240
243
|
cartCount: number;
|
|
241
244
|
/** An add-to-cart write is in flight (pending line under the CTA). */
|
|
242
245
|
adding: boolean;
|
|
246
|
+
addLabel: string;
|
|
243
247
|
notAdding: boolean;
|
|
244
248
|
/** The last add succeeded (confirmation + View cart under the CTA). */
|
|
245
249
|
added: boolean;
|
|
@@ -276,6 +280,11 @@ interface S {
|
|
|
276
280
|
/** Add to cart is blocked: this product has options and they are not all chosen. */
|
|
277
281
|
optionsIncomplete: boolean;
|
|
278
282
|
showOptionErrors: boolean;
|
|
283
|
+
optionValidationRequest: number;
|
|
284
|
+
optionValidationTarget: string;
|
|
285
|
+
opt1ScrollRequest: string;
|
|
286
|
+
opt2ScrollRequest: string;
|
|
287
|
+
opt3ScrollRequest: string;
|
|
279
288
|
addDisabled: boolean;
|
|
280
289
|
/** The product was served from the offline cache, which carries no option groups.
|
|
281
290
|
* "No groups" here means UNKNOWN, not "none" — so the CTA must stay blocked rather
|
|
@@ -323,7 +332,8 @@ export function productGallery(p: StoreProduct): GalleryItem[] {
|
|
|
323
332
|
// image no matter what the read asked for. One reader, not a private copy per
|
|
324
333
|
// worker — that is how the two layouts drifted apart in the first place.
|
|
325
334
|
for (const url of sdkProductGallery(p, WIX_DETAIL_IMAGE)) push(url);
|
|
326
|
-
|
|
335
|
+
for (const group of productOptions(p, WIX_DETAIL_IMAGE)) for (const choice of group.choices) push(choice.image);
|
|
336
|
+
return urls.map((url) => ({ id: url, url }));
|
|
327
337
|
}
|
|
328
338
|
|
|
329
339
|
/** The product's public page URL when the payload carries one ("" otherwise) —
|
|
@@ -361,6 +371,7 @@ function parseQuantity(raw: string): number | undefined {
|
|
|
361
371
|
|
|
362
372
|
function derive(s: S): S {
|
|
363
373
|
const empty = s.status === "ready" && !s.name;
|
|
374
|
+
const galleryIndex = Math.min(Math.max(0, Math.floor(Number(s.galleryIndex) || 0)), Math.max(0, s.gallery.length - 1));
|
|
364
375
|
const hasGallery = s.gallery.length > 1;
|
|
365
376
|
const hasSingleImage = !!s.image && !hasGallery;
|
|
366
377
|
const groups = s.optionGroups;
|
|
@@ -368,6 +379,8 @@ function derive(s: S): S {
|
|
|
368
379
|
const optionsIncomplete = s.optionsUnknown || !!outOfStockPick(groups, s.selection) || (groups.length > 0 && (overflow || !isSelectionComplete(groups, s.selection)));
|
|
369
380
|
return {
|
|
370
381
|
...s,
|
|
382
|
+
galleryIndex,
|
|
383
|
+
galleryLabel: s.gallery.length ? copyTemplate("product.galleryPage", "Image {index} of {count}", { index: String(galleryIndex + 1), count: String(s.gallery.length) }) : "",
|
|
371
384
|
notOnSale: !s.wasPrice,
|
|
372
385
|
wasPriceEmpty: !!s.wasPrice,
|
|
373
386
|
noSku: !s.skuLabel,
|
|
@@ -396,9 +409,12 @@ function derive(s: S): S {
|
|
|
396
409
|
// indistinguishable from one with none, and adding it would post the variant-less
|
|
397
410
|
// line this whole feature exists to prevent.
|
|
398
411
|
optionsIncomplete,
|
|
399
|
-
|
|
412
|
+
...Object.fromEntries([1, 2, 3].map(n => [`opt${n}ScrollRequest`,
|
|
413
|
+
s.showOptionErrors && groups[n - 1]?.id === s.optionValidationTarget && !s.selection[groups[n - 1].id] ? String(s.optionValidationRequest || "") : ""])),
|
|
414
|
+
addDisabled: s.adding || s.optionsUnknown || overflow || !!outOfStockPick(groups, s.selection),
|
|
400
415
|
optionsHint: groups.length ? optionsHint(groups, s.selection) : "",
|
|
401
416
|
saveLabel: s.saved ? copyParam("savedProducts.removeLabel", "Remove from wishlist") : copyParam("savedProducts.addLabel", "Add to wishlist"),
|
|
417
|
+
addLabel: s.adding ? copyParam("product.adding", "Adding to cart…") : copyParam("product.addToCart", "Add to cart"),
|
|
402
418
|
notAdding: !s.adding,
|
|
403
419
|
notAdded: !s.added,
|
|
404
420
|
isLoading: s.status === "loading",
|
|
@@ -433,7 +449,7 @@ const registerProduct = withIapPresentation<S>({
|
|
|
433
449
|
register: withOnlineWrites(registerState, ["beginAdd", "addToCart", "buy"], { derive, messageFields: action => action === "buy" ? ["buyNote"] : ["cartHint"] }),
|
|
434
450
|
adapters: SELLS_THROUGH_APPLE ? [storesProductOrders] : [],
|
|
435
451
|
onCreate: commerce => { productPricing = commerce; }, prefix: "product",
|
|
436
|
-
transientKeys: ["price", "optionsIncomplete", "cartHint", "cartHidden", "buyHidden", "buyLabel", "buyDisabled", "buyNote", "purchasedNote", "addedSheetPresented", "shareHint"], contentActions: ["load", "readChanged"], concurrentPublishActions: ["buy"],
|
|
452
|
+
transientKeys: ["optionValidationTarget", "optionValidationRequest", "opt1ScrollRequest", "opt2ScrollRequest", "opt3ScrollRequest", "galleryIndex", "price", "optionsIncomplete", "cartHint", "cartHidden", "buyHidden", "buyLabel", "buyDisabled", "buyNote", "purchasedNote", "addedSheetPresented", "shareHint"], contentActions: ["load", "readChanged"], concurrentPublishActions: ["buy"],
|
|
437
453
|
items: state => inputId() ? [{ reference: { kind: "storesProduct", id: inputId() }, commerceDisplayPrice: state.price }] : [],
|
|
438
454
|
present: (state, price, allowed) => {
|
|
439
455
|
const purchase = applePurchase(state);
|
|
@@ -441,9 +457,10 @@ const registerProduct = withIapPresentation<S>({
|
|
|
441
457
|
const blocked = lastProduct?.productType?.toLowerCase() === "digital" || (!state.optionsUnknown && !allowed(inputId()));
|
|
442
458
|
const cartHint = state.cartHint === offlineWriteMessage ? state.cartHint
|
|
443
459
|
: !purchase.appleRoute && blocked ? unavailable : state.cartHint === unavailable ? "" : state.cartHint;
|
|
460
|
+
const productState = derive(state);
|
|
444
461
|
return {
|
|
445
|
-
...state, price: price(inputId()), ...(purchase.appleRoute ? { wasPrice: "", wasPriceEmpty: false, notOnSale: true } : {}), optionsIncomplete:
|
|
446
|
-
cartHint, noCartHint: !cartHint || state.added, addDisabled:
|
|
462
|
+
...state, price: price(inputId()), ...(purchase.appleRoute ? { wasPrice: "", wasPriceEmpty: false, notOnSale: true } : {}), optionsIncomplete: productState.optionsIncomplete || !allowed(inputId()) || lastProduct?.productType?.toLowerCase() === "digital",
|
|
463
|
+
cartHint, noCartHint: !cartHint || state.added, addDisabled: productState.addDisabled || blocked,
|
|
447
464
|
cartHidden: state.status !== "ready" || !state.name || purchase.appleRoute,
|
|
448
465
|
buyHidden: state.status !== "ready" || !state.name || !purchase.appleRoute || purchase.accessReady, buyLabel: purchase.buyLabel, buyDisabled: purchase.buyDisabled,
|
|
449
466
|
buyNote: state.buyNote === offlineWriteMessage ? state.buyNote : purchase.buyNote,
|
|
@@ -497,6 +514,7 @@ const svc = onlineService<S, {
|
|
|
497
514
|
toggleReturnPolicy: (s: S) => S;
|
|
498
515
|
toggleShippingInfo: (s: S) => S;
|
|
499
516
|
selectOption: (s: S, arg?: unknown) => S;
|
|
517
|
+
setGalleryIndex: (s: S, arg?: unknown) => S;
|
|
500
518
|
addToCart: (s: S) => Promise<S>;
|
|
501
519
|
beginAdd: (s: S, arg?: unknown) => S;
|
|
502
520
|
setCartCount: (s: S, arg?: unknown) => S;
|
|
@@ -541,6 +559,8 @@ const svc = onlineService<S, {
|
|
|
541
559
|
shippingInfoExpanded: false,
|
|
542
560
|
image: "",
|
|
543
561
|
gallery: [],
|
|
562
|
+
galleryIndex: 0,
|
|
563
|
+
galleryLabel: "",
|
|
544
564
|
hasGallery: false,
|
|
545
565
|
noGallery: true,
|
|
546
566
|
initial: "",
|
|
@@ -548,6 +568,7 @@ const svc = onlineService<S, {
|
|
|
548
568
|
cartHint: "",
|
|
549
569
|
cartCount: 0,
|
|
550
570
|
adding: false,
|
|
571
|
+
addLabel: "",
|
|
551
572
|
notAdding: true,
|
|
552
573
|
added: false,
|
|
553
574
|
notAdded: true,
|
|
@@ -573,6 +594,9 @@ const svc = onlineService<S, {
|
|
|
573
594
|
noOptionsOverflow: true,
|
|
574
595
|
optionsIncomplete: false,
|
|
575
596
|
showOptionErrors: false,
|
|
597
|
+
optionValidationRequest: 0,
|
|
598
|
+
optionValidationTarget: "",
|
|
599
|
+
opt1ScrollRequest: "", opt2ScrollRequest: "", opt3ScrollRequest: "",
|
|
576
600
|
addDisabled: false,
|
|
577
601
|
optionsUnknown: false,
|
|
578
602
|
optionsHint: "",
|
|
@@ -600,7 +624,8 @@ const svc = onlineService<S, {
|
|
|
600
624
|
let saved = false;
|
|
601
625
|
try { saved = isProductSaved(id); } catch { /* save action reports a retryable error */ }
|
|
602
626
|
s = { ...s, saved, saveHint: "",
|
|
603
|
-
|
|
627
|
+
optionValidationTarget: "",
|
|
628
|
+
...(id !== lastLoadedId ? { adding: false, added: false, shareHint: "", addedSheetPresented: false, quantity: 1, showOptionErrors: false, optionValidationRequest: 0, galleryIndex: 0, returnPolicyExpanded: false, shippingInfoExpanded: false } : {}) };
|
|
604
629
|
// A fresh navigation into the product resets any quantity left over
|
|
605
630
|
// from a previous visit to the same worker instance.
|
|
606
631
|
if (!id) {
|
|
@@ -617,8 +642,8 @@ const svc = onlineService<S, {
|
|
|
617
642
|
void cartCount.then((n) => { cartKnown = n; }, () => {});
|
|
618
643
|
// The live product read goes out FIRST too — the local-db read below must never delay it.
|
|
619
644
|
// Settled into a value so a failure is handled where it is awaited, never unhandled.
|
|
620
|
-
//
|
|
621
|
-
const live = getStoreProduct(id, ["DESCRIPTION"], readOptions(arg)).then(
|
|
645
|
+
// Read both the Ricos description and choice-linked images; V3 omits these fields by default.
|
|
646
|
+
const live = getStoreProduct(id, ["DESCRIPTION", "PRODUCT_CHOICES_DISPLAY_IMAGE"], readOptions(arg)).then(
|
|
622
647
|
(r) => ({ ok: true as const, r }),
|
|
623
648
|
(error) => ({ ok: false as const, error }),
|
|
624
649
|
);
|
|
@@ -646,11 +671,12 @@ const svc = onlineService<S, {
|
|
|
646
671
|
if (outcome.ok) {
|
|
647
672
|
const p = (outcome.r.product ?? (outcome.r as unknown as StoreProduct)) as StoreProduct;
|
|
648
673
|
const name = cleanTitle(p.name) || "Product";
|
|
649
|
-
const
|
|
674
|
+
const gallery = productGallery(p);
|
|
675
|
+
const image = productImage(p, WIX_DETAIL_IMAGE) || gallery[0]?.url || "";
|
|
650
676
|
lastProduct = p;
|
|
651
677
|
// A group with exactly one choice is chosen for the shopper; a real choice
|
|
652
678
|
// is left blank so the pick is deliberate.
|
|
653
|
-
const optionGroups = productOptions(p);
|
|
679
|
+
const optionGroups = productOptions(p, WIX_DETAIL_IMAGE);
|
|
654
680
|
const sale = productSale(p);
|
|
655
681
|
// A pooled screen re-appearing re-runs `load`. Wiping `selection` there means a
|
|
656
682
|
// trip to the cart and back silently clears the size the shopper picked and
|
|
@@ -680,7 +706,7 @@ const svc = onlineService<S, {
|
|
|
680
706
|
shippingInfoBody: productPolicyBody(p, "shipping") || copyParam("product.shippingInfoBody", "") || copyParam("product.policyUnavailable", "Policy details have not been provided by this store."),
|
|
681
707
|
...productBody(p),
|
|
682
708
|
image,
|
|
683
|
-
gallery
|
|
709
|
+
gallery,
|
|
684
710
|
initial: (name[0] || "#").toUpperCase(),
|
|
685
711
|
shareUrl: productShareUrl(p),
|
|
686
712
|
cartCount: badge(),
|
|
@@ -700,6 +726,11 @@ const svc = onlineService<S, {
|
|
|
700
726
|
// One chip row per option group. `group` is the descriptor slot ("1".."3");
|
|
701
727
|
// FilterChips sends back the WHOLE selected set, which for a single-select row
|
|
702
728
|
// is either one id or none (re-tapping the active chip clears it).
|
|
729
|
+
setGalleryIndex: (s, arg) => {
|
|
730
|
+
const raw = argValue(arg, "index") || argValue(arg, "value");
|
|
731
|
+
const index = raw.trim() ? Number(raw) : NaN;
|
|
732
|
+
return Number.isInteger(index) && index >= 0 && index < s.gallery.length ? derive({ ...s, galleryIndex: index }) : s;
|
|
733
|
+
},
|
|
703
734
|
selectOption: (s, arg) => {
|
|
704
735
|
const slot = Math.floor(Number(argValue(arg, "group")));
|
|
705
736
|
const group = s.optionGroups[slot - 1];
|
|
@@ -714,7 +745,9 @@ const svc = onlineService<S, {
|
|
|
714
745
|
if (choice) selection[group.id] = choice; else delete selection[group.id];
|
|
715
746
|
// A new choice invalidates the last add's confirmation — it was for the
|
|
716
747
|
// previous variant.
|
|
717
|
-
|
|
748
|
+
const image = group.choices.find(c => c.id === choice)?.image;
|
|
749
|
+
const imageIndex = image ? s.gallery.findIndex(page => page.url === image) : -1;
|
|
750
|
+
return derive({ ...s, selection, optionValidationTarget: "", ...(imageIndex >= 0 ? { galleryIndex: imageIndex } : {}), added: false, addedSheetPresented: false, cartHint: "" });
|
|
718
751
|
},
|
|
719
752
|
// The pending half of addToCart, as its own reducer so it PUBLISHES before the
|
|
720
753
|
// network write starts: the pending line shows and the top-bar badge ticks up in the same
|
|
@@ -743,12 +776,11 @@ const svc = onlineService<S, {
|
|
|
743
776
|
if (!id) return derive({ ...s, cartHint: copyParam("product.cartHintNoProduct", "No product to add.") });
|
|
744
777
|
// A second tap while the first write is in flight must not add the line twice.
|
|
745
778
|
if (s.adding) return s;
|
|
746
|
-
//
|
|
747
|
-
// a voice-control/deep-link dispatch reaches the action without the button.
|
|
779
|
+
// Missing choices show field errors; unavailable products still fail closed.
|
|
748
780
|
if (s.optionsIncomplete) {
|
|
749
781
|
// With no groups in hand there is nothing for `optionsHint` to name, so the
|
|
750
782
|
// offline case needs its own reason rather than an empty string.
|
|
751
|
-
return derive({ ...s, showOptionErrors: true, cartHint: s.optionsUnknown
|
|
783
|
+
return derive({ ...s, showOptionErrors: true, optionValidationTarget: s.optionGroups.find(g => !s.selection[g.id])?.id ?? "", optionValidationRequest: (s.optionValidationRequest || 0) + 1, cartHint: s.optionsUnknown
|
|
752
784
|
? copyParam("product.cartHintOffline", "Reconnect to choose options and add this to your cart.")
|
|
753
785
|
: optionsHint(s.optionGroups, s.selection) || copyParam("product.cartHintNoVariant", "That combination is not available. Try another.") });
|
|
754
786
|
}
|