@spectrum-web-components/picker 1.2.0-beta.9 → 1.3.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/Picker.d.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { CSSResultArray, PropertyValues, TemplateResult } from '@spectrum-web-components/base';
1
+ import { CSSResultArray, PropertyValues, SpectrumElement, TemplateResult } from '@spectrum-web-components/base';
2
2
  import { StyleInfo } from '@spectrum-web-components/base/src/directives.js';
3
- import { Focusable } from '@spectrum-web-components/shared/src/focusable.js';
4
3
  import type { Tooltip } from '@spectrum-web-components/tooltip';
5
4
  import '@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js';
6
5
  import '@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js';
7
6
  import '@spectrum-web-components/menu/sp-menu.js';
8
7
  import type { Menu, MenuItem, MenuItemChildren } from '@spectrum-web-components/menu';
8
+ import type { MenuItemKeydownEvent } from '@spectrum-web-components/menu';
9
9
  import { Placement } from '@spectrum-web-components/overlay';
10
10
  import { MatchMediaController } from '@spectrum-web-components/reactive-controllers/src/MatchMedia.js';
11
11
  import { DependencyManagerController } from '@spectrum-web-components/reactive-controllers/src/DependencyManger.js';
@@ -16,11 +16,16 @@ import type { FieldLabel } from '@spectrum-web-components/field-label';
16
16
  import { DesktopController } from './DesktopController.js';
17
17
  import { MobileController } from './MobileController.js';
18
18
  export declare const DESCRIPTION_ID = "option-picker";
19
- declare const PickerBase_base: typeof Focusable & {
19
+ declare const PickerBase_base: typeof SpectrumElement & {
20
20
  new (...args: any[]): import("@spectrum-web-components/base").SizedElementInterface;
21
21
  prototype: import("@spectrum-web-components/base").SizedElementInterface;
22
22
  };
23
23
  export declare class PickerBase extends PickerBase_base {
24
+ static shadowRootOptions: {
25
+ delegatesFocus: boolean;
26
+ mode: ShadowRootMode;
27
+ slotAssignment?: SlotAssignmentMode | undefined;
28
+ };
24
29
  isMobile: MatchMediaController;
25
30
  strategy: DesktopController | MobileController;
26
31
  appliedLabel?: string;
@@ -48,7 +53,9 @@ export declare class PickerBase extends PickerBase_base {
48
53
  labelAlignment?: 'inline';
49
54
  protected get menuItems(): MenuItem[];
50
55
  optionsMenu: Menu;
51
- private _selfManageFocusElement;
56
+ /**
57
+ * @deprecated
58
+ * */
52
59
  get selfManageFocusElement(): boolean;
53
60
  overlayElement: Overlay;
54
61
  protected tooltipEl?: Tooltip;
@@ -73,12 +80,19 @@ export declare class PickerBase extends PickerBase_base {
73
80
  get focusElement(): HTMLElement;
74
81
  forceFocusVisible(): void;
75
82
  click(): void;
83
+ handleButtonClick(): void;
76
84
  handleButtonBlur(): void;
77
85
  focus(options?: FocusOptions): void;
86
+ /**
87
+ * @deprecated - Use `focus` instead.
88
+ */
78
89
  handleHelperFocus(): void;
90
+ handleFocus(): void;
79
91
  handleChange(event: Event): void;
80
92
  handleButtonFocus(event: FocusEvent): void;
93
+ protected handleEscape: (event: MenuItemKeydownEvent | KeyboardEvent) => void;
81
94
  protected handleKeydown: (event: KeyboardEvent) => void;
95
+ protected keyboardOpen(): Promise<void>;
82
96
  protected setValueFromItem(item: MenuItem, menuChangeEvent?: Event): Promise<void>;
83
97
  protected setMenuItemSelected(item: MenuItem, value: boolean): void;
84
98
  toggle(target?: boolean): void;
@@ -94,9 +108,12 @@ export declare class PickerBase extends PickerBase_base {
94
108
  protected renderLabelContent(content: Node[]): TemplateResult | Node[];
95
109
  protected get buttonContent(): TemplateResult[];
96
110
  applyFocusElementLabel: (value: string, labelElement: FieldLabel) => void;
111
+ protected hasAccessibleLabel(): boolean;
112
+ protected warnNoLabel(): void;
97
113
  protected renderOverlay(menu: TemplateResult): TemplateResult;
98
114
  protected get renderDescriptionSlot(): TemplateResult;
99
115
  protected render(): TemplateResult;
116
+ protected willUpdate(changes: PropertyValues<this>): void;
100
117
  protected update(changes: PropertyValues<this>): void;
101
118
  protected bindButtonKeydownListener(): void;
102
119
  protected updated(changes: PropertyValues<this>): void;
@@ -106,9 +123,22 @@ export declare class PickerBase extends PickerBase_base {
106
123
  protected hasRenderedOverlay: boolean;
107
124
  private onScroll;
108
125
  protected get renderMenu(): TemplateResult;
109
- private willManageSelection;
126
+ /**
127
+ * whether a selection change is already scheduled
128
+ */
129
+ willManageSelection: boolean;
130
+ /**
131
+ * when the value changes or the menu slot changes, manage the selection on the next frame, if not already scheduled
132
+ * @param event
133
+ */
110
134
  protected shouldScheduleManageSelection(event?: Event): void;
135
+ /**
136
+ * when an item is added or updated, manage the selection, if it's not already scheduled
137
+ */
111
138
  protected shouldManageSelection(): void;
139
+ /**
140
+ * updates menu selection based on value
141
+ */
112
142
  protected manageSelection(): Promise<void>;
113
143
  private selectionPromise;
114
144
  private selectionResolver;
package/src/Picker.dev.js CHANGED
@@ -13,7 +13,8 @@ import {
13
13
  html,
14
14
  nothing,
15
15
  render,
16
- SizedMixin
16
+ SizedMixin,
17
+ SpectrumElement
17
18
  } from "@spectrum-web-components/base";
18
19
  import {
19
20
  classMap,
@@ -27,8 +28,6 @@ import {
27
28
  } from "@spectrum-web-components/base/src/decorators.js";
28
29
  import pickerStyles from "./picker.css.js";
29
30
  import chevronStyles from "@spectrum-web-components/icon/src/spectrum-icon-chevron.css.js";
30
- import chevronIconOverrides from "@spectrum-web-components/icon/src/icon-chevron-overrides.css.js";
31
- import { Focusable } from "@spectrum-web-components/shared/src/focusable.js";
32
31
  import "@spectrum-web-components/icons-ui/icons/sp-icon-chevron100.js";
33
32
  import "@spectrum-web-components/icons-workflow/icons/sp-icon-alert.js";
34
33
  import "@spectrum-web-components/menu/sp-menu.js";
@@ -46,7 +45,9 @@ const chevronClass = {
46
45
  xl: "spectrum-UIIcon-ChevronDown300"
47
46
  };
48
47
  export const DESCRIPTION_ID = "option-picker";
49
- export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
48
+ export class PickerBase extends SizedMixin(SpectrumElement, {
49
+ noDefaultSize: true
50
+ }) {
50
51
  /**
51
52
  * Initializes the `PendingStateController` for the Picker component.
52
53
  * The `PendingStateController` manages the pending state of the Picker.
@@ -65,20 +66,32 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
65
66
  this.open = false;
66
67
  this.readonly = false;
67
68
  this.selects = "single";
68
- this._selfManageFocusElement = false;
69
69
  this.placement = "bottom-start";
70
70
  this.quiet = false;
71
71
  this.value = "";
72
72
  this.listRole = "listbox";
73
73
  this.itemRole = "option";
74
+ this.handleEscape = (event) => {
75
+ if (event.key === "Escape") {
76
+ event.stopPropagation();
77
+ event.preventDefault();
78
+ this.toggle(false);
79
+ }
80
+ };
74
81
  this.handleKeydown = (event) => {
75
82
  this.focused = true;
76
- if (event.code !== "ArrowDown" && event.code !== "ArrowUp") {
83
+ if (!["ArrowUp", "ArrowDown", "Enter", " ", "Escape"].includes(
84
+ event.key
85
+ )) {
86
+ return;
87
+ }
88
+ if (event.key === "Escape") {
89
+ this.handleEscape(event);
77
90
  return;
78
91
  }
79
92
  event.stopPropagation();
80
93
  event.preventDefault();
81
- this.toggle(true);
94
+ this.keyboardOpen();
82
95
  };
83
96
  this.handleSlottableRequest = (_event) => {
84
97
  };
@@ -87,12 +100,20 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
87
100
  this.labelAlignment = labelElement.sideAligned ? "inline" : void 0;
88
101
  };
89
102
  this.hasRenderedOverlay = false;
103
+ /**
104
+ * whether a selection change is already scheduled
105
+ */
90
106
  this.willManageSelection = false;
91
107
  this.selectionPromise = Promise.resolve();
92
108
  this.recentlyConnected = false;
93
109
  this.enterKeydownOn = null;
94
110
  this.handleEnterKeydown = (event) => {
95
- if (event.code !== "Enter") {
111
+ if (event.key !== "Enter") {
112
+ return;
113
+ }
114
+ const target = event == null ? void 0 : event.target;
115
+ if (!target.open && target.hasSubmenu) {
116
+ event.preventDefault();
96
117
  return;
97
118
  }
98
119
  if (this.enterKeydownOn) {
@@ -103,7 +124,7 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
103
124
  this.addEventListener(
104
125
  "keyup",
105
126
  async (keyupEvent) => {
106
- if (keyupEvent.code !== "Enter") {
127
+ if (keyupEvent.key !== "Enter") {
107
128
  return;
108
129
  }
109
130
  this.enterKeydownOn = null;
@@ -116,8 +137,11 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
116
137
  get menuItems() {
117
138
  return this.optionsMenu.childItems;
118
139
  }
140
+ /**
141
+ * @deprecated
142
+ * */
119
143
  get selfManageFocusElement() {
120
- return this._selfManageFocusElement;
144
+ return true;
121
145
  }
122
146
  get selectedItem() {
123
147
  return this._selectedItem;
@@ -141,7 +165,12 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
141
165
  }
142
166
  this.focused = true;
143
167
  }
168
+ // handled by interaction controller, desktop or mobile; this is only called with a programmatic this.click()
144
169
  click() {
170
+ this.toggle();
171
+ }
172
+ // pointer events handled by interaction controller, desktop or mobile; this is only called with a programmatic this.button.click()
173
+ handleButtonClick() {
145
174
  if (this.disabled) {
146
175
  return;
147
176
  }
@@ -151,15 +180,21 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
151
180
  this.focused = false;
152
181
  }
153
182
  focus(options) {
154
- super.focus(options);
155
- if (!this.disabled && this.focusElement) {
156
- this.focused = this.hasVisibleFocusInTree();
157
- }
183
+ var _a;
184
+ (_a = this.focusElement) == null ? void 0 : _a.focus(options);
158
185
  }
186
+ /**
187
+ * @deprecated - Use `focus` instead.
188
+ */
159
189
  handleHelperFocus() {
160
190
  this.focused = true;
161
191
  this.button.focus();
162
192
  }
193
+ handleFocus() {
194
+ if (!this.disabled && this.focusElement) {
195
+ this.focused = this.hasVisibleFocusInTree();
196
+ }
197
+ }
163
198
  handleChange(event) {
164
199
  if (this.strategy) {
165
200
  this.strategy.preventNextToggle = "no";
@@ -180,6 +215,9 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
180
215
  var _a;
181
216
  (_a = this.strategy) == null ? void 0 : _a.handleButtonFocus(event);
182
217
  }
218
+ async keyboardOpen() {
219
+ this.toggle(true);
220
+ }
183
221
  async setValueFromItem(item, menuChangeEvent) {
184
222
  var _a;
185
223
  this.open = false;
@@ -229,18 +267,25 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
229
267
  item.selected = value;
230
268
  }
231
269
  toggle(target) {
232
- if (this.readonly || this.pending) {
270
+ if (this.readonly || this.pending || this.disabled) {
233
271
  return;
234
272
  }
235
- this.open = typeof target !== "undefined" ? target : !this.open;
273
+ const open = typeof target !== "undefined" ? target : !this.open;
274
+ if (open && !this.open)
275
+ this.addEventListener(
276
+ "sp-opened",
277
+ () => {
278
+ var _a;
279
+ return (_a = this.optionsMenu) == null ? void 0 : _a.focusOnFirstSelectedItem();
280
+ },
281
+ {
282
+ once: true
283
+ }
284
+ );
285
+ this.open = open;
236
286
  if (this.strategy) {
237
287
  this.strategy.open = this.open;
238
288
  }
239
- if (this.open) {
240
- this._selfManageFocusElement = true;
241
- } else {
242
- this._selfManageFocusElement = false;
243
- }
244
289
  }
245
290
  close() {
246
291
  if (this.readonly) {
@@ -332,11 +377,33 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
332
377
  aria-hidden="true"
333
378
  name="tooltip"
334
379
  id="tooltip"
380
+ @keydown=${this.handleKeydown}
335
381
  @slotchange=${this.handleTooltipSlotchange}
336
382
  ></slot>
337
383
  `
338
384
  ];
339
385
  }
386
+ hasAccessibleLabel() {
387
+ var _a, _b, _c, _d, _e, _f, _g;
388
+ const slotContent = ((_a = this.querySelector('[slot="label"]')) == null ? void 0 : _a.textContent) && ((_c = (_b = this.querySelector('[slot="label"]')) == null ? void 0 : _b.textContent) == null ? void 0 : _c.trim()) !== "";
389
+ const slotAlt = ((_e = (_d = this.querySelector('[slot="label"]')) == null ? void 0 : _d.getAttribute("alt")) == null ? void 0 : _e.trim()) && ((_g = (_f = this.querySelector('[slot="label"]')) == null ? void 0 : _f.getAttribute("alt")) == null ? void 0 : _g.trim()) !== "";
390
+ return !!this.label || !!this.getAttribute("aria-label") || !!this.getAttribute("aria-labelledby") || !!this.appliedLabel || !!slotContent || !!slotAlt;
391
+ }
392
+ warnNoLabel() {
393
+ window.__swc.warn(
394
+ this,
395
+ `<${this.localName}> needs one of the following to be accessible:`,
396
+ "https://opensource.adobe.com/spectrum-web-components/components/picker/#accessibility",
397
+ {
398
+ type: "accessibility",
399
+ issues: [
400
+ `an <sp-field-label> element with a \`for\` attribute referencing the \`id\` of the \`<${this.localName}>\`, or`,
401
+ 'value supplied to the "label" attribute, which will be displayed visually as placeholder text, or',
402
+ 'text content supplied in a <span> with slot="label", which will also be displayed visually as placeholder text.'
403
+ ]
404
+ }
405
+ );
406
+ }
340
407
  renderOverlay(menu) {
341
408
  var _a, _b, _c;
342
409
  if (((_a = this.strategy) == null ? void 0 : _a.overlay) === void 0) {
@@ -362,15 +429,9 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
362
429
  this.tooltipEl.disabled = this.open;
363
430
  }
364
431
  return html`
365
- <span
366
- id="focus-helper"
367
- tabindex="${this.focused || this.open ? "-1" : "0"}"
368
- @focus=${this.handleHelperFocus}
369
- aria-describedby=${DESCRIPTION_ID}
370
- ></span>
371
432
  <button
372
433
  aria-controls=${ifDefined(this.open ? "menu" : void 0)}
373
- aria-describedby="tooltip"
434
+ aria-describedby="tooltip ${DESCRIPTION_ID}"
374
435
  aria-expanded=${this.open ? "true" : "false"}
375
436
  aria-haspopup="true"
376
437
  aria-labelledby="loader icon label applied-label"
@@ -378,35 +439,36 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
378
439
  class=${ifDefined(
379
440
  this.labelAlignment ? `label-${this.labelAlignment}` : void 0
380
441
  )}
442
+ @focus=${this.handleButtonFocus}
381
443
  @blur=${this.handleButtonBlur}
382
444
  @keydown=${{
383
445
  handleEvent: this.handleEnterKeydown,
384
446
  capture: true
385
447
  }}
386
448
  ?disabled=${this.disabled}
387
- tabindex="-1"
388
449
  >
389
450
  ${this.buttonContent}
390
451
  </button>
391
452
  ${this.renderMenu} ${this.renderDescriptionSlot}
392
453
  `;
393
454
  }
455
+ willUpdate(changes) {
456
+ super.willUpdate(changes);
457
+ if (changes.has("tabIndex") && !!this.tabIndex) {
458
+ this.button.tabIndex = this.tabIndex;
459
+ this.removeAttribute("tabindex");
460
+ }
461
+ }
394
462
  update(changes) {
395
463
  var _a, _b;
396
464
  if (this.selects) {
397
465
  this.selects = "single";
398
466
  }
399
467
  if (changes.has("disabled") && this.disabled) {
400
- if (this.strategy) {
401
- this.open = false;
402
- this.strategy.open = false;
403
- }
468
+ this.close();
404
469
  }
405
470
  if (changes.has("pending") && this.pending) {
406
- if (this.strategy) {
407
- this.open = false;
408
- this.strategy.open = false;
409
- }
471
+ this.close();
410
472
  }
411
473
  if (changes.has("value")) {
412
474
  this.shouldScheduleManageSelection();
@@ -429,20 +491,8 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
429
491
  this.updateComplete.then(async () => {
430
492
  await new Promise((res) => requestAnimationFrame(res));
431
493
  await new Promise((res) => requestAnimationFrame(res));
432
- if (!this.label && !this.getAttribute("aria-label") && !this.getAttribute("aria-labelledby") && !this.appliedLabel) {
433
- window.__swc.warn(
434
- this,
435
- `<${this.localName}> needs one of the following to be accessible:`,
436
- "https://opensource.adobe.com/spectrum-web-components/components/picker/#accessibility",
437
- {
438
- type: "accessibility",
439
- issues: [
440
- `an <sp-field-label> element with a \`for\` attribute referencing the \`id\` of the \`<${this.localName}>\`, or`,
441
- 'value supplied to the "label" attribute, which will be displayed visually as placeholder text, or',
442
- 'text content supplied in a <span> with slot="label", which will also be displayed visually as placeholder text.'
443
- ]
444
- }
445
- );
494
+ if (!this.hasAccessibleLabel()) {
495
+ this.warnNoLabel();
446
496
  }
447
497
  });
448
498
  }
@@ -526,6 +576,7 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
526
576
  .selects=${this.selects}
527
577
  .selected=${this.value ? [this.value] : []}
528
578
  size=${this.size}
579
+ @sp-menu-item-keydown=${this.handleEscape}
529
580
  @sp-menu-item-added-or-updated=${this.shouldManageSelection}
530
581
  >
531
582
  <slot @slotchange=${this.shouldScheduleManageSelection}></slot>
@@ -540,6 +591,10 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
540
591
  }
541
592
  return menu;
542
593
  }
594
+ /**
595
+ * when the value changes or the menu slot changes, manage the selection on the next frame, if not already scheduled
596
+ * @param event
597
+ */
543
598
  shouldScheduleManageSelection(event) {
544
599
  if (!this.willManageSelection && (!event || event.target.getRootNode().host === this)) {
545
600
  this.willManageSelection = true;
@@ -550,6 +605,9 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
550
605
  });
551
606
  }
552
607
  }
608
+ /**
609
+ * when an item is added or updated, manage the selection, if it's not already scheduled
610
+ */
553
611
  shouldManageSelection() {
554
612
  if (this.willManageSelection) {
555
613
  return;
@@ -557,6 +615,9 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
557
615
  this.willManageSelection = true;
558
616
  this.manageSelection();
559
617
  }
618
+ /**
619
+ * updates menu selection based on value
620
+ */
560
621
  async manageSelection() {
561
622
  if (this.selects == null) return;
562
623
  this.selectionPromise = new Promise(
@@ -606,6 +667,7 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
606
667
  connectedCallback() {
607
668
  super.connectedCallback();
608
669
  this.recentlyConnected = this.hasUpdated;
670
+ this.addEventListener("focus", this.handleFocus);
609
671
  }
610
672
  disconnectedCallback() {
611
673
  var _a;
@@ -614,6 +676,10 @@ export class PickerBase extends SizedMixin(Focusable, { noDefaultSize: true }) {
614
676
  super.disconnectedCallback();
615
677
  }
616
678
  }
679
+ PickerBase.shadowRootOptions = {
680
+ ...SpectrumElement.shadowRootOptions,
681
+ delegatesFocus: true
682
+ };
617
683
  __decorateClass([
618
684
  state()
619
685
  ], PickerBase.prototype, "appliedLabel", 2);
@@ -678,33 +744,43 @@ export class Picker extends PickerBase {
678
744
  constructor() {
679
745
  super(...arguments);
680
746
  this.handleKeydown = (event) => {
681
- const { code } = event;
747
+ var _a;
748
+ const { key } = event;
749
+ const handledKeys = [
750
+ "ArrowUp",
751
+ "ArrowDown",
752
+ "ArrowLeft",
753
+ "ArrowRight",
754
+ "Enter",
755
+ " ",
756
+ "Escape"
757
+ ].includes(key);
758
+ const openKeys = ["ArrowUp", "ArrowDown", "Enter", " "].includes(key);
682
759
  this.focused = true;
683
- if (!code.startsWith("Arrow") || this.readonly || this.pending) {
760
+ if ("Escape" === key) {
761
+ this.handleEscape(event);
684
762
  return;
685
763
  }
686
- if (code === "ArrowUp" || code === "ArrowDown") {
687
- this.toggle(true);
688
- event.preventDefault();
764
+ if (!handledKeys || this.readonly || this.pending) {
689
765
  return;
690
766
  }
691
- event.preventDefault();
692
- const selectedIndex = this.selectedItem ? this.menuItems.indexOf(this.selectedItem) : -1;
693
- const nextOffset = selectedIndex < 0 || code === "ArrowRight" ? 1 : -1;
694
- let nextIndex = selectedIndex + nextOffset;
695
- while (this.menuItems[nextIndex] && this.menuItems[nextIndex].disabled) {
696
- nextIndex += nextOffset;
697
- }
698
- if (!this.menuItems[nextIndex] || this.menuItems[nextIndex].disabled) {
767
+ if (openKeys) {
768
+ this.keyboardOpen();
769
+ event.preventDefault();
699
770
  return;
700
771
  }
701
- if (!this.value || nextIndex !== selectedIndex) {
702
- this.setValueFromItem(this.menuItems[nextIndex]);
772
+ event.preventDefault();
773
+ const nextItem = (_a = this.optionsMenu) == null ? void 0 : _a.getNeighboringFocusableElement(
774
+ this.selectedItem,
775
+ key === "ArrowLeft"
776
+ );
777
+ if (!this.value || nextItem !== this.selectedItem) {
778
+ if (!!nextItem) this.setValueFromItem(nextItem);
703
779
  }
704
780
  };
705
781
  }
706
782
  static get styles() {
707
- return [pickerStyles, chevronStyles, chevronIconOverrides];
783
+ return [pickerStyles, chevronStyles];
708
784
  }
709
785
  get containerStyles() {
710
786
  const styles = super.containerStyles;