@vaadin/accordion 24.3.2 → 24.4.0-alpha2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vaadin/accordion",
3
- "version": "24.3.2",
3
+ "version": "24.4.0-alpha2",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -24,6 +24,8 @@
24
24
  "theme",
25
25
  "vaadin-*.d.ts",
26
26
  "vaadin-*.js",
27
+ "!vaadin-lit-*.d.ts",
28
+ "!vaadin-lit-*.js",
27
29
  "web-types.json",
28
30
  "web-types.lit.json"
29
31
  ],
@@ -35,13 +37,14 @@
35
37
  "polymer"
36
38
  ],
37
39
  "dependencies": {
40
+ "@open-wc/dedupe-mixin": "^1.3.0",
38
41
  "@polymer/polymer": "^3.0.0",
39
- "@vaadin/a11y-base": "~24.3.2",
40
- "@vaadin/component-base": "~24.3.2",
41
- "@vaadin/details": "~24.3.2",
42
- "@vaadin/vaadin-lumo-styles": "~24.3.2",
43
- "@vaadin/vaadin-material-styles": "~24.3.2",
44
- "@vaadin/vaadin-themable-mixin": "~24.3.2",
42
+ "@vaadin/a11y-base": "24.4.0-alpha2",
43
+ "@vaadin/component-base": "24.4.0-alpha2",
44
+ "@vaadin/details": "24.4.0-alpha2",
45
+ "@vaadin/vaadin-lumo-styles": "24.4.0-alpha2",
46
+ "@vaadin/vaadin-material-styles": "24.4.0-alpha2",
47
+ "@vaadin/vaadin-themable-mixin": "24.4.0-alpha2",
45
48
  "lit": "^3.0.0"
46
49
  },
47
50
  "devDependencies": {
@@ -53,5 +56,5 @@
53
56
  "web-types.json",
54
57
  "web-types.lit.json"
55
58
  ],
56
- "gitHead": "615ee9dd4611f52db90445b0db13dcbb91ca74d4"
59
+ "gitHead": "f303ead58d27e15d81a55db0559611fb77c0e421"
57
60
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { CSSResult } from 'lit';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { css } from 'lit';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { ActiveMixin } from '@vaadin/a11y-base/src/active-mixin.js';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { KeyboardDirectionMixinClass } from '@vaadin/a11y-base/src/keyboard-direction-mixin.js';
8
+
9
+ /**
10
+ * A mixin providing common accordion functionality.
11
+ */
12
+ export declare function AccordionMixin<T extends Constructor<HTMLElement>>(
13
+ base: T,
14
+ ): Constructor<AccordionMixinClass> & Constructor<KeyboardDirectionMixinClass> & T;
15
+
16
+ export declare class AccordionMixinClass {
17
+ /**
18
+ * The index of currently opened panel. First panel is opened by
19
+ * default. Only one panel can be opened at the same time.
20
+ * Setting null or undefined closes all the accordion panels.
21
+ */
22
+ opened: number | null;
23
+
24
+ /**
25
+ * The list of `<vaadin-accordion-panel>` child elements.
26
+ * It is populated from the elements passed to the light DOM,
27
+ * and updated dynamically when adding or removing panels.
28
+ */
29
+ readonly items: HTMLElement[];
30
+ }
@@ -0,0 +1,155 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { isElementFocused } from '@vaadin/a11y-base/src/focus-utils.js';
7
+ import { KeyboardDirectionMixin } from '@vaadin/a11y-base/src/keyboard-direction-mixin.js';
8
+ import { SlotObserver } from '@vaadin/component-base/src/slot-observer.js';
9
+
10
+ /**
11
+ * A mixin providing common accordion functionality.
12
+ *
13
+ * @polymerMixin
14
+ * @mixes KeyboardDirectionMixin
15
+ */
16
+ export const AccordionMixin = (superClass) =>
17
+ class AccordionMixinClass extends KeyboardDirectionMixin(superClass) {
18
+ static get properties() {
19
+ return {
20
+ /**
21
+ * The index of currently opened panel. First panel is opened by
22
+ * default. Only one panel can be opened at the same time.
23
+ * Setting null or undefined closes all the accordion panels.
24
+ * @type {number}
25
+ */
26
+ opened: {
27
+ type: Number,
28
+ value: 0,
29
+ notify: true,
30
+ reflectToAttribute: true,
31
+ },
32
+
33
+ /**
34
+ * The list of `<vaadin-accordion-panel>` child elements.
35
+ * It is populated from the elements passed to the light DOM,
36
+ * and updated dynamically when adding or removing panels.
37
+ * @type {!Array<!AccordionPanel>}
38
+ */
39
+ items: {
40
+ type: Array,
41
+ readOnly: true,
42
+ notify: true,
43
+ },
44
+ };
45
+ }
46
+
47
+ static get observers() {
48
+ return ['_updateItems(items, opened)'];
49
+ }
50
+
51
+ constructor() {
52
+ super();
53
+ this._boundUpdateOpened = this._updateOpened.bind(this);
54
+ }
55
+
56
+ /**
57
+ * Override getter from `KeyboardDirectionMixin`
58
+ * to check if the heading element has focus.
59
+ *
60
+ * @return {Element | null}
61
+ * @protected
62
+ * @override
63
+ */
64
+ get focused() {
65
+ return (this._getItems() || []).find((item) => isElementFocused(item.focusElement));
66
+ }
67
+
68
+ /**
69
+ * @protected
70
+ * @override
71
+ */
72
+ focus() {
73
+ if (this._observer) {
74
+ this._observer.flush();
75
+ }
76
+ super.focus();
77
+ }
78
+
79
+ /** @protected */
80
+ ready() {
81
+ super.ready();
82
+
83
+ const slot = this.shadowRoot.querySelector('slot');
84
+ this._observer = new SlotObserver(slot, (info) => {
85
+ this._setItems(this._filterItems(Array.from(this.children)));
86
+
87
+ this._filterItems(info.addedNodes).forEach((el) => {
88
+ el.addEventListener('opened-changed', this._boundUpdateOpened);
89
+ });
90
+ });
91
+ }
92
+
93
+ /**
94
+ * Override method inherited from `KeyboardDirectionMixin`
95
+ * to use the stored list of accordion panels as items.
96
+ *
97
+ * @return {Element[]}
98
+ * @protected
99
+ * @override
100
+ */
101
+ _getItems() {
102
+ return this.items;
103
+ }
104
+
105
+ /**
106
+ * @param {!Array<!Element>} array
107
+ * @return {!Array<!AccordionPanel>}
108
+ * @protected
109
+ */
110
+ _filterItems(array) {
111
+ return array.filter((el) => el instanceof customElements.get('vaadin-accordion-panel'));
112
+ }
113
+
114
+ /** @private */
115
+ _updateItems(items, opened) {
116
+ if (items) {
117
+ const itemToOpen = items[opened];
118
+ items.forEach((item) => {
119
+ item.opened = item === itemToOpen;
120
+ });
121
+ }
122
+ }
123
+
124
+ /**
125
+ * Override an event listener from `KeyboardMixin`
126
+ * to only handle details toggle buttons events.
127
+ *
128
+ * @param {!KeyboardEvent} event
129
+ * @protected
130
+ * @override
131
+ */
132
+ _onKeyDown(event) {
133
+ // Only check keyboard events on details toggle buttons
134
+ if (!this.items.some((item) => item.focusElement === event.target)) {
135
+ return;
136
+ }
137
+
138
+ super._onKeyDown(event);
139
+ }
140
+
141
+ /** @private */
142
+ _updateOpened(e) {
143
+ const target = this._filterItems(e.composedPath())[0];
144
+ const idx = this.items.indexOf(target);
145
+ if (e.detail.value) {
146
+ if (target.disabled || idx === -1) {
147
+ return;
148
+ }
149
+
150
+ this.opened = idx;
151
+ } else if (!this.items.some((item) => item.opened)) {
152
+ this.opened = null;
153
+ }
154
+ }
155
+ };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type { DelegateFocusMixinClass } from '@vaadin/a11y-base/src/delegate-focus-mixin.js';
8
+ import type { DisabledMixinClass } from '@vaadin/a11y-base/src/disabled-mixin.js';
9
+ import type { FocusMixinClass } from '@vaadin/a11y-base/src/focus-mixin.js';
10
+ import type { TabindexMixinClass } from '@vaadin/a11y-base/src/tabindex-mixin.js';
11
+ import type { DelegateStateMixinClass } from '@vaadin/component-base/src/delegate-state-mixin.js';
12
+ import type { CollapsibleMixinClass } from '@vaadin/details/src/collapsible-mixin.js';
13
+
14
+ /**
15
+ * A mixin providing common accordion panel functionality.
16
+ */
17
+ export declare function AccordionPanelMixin<T extends Constructor<HTMLElement>>(
18
+ base: T,
19
+ ): Constructor<AccordionPanelMixinClass> &
20
+ Constructor<CollapsibleMixinClass> &
21
+ Constructor<DelegateFocusMixinClass> &
22
+ Constructor<DelegateStateMixinClass> &
23
+ Constructor<DisabledMixinClass> &
24
+ Constructor<FocusMixinClass> &
25
+ Constructor<TabindexMixinClass> &
26
+ T;
27
+
28
+ export declare class AccordionPanelMixinClass {
29
+ /**
30
+ * A text that is displayed in the heading, if no
31
+ * element is assigned to the `summary` slot.
32
+ */
33
+ summary: string | null | undefined;
34
+ }
@@ -0,0 +1,105 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { DelegateFocusMixin } from '@vaadin/a11y-base/src/delegate-focus-mixin.js';
7
+ import { DelegateStateMixin } from '@vaadin/component-base/src/delegate-state-mixin.js';
8
+ import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
9
+ import { CollapsibleMixin } from '@vaadin/details/src/collapsible-mixin.js';
10
+ import { SummaryController } from '@vaadin/details/src/summary-controller.js';
11
+
12
+ /**
13
+ * A mixin providing common accordion panel functionality.
14
+ *
15
+ * @polymerMixin
16
+ * @mixes CollapsibleMixin
17
+ * @mixes DelegateFocusMixin
18
+ * @mixes DelegateStateMixin
19
+ */
20
+ export const AccordionPanelMixin = (superClass) =>
21
+ class AccordionPanelMixinClass extends CollapsibleMixin(DelegateFocusMixin(DelegateStateMixin(superClass))) {
22
+ static get properties() {
23
+ return {
24
+ /**
25
+ * A text that is displayed in the heading, if no
26
+ * element is assigned to the `summary` slot.
27
+ */
28
+ summary: {
29
+ type: String,
30
+ observer: '_summaryChanged',
31
+ },
32
+ };
33
+ }
34
+
35
+ static get observers() {
36
+ return ['__updateAriaAttributes(focusElement, _contentElements)'];
37
+ }
38
+
39
+ static get delegateAttrs() {
40
+ return ['theme'];
41
+ }
42
+
43
+ static get delegateProps() {
44
+ return ['disabled', 'opened'];
45
+ }
46
+
47
+ constructor() {
48
+ super();
49
+
50
+ this._summaryController = new SummaryController(this, 'vaadin-accordion-heading');
51
+ this._summaryController.addEventListener('slot-content-changed', (event) => {
52
+ const { node } = event.target;
53
+
54
+ this._setFocusElement(node);
55
+ this.stateTarget = node;
56
+
57
+ this._tooltipController.setTarget(node);
58
+ });
59
+
60
+ this._tooltipController = new TooltipController(this);
61
+ this._tooltipController.setPosition('bottom-start');
62
+ }
63
+
64
+ /** @protected */
65
+ ready() {
66
+ super.ready();
67
+
68
+ this.addController(this._summaryController);
69
+ this.addController(this._tooltipController);
70
+ }
71
+
72
+ /**
73
+ * Override method inherited from `DisabledMixin`
74
+ * to not set `aria-disabled` on the host element.
75
+ *
76
+ * @protected
77
+ * @override
78
+ */
79
+ _setAriaDisabled() {
80
+ // The `aria-disabled` is set on the details summary.
81
+ }
82
+
83
+ /** @private */
84
+ _summaryChanged(summary) {
85
+ this._summaryController.setSummary(summary);
86
+ }
87
+
88
+ /** @private */
89
+ __updateAriaAttributes(focusElement, contentElements) {
90
+ if (focusElement && contentElements) {
91
+ const node = contentElements[0];
92
+
93
+ if (node) {
94
+ node.setAttribute('role', 'region');
95
+ node.setAttribute('aria-labelledby', focusElement.id);
96
+ }
97
+
98
+ if (node && node.id) {
99
+ focusElement.setAttribute('aria-controls', node.id);
100
+ } else {
101
+ focusElement.removeAttribute('aria-controls');
102
+ }
103
+ }
104
+ }
105
+ };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { CSSResult } from 'lit';
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { css } from 'lit';
@@ -1,12 +1,10 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { DelegateFocusMixin } from '@vaadin/a11y-base/src/delegate-focus-mixin.js';
7
- import { DelegateStateMixin } from '@vaadin/component-base/src/delegate-state-mixin.js';
8
- import { CollapsibleMixin } from '@vaadin/details/src/collapsible-mixin.js';
9
6
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
7
+ import { AccordionPanelMixin } from './vaadin-accordion-panel-mixin.js';
10
8
 
11
9
  /**
12
10
  * Fired when the `opened` property changes.
@@ -43,15 +41,7 @@ export type AccordionPanelEventMap = AccordionPanelCustomEventMap & HTMLElementE
43
41
  *
44
42
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
45
43
  */
46
- declare class AccordionPanel extends CollapsibleMixin(
47
- DelegateFocusMixin(DelegateStateMixin(ThemableMixin(HTMLElement))),
48
- ) {
49
- /**
50
- * A text that is displayed in the heading, if no
51
- * element is assigned to the `summary` slot.
52
- */
53
- summary: string | null | undefined;
54
-
44
+ declare class AccordionPanel extends AccordionPanelMixin(ThemableMixin(HTMLElement)) {
55
45
  addEventListener<K extends keyof AccordionPanelEventMap>(
56
46
  type: K,
57
47
  listener: (this: AccordionPanel, ev: AccordionPanelEventMap[K]) => void,
@@ -1,18 +1,14 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import './vaadin-accordion-heading.js';
7
7
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
8
- import { DelegateFocusMixin } from '@vaadin/a11y-base/src/delegate-focus-mixin.js';
9
8
  import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
10
9
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
11
- import { DelegateStateMixin } from '@vaadin/component-base/src/delegate-state-mixin.js';
12
- import { TooltipController } from '@vaadin/component-base/src/tooltip-controller.js';
13
- import { CollapsibleMixin } from '@vaadin/details/src/collapsible-mixin.js';
14
- import { SummaryController } from '@vaadin/details/src/summary-controller.js';
15
10
  import { registerStyles, ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
+ import { AccordionPanelMixin } from './vaadin-accordion-panel-mixin.js';
16
12
  import { accordionPanel } from './vaadin-accordion-panel-styles.js';
17
13
 
18
14
  registerStyles('vaadin-accordion-panel', accordionPanel, { moduleId: 'vaadin-accordion-panel-styles' });
@@ -43,15 +39,11 @@ registerStyles('vaadin-accordion-panel', accordionPanel, { moduleId: 'vaadin-acc
43
39
  *
44
40
  * @customElement
45
41
  * @extends HTMLElement
46
- * @mixes CollapsibleMixin
42
+ * @mixes AccordionPanelMixin
47
43
  * @mixes ControllerMixin
48
- * @mixes DelegateFocusMixin
49
- * @mixes DelegateStateMixin
50
44
  * @mixes ThemableMixin
51
45
  */
52
- class AccordionPanel extends CollapsibleMixin(
53
- DelegateFocusMixin(DelegateStateMixin(ThemableMixin(ControllerMixin(PolymerElement)))),
54
- ) {
46
+ class AccordionPanel extends AccordionPanelMixin(ThemableMixin(ControllerMixin(PolymerElement))) {
55
47
  static get is() {
56
48
  return 'vaadin-accordion-panel';
57
49
  }
@@ -67,90 +59,6 @@ class AccordionPanel extends CollapsibleMixin(
67
59
  <slot name="tooltip"></slot>
68
60
  `;
69
61
  }
70
-
71
- static get properties() {
72
- return {
73
- /**
74
- * A text that is displayed in the heading, if no
75
- * element is assigned to the `summary` slot.
76
- */
77
- summary: {
78
- type: String,
79
- observer: '_summaryChanged',
80
- },
81
- };
82
- }
83
-
84
- static get observers() {
85
- return ['__updateAriaAttributes(focusElement, _contentElements)'];
86
- }
87
-
88
- static get delegateAttrs() {
89
- return ['theme'];
90
- }
91
-
92
- static get delegateProps() {
93
- return ['disabled', 'opened'];
94
- }
95
-
96
- constructor() {
97
- super();
98
-
99
- this._summaryController = new SummaryController(this, 'vaadin-accordion-heading');
100
- this._summaryController.addEventListener('slot-content-changed', (event) => {
101
- const { node } = event.target;
102
-
103
- this._setFocusElement(node);
104
- this.stateTarget = node;
105
-
106
- this._tooltipController.setTarget(node);
107
- });
108
-
109
- this._tooltipController = new TooltipController(this);
110
- this._tooltipController.setPosition('bottom-start');
111
- }
112
-
113
- /** @protected */
114
- ready() {
115
- super.ready();
116
-
117
- this.addController(this._summaryController);
118
- this.addController(this._tooltipController);
119
- }
120
-
121
- /**
122
- * Override method inherited from `DisabledMixin`
123
- * to not set `aria-disabled` on the host element.
124
- *
125
- * @protected
126
- * @override
127
- */
128
- _setAriaDisabled() {
129
- // The `aria-disabled` is set on the details summary.
130
- }
131
-
132
- /** @private */
133
- _summaryChanged(summary) {
134
- this._summaryController.setSummary(summary);
135
- }
136
-
137
- /** @private */
138
- __updateAriaAttributes(focusElement, contentElements) {
139
- if (focusElement && contentElements) {
140
- const node = contentElements[0];
141
-
142
- if (node) {
143
- node.setAttribute('role', 'region');
144
- node.setAttribute('aria-labelledby', focusElement.id);
145
- }
146
-
147
- if (node && node.id) {
148
- focusElement.setAttribute('aria-controls', node.id);
149
- } else {
150
- focusElement.removeAttribute('aria-controls');
151
- }
152
- }
153
- }
154
62
  }
155
63
 
156
64
  defineCustomElement(AccordionPanel);
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
- import { KeyboardDirectionMixin } from '@vaadin/a11y-base/src/keyboard-direction-mixin.js';
7
6
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
8
7
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
8
+ import { AccordionMixin } from './vaadin-accordion-mixin.js';
9
9
  import type { AccordionPanel } from './vaadin-accordion-panel.js';
10
10
 
11
11
  /**
@@ -70,21 +70,7 @@ export type AccordionEventMap = AccordionCustomEventMap & HTMLElementEventMap;
70
70
  * @fires {CustomEvent} items-changed - Fired when the `items` property changes.
71
71
  * @fires {CustomEvent} opened-changed - Fired when the `opened` property changes.
72
72
  */
73
- declare class Accordion extends KeyboardDirectionMixin(ElementMixin(ThemableMixin(HTMLElement))) {
74
- /**
75
- * The index of currently opened panel. First panel is opened by
76
- * default. Only one panel can be opened at the same time.
77
- * Setting null or undefined closes all the accordion panels.
78
- */
79
- opened: number | null;
80
-
81
- /**
82
- * The list of `<vaadin-accordion-panel>` child elements.
83
- * It is populated from the elements passed to the light DOM,
84
- * and updated dynamically when adding or removing panels.
85
- */
86
- readonly items: AccordionPanel[];
87
-
73
+ declare class Accordion extends AccordionMixin(ElementMixin(ThemableMixin(HTMLElement))) {
88
74
  addEventListener<K extends keyof AccordionEventMap>(
89
75
  type: K,
90
76
  listener: (this: Accordion, ev: AccordionEventMap[K]) => void,
@@ -1,16 +1,14 @@
1
1
  /**
2
2
  * @license
3
- * Copyright (c) 2019 - 2023 Vaadin Ltd.
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
+ import './vaadin-accordion-panel.js';
6
7
  import { html, PolymerElement } from '@polymer/polymer/polymer-element.js';
7
- import { isElementFocused } from '@vaadin/a11y-base/src/focus-utils.js';
8
- import { KeyboardDirectionMixin } from '@vaadin/a11y-base/src/keyboard-direction-mixin.js';
9
8
  import { defineCustomElement } from '@vaadin/component-base/src/define.js';
10
9
  import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
11
- import { SlotObserver } from '@vaadin/component-base/src/slot-observer.js';
12
10
  import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
13
- import { AccordionPanel } from './vaadin-accordion-panel.js';
11
+ import { AccordionMixin } from './vaadin-accordion-mixin.js';
14
12
 
15
13
  /**
16
14
  * `<vaadin-accordion>` is a Web Component implementing accordion widget:
@@ -58,11 +56,11 @@ import { AccordionPanel } from './vaadin-accordion-panel.js';
58
56
  *
59
57
  * @customElement
60
58
  * @extends HTMLElement
59
+ * @mixes AccordionMixin
61
60
  * @mixes ElementMixin
62
- * @mixes KeyboardDirectionMixin
63
61
  * @mixes ThemableMixin
64
62
  */
65
- class Accordion extends KeyboardDirectionMixin(ThemableMixin(ElementMixin(PolymerElement))) {
63
+ class Accordion extends AccordionMixin(ThemableMixin(ElementMixin(PolymerElement))) {
66
64
  static get template() {
67
65
  return html`
68
66
  <style>
@@ -81,144 +79,6 @@ class Accordion extends KeyboardDirectionMixin(ThemableMixin(ElementMixin(Polyme
81
79
  static get is() {
82
80
  return 'vaadin-accordion';
83
81
  }
84
-
85
- static get properties() {
86
- return {
87
- /**
88
- * The index of currently opened panel. First panel is opened by
89
- * default. Only one panel can be opened at the same time.
90
- * Setting null or undefined closes all the accordion panels.
91
- * @type {number}
92
- */
93
- opened: {
94
- type: Number,
95
- value: 0,
96
- notify: true,
97
- reflectToAttribute: true,
98
- },
99
-
100
- /**
101
- * The list of `<vaadin-accordion-panel>` child elements.
102
- * It is populated from the elements passed to the light DOM,
103
- * and updated dynamically when adding or removing panels.
104
- * @type {!Array<!AccordionPanel>}
105
- */
106
- items: {
107
- type: Array,
108
- readOnly: true,
109
- notify: true,
110
- },
111
- };
112
- }
113
-
114
- static get observers() {
115
- return ['_updateItems(items, opened)'];
116
- }
117
-
118
- constructor() {
119
- super();
120
- this._boundUpdateOpened = this._updateOpened.bind(this);
121
- }
122
-
123
- /**
124
- * Override getter from `KeyboardDirectionMixin`
125
- * to check if the heading element has focus.
126
- *
127
- * @return {Element | null}
128
- * @protected
129
- * @override
130
- */
131
- get focused() {
132
- return (this._getItems() || []).find((item) => isElementFocused(item.focusElement));
133
- }
134
-
135
- /**
136
- * @protected
137
- * @override
138
- */
139
- focus() {
140
- if (this._observer) {
141
- this._observer.flush();
142
- }
143
- super.focus();
144
- }
145
-
146
- /** @protected */
147
- ready() {
148
- super.ready();
149
-
150
- const slot = this.shadowRoot.querySelector('slot');
151
- this._observer = new SlotObserver(slot, (info) => {
152
- this._setItems(this._filterItems(Array.from(this.children)));
153
-
154
- this._filterItems(info.addedNodes).forEach((el) => {
155
- el.addEventListener('opened-changed', this._boundUpdateOpened);
156
- });
157
- });
158
- }
159
-
160
- /**
161
- * Override method inherited from `KeyboardDirectionMixin`
162
- * to use the stored list of accordion panels as items.
163
- *
164
- * @return {Element[]}
165
- * @protected
166
- * @override
167
- */
168
- _getItems() {
169
- return this.items;
170
- }
171
-
172
- /**
173
- * @param {!Array<!Element>} array
174
- * @return {!Array<!AccordionPanel>}
175
- * @protected
176
- */
177
- _filterItems(array) {
178
- return array.filter((el) => el instanceof AccordionPanel);
179
- }
180
-
181
- /** @private */
182
- _updateItems(items, opened) {
183
- if (items) {
184
- const itemToOpen = items[opened];
185
- items.forEach((item) => {
186
- item.opened = item === itemToOpen;
187
- });
188
- }
189
- }
190
-
191
- /**
192
- * Override an event listener from `KeyboardMixin`
193
- * to only handle details toggle buttons events.
194
- *
195
- * @param {!KeyboardEvent} event
196
- * @protected
197
- * @override
198
- */
199
- _onKeyDown(event) {
200
- // Only check keyboard events on details toggle buttons
201
- if (!this.items.some((item) => item.focusElement === event.target)) {
202
- return;
203
- }
204
-
205
- super._onKeyDown(event);
206
- }
207
-
208
- /** @private */
209
- _updateOpened(e) {
210
- const target = this._filterItems(e.composedPath())[0];
211
- const idx = this.items.indexOf(target);
212
- if (e.detail.value) {
213
- if (target.disabled || idx === -1) {
214
- return;
215
- }
216
-
217
- this.opened = idx;
218
- } else if (!this.items.some((item) => item.opened)) {
219
- this.opened = null;
220
- }
221
- }
222
82
  }
223
83
 
224
84
  defineCustomElement(Accordion);
@@ -0,0 +1 @@
1
+ export * from './vaadin-accordion-heading.js';
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import { html, LitElement } from 'lit';
7
+ import { ActiveMixin } from '@vaadin/a11y-base/src/active-mixin.js';
8
+ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
9
+ import { DirMixin } from '@vaadin/component-base/src/dir-mixin.js';
10
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
11
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
+ import { accordionHeading } from './vaadin-accordion-heading-styles.js';
13
+
14
+ /**
15
+ * LitElement based version of `<vaadin-accordion-heading>` web component.
16
+ *
17
+ * ## Disclaimer
18
+ *
19
+ * This component is an experiment not intended for publishing to npm.
20
+ * There is no ETA regarding specific Vaadin version where it'll land.
21
+ * Feel free to try this code in your apps as per Apache 2.0 license.
22
+ */
23
+ class AccordionHeading extends ActiveMixin(DirMixin(ThemableMixin(PolylitMixin(LitElement)))) {
24
+ static get is() {
25
+ return 'vaadin-accordion-heading';
26
+ }
27
+
28
+ static get shadowRootOptions() {
29
+ return { ...LitElement.shadowRootOptions, delegatesFocus: true };
30
+ }
31
+
32
+ static get styles() {
33
+ return accordionHeading;
34
+ }
35
+
36
+ static get properties() {
37
+ return {
38
+ /**
39
+ * When true, the element is opened.
40
+ */
41
+ opened: {
42
+ type: Boolean,
43
+ reflectToAttribute: true,
44
+ },
45
+ };
46
+ }
47
+
48
+ /** @protected */
49
+ render() {
50
+ return html`
51
+ <button id="button" part="content" ?disabled="${this.disabled}" aria-expanded="${this.opened ? 'true' : 'false'}">
52
+ <span part="toggle" aria-hidden="true"></span>
53
+ <slot></slot>
54
+ </button>
55
+ `;
56
+ }
57
+
58
+ /** @protected */
59
+ ready() {
60
+ super.ready();
61
+
62
+ // By default, if the user hasn't provided a custom role,
63
+ // the role attribute is set to "heading".
64
+ if (!this.hasAttribute('role')) {
65
+ this.setAttribute('role', 'heading');
66
+ }
67
+ }
68
+ }
69
+
70
+ defineCustomElement(AccordionHeading);
71
+
72
+ export { AccordionHeading };
@@ -0,0 +1 @@
1
+ export * from './vaadin-accordion-panel.js';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import './vaadin-lit-accordion-heading.js';
7
+ import { html, LitElement } from 'lit';
8
+ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
9
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
10
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
11
+ import { AccordionPanelMixin } from './vaadin-accordion-panel-mixin.js';
12
+ import { accordionPanel } from './vaadin-accordion-panel-styles.js';
13
+
14
+ /**
15
+ * LitElement based version of `<vaadin-accordion-panel>` web component.
16
+ *
17
+ * ## Disclaimer
18
+ *
19
+ * This component is an experiment not intended for publishing to npm.
20
+ * There is no ETA regarding specific Vaadin version where it'll land.
21
+ * Feel free to try this code in your apps as per Apache 2.0 license.
22
+ */
23
+ class AccordionPanel extends AccordionPanelMixin(ThemableMixin(PolylitMixin(LitElement))) {
24
+ static get is() {
25
+ return 'vaadin-accordion-panel';
26
+ }
27
+
28
+ static get styles() {
29
+ return accordionPanel;
30
+ }
31
+
32
+ /** @protected */
33
+ render() {
34
+ return html`
35
+ <slot name="summary"></slot>
36
+
37
+ <div part="content">
38
+ <slot></slot>
39
+ </div>
40
+
41
+ <slot name="tooltip"></slot>
42
+ `;
43
+ }
44
+ }
45
+
46
+ defineCustomElement(AccordionPanel);
47
+
48
+ export { AccordionPanel };
@@ -0,0 +1 @@
1
+ export * from './vaadin-accordion.js';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * @license
3
+ * Copyright (c) 2019 - 2024 Vaadin Ltd.
4
+ * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
+ */
6
+ import './vaadin-lit-accordion-panel.js';
7
+ import { css, html, LitElement } from 'lit';
8
+ import { defineCustomElement } from '@vaadin/component-base/src/define.js';
9
+ import { ElementMixin } from '@vaadin/component-base/src/element-mixin.js';
10
+ import { PolylitMixin } from '@vaadin/component-base/src/polylit-mixin.js';
11
+ import { ThemableMixin } from '@vaadin/vaadin-themable-mixin/vaadin-themable-mixin.js';
12
+ import { AccordionMixin } from './vaadin-accordion-mixin.js';
13
+
14
+ /**
15
+ * LitElement based version of `<vaadin-accordion>` web component.
16
+ *
17
+ * ## Disclaimer
18
+ *
19
+ * This component is an experiment not intended for publishing to npm.
20
+ * There is no ETA regarding specific Vaadin version where it'll land.
21
+ * Feel free to try this code in your apps as per Apache 2.0 license.
22
+ */
23
+ class Accordion extends AccordionMixin(ThemableMixin(ElementMixin(PolylitMixin(LitElement)))) {
24
+ static get is() {
25
+ return 'vaadin-accordion';
26
+ }
27
+
28
+ static get styles() {
29
+ return css`
30
+ :host {
31
+ display: block;
32
+ }
33
+
34
+ :host([hidden]) {
35
+ display: none !important;
36
+ }
37
+ `;
38
+ }
39
+
40
+ /** @protected */
41
+ render() {
42
+ return html`<slot></slot>`;
43
+ }
44
+ }
45
+
46
+ defineCustomElement(Accordion);
47
+
48
+ export { Accordion };
package/web-types.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/accordion",
4
- "version": "24.3.2",
4
+ "version": "24.4.0-alpha2",
5
5
  "description-markup": "markdown",
6
6
  "contributions": {
7
7
  "html": {
@@ -10,6 +10,17 @@
10
10
  "name": "vaadin-accordion-heading",
11
11
  "description": "The accordion heading element.\n\n`vaadin-accordion-heading` is the element for the headings in the accordion.\nAs recommended by the WAI ARIA Best Practices, each heading needs to wrap a\n`<button>`. This element puts that button in the Shadow DOM, as it is more\nconvenient to use and doesn't make styling of the heading more problematic.\n\nThe WAI ARIA Best Practices also recommend setting `aria-level` depending\non what level the headings are. It is hard to determine the level of a heading\nalgorithmically, and setting it is not strictly required to have an accessible\naccordion. To keep things easier to use, this element does not set `aria-level`\nattribute but leaves that to the developer creating an accordion.\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n-----------|-------------------\n`toggle` | The icon element\n`content` | The content wrapper\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-------------| -----------\n`active` | Set when the element is pressed down, either with mouse, touch or the keyboard.\n`opened` | Set when the collapsible content is expanded and visible.\n`disabled` | Set when the element is disabled.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
12
12
  "attributes": [
13
+ {
14
+ "name": "disabled",
15
+ "description": "If true, the user cannot interact with this element.",
16
+ "value": {
17
+ "type": [
18
+ "boolean",
19
+ "null",
20
+ "undefined"
21
+ ]
22
+ }
23
+ },
13
24
  {
14
25
  "name": "opened",
15
26
  "description": "When true, the element is opened.",
@@ -35,6 +46,17 @@
35
46
  ],
36
47
  "js": {
37
48
  "properties": [
49
+ {
50
+ "name": "disabled",
51
+ "description": "If true, the user cannot interact with this element.",
52
+ "value": {
53
+ "type": [
54
+ "boolean",
55
+ "null",
56
+ "undefined"
57
+ ]
58
+ }
59
+ },
38
60
  {
39
61
  "name": "opened",
40
62
  "description": "When true, the element is opened.",
@@ -163,7 +185,7 @@
163
185
  },
164
186
  {
165
187
  "name": "vaadin-accordion",
166
- "description": "`<vaadin-accordion>` is a Web Component implementing accordion widget:\na vertically stacked set of expandable panels. The component should be\nused as a wrapper for two or more `<vaadin-accordion-panel>` components.\n\nPanel headings function as controls that enable users to open (expand)\nor hide (collapse) their associated sections of content. The user can\ntoggle panels by mouse click, Enter and Space keys.\n\nOnly one panel can be opened at a time, opening a new one forces\nprevious panel to close and hide its content.\n\n```\n<vaadin-accordion>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 1</vaadin-accordion-heading>\n <div>This panel is opened, so the text is visible by default.</div>\n </vaadin-accordion-panel>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 2</vaadin-accordion-heading>\n <div>After opening this panel, the first one becomes closed.</div>\n </vaadin-accordion-panel>\n</vaadin-accordion>\n```\n\n### Styling\n\nSee the [`<vaadin-accordion-panel>`](https://cdn.vaadin.com/vaadin-web-components/24.3.2/#/elements/vaadin-accordion-panel)\ndocumentation for the available state attributes and stylable shadow parts.\n\n**Note:** You can apply the theme to `<vaadin-accordion>` component itself,\nespecially by using the following CSS selector:\n\n```\n:host ::slotted(vaadin-accordion-panel) {\n margin-bottom: 5px;\n}\n```\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
188
+ "description": "`<vaadin-accordion>` is a Web Component implementing accordion widget:\na vertically stacked set of expandable panels. The component should be\nused as a wrapper for two or more `<vaadin-accordion-panel>` components.\n\nPanel headings function as controls that enable users to open (expand)\nor hide (collapse) their associated sections of content. The user can\ntoggle panels by mouse click, Enter and Space keys.\n\nOnly one panel can be opened at a time, opening a new one forces\nprevious panel to close and hide its content.\n\n```\n<vaadin-accordion>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 1</vaadin-accordion-heading>\n <div>This panel is opened, so the text is visible by default.</div>\n </vaadin-accordion-panel>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 2</vaadin-accordion-heading>\n <div>After opening this panel, the first one becomes closed.</div>\n </vaadin-accordion-panel>\n</vaadin-accordion>\n```\n\n### Styling\n\nSee the [`<vaadin-accordion-panel>`](https://cdn.vaadin.com/vaadin-web-components/24.4.0-alpha2/#/elements/vaadin-accordion-panel)\ndocumentation for the available state attributes and stylable shadow parts.\n\n**Note:** You can apply the theme to `<vaadin-accordion>` component itself,\nespecially by using the following CSS selector:\n\n```\n:host ::slotted(vaadin-accordion-panel) {\n margin-bottom: 5px;\n}\n```\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
167
189
  "attributes": [
168
190
  {
169
191
  "name": "opened",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/web-types",
3
3
  "name": "@vaadin/accordion",
4
- "version": "24.3.2",
4
+ "version": "24.4.0-alpha2",
5
5
  "description-markup": "markdown",
6
6
  "framework": "lit",
7
7
  "framework-config": {
@@ -19,6 +19,13 @@
19
19
  "description": "The accordion heading element.\n\n`vaadin-accordion-heading` is the element for the headings in the accordion.\nAs recommended by the WAI ARIA Best Practices, each heading needs to wrap a\n`<button>`. This element puts that button in the Shadow DOM, as it is more\nconvenient to use and doesn't make styling of the heading more problematic.\n\nThe WAI ARIA Best Practices also recommend setting `aria-level` depending\non what level the headings are. It is hard to determine the level of a heading\nalgorithmically, and setting it is not strictly required to have an accessible\naccordion. To keep things easier to use, this element does not set `aria-level`\nattribute but leaves that to the developer creating an accordion.\n\n### Styling\n\nThe following shadow DOM parts are exposed for styling:\n\nPart name | Description\n-----------|-------------------\n`toggle` | The icon element\n`content` | The content wrapper\n\nThe following state attributes are available for styling:\n\nAttribute | Description\n-------------| -----------\n`active` | Set when the element is pressed down, either with mouse, touch or the keyboard.\n`opened` | Set when the collapsible content is expanded and visible.\n`disabled` | Set when the element is disabled.\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
20
20
  "extension": true,
21
21
  "attributes": [
22
+ {
23
+ "name": "?disabled",
24
+ "description": "If true, the user cannot interact with this element.",
25
+ "value": {
26
+ "kind": "expression"
27
+ }
28
+ },
22
29
  {
23
30
  "name": "?opened",
24
31
  "description": "When true, the element is opened.",
@@ -72,7 +79,7 @@
72
79
  },
73
80
  {
74
81
  "name": "vaadin-accordion",
75
- "description": "`<vaadin-accordion>` is a Web Component implementing accordion widget:\na vertically stacked set of expandable panels. The component should be\nused as a wrapper for two or more `<vaadin-accordion-panel>` components.\n\nPanel headings function as controls that enable users to open (expand)\nor hide (collapse) their associated sections of content. The user can\ntoggle panels by mouse click, Enter and Space keys.\n\nOnly one panel can be opened at a time, opening a new one forces\nprevious panel to close and hide its content.\n\n```\n<vaadin-accordion>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 1</vaadin-accordion-heading>\n <div>This panel is opened, so the text is visible by default.</div>\n </vaadin-accordion-panel>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 2</vaadin-accordion-heading>\n <div>After opening this panel, the first one becomes closed.</div>\n </vaadin-accordion-panel>\n</vaadin-accordion>\n```\n\n### Styling\n\nSee the [`<vaadin-accordion-panel>`](https://cdn.vaadin.com/vaadin-web-components/24.3.2/#/elements/vaadin-accordion-panel)\ndocumentation for the available state attributes and stylable shadow parts.\n\n**Note:** You can apply the theme to `<vaadin-accordion>` component itself,\nespecially by using the following CSS selector:\n\n```\n:host ::slotted(vaadin-accordion-panel) {\n margin-bottom: 5px;\n}\n```\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
82
+ "description": "`<vaadin-accordion>` is a Web Component implementing accordion widget:\na vertically stacked set of expandable panels. The component should be\nused as a wrapper for two or more `<vaadin-accordion-panel>` components.\n\nPanel headings function as controls that enable users to open (expand)\nor hide (collapse) their associated sections of content. The user can\ntoggle panels by mouse click, Enter and Space keys.\n\nOnly one panel can be opened at a time, opening a new one forces\nprevious panel to close and hide its content.\n\n```\n<vaadin-accordion>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 1</vaadin-accordion-heading>\n <div>This panel is opened, so the text is visible by default.</div>\n </vaadin-accordion-panel>\n <vaadin-accordion-panel>\n <vaadin-accordion-heading slot=\"summary\">Panel 2</vaadin-accordion-heading>\n <div>After opening this panel, the first one becomes closed.</div>\n </vaadin-accordion-panel>\n</vaadin-accordion>\n```\n\n### Styling\n\nSee the [`<vaadin-accordion-panel>`](https://cdn.vaadin.com/vaadin-web-components/24.4.0-alpha2/#/elements/vaadin-accordion-panel)\ndocumentation for the available state attributes and stylable shadow parts.\n\n**Note:** You can apply the theme to `<vaadin-accordion>` component itself,\nespecially by using the following CSS selector:\n\n```\n:host ::slotted(vaadin-accordion-panel) {\n margin-bottom: 5px;\n}\n```\n\nSee [Styling Components](https://vaadin.com/docs/latest/styling/styling-components) documentation.",
76
83
  "extension": true,
77
84
  "attributes": [
78
85
  {