@foxy.io/elements 1.35.0-beta.1 → 1.35.0-beta.2

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 (52) hide show
  1. package/dist/cdn/foxy-admin-subscription-form.js +1 -1
  2. package/dist/cdn/foxy-cart-form.js +1 -1
  3. package/dist/cdn/foxy-coupon-code-form.js +1 -1
  4. package/dist/cdn/foxy-coupon-form.js +1 -1
  5. package/dist/cdn/foxy-customer-portal.js +1 -1
  6. package/dist/cdn/foxy-email-template-form.js +1 -1
  7. package/dist/cdn/foxy-experimental-add-to-cart-builder.js +1 -1
  8. package/dist/cdn/foxy-gift-card-code-form.js +1 -1
  9. package/dist/cdn/foxy-gift-card-form.js +1 -1
  10. package/dist/cdn/foxy-item-category-form.js +1 -1
  11. package/dist/cdn/foxy-item-form.js +1 -1
  12. package/dist/cdn/foxy-item-option-form.js +1 -1
  13. package/dist/cdn/foxy-payments-api-fraud-protection-form.js +1 -1
  14. package/dist/cdn/foxy-payments-api-payment-method-form.js +1 -1
  15. package/dist/cdn/foxy-payments-api-payment-preset-form.js +1 -1
  16. package/dist/cdn/foxy-store-form.js +1 -1
  17. package/dist/cdn/foxy-store-shipping-method-form.js +1 -1
  18. package/dist/cdn/foxy-subscription-settings-form.js +1 -1
  19. package/dist/cdn/foxy-template-config-form.js +1 -1
  20. package/dist/cdn/foxy-template-form.js +1 -1
  21. package/dist/cdn/foxy-transaction.js +1 -1
  22. package/dist/cdn/foxy-user-invitation-form.js +1 -1
  23. package/dist/cdn/foxy-webhook-form.js +1 -1
  24. package/dist/cdn/shared-44118acb.js +1 -0
  25. package/dist/cdn/translations/experimental-add-to-cart-builder/en.json +445 -432
  26. package/dist/elements/internal/InternalSummaryControl/InternalSummaryControl.d.ts +1 -1
  27. package/dist/elements/internal/InternalSummaryControl/InternalSummaryControl.js +3 -3
  28. package/dist/elements/internal/InternalSummaryControl/InternalSummaryControl.js.map +1 -1
  29. package/dist/elements/public/CustomerPortal/InternalCustomerPortalLoggedOutView.js +1 -0
  30. package/dist/elements/public/CustomerPortal/InternalCustomerPortalLoggedOutView.js.map +1 -1
  31. package/dist/elements/public/ExperimentalAddToCartBuilder/ExperimentalAddToCartBuilder.d.ts +6 -0
  32. package/dist/elements/public/ExperimentalAddToCartBuilder/ExperimentalAddToCartBuilder.js +200 -123
  33. package/dist/elements/public/ExperimentalAddToCartBuilder/ExperimentalAddToCartBuilder.js.map +1 -1
  34. package/dist/elements/public/ExperimentalAddToCartBuilder/index.d.ts +2 -0
  35. package/dist/elements/public/ExperimentalAddToCartBuilder/index.js +2 -0
  36. package/dist/elements/public/ExperimentalAddToCartBuilder/index.js.map +1 -1
  37. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionCard/InternalExperimentalAddToCartBuilderCustomOptionCard.js +2 -2
  38. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionCard/InternalExperimentalAddToCartBuilderCustomOptionCard.js.map +1 -1
  39. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionCard/types.d.ts +1 -1
  40. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionCard/types.js.map +1 -1
  41. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionForm/InternalExperimentalAddToCartBuilderCustomOptionForm.d.ts +2 -1
  42. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionForm/InternalExperimentalAddToCartBuilderCustomOptionForm.js +50 -49
  43. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionForm/InternalExperimentalAddToCartBuilderCustomOptionForm.js.map +1 -1
  44. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionForm/types.d.ts +1 -1
  45. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderCustomOptionForm/types.js.map +1 -1
  46. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderItemControl/InternalExperimentalAddToCartBuilderItemControl.d.ts +4 -0
  47. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderItemControl/InternalExperimentalAddToCartBuilderItemControl.js +109 -91
  48. package/dist/elements/public/ExperimentalAddToCartBuilder/internal/InternalExperimentalAddToCartBuilderItemControl/InternalExperimentalAddToCartBuilderItemControl.js.map +1 -1
  49. package/dist/elements/public/ExperimentalAddToCartBuilder/types.d.ts +30 -27
  50. package/dist/elements/public/ExperimentalAddToCartBuilder/types.js.map +1 -1
  51. package/package.json +3 -2
  52. package/dist/cdn/shared-19cd0786.js +0 -1
@@ -1,5 +1,6 @@
1
1
  import { TranslatableMixin } from "../../../mixins/translatable.js";
2
2
  import { ResponsiveMixin } from "../../../mixins/responsive.js";
3
+ import { BooleanSelector } from '@foxy.io/sdk/core';
3
4
  import { decode, encode } from 'html-entities';
4
5
  import { InternalForm } from "../../internal/InternalForm/InternalForm.js";
5
6
  import { previewCSS } from './preview.css';
@@ -30,6 +31,16 @@ export class ExperimentalAddToCartBuilder extends Base {
30
31
  /** URL of the store this add-to-cart code is created for. */
31
32
  this.store = null;
32
33
  this.__signingSeparator = `--${Date.now()}${(Math.random() * 100000).toFixed(0)}--`;
34
+ this.__emptyOptions = [
35
+ { label: 'option_false', value: 'false' },
36
+ { label: 'option_true', value: 'true' },
37
+ { label: 'option_reset', value: 'reset' },
38
+ ];
39
+ this.__cartOptions = [
40
+ { label: 'option_add', value: 'add' },
41
+ { label: 'option_checkout', value: 'checkout' },
42
+ { label: 'option_redirect', value: 'redirect' },
43
+ ];
33
44
  this.__signAsync = debounce(async (html, encodeHelper) => {
34
45
  if (html === this.__previousUnsignedCode && this.__previousSignedCode)
35
46
  return;
@@ -77,21 +88,26 @@ export class ExperimentalAddToCartBuilder extends Base {
77
88
  __openState: { attribute: false },
78
89
  };
79
90
  }
91
+ get hiddenSelector() {
92
+ const alwaysMatch = [super.hiddenSelector.toString()];
93
+ alwaysMatch.unshift('header:copy-id', 'header:copy-json', 'undo');
94
+ return new BooleanSelector(alwaysMatch.join(' ').trim());
95
+ }
80
96
  renderBody() {
81
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
97
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
82
98
  const addToCartCode = this.__getAddToCartCode();
83
99
  const storeUrl = (_c = (_b = (_a = this.data) === null || _a === void 0 ? void 0 : _a._links['fx:store'].href) !== null && _b !== void 0 ? _b : this.store) !== null && _c !== void 0 ? _c : void 0;
84
100
  const store = (_d = this.__storeLoader) === null || _d === void 0 ? void 0 : _d.data;
85
101
  return html `
86
102
  <div class="grid gap-m items-start sm-grid-cols-2 md-grid-cols-3 h-full overflow-auto">
87
- <div class="space-y-m">
103
+ <foxy-internal-summary-control layout="section" class="space-y-s" infer="items">
88
104
  ${(_e = this.form.items) === null || _e === void 0 ? void 0 : _e.map((product, index) => {
89
105
  var _a;
90
106
  return html `
91
107
  <foxy-internal-summary-control
92
108
  layout="details"
93
109
  label=${ifDefined(product.name.trim() || void 0)}
94
- infer="item"
110
+ infer="item-group"
95
111
  ?open=${ifDefined(this.__openState[index])}
96
112
  @toggle=${(evt) => {
97
113
  const details = evt.currentTarget;
@@ -104,7 +120,8 @@ export class ExperimentalAddToCartBuilder extends Base {
104
120
  currency-code=${ifDefined((_a = this.__resolvedCurrencyCode) !== null && _a !== void 0 ? _a : void 0)}
105
121
  store=${ifDefined(storeUrl)}
106
122
  index=${index}
107
- infer=""
123
+ infer="item"
124
+ .defaultItemCategory=${this.__defaultItemCategory}
108
125
  @remove=${() => {
109
126
  var _a;
110
127
  const newProducts = (_a = this.form.items) === null || _a === void 0 ? void 0 : _a.filter((_, i) => i !== index);
@@ -119,10 +136,11 @@ export class ExperimentalAddToCartBuilder extends Base {
119
136
 
120
137
  <vaadin-button
121
138
  class="w-full"
139
+ theme="success"
122
140
  ?disabled=${this.disabled}
123
141
  @click=${() => {
124
142
  var _a;
125
- const newItem = { name: '', price: 0, custom_options: [] };
143
+ const newItem = { name: '', price: 0, custom_options: [], sub_frequency: '1m' };
126
144
  const existingItems = (_a = this.form.items) !== null && _a !== void 0 ? _a : [];
127
145
  this.edit({ items: [...existingItems, newItem] });
128
146
  this.__openState = [...new Array(existingItems.length).fill(false), true];
@@ -130,7 +148,7 @@ export class ExperimentalAddToCartBuilder extends Base {
130
148
  >
131
149
  <foxy-i18n infer="add-product" key="caption"></foxy-i18n>
132
150
  </vaadin-button>
133
- </div>
151
+ </foxy-internal-summary-control>
134
152
 
135
153
  <div class="space-y-m md-col-span-2 sticky top-0">
136
154
  ${addToCartCode
@@ -212,66 +230,71 @@ export class ExperimentalAddToCartBuilder extends Base {
212
230
  </foxy-internal-summary-control>
213
231
 
214
232
  <foxy-internal-summary-control infer="link">
215
- <div
216
- class="flex items-center leading-s min-w-0 relative"
217
- style="gap: calc(0.625em + (var(--lumo-border-radius) / 4) - 1px)"
218
- >
219
- <foxy-i18n infer="" key="direct_link"></foxy-i18n>
220
-
221
- <a
222
- target="_blank"
223
- style="max-width: 30rem"
224
- href=${addToCartCode.linkHref}
225
- class=${classMap({
226
- 'font-medium truncate ml-auto min-w-0 rounded-s': true,
227
- 'transition-all filter': true,
228
- 'hover-underline': true,
229
- 'focus-outline-none focus-ring-2 focus-ring-primary-50': true,
230
- 'blur-sm': this.__signingState !== 'idle',
231
- })}
232
- >
233
- ${addToCartCode.linkHref}
234
- </a>
235
-
236
- <div
237
- style="top: calc(0.625em + (var(--lumo-border-radius) / 4) - 1px); right: calc(0.625em + (var(--lumo-border-radius) / 4) - 1px)"
238
- class=${classMap({
239
- 'absolute right-0 bg-base rounded-s transition-opacity': true,
240
- 'opacity-0 pointer-events-none': this.__signingState !== 'busy',
241
- })}
242
- >
243
- <div class="bg-contrast-10 rounded-s">
244
- <foxy-spinner
245
- infer="spinner"
246
- state=${this.__signingState === 'fail' ? 'error' : 'busy'}
247
- class="-mx-xs"
248
- style="transform: scale(0.8)"
233
+ ${addToCartCode.linkHref
234
+ ? html `
235
+ <div
236
+ class="flex items-center leading-s min-w-0 relative"
237
+ style="gap: calc(0.625em + (var(--lumo-border-radius) / 4) - 1px)"
249
238
  >
250
- </foxy-spinner>
251
- </div>
252
- </div>
253
-
254
- <foxy-copy-to-clipboard
255
- infer="copy-to-clipboard"
256
- text=${addToCartCode.linkHref}
257
- class=${classMap({
258
- 'flex-shrink-0 text-m transition-opacity': true,
259
- 'opacity-0 pointer-events-none': this.__signingState === 'busy',
260
- })}
261
- >
262
- </foxy-copy-to-clipboard>
263
- </div>
239
+ <foxy-i18n infer="" key="direct_link"></foxy-i18n>
240
+ <a
241
+ target="_blank"
242
+ style="max-width: 30rem"
243
+ href=${addToCartCode.linkHref}
244
+ class=${classMap({
245
+ 'font-medium truncate ml-auto min-w-0 rounded-s': true,
246
+ 'transition-all filter': true,
247
+ 'hover-underline': true,
248
+ 'focus-outline-none focus-ring-2 focus-ring-primary-50': true,
249
+ 'blur-sm': this.__signingState !== 'idle',
250
+ })}
251
+ >
252
+ ${addToCartCode.linkHref}
253
+ </a>
254
+ <div
255
+ style="top: calc(0.625em + (var(--lumo-border-radius) / 4) - 1px); right: calc(0.625em + (var(--lumo-border-radius) / 4) - 1px)"
256
+ class=${classMap({
257
+ 'absolute right-0 bg-base rounded-s transition-opacity': true,
258
+ 'opacity-0 pointer-events-none': this.__signingState !== 'busy',
259
+ })}
260
+ >
261
+ <div class="bg-contrast-10 rounded-s">
262
+ <foxy-spinner
263
+ infer="spinner"
264
+ state=${this.__signingState === 'fail' ? 'error' : 'busy'}
265
+ class="-mx-xs"
266
+ style="transform: scale(0.8)"
267
+ >
268
+ </foxy-spinner>
269
+ </div>
270
+ </div>
271
+ <foxy-copy-to-clipboard
272
+ infer="copy-to-clipboard"
273
+ text=${addToCartCode.linkHref}
274
+ class=${classMap({
275
+ 'flex-shrink-0 text-m transition-opacity': true,
276
+ 'opacity-0 pointer-events-none': this.__signingState === 'busy',
277
+ })}
278
+ >
279
+ </foxy-copy-to-clipboard>
280
+ </div>
281
+ `
282
+ : html `
283
+ <p class="text-disabled">
284
+ <foxy-i18n infer="" key="unavailable"></foxy-i18n>
285
+ </p>
286
+ `}
264
287
  </foxy-internal-summary-control>
265
288
  `
266
289
  : html `
267
290
  <foxy-internal-summary-control infer="preview">
268
291
  <div class="flex items-center justify-center p-xl">
269
- <foxy-spinner infer="unavailable" state="empty"></foxy-spinner>
292
+ <foxy-spinner infer="unavailable"></foxy-spinner>
270
293
  </div>
271
294
  </foxy-internal-summary-control>
272
295
  `}
273
296
 
274
- <foxy-internal-summary-control infer="cart-settings-group">
297
+ <foxy-internal-summary-control infer="cart-settings">
275
298
  <foxy-internal-resource-picker-control
276
299
  layout="summary-item"
277
300
  first=${ifDefined((_g = (_f = this.__storeLoader) === null || _f === void 0 ? void 0 : _f.data) === null || _g === void 0 ? void 0 : _g._links['fx:template_sets'].href)}
@@ -283,21 +306,26 @@ export class ExperimentalAddToCartBuilder extends Base {
283
306
  <foxy-internal-select-control
284
307
  layout="summary-item"
285
308
  infer="empty"
286
- .options=${[
287
- { label: 'option_false', value: 'false' },
288
- { label: 'option_true', value: 'true' },
289
- { label: 'option_reset', value: 'reset' },
290
- ]}
309
+ .options=${this.__emptyOptions}
291
310
  >
292
311
  </foxy-internal-select-control>
293
312
 
294
- <foxy-internal-switch-control
295
- false-alias="add"
296
- true-alias="checkout"
313
+ <foxy-internal-select-control
297
314
  layout="summary-item"
298
315
  infer="cart"
316
+ .options=${this.__cartOptions}
299
317
  >
300
- </foxy-internal-switch-control>
318
+ </foxy-internal-select-control>
319
+
320
+ ${this.form.cart === 'redirect'
321
+ ? html `
322
+ <foxy-internal-text-control layout="summary-item" infer="redirect">
323
+ </foxy-internal-text-control>
324
+ `
325
+ : ''}
326
+
327
+ <foxy-internal-text-control layout="summary-item" infer="coupon">
328
+ </foxy-internal-text-control>
301
329
  </foxy-internal-summary-control>
302
330
  </div>
303
331
  </div>
@@ -314,7 +342,16 @@ export class ExperimentalAddToCartBuilder extends Base {
314
342
  <foxy-nucleon
315
343
  class="hidden"
316
344
  infer=""
317
- href=${ifDefined(this.localeCodes)}
345
+ href=${ifDefined(this.__defaultItemCategoryHref)}
346
+ id="defaultItemCategoryLoader"
347
+ @update=${() => this.requestUpdate()}
348
+ >
349
+ </foxy-nucleon>
350
+
351
+ <foxy-nucleon
352
+ class="hidden"
353
+ infer=""
354
+ href=${ifDefined((_h = this.localeCodes) !== null && _h !== void 0 ? _h : void 0)}
318
355
  id="localeCodesHelperLoader"
319
356
  @update=${() => this.requestUpdate()}
320
357
  >
@@ -323,7 +360,7 @@ export class ExperimentalAddToCartBuilder extends Base {
323
360
  <foxy-nucleon
324
361
  class="hidden"
325
362
  infer=""
326
- href=${ifDefined((_h = this.form.template_set_uri) !== null && _h !== void 0 ? _h : void 0)}
363
+ href=${ifDefined((_j = this.form.template_set_uri) !== null && _j !== void 0 ? _j : void 0)}
327
364
  id="templateSetLoader"
328
365
  @update=${() => this.requestUpdate()}
329
366
  >
@@ -332,29 +369,31 @@ export class ExperimentalAddToCartBuilder extends Base {
332
369
  <foxy-nucleon
333
370
  class="hidden"
334
371
  infer=""
335
- href=${ifDefined((_l = (_k = (_j = this.data) === null || _j === void 0 ? void 0 : _j._links['fx:store'].href) !== null && _k !== void 0 ? _k : this.store) !== null && _l !== void 0 ? _l : void 0)}
372
+ href=${ifDefined((_m = (_l = (_k = this.data) === null || _k === void 0 ? void 0 : _k._links['fx:store'].href) !== null && _l !== void 0 ? _l : this.store) !== null && _m !== void 0 ? _m : void 0)}
336
373
  id="storeLoaderId"
337
374
  @update=${() => this.requestUpdate()}
338
375
  >
339
376
  </foxy-nucleon>
340
377
 
341
- ${(_m = this.form.items) === null || _m === void 0 ? void 0 : _m.map((product, index) => {
378
+ ${(_o = this.form.items) === null || _o === void 0 ? void 0 : _o.map((product, index) => {
379
+ var _a;
342
380
  return html `
343
381
  <foxy-nucleon
344
382
  class="hidden"
345
383
  infer=""
346
- href=${ifDefined(product.item_category_uri)}
384
+ href=${ifDefined((_a = product.item_category_uri) !== null && _a !== void 0 ? _a : void 0)}
347
385
  id="itemCategoryLoaderProduct${index}"
348
386
  @update=${() => this.requestUpdate()}
349
387
  >
350
388
  </foxy-nucleon>
351
389
 
352
390
  ${product.custom_options.map((option, i) => {
391
+ var _a;
353
392
  return html `
354
393
  <foxy-nucleon
355
394
  class="hidden"
356
395
  infer=""
357
- href=${ifDefined(option.item_category_uri)}
396
+ href=${ifDefined((_a = option.item_category_uri) !== null && _a !== void 0 ? _a : void 0)}
358
397
  id="itemCategoryLoaderProduct${index}Option${i}"
359
398
  @update=${() => this.requestUpdate()}
360
399
  >
@@ -369,7 +408,7 @@ export class ExperimentalAddToCartBuilder extends Base {
369
408
  var _a, _b;
370
409
  super.updated(changes);
371
410
  if (this.in('idle') && !((_a = this.form.items) === null || _a === void 0 ? void 0 : _a.length)) {
372
- this.edit({ items: [{ name: '', price: 0, custom_options: [] }] });
411
+ this.edit({ items: [{ name: '', price: 0, sub_frequency: '1m', custom_options: [] }] });
373
412
  this.__openState = [true];
374
413
  }
375
414
  if (((_b = this.form.items) === null || _b === void 0 ? void 0 : _b.length) && !this.__openState.length) {
@@ -377,7 +416,7 @@ export class ExperimentalAddToCartBuilder extends Base {
377
416
  }
378
417
  }
379
418
  submit() {
380
- // Do nothing – in this version of the element, this form is not meant to be submitted.
419
+ // Do nothing – this form is not meant to be submitted.
381
420
  }
382
421
  get __defaultTemplateSetHref() {
383
422
  var _a, _b, _c;
@@ -390,6 +429,17 @@ export class ExperimentalAddToCartBuilder extends Base {
390
429
  return undefined;
391
430
  }
392
431
  }
432
+ get __defaultItemCategoryHref() {
433
+ var _a, _b, _c;
434
+ try {
435
+ const url = new URL((_c = (_b = (_a = this.__storeLoader) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b._links['fx:item_categories'].href) !== null && _c !== void 0 ? _c : '');
436
+ url.searchParams.set('code', 'DEFAULT');
437
+ return url.toString();
438
+ }
439
+ catch (_d) {
440
+ return undefined;
441
+ }
442
+ }
393
443
  get __resolvedCurrencyCode() {
394
444
  var _a, _b, _c, _d;
395
445
  const localeCodesLoader = this.renderRoot.querySelector('#localeCodesHelperLoader');
@@ -403,6 +453,10 @@ export class ExperimentalAddToCartBuilder extends Base {
403
453
  const $ = (s) => this.renderRoot.querySelector(s);
404
454
  return ((_b = (_a = $('#templateSetLoader')) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : (_d = (_c = $('#defaultTemplateSetLoader')) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d._embedded['fx:template_sets'][0]);
405
455
  }
456
+ get __defaultItemCategory() {
457
+ var _a, _b;
458
+ return (_b = (_a = this.renderRoot.querySelector('#defaultItemCategoryLoader')) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b._embedded['fx:item_categories'][0];
459
+ }
406
460
  get __resolvedCartUrl() {
407
461
  var _a;
408
462
  const store = (_a = this.__storeLoader) === null || _a === void 0 ? void 0 : _a.data;
@@ -425,13 +479,14 @@ export class ExperimentalAddToCartBuilder extends Base {
425
479
  return this.renderRoot.querySelector(selector);
426
480
  }
427
481
  __getAddToCartFormHTML() {
428
- var _a, _b, _c, _d, _e, _f, _g;
482
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
429
483
  const currencyCode = this.__resolvedCurrencyCode;
430
484
  const templateSet = this.__resolvedTemplateSet;
431
485
  const cartUrl = this.__resolvedCartUrl;
432
486
  const store = (_a = this.__storeLoader) === null || _a === void 0 ? void 0 : _a.data;
433
487
  if (!this.defaultDomain || !templateSet || !store || !currencyCode || !cartUrl)
434
488
  return '';
489
+ let hasAtLeastOneFieldset = false;
435
490
  let output = `<form action="${encode(cartUrl)}" method="post" target="_blank">`;
436
491
  let level = 1;
437
492
  const newline = () => `\n${' '.repeat(level * 2)}`;
@@ -442,43 +497,50 @@ export class ExperimentalAddToCartBuilder extends Base {
442
497
  };
443
498
  if (templateSet.code !== 'DEFAULT')
444
499
  addHiddenInput('template_set', templateSet.code);
445
- if (this.form.empty)
500
+ if (this.form.empty && this.form.empty !== 'false')
446
501
  addHiddenInput('empty', this.form.empty);
447
502
  if (this.form.cart === 'checkout')
448
503
  addHiddenInput('cart', 'checkout');
504
+ if (this.form.redirect)
505
+ addHiddenInput('redirect', this.form.redirect);
506
+ if (this.form.coupon)
507
+ addHiddenInput('coupon', this.form.coupon);
449
508
  const items = (_b = this.form.items) !== null && _b !== void 0 ? _b : [];
450
509
  const hasMoreThanOneProduct = items.length > 1;
451
510
  for (let productIndex = 0; productIndex < items.length; ++productIndex) {
452
511
  const itemCategoryLoader = this.__getItemCategoryLoader(productIndex);
453
512
  const itemCategory = itemCategoryLoader === null || itemCategoryLoader === void 0 ? void 0 : itemCategoryLoader.data;
454
513
  const product = items[productIndex];
455
- if (!product.name || !product.price)
456
- return '';
457
514
  if (product.item_category_uri && !itemCategory)
458
515
  return '';
459
- const hasConfigurableQuantity = product.quantity_min !== product.quantity_max;
460
- const hasConfigurablePrice = product.price_configurable;
461
- const hasConfigurableOptions = product.custom_options.some((v, i, a) => v.value_configurable || a.findIndex(vv => vv.name === v.name) !== i);
462
- const useFieldset = hasMoreThanOneProduct &&
463
- (hasConfigurablePrice || hasConfigurableQuantity || hasConfigurableOptions);
464
- if (useFieldset) {
516
+ const resolvedMinQty = Math.max(1, (_c = product.quantity_min) !== null && _c !== void 0 ? _c : 1);
517
+ const resolvedMaxQty = Math.max(resolvedMinQty, (_d = product.quantity_max) !== null && _d !== void 0 ? _d : Infinity);
518
+ const varyQty = resolvedMinQty !== resolvedMaxQty &&
519
+ product.expires_format !== 'minutes' &&
520
+ !product.hide_quantity;
521
+ const varyPrice = product.price_configurable;
522
+ const varyptions = product.custom_options.some((v, i, a) => v.value_configurable || a.findIndex(vv => vv.name === v.name) !== i);
523
+ const resolvedName = product.name.trim() || this.t('items.item-group.item.basics-group.name.placeholder');
524
+ const needsFieldset = hasAtLeastOneFieldset || (hasMoreThanOneProduct && (varyPrice || varyQty || varyptions));
525
+ if (needsFieldset) {
526
+ hasAtLeastOneFieldset = true;
465
527
  output += `${newline()}<fieldset>`;
466
528
  level++;
467
- output += `${newline()}<legend>${encode(product.name)}</legend>`;
529
+ output += `${newline()}<legend>${encode(resolvedName)}</legend>`;
468
530
  }
469
531
  const prefix = productIndex === 0 ? '' : `${productIndex + 1}:`;
470
- addHiddenInput(`${prefix}name`, product.name);
532
+ addHiddenInput(`${prefix}name`, resolvedName);
471
533
  const price = `${product.price}${currencyCode}`;
472
534
  if (product.price_configurable) {
473
- const encodedPrice = encode(price);
535
+ const encodedNoCurrencyPrice = encode(product.price.toFixed(2));
474
536
  output += `${newline()}<label>`;
475
537
  level++;
476
538
  output += `${newline()}<span>${encode(this.t('preview.price_label'))}</span>`;
477
539
  if (store.use_cart_validation) {
478
- output += `${newline()}<input required name="${prefix}price" value="--OPEN--" data-replace="${encodedPrice}">`;
540
+ output += `${newline()}<input required name="${prefix}price" value="--OPEN--" data-replace="${encodedNoCurrencyPrice}">`;
479
541
  }
480
542
  else {
481
- output += `${newline()}<input required name="${prefix}price" value="${encodedPrice}">`;
543
+ output += `${newline()}<input required name="${prefix}price" value="${encodedNoCurrencyPrice}">`;
482
544
  }
483
545
  level--;
484
546
  output += `${newline()}</label>`;
@@ -522,7 +584,7 @@ export class ExperimentalAddToCartBuilder extends Base {
522
584
  addHiddenInput(`${prefix}sub_enddate`, `${year}${month}${day}`);
523
585
  }
524
586
  else {
525
- addHiddenInput(`${prefix}sub_enddate`, product.sub_enddate);
587
+ addHiddenInput(`${prefix}sub_enddate`, String(product.sub_enddate));
526
588
  }
527
589
  }
528
590
  }
@@ -532,41 +594,38 @@ export class ExperimentalAddToCartBuilder extends Base {
532
594
  }
533
595
  if (product.expires_value) {
534
596
  if (product.expires_format === 'timestamp') {
535
- addHiddenInput(`${prefix}expires`, (product.expires_value / 1000).toFixed(0));
597
+ addHiddenInput(`${prefix}expires`, product.expires_value.toFixed(0));
536
598
  }
537
599
  else {
538
600
  addHiddenInput(`${prefix}expires`, product.expires_value.toFixed(0));
539
601
  }
540
602
  }
541
- if (product.quantity_min || product.quantity_max) {
603
+ if (varyQty) {
542
604
  output += `${newline()}<label>`;
543
605
  level++;
544
606
  output += `${newline()}<span>${encode(this.t('preview.quantity_label'))}</span>`;
545
607
  output += `${newline()}<input type="number" name="${encode(`${prefix}quantity`)}"`;
546
- if (product.expires_format !== 'minutes') {
547
- if (product.quantity_min)
548
- output += ` min="${encode(String(product.quantity_min))}"`;
549
- if (product.quantity_max)
550
- output += ` max="${encode(String(product.quantity_max))}"`;
551
- }
608
+ output += ` min="${encode(String(resolvedMinQty))}"`;
609
+ if (resolvedMaxQty !== Infinity)
610
+ output += ` max="${encode(String(resolvedMaxQty))}"`;
552
611
  if (store.use_cart_validation) {
553
- output += ` value="--OPEN--" data-replace="${encode(String((_c = product.quantity) !== null && _c !== void 0 ? _c : 1))}">`;
612
+ output += ` value="--OPEN--" data-replace="${encode(String((_e = product.quantity) !== null && _e !== void 0 ? _e : 1))}">`;
554
613
  }
555
614
  else {
556
- output += ` value="${encode(String((_d = product.quantity) !== null && _d !== void 0 ? _d : 1))}">`;
615
+ output += ` value="${encode(String((_f = product.quantity) !== null && _f !== void 0 ? _f : 1))}">`;
557
616
  }
558
617
  level--;
559
618
  output += `${newline()}</label>`;
560
619
  }
561
- else if (((_e = product.quantity) !== null && _e !== void 0 ? _e : 1) > 1) {
562
- addHiddenInput(`${prefix}quantity`, ((_f = product.quantity) !== null && _f !== void 0 ? _f : 1).toString());
620
+ else if (((_g = product.quantity) !== null && _g !== void 0 ? _g : 1) > 1) {
621
+ addHiddenInput(`${prefix}quantity`, ((_h = product.quantity) !== null && _h !== void 0 ? _h : 1).toString());
563
622
  }
564
623
  if (product.expires_format !== 'minutes') {
565
- if (product.quantity_min) {
566
- addHiddenInput(`${prefix}quantity_min`, product.quantity_min.toFixed(0));
624
+ if (resolvedMinQty !== 1) {
625
+ addHiddenInput(`${prefix}quantity_min`, resolvedMinQty.toFixed(0));
567
626
  }
568
- if (product.quantity_max) {
569
- addHiddenInput(`${prefix}quantity_max`, product.quantity_max.toFixed(0));
627
+ if (resolvedMaxQty !== Infinity) {
628
+ addHiddenInput(`${prefix}quantity_max`, resolvedMaxQty.toFixed(0));
570
629
  }
571
630
  }
572
631
  if (product.length)
@@ -600,7 +659,7 @@ export class ExperimentalAddToCartBuilder extends Base {
600
659
  const group = groupedCustomOptions[optionName];
601
660
  if (group.length === 1) {
602
661
  const optionIndex = product.custom_options.indexOf(group[0]);
603
- const itemCategory = (_g = this.__getItemCategoryLoader(productIndex, optionIndex)) === null || _g === void 0 ? void 0 : _g.data;
662
+ const itemCategory = (_j = this.__getItemCategoryLoader(productIndex, optionIndex)) === null || _j === void 0 ? void 0 : _j.data;
604
663
  const modifiers = this.__getOptionModifiers(group[0], itemCategory !== null && itemCategory !== void 0 ? itemCategory : null, currencyCode);
605
664
  const value = `${group[0].value}${modifiers}`;
606
665
  const name = `${prefix}${optionName}`;
@@ -643,7 +702,7 @@ export class ExperimentalAddToCartBuilder extends Base {
643
702
  output += `${newline()}</label>`;
644
703
  }
645
704
  }
646
- if (useFieldset) {
705
+ if (needsFieldset) {
647
706
  level--;
648
707
  output += `${newline()}</fieldset>`;
649
708
  }
@@ -655,7 +714,7 @@ export class ExperimentalAddToCartBuilder extends Base {
655
714
  return output;
656
715
  }
657
716
  __getAddToCartLinkHref() {
658
- var _a, _b, _c, _d, _e, _f;
717
+ var _a, _b, _c, _d, _e, _f, _g, _h;
659
718
  const currencyCode = this.__resolvedCurrencyCode;
660
719
  const templateSet = this.__resolvedTemplateSet;
661
720
  const cartUrl = this.__resolvedCartUrl;
@@ -665,16 +724,26 @@ export class ExperimentalAddToCartBuilder extends Base {
665
724
  const url = new URL(cartUrl);
666
725
  if (templateSet.code !== 'DEFAULT')
667
726
  url.searchParams.set('template_set', templateSet.code);
668
- if (this.form.empty)
669
- url.searchParams.set('empty', this.form.empty);
670
727
  if (this.form.cart === 'checkout')
671
728
  url.searchParams.set('cart', 'checkout');
729
+ if (this.form.redirect)
730
+ url.searchParams.set('redirect', this.form.redirect);
731
+ if (this.form.coupon)
732
+ url.searchParams.set('coupon', this.form.coupon);
733
+ if (this.form.empty && this.form.empty !== 'false') {
734
+ url.searchParams.set('empty', this.form.empty);
735
+ }
672
736
  for (let index = 0; index < ((_c = (_b = this.form.items) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0); ++index) {
673
737
  const product = this.form.items[index];
674
738
  const prefix = index === 0 ? '' : `${index + 1}:`;
675
739
  const itemCategory = (_d = this.__getItemCategoryLoader(index)) === null || _d === void 0 ? void 0 : _d.data;
676
740
  if (product.item_category_uri && !itemCategory)
677
741
  return '';
742
+ if (product.price_configurable)
743
+ return '';
744
+ if (new Set(product.custom_options.map(v => v.name)).size < product.custom_options.length) {
745
+ return '';
746
+ }
678
747
  if (itemCategory && itemCategory.code !== 'DEFAULT') {
679
748
  url.searchParams.set(`${prefix}category`, itemCategory.code);
680
749
  }
@@ -713,7 +782,7 @@ export class ExperimentalAddToCartBuilder extends Base {
713
782
  url.searchParams.set(`${prefix}sub_enddate`, `${year}${month}${day}`);
714
783
  }
715
784
  else {
716
- url.searchParams.set(`${prefix}sub_enddate`, product.sub_enddate);
785
+ url.searchParams.set(`${prefix}sub_enddate`, String(product.sub_enddate));
717
786
  }
718
787
  }
719
788
  }
@@ -723,7 +792,7 @@ export class ExperimentalAddToCartBuilder extends Base {
723
792
  }
724
793
  if (product.expires_value) {
725
794
  if (product.expires_format === 'timestamp') {
726
- url.searchParams.set(`${prefix}expires`, (product.expires_value / 1000).toFixed(0));
795
+ url.searchParams.set(`${prefix}expires`, product.expires_value.toFixed(0));
727
796
  }
728
797
  else {
729
798
  url.searchParams.set(`${prefix}expires`, product.expires_value.toFixed(0));
@@ -748,12 +817,14 @@ export class ExperimentalAddToCartBuilder extends Base {
748
817
  url.searchParams.set(`${prefix}width`, product.width.toFixed(3));
749
818
  if (product.height)
750
819
  url.searchParams.set(`${prefix}height`, product.height.toFixed(3));
751
- product.custom_options.forEach((option, optionIndex) => {
752
- var _a, _b;
753
- const itemCategory = (_a = this.__getItemCategoryLoader(index, optionIndex)) === null || _a === void 0 ? void 0 : _a.data;
820
+ for (let optionIndex = 0; optionIndex < product.custom_options.length; ++optionIndex) {
821
+ const option = product.custom_options[optionIndex];
822
+ if (option.value_configurable)
823
+ return '';
824
+ const itemCategory = (_g = this.__getItemCategoryLoader(index, optionIndex)) === null || _g === void 0 ? void 0 : _g.data;
754
825
  const modifiers = this.__getOptionModifiers(option, itemCategory !== null && itemCategory !== void 0 ? itemCategory : null, currencyCode);
755
- url.searchParams.set(`${prefix}${option.name}`, `${(_b = option.value) !== null && _b !== void 0 ? _b : ''}${modifiers}`);
756
- });
826
+ url.searchParams.set(`${prefix}${option.name}`, `${(_h = option.value) !== null && _h !== void 0 ? _h : ''}${modifiers}`);
827
+ }
757
828
  }
758
829
  return url.toString();
759
830
  }
@@ -764,15 +835,21 @@ export class ExperimentalAddToCartBuilder extends Base {
764
835
  return null;
765
836
  const formHTML = this.__getAddToCartFormHTML();
766
837
  const linkHref = this.__getAddToCartLinkHref();
767
- if (!formHTML || !linkHref)
838
+ if (!formHTML && !linkHref)
768
839
  return null;
769
- const linkHTML = `<a href="${encode(linkHref)}">Add to cart</a>`;
770
- const unsignedCode = `${formHTML}${this.__signingSeparator}${linkHTML}`;
840
+ let unsignedCode;
841
+ if (linkHref) {
842
+ const linkHTML = `<a href="${encode(linkHref)}">Add to cart</a>`;
843
+ unsignedCode = `${formHTML}${this.__signingSeparator}${linkHTML}`;
844
+ }
845
+ else {
846
+ unsignedCode = formHTML;
847
+ }
771
848
  if (unsignedCode === this.__previousUnsignedCode && this.__previousSignedCode) {
772
- const signedCode = this.__previousSignedCode.split(this.__signingSeparator);
849
+ const [formHTML, linkHTML] = this.__previousSignedCode.split(this.__signingSeparator);
773
850
  return {
774
- formHTML: signedCode[0],
775
- linkHref: decode(signedCode[1].substring(9, signedCode[1].length - 17)),
851
+ linkHref: linkHTML ? decode(linkHTML.substring(9, linkHTML.length - 17)) : '',
852
+ formHTML,
776
853
  };
777
854
  }
778
855
  this.__previousUnsignedCode = unsignedCode;