@foxy.io/elements 1.14.0-beta.8 → 1.14.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 (94) hide show
  1. package/dist/cdn/foxy-access-recovery-form.js +1 -1
  2. package/dist/cdn/foxy-address-card.js +1 -1
  3. package/dist/cdn/foxy-address-form.js +1 -1
  4. package/dist/cdn/foxy-applied-tax-card.js +1 -1
  5. package/dist/cdn/foxy-attribute-card.js +1 -1
  6. package/dist/cdn/foxy-attribute-form.js +1 -1
  7. package/dist/cdn/foxy-cancellation-form.js +1 -1
  8. package/dist/cdn/foxy-collection-page.js +1 -1
  9. package/dist/cdn/foxy-collection-pages.js +1 -1
  10. package/dist/cdn/foxy-custom-field-card.js +1 -1
  11. package/dist/cdn/foxy-custom-field-form.js +1 -1
  12. package/dist/cdn/foxy-customer-card.js +1 -1
  13. package/dist/cdn/foxy-customer-form.js +1 -1
  14. package/dist/cdn/foxy-customer-portal-settings.js +1 -1
  15. package/dist/cdn/foxy-customer-portal.js +18 -15
  16. package/dist/cdn/foxy-customer.js +1 -1
  17. package/dist/cdn/foxy-customers-table.js +1 -1
  18. package/dist/cdn/foxy-discount-card.js +1 -1
  19. package/dist/cdn/foxy-donation.js +1 -1
  20. package/dist/cdn/foxy-email-template-form.js +1 -1
  21. package/dist/cdn/foxy-error-entry-card.js +1 -1
  22. package/dist/cdn/foxy-form-dialog.js +1 -1
  23. package/dist/cdn/foxy-i18n.js +1 -1
  24. package/dist/cdn/foxy-items-form.js +1 -1
  25. package/dist/cdn/foxy-payment-card.js +1 -1
  26. package/dist/cdn/foxy-payment-method-card.js +1 -1
  27. package/dist/cdn/foxy-query-builder.js +1 -1
  28. package/dist/cdn/foxy-sign-in-form.js +1 -1
  29. package/dist/cdn/foxy-spinner.js +1 -1
  30. package/dist/cdn/foxy-subscription-card.js +1 -1
  31. package/dist/cdn/foxy-subscription-form.js +3 -3
  32. package/dist/cdn/foxy-subscriptions-table.js +1 -1
  33. package/dist/cdn/foxy-table.js +1 -1
  34. package/dist/cdn/foxy-tax-card.js +1 -1
  35. package/dist/cdn/foxy-tax-form.js +1 -1
  36. package/dist/cdn/foxy-template-config-form.js +1 -1
  37. package/dist/cdn/foxy-template-form.js +1 -1
  38. package/dist/cdn/foxy-transaction-card.js +1 -1
  39. package/dist/cdn/foxy-transactions-table.js +1 -1
  40. package/dist/cdn/foxy-user-form.js +1 -1
  41. package/dist/cdn/foxy-users-table.js +1 -1
  42. package/dist/cdn/{shared-4ba926ca.js → shared-07abcd7b.js} +1 -1
  43. package/dist/cdn/{shared-31d03530.js → shared-1f1734cb.js} +1 -1
  44. package/dist/cdn/{shared-ca7c3b9a.js → shared-322e60b1.js} +1 -1
  45. package/dist/cdn/{shared-7007dedb.js → shared-5f54e916.js} +1 -1
  46. package/dist/cdn/{shared-0f9809ab.js → shared-66cb6a36.js} +1 -1
  47. package/dist/cdn/{shared-a3d2c48e.js → shared-6ebe3825.js} +1 -1
  48. package/dist/cdn/{shared-5d94bacb.js → shared-74b9e1d1.js} +1 -1
  49. package/dist/cdn/{shared-00070cc4.js → shared-7a42073a.js} +5 -5
  50. package/dist/cdn/{shared-b24377bf.js → shared-8a7bee0d.js} +1 -1
  51. package/dist/cdn/{shared-da787055.js → shared-91e768be.js} +1 -1
  52. package/dist/cdn/{shared-d01035c5.js → shared-9a40309d.js} +1 -1
  53. package/dist/cdn/shared-9c099da6.js +1 -0
  54. package/dist/cdn/{shared-daf6b763.js → shared-b1fc5dc3.js} +1 -1
  55. package/dist/cdn/{shared-d05c93a5.js → shared-bc2bfe52.js} +1 -1
  56. package/dist/cdn/{shared-c5ae5d33.js → shared-ce1da35d.js} +1 -1
  57. package/dist/cdn/{shared-007c4e34.js → shared-f1dc1c6c.js} +1 -1
  58. package/dist/cdn/translations/shared/de.json +94 -0
  59. package/dist/cdn/translations/shared/en.json +83 -83
  60. package/dist/cdn/translations/shared/es.json +93 -0
  61. package/dist/elements/public/CustomerPortal/InternalCustomerPortalLink.d.ts +1 -0
  62. package/dist/elements/public/CustomerPortal/InternalCustomerPortalLink.js +17 -8
  63. package/dist/elements/public/CustomerPortal/InternalCustomerPortalLink.js.map +1 -1
  64. package/dist/elements/public/CustomerPortal/InternalCustomerPortalLoggedInView.js +19 -6
  65. package/dist/elements/public/CustomerPortal/InternalCustomerPortalLoggedInView.js.map +1 -1
  66. package/dist/elements/public/CustomerPortal/InternalCustomerPortalSubscriptions.js +11 -3
  67. package/dist/elements/public/CustomerPortal/InternalCustomerPortalSubscriptions.js.map +1 -1
  68. package/dist/elements/public/EmailTemplateForm/EmailTemplateForm.d.ts +21 -0
  69. package/dist/elements/public/EmailTemplateForm/EmailTemplateForm.js +21 -0
  70. package/dist/elements/public/EmailTemplateForm/EmailTemplateForm.js.map +1 -1
  71. package/dist/elements/public/I18n/I18n.js +1 -1
  72. package/dist/elements/public/I18n/I18n.js.map +1 -1
  73. package/dist/elements/public/ItemsForm/private/Picture.d.ts +1 -0
  74. package/dist/elements/public/ItemsForm/private/Picture.js +2 -0
  75. package/dist/elements/public/ItemsForm/private/Picture.js.map +1 -1
  76. package/dist/elements/public/SubscriptionForm/SubscriptionForm.js +12 -4
  77. package/dist/elements/public/SubscriptionForm/SubscriptionForm.js.map +1 -1
  78. package/dist/elements/public/TemplateConfigForm/CountriesList.d.ts +2 -4
  79. package/dist/elements/public/TemplateConfigForm/CountriesList.js +19 -20
  80. package/dist/elements/public/TemplateConfigForm/CountriesList.js.map +1 -1
  81. package/dist/elements/public/TemplateConfigForm/CountryCard.d.ts +1 -3
  82. package/dist/elements/public/TemplateConfigForm/CountryCard.js +21 -18
  83. package/dist/elements/public/TemplateConfigForm/CountryCard.js.map +1 -1
  84. package/dist/elements/public/TemplateConfigForm/TemplateConfigForm.js +184 -166
  85. package/dist/elements/public/TemplateConfigForm/TemplateConfigForm.js.map +1 -1
  86. package/dist/elements/public/TemplateForm/TemplateForm.d.ts +21 -0
  87. package/dist/elements/public/TemplateForm/TemplateForm.js +21 -0
  88. package/dist/elements/public/TemplateForm/TemplateForm.js.map +1 -1
  89. package/dist/mixins/themeable.js +10 -8
  90. package/dist/mixins/themeable.js.map +1 -1
  91. package/dist/mixins/translatable.js +1 -1
  92. package/dist/mixins/translatable.js.map +1 -1
  93. package/package.json +1 -1
  94. package/dist/cdn/shared-fe8a7aa2.js +0 -1
@@ -101,16 +101,11 @@ export class TemplateConfigForm extends Base {
101
101
  }
102
102
  render() {
103
103
  var _a, _b;
104
- const hidden = this.hiddenControls;
104
+ const hidden = this.hiddenSelector;
105
105
  const json = this.form.json ? JSON.parse(this.form.json) : getDefaultJSON();
106
106
  return html `
107
107
  <div class="relative" aria-busy=${this.in('busy')} aria-live="polite">
108
- <div
109
- class=${classMap({
110
- 'space-y-l transition-opacity': true,
111
- 'opacity-50': !this.in('idle'),
112
- })}
113
- >
108
+ <div class="space-y-l">
114
109
  ${hidden.matches('cart-type', true) ? '' : this.__renderCartType(json)}
115
110
  ${hidden.matches('foxycomplete', true) ? '' : this.__renderFoxycomplete(json)}
116
111
  ${hidden.matches('locations', true) ? '' : this.__renderLocations(json)}
@@ -149,9 +144,9 @@ export class TemplateConfigForm extends Base {
149
144
  __renderCartType(json) {
150
145
  const { lang, ns } = this;
151
146
  const items = ['default', 'fullpage', 'custom'];
152
- const isDisabled = this.disabledSelector.matches('cart-type', true);
147
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('cart-type', true);
153
148
  return html `
154
- <div>
149
+ <div data-testid="cart-type">
155
150
  ${this.renderTemplateOrSlot('cart-type:before')}
156
151
 
157
152
  <x-group frame>
@@ -165,6 +160,7 @@ export class TemplateConfigForm extends Base {
165
160
  </foxy-i18n>
166
161
 
167
162
  <x-choice
163
+ data-testid="cart-type-choice"
168
164
  .value=${json.cart_type}
169
165
  .items=${items}
170
166
  ?disabled=${isDisabled}
@@ -196,32 +192,27 @@ export class TemplateConfigForm extends Base {
196
192
  }
197
193
  __renderFoxycomplete(json) {
198
194
  const { lang, ns } = this;
199
- const isDisabled = this.disabledSelector.matches('foxycomplete', true);
195
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('foxycomplete', true);
200
196
  const isReadonly = this.readonlySelector.matches('foxycomplete', true);
197
+ const config = json.foxycomplete;
201
198
  const items = ['combobox', 'search', 'disabled'];
202
- const value = json.foxycomplete.usage === 'none'
203
- ? 'disabled'
204
- : json.foxycomplete.show_combobox
205
- ? 'combobox'
206
- : 'search';
207
- const renderFlagsCheckbox = () => html `
199
+ const value = config.usage === 'none' ? 'disabled' : config.show_combobox ? 'combobox' : 'search';
200
+ const flagsCheckbox = html `
208
201
  <x-checkbox
202
+ data-testid="foxycomplete-flags-check"
209
203
  ?disabled=${isDisabled}
210
204
  ?readonly=${isReadonly}
211
- ?checked=${json.foxycomplete.show_flags}
205
+ ?checked=${config.show_flags}
212
206
  @change=${(evt) => {
213
- const newConfig = {
214
- ...json.foxycomplete,
215
- show_flags: evt.detail,
216
- };
217
- this.edit({ json: JSON.stringify({ ...json, foxycomplete: newConfig }) });
207
+ config.show_flags = evt.detail;
208
+ this.edit({ json: JSON.stringify(json) });
218
209
  }}
219
210
  >
220
211
  <foxy-i18n lang=${lang} key="show_country_flags" ns=${ns}></foxy-i18n>
221
212
  </x-checkbox>
222
213
  `;
223
214
  return html `
224
- <div>
215
+ <div data-testid="foxycomplete">
225
216
  ${this.renderTemplateOrSlot('foxycomplete:before')}
226
217
 
227
218
  <x-group frame>
@@ -235,6 +226,7 @@ export class TemplateConfigForm extends Base {
235
226
  </foxy-i18n>
236
227
 
237
228
  <x-choice
229
+ data-testid="foxycomplete-choice"
238
230
  .value=${value}
239
231
  .items=${items}
240
232
  ?disabled=${isDisabled}
@@ -242,12 +234,9 @@ export class TemplateConfigForm extends Base {
242
234
  @change=${(evt) => {
243
235
  if (!(evt instanceof ChoiceChangeEvent))
244
236
  return;
245
- const newConfig = {
246
- ...json.foxycomplete,
247
- usage: evt.detail === 'disabled' ? 'none' : 'required',
248
- show_combobox: evt.detail === 'combobox',
249
- };
250
- this.edit({ json: JSON.stringify({ ...json, foxycomplete: newConfig }) });
237
+ config.usage = evt.detail === 'disabled' ? 'none' : 'required';
238
+ config.show_combobox = evt.detail === 'combobox';
239
+ this.edit({ json: JSON.stringify(json) });
251
240
  }}
252
241
  >
253
242
  ${items.map(item => {
@@ -271,17 +260,15 @@ export class TemplateConfigForm extends Base {
271
260
  const field = action === 'open' ? 'combobox_open' : 'combobox_close';
272
261
  return html `
273
262
  <vaadin-text-field
263
+ data-testid="foxycomplete-${action}-icon"
274
264
  label=${this.t(`${action}_icon`)}
275
- .value=${json.foxycomplete[field]}
265
+ .value=${config[field]}
276
266
  ?disabled=${isDisabled}
277
267
  ?readonly=${isReadonly}
268
+ @keydown=${(evt) => evt.key === 'Enter' && this.submit()}
278
269
  @input=${(evt) => {
279
- const target = evt.currentTarget;
280
- const newConfig = {
281
- ...json.foxycomplete,
282
- [field]: target.value,
283
- };
284
- this.edit({ json: JSON.stringify({ ...json, foxycomplete: newConfig }) });
270
+ config[field] = evt.currentTarget.value;
271
+ this.edit({ json: JSON.stringify(json) });
285
272
  }}
286
273
  >
287
274
  </vaadin-text-field>
@@ -289,24 +276,21 @@ export class TemplateConfigForm extends Base {
289
276
  })}
290
277
  </div>
291
278
 
292
- ${renderFlagsCheckbox()}
279
+ ${flagsCheckbox}
293
280
  </div>
294
281
 
295
- <div slot="search" class="pb-s" ?hidden=${value !== 'search'}>
296
- ${renderFlagsCheckbox()}
297
- </div>
282
+ <div slot="search" class="pb-s" ?hidden=${value !== 'search'}>${flagsCheckbox}</div>
298
283
  </x-choice>
299
284
 
300
285
  <div class="border-t border-contrast-10 p-m">
301
286
  <x-checkbox
287
+ data-testid="foxycomplete-lookup-check"
302
288
  ?disabled=${isDisabled}
303
289
  ?readonly=${isReadonly}
304
290
  ?checked=${json.postal_code_lookup.usage === 'enabled'}
305
291
  @change=${(evt) => {
306
- const newConfig = {
307
- usage: evt.detail ? 'enabled' : 'none',
308
- };
309
- this.edit({ json: JSON.stringify({ ...json, postal_code_lookup: newConfig }) });
292
+ json.postal_code_lookup.usage = evt.detail ? 'enabled' : 'none';
293
+ this.edit({ json: JSON.stringify(json) });
310
294
  }}
311
295
  >
312
296
  <foxy-i18n lang=${lang} key="enable_postcode_lookup" ns=${ns}></foxy-i18n>
@@ -321,7 +305,7 @@ export class TemplateConfigForm extends Base {
321
305
  __renderLocations(json) {
322
306
  const { lang, ns } = this;
323
307
  const config = json.location_filtering;
324
- const isDisabled = this.disabledSelector.matches('locations', true);
308
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('locations', true);
325
309
  const isReadonly = this.readonlySelector.matches('locations', true);
326
310
  const shippingChoice = config.shipping_filter_type === 'blacklist' ? 'block' : 'allow';
327
311
  const billingChoice = config.usage === 'both'
@@ -352,81 +336,85 @@ export class TemplateConfigForm extends Base {
352
336
  }
353
337
  };
354
338
  return html `
355
- ${this.renderTemplateOrSlot('locations:before')}
356
-
357
- <x-group frame>
358
- <foxy-i18n
359
- class=${isDisabled ? 'text-disabled' : ''}
360
- slot="header"
361
- lang=${lang}
362
- key="location_plural"
363
- ns=${ns}
364
- >
365
- </foxy-i18n>
339
+ <div data-testid="locations">
340
+ ${this.renderTemplateOrSlot('locations:before')}
366
341
 
367
- <div class="grid sm-grid-cols-2 bg-contrast-10" style="gap: 1px">
368
- <x-group class="bg-base pt-m">
369
- <foxy-i18n
370
- class=${isDisabled ? 'text-disabled' : 'text-tertiary'}
371
- slot="header"
372
- lang=${lang}
373
- key="shipping"
374
- ns=${ns}
375
- >
376
- </foxy-i18n>
342
+ <x-group frame>
343
+ <foxy-i18n
344
+ class=${isDisabled ? 'text-disabled' : ''}
345
+ slot="header"
346
+ lang=${lang}
347
+ key="location_plural"
348
+ ns=${ns}
349
+ >
350
+ </foxy-i18n>
377
351
 
378
- <x-choice
379
- .items=${['allow', 'block']}
380
- .value=${shippingChoice}
381
- ?disabled=${isDisabled}
382
- ?readonly=${isReadonly}
383
- @change=${(evt) => {
352
+ <div class="grid sm-grid-cols-2 bg-contrast-10" style="gap: 1px">
353
+ <x-group class="bg-base pt-m">
354
+ <foxy-i18n
355
+ class=${isDisabled ? 'text-disabled' : 'text-tertiary'}
356
+ slot="header"
357
+ lang=${lang}
358
+ key="shipping"
359
+ ns=${ns}
360
+ >
361
+ </foxy-i18n>
362
+
363
+ <x-choice
364
+ data-testid="locations-shipping-choice"
365
+ .items=${['allow', 'block']}
366
+ .value=${shippingChoice}
367
+ ?disabled=${isDisabled}
368
+ ?readonly=${isReadonly}
369
+ @change=${(evt) => {
384
370
  if (config.usage !== 'both')
385
371
  config.usage = 'independent';
386
372
  config.shipping_filter_type = evt.detail === 'block' ? 'blacklist' : 'whitelist';
387
373
  normalize();
388
374
  this.edit({ json: JSON.stringify(json) });
389
375
  }}
390
- >
391
- <foxy-i18n slot="allow-label" lang=${lang} key="allowlist" ns=${ns}></foxy-i18n>
392
- <foxy-i18n slot="block-label" lang=${lang} key="blocklist" ns=${ns}></foxy-i18n>
393
-
394
- <x-countries-list
395
- countries=${JSON.stringify(config.shipping_filter_values)}
396
- regions=${this.regions}
397
- class="mb-m"
398
- href=${this.countries}
399
- slot=${shippingChoice}
400
- lang=${lang}
401
- ns=${ns}
402
- ?disabled=${isDisabled}
403
- ?readonly=${isReadonly}
404
- @update:countries=${(evt) => {
376
+ >
377
+ <foxy-i18n slot="allow-label" lang=${lang} key="allowlist" ns=${ns}></foxy-i18n>
378
+ <foxy-i18n slot="block-label" lang=${lang} key="blocklist" ns=${ns}></foxy-i18n>
379
+
380
+ <x-countries-list
381
+ data-testid="locations-shipping-list"
382
+ countries=${JSON.stringify(config.shipping_filter_values)}
383
+ regions=${this.regions}
384
+ class="mb-m"
385
+ href=${this.countries}
386
+ slot=${shippingChoice}
387
+ lang=${lang}
388
+ ns=${ns}
389
+ ?disabled=${isDisabled}
390
+ ?readonly=${isReadonly}
391
+ @update:countries=${(evt) => {
405
392
  config.shipping_filter_values = evt.currentTarget.countries;
406
393
  normalize();
407
394
  this.edit({ json: JSON.stringify(json) });
408
395
  }}
409
- >
410
- </x-countries-list>
411
- </x-choice>
412
- </x-group>
396
+ >
397
+ </x-countries-list>
398
+ </x-choice>
399
+ </x-group>
413
400
 
414
- <x-group class="bg-base pt-m">
415
- <foxy-i18n
416
- class=${isDisabled ? 'text-disabled' : 'text-tertiary'}
417
- slot="header"
418
- lang=${lang}
419
- key="billing"
420
- ns=${ns}
421
- >
422
- </foxy-i18n>
401
+ <x-group class="bg-base pt-m">
402
+ <foxy-i18n
403
+ class=${isDisabled ? 'text-disabled' : 'text-tertiary'}
404
+ slot="header"
405
+ lang=${lang}
406
+ key="billing"
407
+ ns=${ns}
408
+ >
409
+ </foxy-i18n>
423
410
 
424
- <x-choice
425
- .items=${['allow', 'block', 'copy']}
426
- .value=${billingChoice}
427
- ?disabled=${isDisabled}
428
- ?readonly=${isReadonly}
429
- @change=${(evt) => {
411
+ <x-choice
412
+ data-testid="locations-billing-choice"
413
+ .items=${['allow', 'block', 'copy']}
414
+ .value=${billingChoice}
415
+ ?disabled=${isDisabled}
416
+ ?readonly=${isReadonly}
417
+ @change=${(evt) => {
430
418
  if (evt.detail === 'copy') {
431
419
  config.usage = 'both';
432
420
  }
@@ -437,35 +425,38 @@ export class TemplateConfigForm extends Base {
437
425
  normalize();
438
426
  this.edit({ json: JSON.stringify(json) });
439
427
  }}
440
- >
441
- <foxy-i18n slot="allow-label" lang=${lang} key="allowlist" ns=${ns}></foxy-i18n>
442
- <foxy-i18n slot="block-label" lang=${lang} key="blocklist" ns=${ns}></foxy-i18n>
443
- <foxy-i18n slot="copy-label" lang=${lang} key="same_as_shipping" ns=${ns}></foxy-i18n>
444
-
445
- <x-countries-list
446
- countries=${JSON.stringify(config.billing_filter_values)}
447
- regions=${this.regions}
448
- class="mb-m"
449
- href=${this.countries}
450
- slot=${billingChoice}
451
- lang=${lang}
452
- ns=${ns}
453
- ?disabled=${isDisabled}
454
- ?readonly=${isReadonly}
455
- ?hidden=${billingChoice === 'copy'}
456
- @update:countries=${(evt) => {
428
+ >
429
+ <foxy-i18n slot="allow-label" lang=${lang} key="allowlist" ns=${ns}></foxy-i18n>
430
+ <foxy-i18n slot="block-label" lang=${lang} key="blocklist" ns=${ns}></foxy-i18n>
431
+ <foxy-i18n slot="copy-label" lang=${lang} key="same_as_shipping" ns=${ns}>
432
+ </foxy-i18n>
433
+
434
+ <x-countries-list
435
+ data-testid="locations-billing-list"
436
+ countries=${JSON.stringify(config.billing_filter_values)}
437
+ regions=${this.regions}
438
+ class="mb-m"
439
+ href=${this.countries}
440
+ slot=${billingChoice}
441
+ lang=${lang}
442
+ ns=${ns}
443
+ ?disabled=${isDisabled}
444
+ ?readonly=${isReadonly}
445
+ ?hidden=${billingChoice === 'copy'}
446
+ @update:countries=${(evt) => {
457
447
  config.billing_filter_values = evt.currentTarget.countries;
458
448
  normalize();
459
449
  this.edit({ json: JSON.stringify(json) });
460
450
  }}
461
- >
462
- </x-countries-list>
463
- </x-choice>
464
- </x-group>
465
- </div>
466
- </x-group>
451
+ >
452
+ </x-countries-list>
453
+ </x-choice>
454
+ </x-group>
455
+ </div>
456
+ </x-group>
467
457
 
468
- ${this.renderTemplateOrSlot('locations:after')}
458
+ ${this.renderTemplateOrSlot('locations:after')}
459
+ </div>
469
460
  `;
470
461
  }
471
462
  __renderHiddenFields(json) {
@@ -473,7 +464,7 @@ export class TemplateConfigForm extends Base {
473
464
  const suggestions = [];
474
465
  const fields = [];
475
466
  const config = json.cart_display_config;
476
- const isDisabled = this.disabledSelector.matches('hidden-fields', true);
467
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('hidden-fields', true);
477
468
  const isReadonly = this.readonlySelector.matches('hidden-fields', true);
478
469
  for (const key in config) {
479
470
  if (!key.startsWith('show_'))
@@ -499,8 +490,9 @@ export class TemplateConfigForm extends Base {
499
490
  };
500
491
  const radius = 'calc(var(--lumo-border-radius-l) / 1.2)';
501
492
  const inputRadius = fields.length === 0 ? [radius] : ['0', '0', radius, radius];
493
+ const isAddButtonDisabled = isDisabled || !this.__addHiddenFieldInputValue;
502
494
  return html `
503
- <div>
495
+ <div data-testid="hidden-fields">
504
496
  ${this.renderTemplateOrSlot('hidden-fields:before')}
505
497
 
506
498
  <x-group frame>
@@ -513,7 +505,7 @@ export class TemplateConfigForm extends Base {
513
505
  >
514
506
  </foxy-i18n>
515
507
 
516
- <div class="divide-y divide-contrast-10">
508
+ <div class="divide-y divide-contrast-10" data-testid="hidden-fields-list">
517
509
  ${fields.map(field => {
518
510
  return html `
519
511
  <div
@@ -528,6 +520,7 @@ export class TemplateConfigForm extends Base {
528
520
  : html `<span>${field}</span>`}
529
521
 
530
522
  <button
523
+ aria-label=${this.t('delete')}
531
524
  class=${classMap({
532
525
  'w-xs h-xs rounded-full transition-colors': true,
533
526
  'hover-bg-error-10 hover-text-error': !isDisabled,
@@ -555,6 +548,7 @@ export class TemplateConfigForm extends Base {
555
548
  </div>
556
549
 
557
550
  <div
551
+ data-testid="hidden-fields-new"
558
552
  style="border-radius: ${inputRadius.join(' ')}"
559
553
  class=${classMap({
560
554
  'h-m flex items-center ring-inset ring-primary-50 focus-within-ring-2': true,
@@ -569,6 +563,7 @@ export class TemplateConfigForm extends Base {
569
563
  list="hidden-fields-list"
570
564
  .value=${live(this.__addHiddenFieldInputValue)}
571
565
  ?disabled=${isDisabled}
566
+ ?readonly=${isReadonly}
572
567
  @keydown=${(evt) => evt.key === 'Enter' && addField()}
573
568
  @input=${(evt) => {
574
569
  this.__addHiddenFieldInputValue = evt.currentTarget.value;
@@ -586,12 +581,12 @@ export class TemplateConfigForm extends Base {
586
581
  class=${classMap({
587
582
  'w-xs h-xs mr-xs flex-shrink-0 ring-inset ring-success-50': true,
588
583
  'flex items-center justify-center rounded-full transition-colors': true,
589
- 'bg-contrast-5 text-disabled cursor-default': !this.__addHiddenFieldInputValue,
590
- 'bg-success-10 text-success cursor-pointer': !!this.__addHiddenFieldInputValue,
591
- 'hover-bg-success hover-text-success-contrast': !!this.__addHiddenFieldInputValue,
592
- 'focus-outline-none focus-ring-2': !!this.__addHiddenFieldInputValue,
584
+ 'bg-contrast-5 text-disabled cursor-default': isAddButtonDisabled,
585
+ 'bg-success-10 text-success cursor-pointer': !isAddButtonDisabled,
586
+ 'hover-bg-success hover-text-success-contrast': !isAddButtonDisabled,
587
+ 'focus-outline-none focus-ring-2': !isAddButtonDisabled,
593
588
  })}
594
- ?disabled=${!this.__addHiddenFieldInputValue}
589
+ ?disabled=${isAddButtonDisabled}
595
590
  @click=${addField}
596
591
  >
597
592
  <iron-icon icon="icons:add" class="icon-inline text-m"></iron-icon>
@@ -605,7 +600,7 @@ export class TemplateConfigForm extends Base {
605
600
  }
606
601
  __renderCards(json) {
607
602
  const { lang, ns } = this;
608
- const isDisabled = this.disabledSelector.matches('cards', true);
603
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('cards', true);
609
604
  const isReadonly = this.readonlySelector.matches('cards', true);
610
605
  const config = json.supported_payment_cards;
611
606
  let skipForSaved;
@@ -633,7 +628,7 @@ export class TemplateConfigForm extends Base {
633
628
  visa: 'Visa',
634
629
  };
635
630
  return html `
636
- <div>
631
+ <div data-testid="cards">
637
632
  ${this.renderTemplateOrSlot('cards:before')}
638
633
 
639
634
  <div class="space-y-xs">
@@ -681,16 +676,17 @@ export class TemplateConfigForm extends Base {
681
676
  type="checkbox"
682
677
  class="sr-only"
683
678
  ?disabled=${isDisabled}
679
+ ?readonly=${isReadonly}
684
680
  ?checked=${isChecked}
685
681
  @change=${(evt) => {
686
682
  if (isReadonly)
687
683
  return evt.preventDefault();
688
684
  evt.stopPropagation();
689
- if (isChecked) {
690
- config.splice(config.indexOf(type), 1);
685
+ if (evt.currentTarget.checked) {
686
+ config.push(type);
691
687
  }
692
688
  else {
693
- config.push(type);
689
+ config.splice(config.indexOf(type), 1);
694
690
  }
695
691
  this.edit({ json: JSON.stringify(json) });
696
692
  }}
@@ -703,6 +699,7 @@ export class TemplateConfigForm extends Base {
703
699
 
704
700
  <div class="flex flex-wrap p-s border-t border-contrast-10">
705
701
  <x-checkbox
702
+ data-testid="cards-saved-check"
706
703
  class="m-s"
707
704
  ?disabled=${isDisabled || json.csc_requirements === 'new_cards_only'}
708
705
  ?readonly=${isReadonly}
@@ -717,6 +714,7 @@ export class TemplateConfigForm extends Base {
717
714
  </x-checkbox>
718
715
 
719
716
  <x-checkbox
717
+ data-testid="cards-sso-check"
720
718
  class="m-s"
721
719
  ?disabled=${isDisabled}
722
720
  ?readonly=${isReadonly}
@@ -751,10 +749,10 @@ export class TemplateConfigForm extends Base {
751
749
  }
752
750
  __renderCheckoutType(json) {
753
751
  const { lang, ns } = this;
754
- const isDisabled = this.disabledSelector.matches('checkout-type', true);
752
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('checkout-type', true);
755
753
  const isReadonly = this.readonlySelector.matches('checkout-type', true);
756
754
  return html `
757
- <div>
755
+ <div data-testid="checkout-type">
758
756
  ${this.renderTemplateOrSlot('checkout-type:before')}
759
757
 
760
758
  <div class="space-y-xs">
@@ -769,6 +767,7 @@ export class TemplateConfigForm extends Base {
769
767
  </foxy-i18n>
770
768
 
771
769
  <x-choice
770
+ data-testid="checkout-type-choice"
772
771
  ?disabled=${isDisabled}
773
772
  ?readonly=${isReadonly}
774
773
  .items=${['default_account', 'default_guest', 'guest_only', 'account_only']}
@@ -800,11 +799,11 @@ export class TemplateConfigForm extends Base {
800
799
  const tosConfig = json.tos_checkbox_settings;
801
800
  const mailConfig = json.newsletter_subscribe;
802
801
  const sdtaConfig = json.eu_secure_data_transfer_consent;
803
- const isDisabled = this.disabledSelector.matches('consent', true);
802
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('consent', true);
804
803
  const isReadonly = this.readonlySelector.matches('consent', true);
805
804
  const dividerStyle = 'margin-left: calc(1.125rem + (var(--lumo-space-m) * 2))';
806
805
  return html `
807
- <div>
806
+ <div data-testid="consent">
808
807
  ${this.renderTemplateOrSlot('consent:before')}
809
808
 
810
809
  <x-group frame>
@@ -818,6 +817,7 @@ export class TemplateConfigForm extends Base {
818
817
  </foxy-i18n>
819
818
 
820
819
  <x-checkbox
820
+ data-testid="consent-tos-check"
821
821
  ?disabled=${isDisabled}
822
822
  ?readonly=${isReadonly}
823
823
  ?checked=${tosConfig.usage === 'required' || tosConfig.usage === 'optional'}
@@ -843,6 +843,7 @@ export class TemplateConfigForm extends Base {
843
843
 
844
844
  <div slot="content" ?hidden=${tosConfig.usage === 'none'}>
845
845
  <vaadin-text-field
846
+ data-testid="consent-tos-field"
846
847
  label=${this.t('location_url')}
847
848
  class="w-full mt-m"
848
849
  placeholder="https://example.com/path/to/tos"
@@ -859,8 +860,10 @@ export class TemplateConfigForm extends Base {
859
860
 
860
861
  <div class="flex flex-wrap -mx-s -mb-s mt-s">
861
862
  <x-checkbox
863
+ data-testid="consent-tos-require-check"
862
864
  class="m-s"
863
865
  ?disabled=${isDisabled}
866
+ ?readonly=${isReadonly}
864
867
  ?checked=${tosConfig.usage === 'required'}
865
868
  @change=${(evt) => {
866
869
  tosConfig.usage = evt.detail ? 'required' : 'optional';
@@ -872,8 +875,10 @@ export class TemplateConfigForm extends Base {
872
875
  </x-checkbox>
873
876
 
874
877
  <x-checkbox
878
+ data-testid="consent-tos-state-check"
875
879
  class="m-s"
876
880
  ?disabled=${isDisabled}
881
+ ?readonly=${isReadonly}
877
882
  ?checked=${tosConfig.initial_state === 'checked'}
878
883
  @change=${(evt) => {
879
884
  tosConfig.initial_state = evt.detail ? 'checked' : 'unchecked';
@@ -890,6 +895,7 @@ export class TemplateConfigForm extends Base {
890
895
  <div style=${dividerStyle} class="border-b border-contrast-10"></div>
891
896
 
892
897
  <x-checkbox
898
+ data-testid="consent-mail-check"
893
899
  ?disabled=${isDisabled}
894
900
  ?readonly=${isReadonly}
895
901
  ?checked=${mailConfig.usage === 'required'}
@@ -914,6 +920,7 @@ export class TemplateConfigForm extends Base {
914
920
  <div style=${dividerStyle} class="border-b border-contrast-10"></div>
915
921
 
916
922
  <x-checkbox
923
+ data-testid="consent-sdta-check"
917
924
  ?disabled=${isDisabled}
918
925
  ?readonly=${isReadonly}
919
926
  ?checked=${sdtaConfig.usage === 'required'}
@@ -936,13 +943,13 @@ export class TemplateConfigForm extends Base {
936
943
  </x-checkbox>
937
944
  </x-group>
938
945
 
939
- ${this.renderTemplateOrSlot('consent:before')}
946
+ ${this.renderTemplateOrSlot('consent:after')}
940
947
  </div>
941
948
  `;
942
949
  }
943
950
  __renderFields(json) {
944
951
  const { lang, ns } = this;
945
- const isDisabled = this.disabledSelector.matches('fields', true);
952
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('fields', true);
946
953
  const isReadonly = this.readonlySelector.matches('fields', true);
947
954
  const config = json.custom_checkout_field_requirements;
948
955
  const options = {
@@ -961,7 +968,7 @@ export class TemplateConfigForm extends Base {
961
968
  billing_country: ['default', 'optional', 'required', 'hidden'],
962
969
  };
963
970
  return html `
964
- <div>
971
+ <div data-testid="fields">
965
972
  ${this.renderTemplateOrSlot('fields:before')}
966
973
 
967
974
  <x-group frame>
@@ -1013,6 +1020,7 @@ export class TemplateConfigForm extends Base {
1013
1020
  })}
1014
1021
  >
1015
1022
  <select
1023
+ data-testid="fields-${property}"
1016
1024
  class=${classMap({
1017
1025
  'h-s mr-xs text-right appearance-none bg-transparent font-medium': true,
1018
1026
  'focus-outline-none cursor-pointer': !isDisabled,
@@ -1062,10 +1070,10 @@ export class TemplateConfigForm extends Base {
1062
1070
  const config = json.analytics_config;
1063
1071
  const sioConfig = config.segment_io;
1064
1072
  const gaConfig = config.google_analytics;
1065
- const isDisabled = this.disabledSelector.matches('google-analytics', true);
1073
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('google-analytics', true);
1066
1074
  const isReadonly = this.readonlySelector.matches('google-analytics', true);
1067
1075
  return html `
1068
- <div>
1076
+ <div data-testid="google-analytics">
1069
1077
  ${this.renderTemplateOrSlot('google-analytics:before')}
1070
1078
 
1071
1079
  <x-group frame>
@@ -1073,6 +1081,7 @@ export class TemplateConfigForm extends Base {
1073
1081
 
1074
1082
  <div class="p-m space-y-m">
1075
1083
  <vaadin-text-field
1084
+ data-testid="google-analytics-field"
1076
1085
  class="w-full"
1077
1086
  label=${this.t('ga_account_id')}
1078
1087
  placeholder="UA-1234567-1"
@@ -1086,11 +1095,13 @@ export class TemplateConfigForm extends Base {
1086
1095
  gaConfig.account_id = evt.currentTarget.value;
1087
1096
  gaConfig.usage = gaConfig.account_id ? 'required' : 'none';
1088
1097
  config.usage = gaConfig.account_id || sioConfig.account_id ? 'required' : 'none';
1098
+ this.edit({ json: JSON.stringify(json) });
1089
1099
  }}
1090
1100
  >
1091
1101
  </vaadin-text-field>
1092
1102
 
1093
1103
  <x-checkbox
1104
+ data-testid="google-analytics-check"
1094
1105
  ?disabled=${isDisabled}
1095
1106
  ?readonly=${isReadonly}
1096
1107
  ?checked=${gaConfig.include_on_site}
@@ -1121,10 +1132,10 @@ export class TemplateConfigForm extends Base {
1121
1132
  const config = json.analytics_config;
1122
1133
  const sioConfig = config.segment_io;
1123
1134
  const gaConfig = config.google_analytics;
1124
- const isDisabled = this.disabledSelector.matches('segment-io', true);
1135
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('segment-io', true);
1125
1136
  const isReadonly = this.readonlySelector.matches('segment-io', true);
1126
1137
  return html `
1127
- <div>
1138
+ <div data-testid="segment-io">
1128
1139
  ${this.renderTemplateOrSlot('segment-io:before')}
1129
1140
 
1130
1141
  <x-group frame>
@@ -1132,6 +1143,7 @@ export class TemplateConfigForm extends Base {
1132
1143
 
1133
1144
  <div class="p-m">
1134
1145
  <vaadin-text-field
1146
+ data-testid="segment-io-field"
1135
1147
  class="w-full"
1136
1148
  label=${this.t('sio_account_id')}
1137
1149
  placeholder="MY-WRITE-KEY"
@@ -1145,6 +1157,7 @@ export class TemplateConfigForm extends Base {
1145
1157
  sioConfig.account_id = evt.currentTarget.value;
1146
1158
  sioConfig.usage = sioConfig.account_id ? 'required' : 'none';
1147
1159
  config.usage = gaConfig.account_id || sioConfig.account_id ? 'required' : 'none';
1160
+ this.edit({ json: JSON.stringify(json) });
1148
1161
  }}
1149
1162
  >
1150
1163
  </vaadin-text-field>
@@ -1158,10 +1171,10 @@ export class TemplateConfigForm extends Base {
1158
1171
  __renderTroubleshooting(json) {
1159
1172
  const { lang, ns } = this;
1160
1173
  const config = json.debug;
1161
- const isDisabled = this.disabledSelector.matches('troubleshooting', true);
1174
+ const isDisabled = !this.in('idle') || this.disabledSelector.matches('troubleshooting', true);
1162
1175
  const isReadonly = this.readonlySelector.matches('troubleshooting', true);
1163
1176
  return html `
1164
- <div>
1177
+ <div data-testid="troubleshooting">
1165
1178
  ${this.renderTemplateOrSlot('troubleshooting:before')}
1166
1179
 
1167
1180
  <x-group frame>
@@ -1176,6 +1189,7 @@ export class TemplateConfigForm extends Base {
1176
1189
 
1177
1190
  <div class="p-m space-y-m">
1178
1191
  <x-checkbox
1192
+ data-testid="troubleshooting-check"
1179
1193
  ?disabled=${isDisabled}
1180
1194
  ?readonly=${isReadonly}
1181
1195
  ?checked=${config.usage === 'required'}
@@ -1204,16 +1218,17 @@ export class TemplateConfigForm extends Base {
1204
1218
  }
1205
1219
  __renderCustomConfig(json) {
1206
1220
  return html `
1207
- <div>
1221
+ <div data-testid="custom-config">
1208
1222
  ${this.renderTemplateOrSlot('custom-config:before')}
1209
1223
 
1210
1224
  <vaadin-text-area
1225
+ data-testid="custom-config-field"
1211
1226
  class="w-full"
1212
1227
  label=${this.t('custom_config')}
1213
1228
  placeholder='{ "key": "value" }'
1214
1229
  helper-text=${this.t('custom_config_helper_text')}
1215
1230
  .value=${json.custom_config ? JSON.stringify(json.custom_config, null, 2) : ''}
1216
- ?disabled=${this.disabledSelector.matches('custom-config', true)}
1231
+ ?disabled=${!this.in('idle') || this.disabledSelector.matches('custom-config', true)}
1217
1232
  ?readonly=${this.readonlySelector.matches('custom-config', true)}
1218
1233
  @input=${(evt) => {
1219
1234
  const input = evt.currentTarget;
@@ -1235,15 +1250,16 @@ export class TemplateConfigForm extends Base {
1235
1250
  }
1236
1251
  __renderHeader(json) {
1237
1252
  return html `
1238
- <div>
1253
+ <div data-testid="header">
1239
1254
  ${this.renderTemplateOrSlot('header:before')}
1240
1255
 
1241
1256
  <vaadin-text-area
1257
+ data-testid="header-field"
1242
1258
  class="w-full"
1243
1259
  label=${this.t('custom_header')}
1244
1260
  helper-text=${this.t('custom_header_helper_text')}
1245
1261
  .value=${json.custom_script_values.header}
1246
- ?disabled=${this.disabledSelector.matches('header', true)}
1262
+ ?disabled=${!this.in('idle') || this.disabledSelector.matches('header', true)}
1247
1263
  ?readonly=${this.readonlySelector.matches('header', true)}
1248
1264
  @input=${(evt) => {
1249
1265
  const target = evt.currentTarget;
@@ -1262,16 +1278,17 @@ export class TemplateConfigForm extends Base {
1262
1278
  }
1263
1279
  __renderCustomFields(json) {
1264
1280
  return html `
1265
- <div>
1281
+ <div data-testid="custom-fields">
1266
1282
  ${this.renderTemplateOrSlot('custom-fields:before')}
1267
1283
 
1268
1284
  <vaadin-text-area
1285
+ data-testid="custom-fields-field"
1269
1286
  class="w-full"
1270
1287
  label=${this.t('custom_fields')}
1271
1288
  helper-text=${this.t('custom_fields_helper_text')}
1272
- .value=${json.custom_script_values.header}
1273
- ?disabled=${this.disabledSelector.matches('header', true)}
1274
- ?readonly=${this.readonlySelector.matches('header', true)}
1289
+ .value=${json.custom_script_values.checkout_fields}
1290
+ ?disabled=${!this.in('idle') || this.disabledSelector.matches('custom-fields', true)}
1291
+ ?readonly=${this.readonlySelector.matches('custom-fields', true)}
1275
1292
  @input=${(evt) => {
1276
1293
  const newValue = evt.currentTarget.value;
1277
1294
  json.custom_script_values.checkout_fields = newValue;
@@ -1286,15 +1303,16 @@ export class TemplateConfigForm extends Base {
1286
1303
  }
1287
1304
  __renderFooter(json) {
1288
1305
  return html `
1289
- <div>
1306
+ <div data-testid="footer">
1290
1307
  ${this.renderTemplateOrSlot('footer:before')}
1291
1308
 
1292
1309
  <vaadin-text-area
1310
+ data-testid="footer-field"
1293
1311
  class="w-full"
1294
1312
  label=${this.t('custom_footer')}
1295
1313
  helper-text=${this.t('custom_footer_helper_text')}
1296
1314
  .value=${json.custom_script_values.footer}
1297
- ?disabled=${this.disabledSelector.matches('footer', true)}
1315
+ ?disabled=${!this.in('idle') || this.disabledSelector.matches('footer', true)}
1298
1316
  ?readonly=${this.readonlySelector.matches('footer', true)}
1299
1317
  @input=${(evt) => {
1300
1318
  const target = evt.currentTarget;