@justeattakeaway/pie-switch 2.1.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -274,6 +274,10 @@
274
274
  {
275
275
  "name": "FormControlMixin",
276
276
  "package": "@justeattakeaway/pie-webc-core"
277
+ },
278
+ {
279
+ "name": "DelegatesFocusMixin",
280
+ "package": "@justeattakeaway/pie-webc-core"
277
281
  }
278
282
  ],
279
283
  "superclass": {
package/dist/index.js CHANGED
@@ -1,19 +1,19 @@
1
1
  import { LitElement as Ft, nothing as L, html as N, unsafeCSS as It } from "lit";
2
- import { property as y, query as dt, state as St } from "lit/decorators.js";
2
+ import { property as E, query as dt, state as St } from "lit/decorators.js";
3
3
  import { classMap as Vt } from "lit/directives/class-map.js";
4
4
  import { ifDefined as Tt } from "lit/directives/if-defined.js";
5
- import { FormControlMixin as Lt, wrapNativeEvent as Nt, validPropertyValues as Ot, safeCustomElement as Pt } from "@justeattakeaway/pie-webc-core";
5
+ import { FormControlMixin as Lt, DelegatesFocusMixin as Nt, wrapNativeEvent as Ot, validPropertyValues as Pt, safeCustomElement as _t } from "@justeattakeaway/pie-webc-core";
6
6
  import "@justeattakeaway/pie-icons-webc/dist/IconCheck.js";
7
7
  const O = class O extends Ft {
8
8
  willUpdate() {
9
9
  this.getAttribute("v") || this.setAttribute("v", O.v);
10
10
  }
11
11
  };
12
- O.v = "2.1.0";
12
+ O.v = "2.3.0";
13
13
  let q = O;
14
14
  (function() {
15
- (function(n) {
16
- const l = /* @__PURE__ */ new WeakMap(), h = /* @__PURE__ */ new WeakMap(), m = /* @__PURE__ */ new WeakMap(), c = /* @__PURE__ */ new WeakMap(), E = /* @__PURE__ */ new WeakMap(), M = /* @__PURE__ */ new WeakMap(), P = /* @__PURE__ */ new WeakMap(), g = /* @__PURE__ */ new WeakMap(), B = /* @__PURE__ */ new WeakMap(), A = /* @__PURE__ */ new WeakMap(), U = /* @__PURE__ */ new WeakMap(), j = /* @__PURE__ */ new WeakMap(), K = /* @__PURE__ */ new WeakMap(), G = /* @__PURE__ */ new WeakMap(), C = /* @__PURE__ */ new WeakMap(), F = {
15
+ (function(l) {
16
+ const n = /* @__PURE__ */ new WeakMap(), h = /* @__PURE__ */ new WeakMap(), m = /* @__PURE__ */ new WeakMap(), c = /* @__PURE__ */ new WeakMap(), g = /* @__PURE__ */ new WeakMap(), k = /* @__PURE__ */ new WeakMap(), P = /* @__PURE__ */ new WeakMap(), y = /* @__PURE__ */ new WeakMap(), B = /* @__PURE__ */ new WeakMap(), A = /* @__PURE__ */ new WeakMap(), U = /* @__PURE__ */ new WeakMap(), j = /* @__PURE__ */ new WeakMap(), K = /* @__PURE__ */ new WeakMap(), G = /* @__PURE__ */ new WeakMap(), C = /* @__PURE__ */ new WeakMap(), F = {
17
17
  ariaAtomic: "aria-atomic",
18
18
  ariaAutoComplete: "aria-autocomplete",
19
19
  ariaBusy: "aria-busy",
@@ -110,7 +110,7 @@ let q = O;
110
110
  s.setAttribute("internals-valid", d.validity.valid.toString()), s.setAttribute("internals-invalid", (!d.validity.valid).toString()), s.setAttribute("aria-invalid", (!d.validity.valid).toString()), C.delete(s);
111
111
  }
112
112
  if (s.localName === "form") {
113
- const d = g.get(s), w = document.createTreeWalker(s, NodeFilter.SHOW_ELEMENT, {
113
+ const d = y.get(s), w = document.createTreeWalker(s, NodeFilter.SHOW_ELEMENT, {
114
114
  acceptNode(z) {
115
115
  return c.has(z) && z.constructor.formAssociated && !(d && d.has(z)) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;
116
116
  }
@@ -163,7 +163,7 @@ let q = O;
163
163
  t[0].id || (i = `${t[0].htmlFor}_Label`, t[0].id = i), e.setAttribute("aria-labelledby", i);
164
164
  }
165
165
  }, S = (e) => {
166
- const t = Array.from(e.elements).filter((o) => !o.tagName.includes("-") && o.validity).map((o) => o.validity.valid), i = g.get(e) || [], a = Array.from(i).filter((o) => o.isConnected).map((o) => c.get(o).validity.valid), r = [...t, ...a].includes(!1);
166
+ const t = Array.from(e.elements).filter((o) => !o.tagName.includes("-") && o.validity).map((o) => o.validity.valid), i = y.get(e) || [], a = Array.from(i).filter((o) => o.isConnected).map((o) => c.get(o).validity.valid), r = [...t, ...a].includes(!1);
167
167
  e.toggleAttribute("internals-invalid", r), e.toggleAttribute("internals-valid", !r);
168
168
  }, ft = (e) => {
169
169
  S(V(e.target));
@@ -173,27 +173,27 @@ let q = O;
173
173
  const t = ["button[type=submit]", "input[type=submit]", "button:not([type])"].map((i) => `${i}:not([disabled])`).map((i) => `${i}:not([form])${e.id ? `,${i}[form='${e.id}']` : ""}`).join(",");
174
174
  e.addEventListener("click", (i) => {
175
175
  if (i.target.closest(t)) {
176
- const r = g.get(e);
176
+ const r = y.get(e);
177
177
  if (e.noValidate)
178
178
  return;
179
179
  r.size && Array.from(r).reverse().map((u) => c.get(u).reportValidity()).includes(!1) && i.preventDefault();
180
180
  }
181
181
  });
182
182
  }, wt = (e) => {
183
- const t = g.get(e.target);
183
+ const t = y.get(e.target);
184
184
  t && t.size && t.forEach((i) => {
185
185
  i.constructor.formAssociated && i.formResetCallback && i.formResetCallback.apply(i);
186
186
  });
187
187
  }, et = (e, t, i) => {
188
188
  if (t) {
189
- const a = g.get(t);
189
+ const a = y.get(t);
190
190
  if (a)
191
191
  a.add(e);
192
192
  else {
193
193
  const r = /* @__PURE__ */ new Set();
194
- r.add(e), g.set(t, r), vt(t), t.addEventListener("reset", wt), t.addEventListener("input", ft), t.addEventListener("change", bt);
194
+ r.add(e), y.set(t, r), vt(t), t.addEventListener("reset", wt), t.addEventListener("input", ft), t.addEventListener("change", bt);
195
195
  }
196
- M.set(t, { ref: e, internals: i }), e.constructor.formAssociated && e.formAssociatedCallback && setTimeout(() => {
196
+ k.set(t, { ref: e, internals: i }), e.constructor.formAssociated && e.formAssociatedCallback && setTimeout(() => {
197
197
  e.formAssociatedCallback.apply(e, [t]);
198
198
  }, 0), S(t);
199
199
  }
@@ -204,7 +204,7 @@ let q = O;
204
204
  if (!e.constructor.formAssociated)
205
205
  throw new i(t);
206
206
  }, it = (e, t, i) => {
207
- const a = g.get(e);
207
+ const a = y.get(e);
208
208
  return a && a.size && a.forEach((r) => {
209
209
  c.get(r)[i]() || (t = !1);
210
210
  }), t;
@@ -307,7 +307,7 @@ let q = O;
307
307
  const { get: r } = Object.getOwnPropertyDescriptor(HTMLFormElement.prototype, "elements");
308
308
  Object.defineProperty(HTMLFormElement.prototype, "elements", {
309
309
  get(...o) {
310
- const s = r.call(this, ...o), u = Array.from(g.get(this) || []);
310
+ const s = r.call(this, ...o), u = Array.from(y.get(this) || []);
311
311
  if (u.length === 0)
312
312
  return s;
313
313
  const d = Array.from(s).concat(u).sort((w, b) => w.compareDocumentPosition ? w.compareDocumentPosition(b) & 2 ? 1 : -1 : 0);
@@ -323,10 +323,10 @@ let q = O;
323
323
  if (!t || !t.tagName || t.tagName.indexOf("-") === -1)
324
324
  throw new TypeError("Illegal constructor");
325
325
  const i = t.getRootNode(), a = new gt();
326
- this.states = new H(t), l.set(this, t), h.set(this, a), c.set(t, this), ht(t, this), mt(t, this), Object.seal(this), i instanceof DocumentFragment && pt(i);
326
+ this.states = new H(t), n.set(this, t), h.set(this, a), c.set(t, this), ht(t, this), mt(t, this), Object.seal(this), i instanceof DocumentFragment && pt(i);
327
327
  }
328
328
  checkValidity() {
329
- const t = l.get(this);
329
+ const t = n.get(this);
330
330
  if (v(t, "Failed to execute 'checkValidity' on 'ElementInternals': The target element is not a form-associated custom element."), !this.willValidate)
331
331
  return !0;
332
332
  const i = h.get(this);
@@ -341,19 +341,19 @@ let q = O;
341
341
  return i.valid;
342
342
  }
343
343
  get form() {
344
- const t = l.get(this);
344
+ const t = n.get(this);
345
345
  v(t, "Failed to read the 'form' property from 'ElementInternals': The target element is not a form-associated custom element.");
346
346
  let i;
347
347
  return t.constructor.formAssociated === !0 && (i = V(t)), i;
348
348
  }
349
349
  get labels() {
350
- const t = l.get(this);
350
+ const t = n.get(this);
351
351
  v(t, "Failed to read the 'labels' property from 'ElementInternals': The target element is not a form-associated custom element.");
352
352
  const i = t.getAttribute("id"), a = t.getRootNode();
353
353
  return a && i ? a.querySelectorAll(`[for="${i}"]`) : [];
354
354
  }
355
355
  reportValidity() {
356
- const t = l.get(this);
356
+ const t = n.get(this);
357
357
  if (v(t, "Failed to execute 'reportValidity' on 'ElementInternals': The target element is not a form-associated custom element."), !this.willValidate)
358
358
  return !0;
359
359
  const i = this.checkValidity(), a = j.get(this);
@@ -362,7 +362,7 @@ let q = O;
362
362
  return !i && a && (t.focus(), a.focus()), i;
363
363
  }
364
364
  setFormValue(t) {
365
- const i = l.get(this);
365
+ const i = n.get(this);
366
366
  if (v(i, "Failed to execute 'setFormValue' on 'ElementInternals': The target element is not a form-associated custom element."), X(this), t != null && !(t instanceof FormData)) {
367
367
  if (i.getAttribute("name")) {
368
368
  const a = Z(i, this);
@@ -377,7 +377,7 @@ let q = O;
377
377
  B.set(i, t);
378
378
  }
379
379
  setValidity(t, i, a) {
380
- const r = l.get(this);
380
+ const r = n.get(this);
381
381
  if (v(r, "Failed to execute 'setValidity' on 'ElementInternals': The target element is not a form-associated custom element."), !t)
382
382
  throw new TypeError("Failed to execute 'setValidity' on 'ElementInternals': 1 argument required, but only 0 present.");
383
383
  j.set(this, a);
@@ -390,22 +390,22 @@ let q = O;
390
390
  const { valid: d } = Et(o, u, this.form);
391
391
  if (!d && !i)
392
392
  throw new DOMException("Failed to execute 'setValidity' on 'ElementInternals': The second argument should not be empty if one or more flags in the first argument are true.");
393
- E.set(this, d ? "" : i), r.isConnected ? (r.toggleAttribute("internals-invalid", !d), r.toggleAttribute("internals-valid", d), r.setAttribute("aria-invalid", `${!d}`)) : C.set(r, this);
393
+ g.set(this, d ? "" : i), r.isConnected ? (r.toggleAttribute("internals-invalid", !d), r.toggleAttribute("internals-valid", d), r.setAttribute("aria-invalid", `${!d}`)) : C.set(r, this);
394
394
  }
395
395
  get shadowRoot() {
396
- const t = l.get(this), i = U.get(t);
396
+ const t = n.get(this), i = U.get(t);
397
397
  return i || null;
398
398
  }
399
399
  get validationMessage() {
400
- const t = l.get(this);
401
- return v(t, "Failed to read the 'validationMessage' property from 'ElementInternals': The target element is not a form-associated custom element."), E.get(this);
400
+ const t = n.get(this);
401
+ return v(t, "Failed to read the 'validationMessage' property from 'ElementInternals': The target element is not a form-associated custom element."), g.get(this);
402
402
  }
403
403
  get validity() {
404
- const t = l.get(this);
404
+ const t = n.get(this);
405
405
  return v(t, "Failed to read the 'validity' property from 'ElementInternals': The target element is not a form-associated custom element."), h.get(this);
406
406
  }
407
407
  get willValidate() {
408
- const t = l.get(this);
408
+ const t = n.get(this);
409
409
  return v(t, "Failed to read the 'willValidate' property from 'ElementInternals': The target element is not a form-associated custom element."), !(t.disabled || t.hasAttribute("disabled") || t.hasAttribute("readonly"));
410
410
  }
411
411
  }
@@ -477,29 +477,29 @@ let q = O;
477
477
  T() && typeof document < "u" && new MutationObserver(_).observe(document.documentElement, $), typeof HTMLFormElement < "u" && At(), (e || typeof window < "u" && !window.CustomStateSet) && W();
478
478
  }
479
479
  }
480
- return !!customElements.polyfillWrapFlushCallback || (Ct() ? typeof window < "u" && !window.CustomStateSet && W(HTMLElement.prototype.attachInternals) : ct(!1)), n.forceCustomStateSetPolyfill = W, n.forceElementInternalsPolyfill = ct, Object.defineProperty(n, "__esModule", { value: !0 }), n;
480
+ return !!customElements.polyfillWrapFlushCallback || (Ct() ? typeof window < "u" && !window.CustomStateSet && W(HTMLElement.prototype.attachInternals) : ct(!1)), l.forceCustomStateSetPolyfill = W, l.forceElementInternalsPolyfill = ct, Object.defineProperty(l, "__esModule", { value: !0 }), l;
481
481
  })({});
482
482
  })();
483
- const _t = "*,*:after,*:before{box-sizing:inherit}:host{display:block}*,*:before,*:after{cursor:inherit}.c-switch-wrapper{display:inline-flex;align-items:center;gap:var(--dt-spacing-b);vertical-align:top;font-family:var(--dt-font-body-l-family);cursor:pointer}.c-switch-wrapper[disabled]{cursor:not-allowed}.c-switch{--int-states-mixin-bg-color: var(--dt-color-interactive-form);--switch-bg-color--checked: var(--dt-color-interactive-brand);--switch-bg-color--disabled: var(--dt-color-disabled-01);--switch-width: 48px;--switch-height: 24px;--switch-control-size: 20px;--switch-padding: 2px;--switch-radius: var(--dt-radius-rounded-e);--switch-translation: calc(var(--switch-width) - var(--switch-control-size) - 2 * var(--switch-padding));position:relative;display:flex;width:var(--switch-width);height:var(--switch-height);flex-shrink:0;padding:var(--switch-padding);border-radius:var(--switch-radius);background-color:var(--int-states-mixin-bg-color)}.c-switch:hover:not(:disabled,.is-disabled,.is-dismissible){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-form-h), var(--dt-color-interactive-form-s), calc(var(--dt-color-interactive-form-l) + var(--hover-modifier)))}.c-switch:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch.is-loading:not(:disabled,.is-disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-form-h), var(--dt-color-interactive-form-s), calc(var(--dt-color-interactive-form-l) + var(--active-modifier)))}@supports (background-color: color-mix(in srgb,black,white)){.c-switch:hover:not(:disabled,.is-disabled,.is-dismissible){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-interactive-form))}.c-switch:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch.is-loading:not(:disabled,.is-disabled){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-active-01-bg) var(--dt-color-active-01), var(--dt-color-interactive-form))}}.c-switch[checked]{--int-states-mixin-bg-color: var(--dt-color-interactive-brand)}.c-switch[checked]:hover:not(:disabled,.is-disabled,.is-dismissible){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--hover-modifier)))}.c-switch[checked]:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch[checked].is-loading:not(:disabled,.is-disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--active-modifier)))}@supports (background-color: color-mix(in srgb,black,white)){.c-switch[checked]:hover:not(:disabled,.is-disabled,.is-dismissible){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-interactive-brand))}.c-switch[checked]:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch[checked].is-loading:not(:disabled,.is-disabled){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-active-01-bg) var(--dt-color-active-01), var(--dt-color-interactive-brand))}}[disabled] .c-switch{--int-states-mixin-bg-color: var(--switch-bg-color--disabled);pointer-events:none}.c-switch:has(.c-switch-input:focus-visible){box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-switch-input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;left:50%;transform:translate(-50%) translateY(-50%);bottom:0}.c-switch-input:disabled{background-color:transparent}.c-switch-control{position:absolute;left:2px;width:var(--switch-control-size);height:var(--switch-control-size);border-radius:var(--switch-radius);background-color:var(--dt-color-interactive-light);padding:var(--switch-padding)}.c-switch-wrapper:dir(rtl) .c-switch-control{position:absolute;left:initial;right:2px}.c-switch-control .c-pieIcon--check{vertical-align:top}.c-switch-input:checked+.c-switch-control{transform:translate(var(--switch-translation))}.c-switch-input:checked+.c-switch-control .c-pieIcon--check{color:var(--dt-color-interactive-brand)}.c-switch-input:disabled~.c-switch-control{color:var(--switch-bg-color--disabled)}.c-switch-input:disabled~.c-switch-control .c-pieIcon--check{color:var(--switch-bg-color--disabled)}.c-switch-label{color:var(--dt-color-content-default)}.c-switch-description{position:absolute;display:block;height:1px;width:1px;overflow:hidden;padding:1px;white-space:nowrap}@media (prefers-reduced-motion: no-preference){.c-switch-wrapper--allow-animation .c-switch{transition:background-color .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-wrapper--allow-animation .c-switch[checked]{transition:background-color .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-wrapper--allow-animation .c-switch-control{transition:transform .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-input:checked+.c-switch-wrapper--allow-animation .c-switch-control{transition:transform .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-input:checked+.c-switch-wrapper--allow-animation .c-switch-control .c-pieIcon--check{transition:color .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-input:disabled~.c-switch-wrapper--allow-animation .c-switch-control .c-pieIcon--check{transition:color .15s cubic-bezier(.4,0,.9,1) 0s}}.c-switch-wrapper:dir(rtl) .c-switch-input:checked+.c-switch-control{transform:translate(calc(-1 * var(--switch-translation)))}", $t = ["leading", "trailing"], Gt = "change", k = {
483
+ const $t = "*,*:after,*:before{box-sizing:inherit}:host{display:block}*,*:before,*:after{cursor:inherit}.c-switch-wrapper{display:inline-flex;align-items:center;gap:var(--dt-spacing-b);vertical-align:top;font-family:var(--dt-font-body-l-family);cursor:pointer}.c-switch-wrapper[disabled]{cursor:not-allowed}.c-switch{--int-states-mixin-bg-color: var(--dt-color-interactive-form);--switch-bg-color--checked: var(--dt-color-interactive-brand);--switch-bg-color--disabled: var(--dt-color-disabled-01);--switch-width: 48px;--switch-height: 24px;--switch-control-size: 20px;--switch-padding: 2px;--switch-radius: var(--dt-radius-rounded-e);--switch-translation: calc(var(--switch-width) - var(--switch-control-size) - 2 * var(--switch-padding));position:relative;display:flex;width:var(--switch-width);height:var(--switch-height);flex-shrink:0;padding:var(--switch-padding);border-radius:var(--switch-radius);background-color:var(--int-states-mixin-bg-color)}.c-switch:hover:not(:disabled,.is-disabled,.is-dismissible){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-form-h), var(--dt-color-interactive-form-s), calc(var(--dt-color-interactive-form-l) + var(--hover-modifier)))}.c-switch:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch.is-loading:not(:disabled,.is-disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-form-h), var(--dt-color-interactive-form-s), calc(var(--dt-color-interactive-form-l) + var(--active-modifier)))}@supports (background-color: color-mix(in srgb,black,white)){.c-switch:hover:not(:disabled,.is-disabled,.is-dismissible){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-interactive-form))}.c-switch:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch.is-loading:not(:disabled,.is-disabled){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-active-01-bg) var(--dt-color-active-01), var(--dt-color-interactive-form))}}.c-switch[checked]{--int-states-mixin-bg-color: var(--dt-color-interactive-brand)}.c-switch[checked]:hover:not(:disabled,.is-disabled,.is-dismissible){--hover-modifier: calc(-1 * var(--dt-color-hover-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--hover-modifier)))}.c-switch[checked]:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch[checked].is-loading:not(:disabled,.is-disabled){--active-modifier: calc(-1 * var(--dt-color-active-01));--int-states-mixin-bg-color: hsl(var(--dt-color-interactive-brand-h), var(--dt-color-interactive-brand-s), calc(var(--dt-color-interactive-brand-l) + var(--active-modifier)))}@supports (background-color: color-mix(in srgb,black,white)){.c-switch[checked]:hover:not(:disabled,.is-disabled,.is-dismissible){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-hover-01-bg) var(--dt-color-hover-01), var(--dt-color-interactive-brand))}.c-switch[checked]:active:not(:disabled,.is-disabled,.is-dismissible),.c-switch[checked].is-loading:not(:disabled,.is-disabled){--int-states-mixin-bg-color: color-mix(in srgb, var(--dt-color-active-01-bg) var(--dt-color-active-01), var(--dt-color-interactive-brand))}}[disabled] .c-switch{--int-states-mixin-bg-color: var(--switch-bg-color--disabled);pointer-events:none}.c-switch:has(.c-switch-input:focus-visible){box-shadow:0 0 0 2px var(--dt-color-focus-inner),0 0 0 4px var(--dt-color-focus-outer);outline:none}.c-switch-input{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0;left:50%;transform:translate(-50%) translateY(-50%);bottom:0}.c-switch-input:disabled{background-color:transparent}.c-switch-control{position:absolute;left:2px;width:var(--switch-control-size);height:var(--switch-control-size);border-radius:var(--switch-radius);background-color:var(--dt-color-interactive-light);padding:var(--switch-padding)}.c-switch-wrapper:dir(rtl) .c-switch-control{position:absolute;left:initial;right:2px}.c-switch-control .c-pieIcon--check{vertical-align:top}.c-switch-input:checked+.c-switch-control{transform:translate(var(--switch-translation))}.c-switch-input:checked+.c-switch-control .c-pieIcon--check{color:var(--dt-color-interactive-brand)}.c-switch-input:disabled~.c-switch-control{color:var(--switch-bg-color--disabled)}.c-switch-input:disabled~.c-switch-control .c-pieIcon--check{color:var(--switch-bg-color--disabled)}.c-switch-label{color:var(--dt-color-content-default-solid)}.c-switch-description{position:absolute;display:block;height:1px;width:1px;overflow:hidden;padding:1px;white-space:nowrap}@media (prefers-reduced-motion: no-preference){.c-switch-wrapper--allow-animation .c-switch{transition:background-color .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-wrapper--allow-animation .c-switch[checked]{transition:background-color .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-wrapper--allow-animation .c-switch-control{transition:transform .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-input:checked+.c-switch-wrapper--allow-animation .c-switch-control{transition:transform .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-input:checked+.c-switch-wrapper--allow-animation .c-switch-control .c-pieIcon--check{transition:color .15s cubic-bezier(.4,0,.9,1) 0s}}@media (prefers-reduced-motion: no-preference){.c-switch-input:disabled~.c-switch-wrapper--allow-animation .c-switch-control .c-pieIcon--check{transition:color .15s cubic-bezier(.4,0,.9,1) 0s}}.c-switch-wrapper:dir(rtl) .c-switch-input:checked+.c-switch-control{transform:translate(calc(-1 * var(--switch-translation)))}", Dt = ["leading", "trailing"], Yt = "change", M = {
484
484
  checked: !1,
485
485
  disabled: !1,
486
486
  labelPlacement: "leading",
487
487
  required: !1,
488
488
  value: "on"
489
489
  };
490
- var Dt = Object.defineProperty, Rt = Object.getOwnPropertyDescriptor, f = (n, l, h, m) => {
491
- for (var c = m > 1 ? void 0 : m ? Rt(l, h) : l, E = n.length - 1, M; E >= 0; E--)
492
- (M = n[E]) && (c = (m ? M(l, h, c) : M(c)) || c);
493
- return m && c && Dt(l, h, c), c;
490
+ var Rt = Object.defineProperty, Ht = Object.getOwnPropertyDescriptor, f = (l, n, h, m) => {
491
+ for (var c = m > 1 ? void 0 : m ? Ht(n, h) : n, g = l.length - 1, k; g >= 0; g--)
492
+ (k = l[g]) && (c = (m ? k(n, h, c) : k(c)) || c);
493
+ return m && c && Rt(n, h, c), c;
494
494
  };
495
- const Ht = "pie-switch";
496
- let p = class extends Lt(q) {
495
+ const Wt = "pie-switch";
496
+ let p = class extends Lt(Nt(q)) {
497
497
  constructor() {
498
- super(...arguments), this.labelPlacement = k.labelPlacement, this.checked = k.checked, this.required = k.required, this.value = k.value, this.disabled = k.disabled, this._isAnimationAllowed = !1;
498
+ super(...arguments), this.labelPlacement = M.labelPlacement, this.checked = M.checked, this.required = M.required, this.value = M.value, this.disabled = M.disabled, this._isAnimationAllowed = !1;
499
499
  }
500
500
  firstUpdated() {
501
- this.handleFormAssociation(), this.input.addEventListener("invalid", (n) => {
502
- this.dispatchEvent(new Event("invalid", n));
501
+ this.handleFormAssociation(), this.input.addEventListener("invalid", (l) => {
502
+ this.dispatchEvent(new Event("invalid", l));
503
503
  });
504
504
  }
505
505
  updated() {
@@ -515,10 +515,10 @@ let p = class extends Lt(q) {
515
515
  * The handleChange function updates the checkbox state and emits an event for consumers.
516
516
  * @param {Event} event - This should be the change event that was listened for on an input element with `type="checkbox"`.
517
517
  */
518
- handleChange(n) {
519
- const { checked: l } = n == null ? void 0 : n.currentTarget;
520
- this.checked = l;
521
- const h = Nt(n);
518
+ handleChange(l) {
519
+ const { checked: n } = l == null ? void 0 : l.currentTarget;
520
+ this.checked = n;
521
+ const h = Ot(l);
522
522
  this._isAnimationAllowed || (this._isAnimationAllowed = !0), this.dispatchEvent(h), this.handleFormAssociation();
523
523
  }
524
524
  /**
@@ -541,8 +541,8 @@ let p = class extends Lt(q) {
541
541
  * Allows a consumer to set a custom validation message on the switch. An empty string counts as valid.
542
542
  * https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/setCustomValidity
543
543
  */
544
- setCustomValidity(n) {
545
- this.input.setCustomValidity(n), this._internals.setValidity(this.validity, this.validationMessage, this.input);
544
+ setCustomValidity(l) {
545
+ this.input.setCustomValidity(l), this._internals.setValidity(this.validity, this.validationMessage, this.input);
546
546
  }
547
547
  /**
548
548
  * (Read-only) returns a ValidityState with the validity states that this element is in.
@@ -565,19 +565,21 @@ let p = class extends Lt(q) {
565
565
  *
566
566
  * @private
567
567
  */
568
- renderSwitchLabel(n) {
569
- const { label: l, labelPlacement: h } = this;
570
- return !l || h !== n ? L : N`
568
+ renderSwitchLabel(l) {
569
+ const { label: n, labelPlacement: h } = this;
570
+ return !n || h !== l ? L : N`
571
571
  <span
572
+ aria-hidden="true"
572
573
  data-test-id="switch-label-${h}"
573
574
  class="c-switch-label">
574
- ${l}
575
+ ${n}
575
576
  </span>`;
576
577
  }
577
578
  renderAriaDescription() {
578
- var n;
579
- return (n = this.aria) != null && n.describedBy ? N`
579
+ var l;
580
+ return (l = this.aria) != null && l.describedBy ? N`
580
581
  <div
582
+ aria-hidden="true"
581
583
  id="switch-description"
582
584
  data-test-id="switch-description"
583
585
  class="c-switch-description">
@@ -586,37 +588,38 @@ let p = class extends Lt(q) {
586
588
  }
587
589
  render() {
588
590
  const {
591
+ label: l,
589
592
  aria: n,
590
- checked: l,
591
- disabled: h,
592
- required: m,
593
- _isAnimationAllowed: c
593
+ checked: h,
594
+ disabled: m,
595
+ required: c,
596
+ _isAnimationAllowed: g
594
597
  } = this;
595
598
  return N`
596
599
  <label
597
600
  class="${Vt({
598
601
  "c-switch-wrapper": !0,
599
- "c-switch-wrapper--allow-animation": c
602
+ "c-switch-wrapper--allow-animation": g
600
603
  })}"
601
- ?disabled=${h}>
604
+ ?disabled=${m}>
602
605
  ${this.renderSwitchLabel("leading")}
603
606
  <div
604
607
  data-test-id="switch-component"
605
608
  class="c-switch"
606
- ?checked=${l}>
609
+ ?checked=${h}>
607
610
  <input
608
611
  data-test-id="switch-input"
609
612
  role="switch"
610
613
  type="checkbox"
611
614
  class="c-switch-input"
612
- .required=${m}
613
- .checked="${l}"
614
- .disabled="${h}"
615
+ .required=${c}
616
+ .checked="${h}"
617
+ .disabled="${m}"
615
618
  @change="${this.handleChange}"
616
- aria-label="${Tt(n == null ? void 0 : n.label)}"
619
+ aria-label="${Tt((n == null ? void 0 : n.label) || l)}"
617
620
  aria-describedby="${n != null && n.describedBy ? "switch-description" : L}">
618
621
  <div class="c-switch-control">
619
- ${l ? N`<icon-check></icon-check>` : L}
622
+ ${h ? N`<icon-check></icon-check>` : L}
620
623
  </div>
621
624
  </div>
622
625
  ${this.renderSwitchLabel("trailing")}
@@ -624,31 +627,31 @@ let p = class extends Lt(q) {
624
627
  </label>`;
625
628
  }
626
629
  };
627
- p.styles = It(_t);
630
+ p.styles = It($t);
628
631
  f([
629
- y({ type: String })
632
+ E({ type: String })
630
633
  ], p.prototype, "label", 2);
631
634
  f([
632
- y({ type: String }),
633
- Ot(Ht, $t, k.labelPlacement)
635
+ E({ type: String }),
636
+ Pt(Wt, Dt, M.labelPlacement)
634
637
  ], p.prototype, "labelPlacement", 2);
635
638
  f([
636
- y({ type: Object })
639
+ E({ type: Object })
637
640
  ], p.prototype, "aria", 2);
638
641
  f([
639
- y({ type: Boolean, reflect: !0 })
642
+ E({ type: Boolean, reflect: !0 })
640
643
  ], p.prototype, "checked", 2);
641
644
  f([
642
- y({ type: Boolean, reflect: !0 })
645
+ E({ type: Boolean, reflect: !0 })
643
646
  ], p.prototype, "required", 2);
644
647
  f([
645
- y({ type: String })
648
+ E({ type: String })
646
649
  ], p.prototype, "value", 2);
647
650
  f([
648
- y({ type: String, reflect: !0 })
651
+ E({ type: String, reflect: !0 })
649
652
  ], p.prototype, "name", 2);
650
653
  f([
651
- y({ type: Boolean, reflect: !0 })
654
+ E({ type: Boolean, reflect: !0 })
652
655
  ], p.prototype, "disabled", 2);
653
656
  f([
654
657
  dt('input[type="checkbox"]')
@@ -660,11 +663,11 @@ f([
660
663
  St()
661
664
  ], p.prototype, "_isAnimationAllowed", 2);
662
665
  p = f([
663
- Pt("pie-switch")
666
+ _t("pie-switch")
664
667
  ], p);
665
668
  export {
666
- Gt as ON_SWITCH_CHANGED_EVENT,
669
+ Yt as ON_SWITCH_CHANGED_EVENT,
667
670
  p as PieSwitch,
668
- k as defaultProps,
669
- $t as labelPlacements
671
+ M as defaultProps,
672
+ Dt as labelPlacements
670
673
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@justeattakeaway/pie-switch",
3
3
  "description": "PIE Design System Switch built using Web Components",
4
- "version": "2.1.0",
4
+ "version": "2.3.0",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/justeattakeaway/pie",
@@ -40,14 +40,14 @@
40
40
  "devDependencies": {
41
41
  "@custom-elements-manifest/analyzer": "0.9.0",
42
42
  "@justeattakeaway/pie-components-config": "0.21.0",
43
- "@justeattakeaway/pie-css": "0.19.0",
43
+ "@justeattakeaway/pie-css": "0.22.0",
44
44
  "@justeattakeaway/pie-monorepo-utils": "0.7.0",
45
45
  "@justeattakeaway/pie-wrapper-react": "0.14.3",
46
46
  "cem-plugin-module-file-extensions": "0.0.5"
47
47
  },
48
48
  "dependencies": {
49
- "@justeattakeaway/pie-icons-webc": "1.14.2",
50
- "@justeattakeaway/pie-webc-core": "1.1.0",
49
+ "@justeattakeaway/pie-icons-webc": "1.15.0",
50
+ "@justeattakeaway/pie-webc-core": "2.0.0",
51
51
  "element-internals-polyfill": "1.3.11"
52
52
  },
53
53
  "volta": {
package/src/index.ts CHANGED
@@ -10,6 +10,7 @@ import 'element-internals-polyfill';
10
10
  import {
11
11
  validPropertyValues,
12
12
  FormControlMixin,
13
+ DelegatesFocusMixin,
13
14
  wrapNativeEvent,
14
15
  safeCustomElement,
15
16
  type PIEInputElement,
@@ -29,7 +30,7 @@ const componentSelector = 'pie-switch';
29
30
  * @event {CustomEvent} change - when the switch checked state is changed.
30
31
  */
31
32
  @safeCustomElement('pie-switch')
32
- export class PieSwitch extends FormControlMixin(PieElement) implements SwitchProps, PIEInputElement {
33
+ export class PieSwitch extends FormControlMixin(DelegatesFocusMixin(PieElement)) implements SwitchProps, PIEInputElement {
33
34
  @property({ type: String })
34
35
  public label: SwitchProps['label'];
35
36
 
@@ -172,8 +173,11 @@ export class PieSwitch extends FormControlMixin(PieElement) implements SwitchPro
172
173
  return nothing;
173
174
  }
174
175
 
176
+ // Using aria-hidden here to prevent the label from potentially being narrated twice by screen readers such as Apple VoiceOver.
177
+ // Instead, we apply the label as an aria-label attribute on the input (if no aria.label prop is provided).
175
178
  return html`
176
179
  <span
180
+ aria-hidden="true"
177
181
  data-test-id="switch-label-${labelPlacement}"
178
182
  class="c-switch-label">
179
183
  ${label}
@@ -185,8 +189,11 @@ export class PieSwitch extends FormControlMixin(PieElement) implements SwitchPro
185
189
  return nothing;
186
190
  }
187
191
 
192
+ // we apply aria-hidden to the element containing the description because it prevent some screen readers such as Apple VoiceOver from announcing the description once
193
+ // on the input and again separately. The description is still announced once, when the input is focused/selected.
188
194
  return html`
189
195
  <div
196
+ aria-hidden="true"
190
197
  id="switch-description"
191
198
  data-test-id="switch-description"
192
199
  class="c-switch-description">
@@ -196,6 +203,7 @@ export class PieSwitch extends FormControlMixin(PieElement) implements SwitchPro
196
203
 
197
204
  render () {
198
205
  const {
206
+ label,
199
207
  aria,
200
208
  checked,
201
209
  disabled,
@@ -226,7 +234,7 @@ export class PieSwitch extends FormControlMixin(PieElement) implements SwitchPro
226
234
  .checked="${checked}"
227
235
  .disabled="${disabled}"
228
236
  @change="${this.handleChange}"
229
- aria-label="${ifDefined(aria?.label)}"
237
+ aria-label="${ifDefined(aria?.label || label)}"
230
238
  aria-describedby="${aria?.describedBy ? 'switch-description' : nothing}">
231
239
  <div class="c-switch-control">
232
240
  ${checked ? html`<icon-check></icon-check>` : nothing}
package/src/switch.scss CHANGED
@@ -123,7 +123,7 @@
123
123
  }
124
124
 
125
125
  .c-switch-label {
126
- color: var(--dt-color-content-default);
126
+ color: var(--dt-color-content-default-solid);
127
127
  }
128
128
 
129
129
  // The description is only required for screen readers so we need to visually hide the description