@wix/headless-stores 0.0.9 → 0.0.11

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 (135) hide show
  1. package/cjs/dist/enums/index.d.ts +2 -0
  2. package/cjs/dist/enums/index.js +18 -0
  3. package/cjs/dist/enums/social-platform-enums.d.ts +25 -0
  4. package/cjs/dist/enums/social-platform-enums.js +30 -0
  5. package/cjs/dist/enums/sort-enums.d.ts +17 -0
  6. package/cjs/dist/enums/sort-enums.js +21 -0
  7. package/cjs/dist/react/BuyNow.d.ts +2 -4
  8. package/cjs/dist/react/Category.d.ts +15 -0
  9. package/cjs/dist/react/Category.js +22 -0
  10. package/cjs/dist/react/Collection.d.ts +151 -0
  11. package/cjs/dist/react/Collection.js +209 -0
  12. package/cjs/dist/react/FilteredCollection.d.ts +95 -0
  13. package/cjs/dist/react/FilteredCollection.js +150 -0
  14. package/cjs/dist/react/PayNow.d.ts +2 -4
  15. package/cjs/dist/react/Product.d.ts +43 -0
  16. package/cjs/dist/react/Product.js +35 -0
  17. package/cjs/dist/react/ProductActions.d.ts +42 -0
  18. package/cjs/dist/react/ProductActions.js +83 -0
  19. package/cjs/dist/react/ProductModifiers.d.ts +164 -0
  20. package/cjs/dist/react/ProductModifiers.js +168 -0
  21. package/cjs/dist/react/ProductVariantSelector.d.ts +153 -0
  22. package/cjs/dist/react/ProductVariantSelector.js +138 -0
  23. package/cjs/dist/react/RelatedProducts.d.ts +64 -0
  24. package/cjs/dist/react/RelatedProducts.js +73 -0
  25. package/cjs/dist/react/SelectedVariant.d.ts +66 -0
  26. package/cjs/dist/react/SelectedVariant.js +52 -0
  27. package/cjs/dist/react/SocialSharing.d.ts +112 -0
  28. package/cjs/dist/react/SocialSharing.js +86 -0
  29. package/cjs/dist/react/Sort.d.ts +14 -0
  30. package/cjs/dist/react/Sort.js +17 -0
  31. package/cjs/dist/react/index.d.ts +11 -0
  32. package/cjs/dist/react/index.js +34 -0
  33. package/cjs/dist/services/buy-now-service.js +2 -2
  34. package/cjs/dist/services/catalog-options-service.d.ts +30 -0
  35. package/cjs/dist/services/catalog-options-service.js +156 -0
  36. package/cjs/dist/services/catalog-price-range-service.d.ts +23 -0
  37. package/cjs/dist/services/catalog-price-range-service.js +97 -0
  38. package/cjs/dist/services/category-service.d.ts +26 -0
  39. package/cjs/dist/services/category-service.js +71 -0
  40. package/cjs/dist/services/collection-service.d.ts +37 -0
  41. package/cjs/dist/services/collection-service.js +569 -0
  42. package/cjs/dist/services/filter-service.d.ts +56 -0
  43. package/cjs/dist/services/filter-service.js +147 -0
  44. package/cjs/dist/services/product-media-gallery-service.d.ts +25 -0
  45. package/cjs/dist/services/product-media-gallery-service.js +105 -0
  46. package/cjs/dist/services/product-modifiers-service.d.ts +34 -0
  47. package/cjs/dist/services/product-modifiers-service.js +111 -0
  48. package/cjs/dist/services/product-service.d.ts +28 -0
  49. package/cjs/dist/services/product-service.js +68 -0
  50. package/cjs/dist/services/related-products-service.d.ts +25 -0
  51. package/cjs/dist/services/related-products-service.js +54 -0
  52. package/cjs/dist/services/selected-variant-service.d.ts +59 -0
  53. package/cjs/dist/services/selected-variant-service.js +541 -0
  54. package/cjs/dist/services/social-sharing-service.d.ts +41 -0
  55. package/cjs/dist/services/social-sharing-service.js +141 -0
  56. package/cjs/dist/services/sort-service.d.ts +20 -0
  57. package/cjs/dist/services/sort-service.js +32 -0
  58. package/cjs/dist/utils/url-params.d.ts +5 -0
  59. package/cjs/dist/utils/url-params.js +50 -0
  60. package/dist/enums/index.d.ts +2 -0
  61. package/dist/enums/index.js +2 -0
  62. package/dist/enums/social-platform-enums.d.ts +25 -0
  63. package/dist/enums/social-platform-enums.js +27 -0
  64. package/dist/enums/sort-enums.d.ts +17 -0
  65. package/dist/enums/sort-enums.js +18 -0
  66. package/dist/react/BuyNow.d.ts +2 -4
  67. package/dist/react/Category.d.ts +15 -0
  68. package/dist/react/Category.js +18 -0
  69. package/dist/react/Collection.d.ts +151 -0
  70. package/dist/react/Collection.js +201 -0
  71. package/dist/react/FilteredCollection.d.ts +95 -0
  72. package/dist/react/FilteredCollection.js +140 -0
  73. package/dist/react/PayNow.d.ts +2 -4
  74. package/dist/react/Product.d.ts +43 -0
  75. package/dist/react/Product.js +30 -0
  76. package/dist/react/ProductActions.d.ts +42 -0
  77. package/dist/react/ProductActions.js +79 -0
  78. package/dist/react/ProductModifiers.d.ts +164 -0
  79. package/dist/react/ProductModifiers.js +160 -0
  80. package/dist/react/ProductVariantSelector.d.ts +153 -0
  81. package/dist/react/ProductVariantSelector.js +130 -0
  82. package/dist/react/RelatedProducts.d.ts +64 -0
  83. package/dist/react/RelatedProducts.js +65 -0
  84. package/dist/react/SelectedVariant.d.ts +66 -0
  85. package/dist/react/SelectedVariant.js +46 -0
  86. package/dist/react/SocialSharing.d.ts +112 -0
  87. package/dist/react/SocialSharing.js +77 -0
  88. package/dist/react/Sort.d.ts +14 -0
  89. package/dist/react/Sort.js +14 -0
  90. package/dist/react/index.d.ts +11 -0
  91. package/dist/react/index.js +11 -0
  92. package/dist/services/buy-now-service.js +2 -2
  93. package/dist/services/catalog-options-service.d.ts +30 -0
  94. package/dist/services/catalog-options-service.js +152 -0
  95. package/dist/services/catalog-price-range-service.d.ts +23 -0
  96. package/dist/services/catalog-price-range-service.js +93 -0
  97. package/dist/services/category-service.d.ts +26 -0
  98. package/dist/services/category-service.js +67 -0
  99. package/dist/services/collection-service.d.ts +37 -0
  100. package/dist/services/collection-service.js +532 -0
  101. package/dist/services/filter-service.d.ts +56 -0
  102. package/dist/services/filter-service.js +144 -0
  103. package/dist/services/product-media-gallery-service.d.ts +25 -0
  104. package/dist/services/product-media-gallery-service.js +101 -0
  105. package/dist/services/product-modifiers-service.d.ts +34 -0
  106. package/dist/services/product-modifiers-service.js +107 -0
  107. package/dist/services/product-service.d.ts +28 -0
  108. package/dist/services/product-service.js +64 -0
  109. package/dist/services/related-products-service.d.ts +25 -0
  110. package/dist/services/related-products-service.js +50 -0
  111. package/dist/services/selected-variant-service.d.ts +59 -0
  112. package/dist/services/selected-variant-service.js +538 -0
  113. package/dist/services/social-sharing-service.d.ts +41 -0
  114. package/dist/services/social-sharing-service.js +137 -0
  115. package/dist/services/sort-service.d.ts +20 -0
  116. package/dist/services/sort-service.js +29 -0
  117. package/dist/utils/url-params.d.ts +5 -0
  118. package/dist/utils/url-params.js +46 -0
  119. package/package.json +8 -1
  120. package/dist/astro/BuyNowServiceContext.d.ts +0 -2
  121. package/dist/astro/BuyNowServiceContext.js +0 -6
  122. package/dist/astro/ManagerProviderContext.d.ts +0 -2
  123. package/dist/astro/ManagerProviderContext.js +0 -7
  124. package/dist/astro/withBuyButtonService.d.ts +0 -2
  125. package/dist/astro/withBuyButtonService.js +0 -16
  126. package/dist/react/CurrentCartServiceProvider.d.ts +0 -5
  127. package/dist/react/CurrentCartServiceProvider.js +0 -12
  128. package/dist/react/VariantSelectorServiceProvider.d.ts +0 -7
  129. package/dist/react/VariantSelectorServiceProvider.js +0 -22
  130. package/dist/react/hookim/index.d.ts +0 -5
  131. package/dist/react/hookim/index.js +0 -22
  132. package/dist/services/CurrentCartService.d.ts +0 -18
  133. package/dist/services/CurrentCartService.js +0 -9
  134. package/dist/services/VariantSelectorServices.d.ts +0 -8
  135. package/dist/services/VariantSelectorServices.js +0 -20
@@ -0,0 +1,538 @@
1
+ import { defineService, implementService } from '@wix/services-definitions';
2
+ import { SignalsServiceDefinition } from '@wix/services-definitions/core-services/signals';
3
+ import { ModifierRenderType, InventoryAvailabilityStatus, } from '@wix/auto_sdk_stores_products-v-3';
4
+ import { queryInventoryItems } from '@wix/auto_sdk_stores_inventory-items-v-3';
5
+ // import { CurrentCartServiceDefinition } from '../../ecom/services/current-cart-service';
6
+ import { ProductServiceDefinition } from './product-service';
7
+ export const SelectedVariantServiceDefinition = defineService('selectedVariant');
8
+ export const SelectedVariantService = implementService.withConfig()(SelectedVariantServiceDefinition, ({ getService }) => {
9
+ const signalsService = getService(SignalsServiceDefinition);
10
+ // const cartService = getService(CurrentCartServiceDefinition);
11
+ const productService = getService(ProductServiceDefinition);
12
+ // const mediaService = getService(MediaGalleryServiceDefinition);
13
+ const selectedChoices = signalsService.signal({});
14
+ const preOrderMessage = signalsService.signal(null);
15
+ const initialProduct = productService.product.get();
16
+ signalsService.effect(() => {
17
+ const product = productService.product.get();
18
+ const selectedChoicesValue = selectedChoices.get() || {};
19
+ let mediaToDisplay = [];
20
+ const productItemsImages = product?.media?.itemsInfo?.items?.map(item => item).filter(Boolean) ??
21
+ [];
22
+ if (productItemsImages.length) {
23
+ mediaToDisplay = productItemsImages;
24
+ }
25
+ else if (product?.media?.main) {
26
+ mediaToDisplay = [product.media.main];
27
+ }
28
+ // Get images based on selected choices if available
29
+ let selectedChoicesImages = [];
30
+ Object.keys(selectedChoicesValue).forEach(choiceKey => {
31
+ const productOption = product?.options
32
+ ?.find((option) => option.name === choiceKey)
33
+ ?.choicesSettings?.choices?.find((choice) => choice.name === selectedChoicesValue[choiceKey]);
34
+ if (productOption) {
35
+ selectedChoicesImages.push(...(productOption.linkedMedia ?? []));
36
+ }
37
+ });
38
+ if (selectedChoicesImages?.length) {
39
+ mediaToDisplay = selectedChoicesImages;
40
+ }
41
+ console.log({ mediaToDisplay });
42
+ // mediaService.setMediaToDisplay(mediaToDisplay ?? []);
43
+ });
44
+ const parsePrice = (amount) => {
45
+ if (!amount)
46
+ return 0;
47
+ const parsed = parseFloat(amount);
48
+ return isNaN(parsed) ? 0 : parsed;
49
+ };
50
+ const processVariantChoices = (variant) => {
51
+ const choices = {};
52
+ if (variant.choices) {
53
+ for (const choice of variant.choices) {
54
+ if (choice.optionChoiceNames?.optionName &&
55
+ choice.optionChoiceNames?.choiceName) {
56
+ choices[choice.optionChoiceNames.optionName] =
57
+ choice.optionChoiceNames.choiceName;
58
+ }
59
+ }
60
+ }
61
+ return choices;
62
+ };
63
+ const findVariantByChoices = (variants, selectedChoices) => {
64
+ return (variants.find(variant => {
65
+ const variantChoices = processVariantChoices(variant);
66
+ const choiceKeys = Object.keys(selectedChoices);
67
+ return choiceKeys.every(key => variantChoices[key] === selectedChoices[key]);
68
+ }) || null);
69
+ };
70
+ const findVariantWithMinPrice = () => {
71
+ const variantsList = variants.get();
72
+ const variantPrices = variantsList.map(x => Number(x.price?.actualPrice?.formattedAmount) ||
73
+ Number(x.price?.actualPrice?.amount));
74
+ const minPrice = String(Math.min(...variantPrices));
75
+ return variantsList.find(x => x.price?.actualPrice?.formattedAmount === minPrice ||
76
+ x.price?.actualPrice?.amount === minPrice);
77
+ };
78
+ const updateInventoryItemData = async (variantId, inStock, preOrderEnabled) => {
79
+ if (!variantId) {
80
+ preOrderMessage.set(null);
81
+ return;
82
+ }
83
+ try {
84
+ // Use the correct Wix inventoryItemsV3.queryInventoryItems() API
85
+ const queryResult = await queryInventoryItems()
86
+ .eq('variantId', variantId)
87
+ .find();
88
+ const inventoryItem = queryResult.items?.[0];
89
+ const isTrackingQuantity = inventoryItem?.trackQuantity ?? false;
90
+ trackQuantity.set(isTrackingQuantity);
91
+ preOrderMessage.set(inventoryItem?.preorderInfo?.message || null);
92
+ if (!inventoryItem || !isTrackingQuantity) {
93
+ quantityAvailable.set(null);
94
+ return;
95
+ }
96
+ if (inStock && inventoryItem?.quantity) {
97
+ quantityAvailable.set(inventoryItem.quantity);
98
+ }
99
+ else if (preOrderEnabled && inventoryItem.preorderInfo?.limit) {
100
+ quantityAvailable.set(inventoryItem.preorderInfo.limit);
101
+ }
102
+ else {
103
+ quantityAvailable.set(null);
104
+ }
105
+ }
106
+ catch (error) {
107
+ console.error('Failed to fetch inventory quantity:', error);
108
+ // Fallback on error
109
+ quantityAvailable.set(null);
110
+ trackQuantity.set(false);
111
+ }
112
+ };
113
+ const updateDataFromVariant = (variant) => {
114
+ if (variant) {
115
+ const inStock = variant.inventoryStatus?.inStock ?? true;
116
+ const preOrderEnabled = variant.inventoryStatus?.preorderEnabled ?? false;
117
+ // update the quantity available, tracking indication and pre-order message from the inventory API
118
+ updateInventoryItemData(variant._id, inStock, preOrderEnabled);
119
+ }
120
+ else {
121
+ quantityAvailable.set(0);
122
+ trackQuantity.set(false);
123
+ }
124
+ };
125
+ const isLoading = signalsService.signal(false);
126
+ const error = signalsService.signal(null);
127
+ const variants = signalsService.signal([]);
128
+ const options = signalsService.signal({});
129
+ const basePrice = signalsService.signal(0);
130
+ const discountPrice = signalsService.signal(null);
131
+ const isOnSale = signalsService.signal(null);
132
+ const quantityAvailable = signalsService.signal(null);
133
+ const trackQuantity = signalsService.signal(false);
134
+ const selectedQuantity = signalsService.signal(1);
135
+ const productId = signalsService.signal('');
136
+ const ribbonLabel = signalsService.signal(null);
137
+ const v3Product = signalsService.signal(initialProduct);
138
+ const init = (currentProduct) => {
139
+ if (currentProduct) {
140
+ v3Product.set(currentProduct);
141
+ productId.set(currentProduct._id || '');
142
+ ribbonLabel.set(currentProduct.ribbon?.name || null);
143
+ const actualPrice = currentProduct.actualPriceRange?.minValue?.amount;
144
+ const compareAtPrice = currentProduct.compareAtPriceRange?.minValue?.amount;
145
+ basePrice.set(parsePrice(actualPrice));
146
+ discountPrice.set(compareAtPrice ? parsePrice(compareAtPrice) : null);
147
+ isOnSale.set(!!compareAtPrice &&
148
+ parsePrice(compareAtPrice) > parsePrice(actualPrice));
149
+ if (currentProduct.options) {
150
+ const optionsMap = {};
151
+ currentProduct.options.forEach((option) => {
152
+ if (option.name && option.choicesSettings?.choices) {
153
+ optionsMap[option.name] = option.choicesSettings.choices.map((choice) => choice.name || '');
154
+ }
155
+ });
156
+ options.set(optionsMap);
157
+ }
158
+ if (currentProduct.variantSummary.variantCount > 1) {
159
+ variants.set(currentProduct.variantsInfo?.variants || []);
160
+ if (currentProduct.variantsInfo?.variants?.length) {
161
+ // updateDataFromVariant(currentProduct.variantsInfo?.variants[0]);
162
+ }
163
+ }
164
+ else {
165
+ const singleVariant = {
166
+ _id: 'default',
167
+ visible: true,
168
+ choices: [],
169
+ price: {
170
+ actualPrice: currentProduct.actualPriceRange?.minValue,
171
+ compareAtPrice: currentProduct.compareAtPriceRange?.minValue,
172
+ },
173
+ inventoryStatus: {
174
+ inStock: currentProduct.inventory?.availabilityStatus ===
175
+ InventoryAvailabilityStatus.IN_STOCK ||
176
+ currentProduct.inventory?.availabilityStatus ===
177
+ InventoryAvailabilityStatus.PARTIALLY_OUT_OF_STOCK,
178
+ preorderEnabled: currentProduct.inventory?.preorderStatus === 'ENABLED',
179
+ },
180
+ };
181
+ variants.set([singleVariant]);
182
+ updateDataFromVariant(singleVariant);
183
+ }
184
+ }
185
+ };
186
+ signalsService.effect(() => {
187
+ const currentProduct = productService.product.get();
188
+ init(currentProduct);
189
+ });
190
+ const currentVariant = signalsService.computed((() => {
191
+ const choices = selectedChoices.get();
192
+ const variantsList = variants.get();
193
+ if (!variantsList || variantsList.length === 0)
194
+ return null;
195
+ return (variantsList.find((variant) => {
196
+ const variantChoices = processVariantChoices(variant);
197
+ if (Object.keys(choices).length !== Object.keys(variantChoices).length)
198
+ return false;
199
+ return Object.entries(choices).every(([optionName, optionValue]) => {
200
+ return variantChoices[optionName] === optionValue;
201
+ });
202
+ }) || null);
203
+ }));
204
+ const selectedVariantId = signalsService.computed(() => {
205
+ const variant = currentVariant.get();
206
+ return variant?._id || null;
207
+ });
208
+ const variantWithMinPrice = findVariantWithMinPrice();
209
+ const currentPrice = signalsService.computed(() => {
210
+ const variant = currentVariant.get();
211
+ if (!variant && variantWithMinPrice) {
212
+ const formattedAmount = variantWithMinPrice?.price?.actualPrice?.formattedAmount;
213
+ if (formattedAmount) {
214
+ return formattedAmount;
215
+ }
216
+ const amount = variantWithMinPrice?.price?.actualPrice?.amount;
217
+ if (amount) {
218
+ return `$${amount}`;
219
+ }
220
+ }
221
+ const prod = v3Product.get();
222
+ // Try to get formatted amount first (if fields worked)
223
+ if (variant?.price?.actualPrice?.formattedAmount) {
224
+ return variant.price.actualPrice.formattedAmount;
225
+ }
226
+ if (prod?.actualPriceRange?.minValue?.formattedAmount) {
227
+ return prod.actualPriceRange.minValue.formattedAmount;
228
+ }
229
+ // Fallback: create our own formatted price from amount
230
+ let rawAmount = null;
231
+ if (variant?.price?.actualPrice?.amount) {
232
+ rawAmount = variant.price.actualPrice.amount;
233
+ }
234
+ else if (prod?.actualPriceRange?.minValue?.amount) {
235
+ rawAmount = prod.actualPriceRange.minValue.amount;
236
+ }
237
+ return rawAmount ? `$${rawAmount}` : '';
238
+ });
239
+ const currentCompareAtPrice = signalsService.computed(() => {
240
+ const variant = currentVariant.get();
241
+ const prod = v3Product.get();
242
+ if (!variant && variantWithMinPrice) {
243
+ const formattedAmount = variantWithMinPrice?.price?.compareAtPrice?.formattedAmount;
244
+ if (formattedAmount) {
245
+ return formattedAmount;
246
+ }
247
+ const amount = variantWithMinPrice?.price?.compareAtPrice?.amount;
248
+ if (amount) {
249
+ return `$${amount}`;
250
+ }
251
+ }
252
+ // Try to get formatted compare-at price first
253
+ if (variant?.price?.compareAtPrice?.formattedAmount) {
254
+ return variant.price.compareAtPrice.formattedAmount;
255
+ }
256
+ if (prod?.compareAtPriceRange?.minValue?.formattedAmount) {
257
+ return prod.compareAtPriceRange.minValue.formattedAmount;
258
+ }
259
+ // Fallback: create our own formatted price from amount
260
+ let rawAmount = null;
261
+ if (variant?.price?.compareAtPrice?.amount) {
262
+ rawAmount = variant.price.compareAtPrice.amount;
263
+ }
264
+ else if (prod?.compareAtPriceRange?.minValue?.amount) {
265
+ rawAmount = prod.compareAtPriceRange.minValue.amount;
266
+ }
267
+ return rawAmount ? `$${rawAmount}` : null;
268
+ });
269
+ const isInStock = signalsService.computed(() => {
270
+ const variant = currentVariant.get();
271
+ if (variant) {
272
+ return variant.inventoryStatus?.inStock ?? false;
273
+ }
274
+ else {
275
+ return false;
276
+ }
277
+ });
278
+ const isPreOrderEnabled = signalsService.computed(() => {
279
+ const variant = currentVariant.get();
280
+ return variant?.inventoryStatus?.preorderEnabled ?? false;
281
+ });
282
+ const product = v3Product;
283
+ const productOptions = signalsService.computed(() => {
284
+ const prod = v3Product.get();
285
+ return prod?.options || [];
286
+ });
287
+ const currency = signalsService.computed(() => {
288
+ const prod = v3Product.get();
289
+ return prod?.currency || 'USD';
290
+ });
291
+ const selectedVariant = () => {
292
+ const variantId = selectedVariantId.get();
293
+ const variantsList = variants.get();
294
+ return variantsList.find(v => v._id === variantId) || null;
295
+ };
296
+ const finalPrice = () => {
297
+ const discount = discountPrice.get();
298
+ const base = basePrice.get();
299
+ return discount !== null ? discount : base;
300
+ };
301
+ const isLowStock = () => {
302
+ // Note: Currently always returns false as inventory quantity tracking
303
+ // is handled separately by the inventory service
304
+ return false;
305
+ };
306
+ const setSelectedChoices = (choices) => {
307
+ selectedChoices.set(choices);
308
+ selectedQuantity.set(1); // Reset quantity when choices change
309
+ const matchingVariant = findVariantByChoices(variants.get(), choices);
310
+ updateDataFromVariant(matchingVariant);
311
+ };
312
+ const addToCart = async (_quantity = 1, modifiers) => {
313
+ try {
314
+ isLoading.set(true);
315
+ error.set(null);
316
+ const prod = v3Product.get();
317
+ const variant = currentVariant.get();
318
+ if (!prod?._id) {
319
+ throw new Error('Product not found');
320
+ }
321
+ // Build catalog reference with modifiers if provided
322
+ const catalogReference = {
323
+ catalogItemId: prod._id,
324
+ appId: '215238eb-22a5-4c36-9e7b-e7c08025e04e',
325
+ options: variant?._id && variant._id !== 'default'
326
+ ? {
327
+ variantId: variant._id,
328
+ preOrderRequested: !!variant?.inventoryStatus?.preorderEnabled,
329
+ }
330
+ : undefined,
331
+ };
332
+ // Transform and add modifiers to catalog reference if they exist
333
+ if (modifiers && Object.keys(modifiers).length > 0) {
334
+ const options = {};
335
+ const customTextFields = {};
336
+ // Get product modifiers to determine types and keys
337
+ const productModifiers = prod.modifiers || [];
338
+ Object.values(modifiers).forEach((modifierValue) => {
339
+ const modifierName = modifierValue.modifierName;
340
+ const productModifier = productModifiers.find(m => m.name === modifierName);
341
+ if (!productModifier)
342
+ return;
343
+ const renderType = productModifier.modifierRenderType;
344
+ if (renderType === ModifierRenderType.TEXT_CHOICES ||
345
+ renderType === ModifierRenderType.SWATCH_CHOICES) {
346
+ // For choice modifiers, use the modifier key and choice value
347
+ const modifierKey = productModifier.key || modifierName;
348
+ if (modifierValue.choiceValue) {
349
+ options[modifierKey] = modifierValue.choiceValue;
350
+ }
351
+ }
352
+ else if (renderType === ModifierRenderType.FREE_TEXT) {
353
+ // For free text modifiers, use the freeTextSettings key
354
+ const freeTextKey = productModifier.freeTextSettings?.key || modifierName;
355
+ if (modifierValue.freeTextValue) {
356
+ customTextFields[freeTextKey] = modifierValue.freeTextValue;
357
+ }
358
+ }
359
+ });
360
+ // Add formatted modifiers to catalog reference
361
+ if (Object.keys(options).length > 0) {
362
+ catalogReference.options = {
363
+ ...catalogReference.options,
364
+ options,
365
+ };
366
+ }
367
+ if (Object.keys(customTextFields).length > 0) {
368
+ catalogReference.options = {
369
+ ...catalogReference.options,
370
+ customTextFields,
371
+ };
372
+ }
373
+ }
374
+ // const lineItems = [
375
+ // {
376
+ // catalogReference,
377
+ // quantity,
378
+ // },
379
+ // ];
380
+ // await cartService.addToCart(lineItems);
381
+ }
382
+ catch (err) {
383
+ error.set(err instanceof Error ? err.message : 'Failed to add to cart');
384
+ }
385
+ finally {
386
+ isLoading.set(false);
387
+ }
388
+ };
389
+ const setOption = (group, value) => {
390
+ const currentChoices = selectedChoices.get();
391
+ const newChoices = { ...currentChoices, [group]: value };
392
+ setSelectedChoices(newChoices);
393
+ };
394
+ const selectVariantById = (id) => {
395
+ const variantsList = variants.get();
396
+ const variant = variantsList.find(v => v._id === id);
397
+ if (variant) {
398
+ const variantChoices = processVariantChoices(variant);
399
+ selectedChoices.set(variantChoices);
400
+ updateDataFromVariant(variant);
401
+ }
402
+ };
403
+ const resetSelections = () => {
404
+ selectedChoices.set({});
405
+ selectedQuantity.set(1); // Reset quantity when resetting selections
406
+ };
407
+ // Quantity management methods
408
+ const setSelectedQuantity = (quantity) => {
409
+ const maxQuantity = quantityAvailable.get();
410
+ const validQuantity = Math.max(1, Math.min(quantity, maxQuantity || 999));
411
+ selectedQuantity.set(validQuantity);
412
+ };
413
+ const incrementQuantity = () => {
414
+ const current = selectedQuantity.get();
415
+ const maxQuantity = quantityAvailable.get();
416
+ const newQuantity = Math.min(current + 1, maxQuantity || 999);
417
+ selectedQuantity.set(newQuantity);
418
+ };
419
+ const decrementQuantity = () => {
420
+ const current = selectedQuantity.get();
421
+ const newQuantity = Math.max(1, current - 1);
422
+ selectedQuantity.set(newQuantity);
423
+ };
424
+ // New methods for smart variant selection
425
+ const getAvailableChoicesForOption = (optionName) => {
426
+ const currentChoices = selectedChoices.get();
427
+ const variantsList = variants.get();
428
+ // Get all possible choices for this option that result in valid variants
429
+ const availableChoices = new Set();
430
+ variantsList.forEach(variant => {
431
+ const variantChoices = processVariantChoices(variant);
432
+ // Check if this variant matches all currently selected choices (except for the option we're checking)
433
+ const matchesOtherChoices = Object.entries(currentChoices)
434
+ .filter(([key]) => key !== optionName)
435
+ .every(([key, value]) => variantChoices[key] === value);
436
+ if (matchesOtherChoices && variantChoices[optionName]) {
437
+ availableChoices.add(variantChoices[optionName]);
438
+ }
439
+ });
440
+ return Array.from(availableChoices);
441
+ };
442
+ // Core method that provides both availability and stock info efficiently
443
+ const getChoiceInfo = (optionName, choiceValue) => {
444
+ // Create hypothetical choices with this choice selected
445
+ const currentChoices = selectedChoices.get();
446
+ const hypotheticalChoices = {
447
+ ...currentChoices,
448
+ [optionName]: choiceValue,
449
+ };
450
+ // Get all variants and find one that matches these choices
451
+ const variantsList = variants.get();
452
+ const matchingVariants = variantsList.filter(variant => {
453
+ if (!variant.choices)
454
+ return false;
455
+ const variantChoices = {};
456
+ for (const choice of variant.choices) {
457
+ if (choice.optionChoiceNames?.optionName &&
458
+ choice.optionChoiceNames?.choiceName) {
459
+ variantChoices[choice.optionChoiceNames.optionName] =
460
+ choice.optionChoiceNames.choiceName;
461
+ }
462
+ }
463
+ // Check if this variant matches our hypothetical choices
464
+ return Object.entries(hypotheticalChoices).every(([key, value]) => variantChoices[key] === value);
465
+ });
466
+ const isAvailable = matchingVariants.length > 0;
467
+ // Check if ANY of the matching variants are in stock
468
+ const isInStock = matchingVariants.some(variant => variant.inventoryStatus?.inStock === true);
469
+ // Check if ANY of the matching variants have pre-order enabled
470
+ const isPreOrderEnabled = matchingVariants.some(variant => variant.inventoryStatus?.preorderEnabled === true);
471
+ return { isAvailable, isInStock, isPreOrderEnabled };
472
+ };
473
+ // Simplified methods using the core getChoiceInfo
474
+ const isChoiceAvailable = (optionName, choiceValue) => {
475
+ return getChoiceInfo(optionName, choiceValue).isAvailable;
476
+ };
477
+ const isChoiceInStock = (optionName, choiceValue) => {
478
+ return getChoiceInfo(optionName, choiceValue).isInStock;
479
+ };
480
+ const isChoicePreOrderEnabled = (optionName, choiceValue) => {
481
+ return getChoiceInfo(optionName, choiceValue).isPreOrderEnabled;
482
+ };
483
+ const hasAnySelections = () => {
484
+ const currentChoices = selectedChoices.get();
485
+ return Object.keys(currentChoices).length > 0;
486
+ };
487
+ const IsAllVariantsAreOutOfStock = () => {
488
+ const variantsList = variants.get();
489
+ // All variants must be out of stock AND none should have preorder enabled
490
+ return (variantsList?.every(variant => !variant.inventoryStatus?.inStock &&
491
+ !variant.inventoryStatus?.preorderEnabled) ?? true);
492
+ };
493
+ return {
494
+ selectedChoices,
495
+ selectedVariantId,
496
+ currentVariant,
497
+ currentPrice,
498
+ currentCompareAtPrice,
499
+ isInStock,
500
+ isPreOrderEnabled,
501
+ preOrderMessage,
502
+ isLoading,
503
+ error,
504
+ variants,
505
+ options,
506
+ basePrice,
507
+ discountPrice,
508
+ isOnSale,
509
+ quantityAvailable,
510
+ trackQuantity,
511
+ selectedQuantity,
512
+ productId,
513
+ ribbonLabel,
514
+ setSelectedChoices,
515
+ addToCart,
516
+ setOption,
517
+ selectVariantById,
518
+ resetSelections,
519
+ // New methods for smart variant selection
520
+ getAvailableChoicesForOption,
521
+ getChoiceInfo,
522
+ isChoiceAvailable,
523
+ isChoiceInStock,
524
+ isChoicePreOrderEnabled,
525
+ hasAnySelections,
526
+ // Quantity management methods
527
+ setSelectedQuantity,
528
+ incrementQuantity,
529
+ decrementQuantity,
530
+ selectedVariant,
531
+ finalPrice,
532
+ isLowStock,
533
+ product,
534
+ productOptions,
535
+ currency,
536
+ IsAllVariantsAreOutOfStock,
537
+ };
538
+ });
@@ -0,0 +1,41 @@
1
+ import { type ServiceFactoryConfig } from '@wix/services-definitions';
2
+ import type { Signal } from '../../Signal';
3
+ export interface SharingPlatform {
4
+ name: string;
5
+ icon: string;
6
+ color: string;
7
+ shareUrl: string;
8
+ }
9
+ export interface SocialSharingServiceAPI {
10
+ availablePlatforms: Signal<SharingPlatform[]>;
11
+ shareCount: Signal<number>;
12
+ lastSharedPlatform: Signal<string | null>;
13
+ shareToFacebook: (url: string, title: string, description?: string) => void;
14
+ shareToTwitter: (url: string, text: string, hashtags?: string[]) => void;
15
+ shareToLinkedIn: (url: string, title: string, summary?: string) => void;
16
+ shareToWhatsApp: (url: string, text: string) => void;
17
+ shareToEmail: (url: string, subject: string, body: string) => void;
18
+ copyToClipboard: (url: string) => Promise<boolean>;
19
+ shareNative: (data: {
20
+ title: string;
21
+ text: string;
22
+ url: string;
23
+ }) => Promise<boolean>;
24
+ trackShare: (platform: string) => void;
25
+ }
26
+ export declare const SocialSharingServiceDefinition: string & {
27
+ __api: SocialSharingServiceAPI;
28
+ __config: {};
29
+ isServiceDefinition?: boolean;
30
+ } & SocialSharingServiceAPI;
31
+ export declare const SocialSharingService: import("@wix/services-definitions").ServiceFactory<string & {
32
+ __api: SocialSharingServiceAPI;
33
+ __config: {};
34
+ isServiceDefinition?: boolean;
35
+ } & SocialSharingServiceAPI, {
36
+ productName: string;
37
+ productUrl: string;
38
+ productDescription?: string;
39
+ productImage?: string;
40
+ }, import("@wix/services-definitions").ThreadMode.MAIN>;
41
+ export declare function loadSocialSharingServiceConfig(productName: string, productUrl: string, productDescription?: string, productImage?: string): Promise<ServiceFactoryConfig<typeof SocialSharingService>>;