@digital-realty/ix-select 1.0.1
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/LICENSE +21 -0
- package/README.md +91 -0
- package/demo/index.html +58 -0
- package/dist/src/IxSelect.d.ts +57 -0
- package/dist/src/IxSelect.js +215 -0
- package/dist/src/IxSelect.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/ix-select.d.ts +1 -0
- package/dist/src/ix-select.js +3 -0
- package/dist/src/ix-select.js.map +1 -0
- package/dist/src/react/IxSelect.d.ts +4 -0
- package/dist/src/react/IxSelect.js +13 -0
- package/dist/src/react/IxSelect.js.map +1 -0
- package/dist/src/react/IxSelectOption.d.ts +4 -0
- package/dist/src/react/IxSelectOption.js +13 -0
- package/dist/src/react/IxSelectOption.js.map +1 -0
- package/dist/src/selectoption/IxSelectOption.d.ts +83 -0
- package/dist/src/selectoption/IxSelectOption.js +187 -0
- package/dist/src/selectoption/IxSelectOption.js.map +1 -0
- package/dist/src/selectoption/ix-select-option.d.ts +1 -0
- package/dist/src/selectoption/ix-select-option.js +3 -0
- package/dist/src/selectoption/ix-select-option.js.map +1 -0
- package/dist/src/selectoption/selectOptionController.d.ts +91 -0
- package/dist/src/selectoption/selectOptionController.js +118 -0
- package/dist/src/selectoption/selectOptionController.js.map +1 -0
- package/dist/test/ix-select.test.d.ts +1 -0
- package/dist/test/ix-select.test.js +58 -0
- package/dist/test/ix-select.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +97 -0
- package/src/IxSelect.ts +218 -0
- package/src/index.ts +2 -0
- package/src/ix-select.ts +3 -0
- package/src/react/IxSelect.ts +14 -0
- package/src/react/IxSelectOption.ts +14 -0
- package/src/selectoption/IxSelectOption.ts +192 -0
- package/src/selectoption/ix-select-option.ts +3 -0
- package/src/selectoption/selectOptionController.ts +179 -0
- package/test/ix-select.test.ts +79 -0
- package/tsconfig.json +21 -0
- package/web-dev-server.config.mjs +27 -0
- package/web-test-runner.config.mjs +41 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { __decorate } from "tslib";
|
|
7
|
+
import '@material/web/ripple/ripple.js';
|
|
8
|
+
import '@material/web/focus/md-focus-ring.js';
|
|
9
|
+
import '@material/web/labs/item/item.js';
|
|
10
|
+
import { html, LitElement, nothing } from 'lit';
|
|
11
|
+
import { property, query, queryAssignedElements } from 'lit/decorators.js';
|
|
12
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
13
|
+
import { requestUpdateOnAriaChange } from '@material/web/internal/aria/delegate.js';
|
|
14
|
+
import { SelectOptionController, } from './selectOptionController.js';
|
|
15
|
+
/**
|
|
16
|
+
* @fires close-menu Closes the encapsulating menu on
|
|
17
|
+
* @fires request-selection Requests the parent md-select to select this element
|
|
18
|
+
* (and deselect others if single-selection) when `selected` changed to `true`.
|
|
19
|
+
* @fires request-deselection Requests the parent md-select to deselect this
|
|
20
|
+
* element when `selected` changed to `false`.
|
|
21
|
+
*/
|
|
22
|
+
export class IxSelectOption extends LitElement {
|
|
23
|
+
constructor() {
|
|
24
|
+
super(...arguments);
|
|
25
|
+
/**
|
|
26
|
+
* Disables the item and makes it non-selectable and non-interactive.
|
|
27
|
+
*/
|
|
28
|
+
this.disabled = false;
|
|
29
|
+
/**
|
|
30
|
+
* READONLY: self-identifies as a menu item and sets its identifying attribute
|
|
31
|
+
*/
|
|
32
|
+
this.isMenuItem = true;
|
|
33
|
+
/**
|
|
34
|
+
* Sets the item in the selected visual state when a submenu is opened.
|
|
35
|
+
*/
|
|
36
|
+
this.selected = false;
|
|
37
|
+
/**
|
|
38
|
+
* Form value of the option.
|
|
39
|
+
*/
|
|
40
|
+
this.value = '';
|
|
41
|
+
this.type = 'option';
|
|
42
|
+
this.selectOptionController = new SelectOptionController(this, {
|
|
43
|
+
getHeadlineElements: () => this.headlineElements,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The text that is selectable via typeahead. If not set, defaults to the
|
|
48
|
+
* innerText of the item slotted into the `"headline"` slot.
|
|
49
|
+
*/
|
|
50
|
+
get typeaheadText() {
|
|
51
|
+
return this.selectOptionController.typeaheadText;
|
|
52
|
+
}
|
|
53
|
+
set typeaheadText(text) {
|
|
54
|
+
this.selectOptionController.setTypeaheadText(text);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* The text that is displayed in the select field when selected. If not set,
|
|
58
|
+
* defaults to the textContent of the item slotted into the `"headline"` slot.
|
|
59
|
+
*/
|
|
60
|
+
get displayText() {
|
|
61
|
+
return this.selectOptionController.displayText;
|
|
62
|
+
}
|
|
63
|
+
set displayText(text) {
|
|
64
|
+
this.selectOptionController.setDisplayText(text);
|
|
65
|
+
}
|
|
66
|
+
render() {
|
|
67
|
+
return this.renderListItem(html `
|
|
68
|
+
<md-item>
|
|
69
|
+
<div slot="container">
|
|
70
|
+
${this.renderRipple()} ${this.renderFocusRing()}
|
|
71
|
+
</div>
|
|
72
|
+
<slot name="start" slot="start"></slot>
|
|
73
|
+
<slot name="end" slot="end"></slot>
|
|
74
|
+
${this.renderBody()}
|
|
75
|
+
</md-item>
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Renders the root list item.
|
|
80
|
+
*
|
|
81
|
+
* @param content the child content of the list item.
|
|
82
|
+
*/
|
|
83
|
+
renderListItem(content) {
|
|
84
|
+
return html `
|
|
85
|
+
<li
|
|
86
|
+
id="item"
|
|
87
|
+
tabindex=${this.disabled ? -1 : 0}
|
|
88
|
+
role=${this.selectOptionController.role}
|
|
89
|
+
aria-label=${this.ariaLabel || nothing}
|
|
90
|
+
aria-selected=${this.ariaSelected || nothing}
|
|
91
|
+
aria-checked=${this.ariaChecked || nothing}
|
|
92
|
+
aria-expanded=${this.ariaExpanded || nothing}
|
|
93
|
+
aria-haspopup=${this.ariaHasPopup || nothing}
|
|
94
|
+
class="list-item ${classMap(this.getRenderClasses())}"
|
|
95
|
+
@click=${this.selectOptionController.onClick}
|
|
96
|
+
@keydown=${this.selectOptionController.onKeydown}
|
|
97
|
+
>
|
|
98
|
+
${content}
|
|
99
|
+
</li>
|
|
100
|
+
`;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Handles rendering of the ripple element.
|
|
104
|
+
*/
|
|
105
|
+
renderRipple() {
|
|
106
|
+
return html ` <md-ripple
|
|
107
|
+
part="ripple"
|
|
108
|
+
for="item"
|
|
109
|
+
?disabled=${this.disabled}
|
|
110
|
+
></md-ripple>`;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Handles rendering of the focus ring.
|
|
114
|
+
*/
|
|
115
|
+
// eslint-disable-next-line class-methods-use-this
|
|
116
|
+
renderFocusRing() {
|
|
117
|
+
return html ` <md-focus-ring
|
|
118
|
+
part="focus-ring"
|
|
119
|
+
for="item"
|
|
120
|
+
inward
|
|
121
|
+
></md-focus-ring>`;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Classes applied to the list item root.
|
|
125
|
+
*/
|
|
126
|
+
getRenderClasses() {
|
|
127
|
+
return {
|
|
128
|
+
disabled: this.disabled,
|
|
129
|
+
selected: this.selected,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Handles rendering the headline and supporting text.
|
|
134
|
+
*/
|
|
135
|
+
// eslint-disable-next-line class-methods-use-this
|
|
136
|
+
renderBody() {
|
|
137
|
+
return html `
|
|
138
|
+
<slot></slot>
|
|
139
|
+
<slot name="overline" slot="overline"></slot>
|
|
140
|
+
<slot name="headline" slot="headline"></slot>
|
|
141
|
+
<slot name="supporting-text" slot="supporting-text"></slot>
|
|
142
|
+
<slot
|
|
143
|
+
name="trailing-supporting-text"
|
|
144
|
+
slot="trailing-supporting-text"
|
|
145
|
+
></slot>
|
|
146
|
+
`;
|
|
147
|
+
}
|
|
148
|
+
focus() {
|
|
149
|
+
var _a;
|
|
150
|
+
// TODO(b/300334509): needed for some cases where delegatesFocus doesn't
|
|
151
|
+
// work programmatically like in FF and select-option
|
|
152
|
+
(_a = this.listItemRoot) === null || _a === void 0 ? void 0 : _a.focus();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
(() => {
|
|
156
|
+
requestUpdateOnAriaChange(IxSelectOption);
|
|
157
|
+
})();
|
|
158
|
+
/** @nocollapse */
|
|
159
|
+
IxSelectOption.shadowRootOptions = {
|
|
160
|
+
...LitElement.shadowRootOptions,
|
|
161
|
+
delegatesFocus: true,
|
|
162
|
+
};
|
|
163
|
+
__decorate([
|
|
164
|
+
property({ type: Boolean, reflect: true })
|
|
165
|
+
], IxSelectOption.prototype, "disabled", void 0);
|
|
166
|
+
__decorate([
|
|
167
|
+
property({ type: Boolean, attribute: 'md-menu-item', reflect: true })
|
|
168
|
+
], IxSelectOption.prototype, "isMenuItem", void 0);
|
|
169
|
+
__decorate([
|
|
170
|
+
property({ type: Boolean })
|
|
171
|
+
], IxSelectOption.prototype, "selected", void 0);
|
|
172
|
+
__decorate([
|
|
173
|
+
property()
|
|
174
|
+
], IxSelectOption.prototype, "value", void 0);
|
|
175
|
+
__decorate([
|
|
176
|
+
query('.list-item')
|
|
177
|
+
], IxSelectOption.prototype, "listItemRoot", void 0);
|
|
178
|
+
__decorate([
|
|
179
|
+
queryAssignedElements({ slot: 'headline' })
|
|
180
|
+
], IxSelectOption.prototype, "headlineElements", void 0);
|
|
181
|
+
__decorate([
|
|
182
|
+
property({ attribute: 'typeahead-text' })
|
|
183
|
+
], IxSelectOption.prototype, "typeaheadText", null);
|
|
184
|
+
__decorate([
|
|
185
|
+
property({ attribute: 'display-text' })
|
|
186
|
+
], IxSelectOption.prototype, "displayText", null);
|
|
187
|
+
//# sourceMappingURL=IxSelectOption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IxSelectOption.js","sourceRoot":"","sources":["../../../src/selectoption/IxSelectOption.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport '@material/web/ripple/ripple.js';\nimport '@material/web/focus/md-focus-ring.js';\nimport '@material/web/labs/item/item.js';\n\nimport { html, LitElement, nothing } from 'lit';\nimport { property, query, queryAssignedElements } from 'lit/decorators.js';\nimport { ClassInfo, classMap } from 'lit/directives/class-map.js';\n\nimport { ARIAMixinStrict } from '@material/web/internal/aria/aria.js';\nimport { requestUpdateOnAriaChange } from '@material/web/internal/aria/delegate.js';\n\nimport {\n SelectOption,\n SelectOptionController,\n} from './selectOptionController.js';\n\n/**\n * @fires close-menu Closes the encapsulating menu on\n * @fires request-selection Requests the parent md-select to select this element\n * (and deselect others if single-selection) when `selected` changed to `true`.\n * @fires request-deselection Requests the parent md-select to deselect this\n * element when `selected` changed to `false`.\n */\nexport class IxSelectOption extends LitElement implements SelectOption {\n static {\n requestUpdateOnAriaChange(IxSelectOption);\n }\n\n /** @nocollapse */\n static override shadowRootOptions = {\n ...LitElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n /**\n * Disables the item and makes it non-selectable and non-interactive.\n */\n @property({ type: Boolean, reflect: true }) disabled = false;\n\n /**\n * READONLY: self-identifies as a menu item and sets its identifying attribute\n */\n @property({ type: Boolean, attribute: 'md-menu-item', reflect: true })\n isMenuItem = true;\n\n /**\n * Sets the item in the selected visual state when a submenu is opened.\n */\n @property({ type: Boolean }) selected = false;\n\n /**\n * Form value of the option.\n */\n @property() value = '';\n\n @query('.list-item') protected readonly listItemRoot!: HTMLElement | null;\n\n @queryAssignedElements({ slot: 'headline' })\n protected readonly headlineElements!: HTMLElement[];\n\n type = 'option' as const;\n\n /**\n * The text that is selectable via typeahead. If not set, defaults to the\n * innerText of the item slotted into the `\"headline\"` slot.\n */\n get typeaheadText() {\n return this.selectOptionController.typeaheadText;\n }\n\n @property({ attribute: 'typeahead-text' })\n set typeaheadText(text: string) {\n this.selectOptionController.setTypeaheadText(text);\n }\n\n /**\n * The text that is displayed in the select field when selected. If not set,\n * defaults to the textContent of the item slotted into the `\"headline\"` slot.\n */\n get displayText() {\n return this.selectOptionController.displayText;\n }\n\n @property({ attribute: 'display-text' })\n set displayText(text: string) {\n this.selectOptionController.setDisplayText(text);\n }\n\n private readonly selectOptionController = new SelectOptionController(this, {\n getHeadlineElements: () => this.headlineElements,\n });\n\n protected override render() {\n return this.renderListItem(html`\n <md-item>\n <div slot=\"container\">\n ${this.renderRipple()} ${this.renderFocusRing()}\n </div>\n <slot name=\"start\" slot=\"start\"></slot>\n <slot name=\"end\" slot=\"end\"></slot>\n ${this.renderBody()}\n </md-item>\n `);\n }\n\n /**\n * Renders the root list item.\n *\n * @param content the child content of the list item.\n */\n protected renderListItem(content: unknown) {\n return html`\n <li\n id=\"item\"\n tabindex=${this.disabled ? -1 : 0}\n role=${this.selectOptionController.role}\n aria-label=${(this as ARIAMixinStrict).ariaLabel || nothing}\n aria-selected=${(this as ARIAMixinStrict).ariaSelected || nothing}\n aria-checked=${(this as ARIAMixinStrict).ariaChecked || nothing}\n aria-expanded=${(this as ARIAMixinStrict).ariaExpanded || nothing}\n aria-haspopup=${(this as ARIAMixinStrict).ariaHasPopup || nothing}\n class=\"list-item ${classMap(this.getRenderClasses())}\"\n @click=${this.selectOptionController.onClick}\n @keydown=${this.selectOptionController.onKeydown}\n >\n ${content}\n </li>\n `;\n }\n\n /**\n * Handles rendering of the ripple element.\n */\n protected renderRipple() {\n return html` <md-ripple\n part=\"ripple\"\n for=\"item\"\n ?disabled=${this.disabled}\n ></md-ripple>`;\n }\n\n /**\n * Handles rendering of the focus ring.\n */\n // eslint-disable-next-line class-methods-use-this\n protected renderFocusRing() {\n return html` <md-focus-ring\n part=\"focus-ring\"\n for=\"item\"\n inward\n ></md-focus-ring>`;\n }\n\n /**\n * Classes applied to the list item root.\n */\n protected getRenderClasses(): ClassInfo {\n return {\n disabled: this.disabled,\n selected: this.selected,\n };\n }\n\n /**\n * Handles rendering the headline and supporting text.\n */\n // eslint-disable-next-line class-methods-use-this\n protected renderBody() {\n return html`\n <slot></slot>\n <slot name=\"overline\" slot=\"overline\"></slot>\n <slot name=\"headline\" slot=\"headline\"></slot>\n <slot name=\"supporting-text\" slot=\"supporting-text\"></slot>\n <slot\n name=\"trailing-supporting-text\"\n slot=\"trailing-supporting-text\"\n ></slot>\n `;\n }\n\n override focus() {\n // TODO(b/300334509): needed for some cases where delegatesFocus doesn't\n // work programmatically like in FF and select-option\n this.listItemRoot?.focus();\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ix-select-option.js","sourceRoot":"","sources":["../../../src/selectoption/ix-select-option.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,kBAAkB,EAAE,cAAc,CAAC,CAAC","sourcesContent":["import { IxSelectOption } from './IxSelectOption.js';\n\nwindow.customElements.define('ix-select-option', IxSelectOption);\n"]}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
7
|
+
import { MenuItem, MenuItemControllerConfig } from '@material/web/menu/internal/controllers/menuItemController.js';
|
|
8
|
+
/**
|
|
9
|
+
* The interface specific to a Select Option
|
|
10
|
+
*/
|
|
11
|
+
interface SelectOptionSelf {
|
|
12
|
+
/**
|
|
13
|
+
* The form value associated with the Select Option. (Note: the visual portion
|
|
14
|
+
* of the SelectOption is the headline defined in ListItem)
|
|
15
|
+
*/
|
|
16
|
+
value: string;
|
|
17
|
+
/**
|
|
18
|
+
* Whether or not the SelectOption is selected.
|
|
19
|
+
*/
|
|
20
|
+
selected: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The text to display in the select when selected. Defaults to the
|
|
23
|
+
* textContent of the Element slotted into the headline.
|
|
24
|
+
*/
|
|
25
|
+
displayText: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The interface to implement for a select option. Additionally, the element
|
|
29
|
+
* must have `md-list-item` and `md-menu-item` attributes on the host.
|
|
30
|
+
*/
|
|
31
|
+
export type SelectOption = SelectOptionSelf & MenuItem;
|
|
32
|
+
/**
|
|
33
|
+
* Creates an event fired by a SelectOption to request selection from md-select.
|
|
34
|
+
* Typically fired after `selected` changes from `false` to `true`.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createRequestSelectionEvent(): Event;
|
|
37
|
+
/**
|
|
38
|
+
* Creates an event fired by a SelectOption to request deselection from
|
|
39
|
+
* md-select. Typically fired after `selected` changes from `true` to `false`.
|
|
40
|
+
*/
|
|
41
|
+
export declare function createRequestDeselectionEvent(): Event;
|
|
42
|
+
/**
|
|
43
|
+
* The options used to inialize SelectOptionController.
|
|
44
|
+
*/
|
|
45
|
+
export type SelectOptionConfig = MenuItemControllerConfig;
|
|
46
|
+
/**
|
|
47
|
+
* A controller that provides most functionality and md-select compatibility for
|
|
48
|
+
* an element that implements the SelectOption interface.
|
|
49
|
+
*/
|
|
50
|
+
export declare class SelectOptionController implements ReactiveController {
|
|
51
|
+
private readonly host;
|
|
52
|
+
private readonly menuItemController;
|
|
53
|
+
private readonly getHeadlineElements;
|
|
54
|
+
private internalDisplayText;
|
|
55
|
+
private lastSelected;
|
|
56
|
+
private firstUpdate;
|
|
57
|
+
/**
|
|
58
|
+
* The recommended role of the select option.
|
|
59
|
+
*/
|
|
60
|
+
get role(): "menuitem" | "option";
|
|
61
|
+
/**
|
|
62
|
+
* The text that is selectable via typeahead. If not set, defaults to the
|
|
63
|
+
* innerText of the item slotted into the `"headline"` slot.
|
|
64
|
+
*/
|
|
65
|
+
get typeaheadText(): string;
|
|
66
|
+
setTypeaheadText(text: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* The text that is displayed in the select field when selected. If not set,
|
|
69
|
+
* defaults to the textContent of the item slotted into the `"headline"` slot.
|
|
70
|
+
*/
|
|
71
|
+
get displayText(): string;
|
|
72
|
+
setDisplayText(text: string): void;
|
|
73
|
+
/**
|
|
74
|
+
* @param host The SelectOption in which to attach this controller to.
|
|
75
|
+
* @param config The object that configures this controller's behavior.
|
|
76
|
+
*/
|
|
77
|
+
constructor(host: ReactiveControllerHost & SelectOption, config: SelectOptionConfig);
|
|
78
|
+
hostUpdate(): void;
|
|
79
|
+
hostUpdated(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Bind this click listener to the interactive element. Handles closing the
|
|
82
|
+
* menu.
|
|
83
|
+
*/
|
|
84
|
+
onClick: () => void;
|
|
85
|
+
/**
|
|
86
|
+
* Bind this click listener to the interactive element. Handles closing the
|
|
87
|
+
* menu.
|
|
88
|
+
*/
|
|
89
|
+
onKeydown: (e: KeyboardEvent) => void;
|
|
90
|
+
}
|
|
91
|
+
export {};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2023 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
import { MenuItemController, } from '@material/web/menu/internal/controllers/menuItemController.js';
|
|
7
|
+
/**
|
|
8
|
+
* Creates an event fired by a SelectOption to request selection from md-select.
|
|
9
|
+
* Typically fired after `selected` changes from `false` to `true`.
|
|
10
|
+
*/
|
|
11
|
+
export function createRequestSelectionEvent() {
|
|
12
|
+
return new Event('request-selection', {
|
|
13
|
+
bubbles: true,
|
|
14
|
+
composed: true,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates an event fired by a SelectOption to request deselection from
|
|
19
|
+
* md-select. Typically fired after `selected` changes from `true` to `false`.
|
|
20
|
+
*/
|
|
21
|
+
export function createRequestDeselectionEvent() {
|
|
22
|
+
return new Event('request-deselection', {
|
|
23
|
+
bubbles: true,
|
|
24
|
+
composed: true,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* A controller that provides most functionality and md-select compatibility for
|
|
29
|
+
* an element that implements the SelectOption interface.
|
|
30
|
+
*/
|
|
31
|
+
export class SelectOptionController {
|
|
32
|
+
/**
|
|
33
|
+
* The recommended role of the select option.
|
|
34
|
+
*/
|
|
35
|
+
get role() {
|
|
36
|
+
return this.menuItemController.role;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The text that is selectable via typeahead. If not set, defaults to the
|
|
40
|
+
* innerText of the item slotted into the `"headline"` slot.
|
|
41
|
+
*/
|
|
42
|
+
get typeaheadText() {
|
|
43
|
+
return this.menuItemController.typeaheadText;
|
|
44
|
+
}
|
|
45
|
+
setTypeaheadText(text) {
|
|
46
|
+
this.menuItemController.setTypeaheadText(text);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The text that is displayed in the select field when selected. If not set,
|
|
50
|
+
* defaults to the textContent of the item slotted into the `"headline"` slot.
|
|
51
|
+
*/
|
|
52
|
+
get displayText() {
|
|
53
|
+
if (this.internalDisplayText !== null) {
|
|
54
|
+
return this.internalDisplayText;
|
|
55
|
+
}
|
|
56
|
+
const headlineElements = this.getHeadlineElements();
|
|
57
|
+
const textParts = [];
|
|
58
|
+
headlineElements.forEach(headlineElement => {
|
|
59
|
+
if (headlineElement.textContent && headlineElement.textContent.trim()) {
|
|
60
|
+
textParts.push(headlineElement.textContent.trim());
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
return textParts.join(' ');
|
|
64
|
+
}
|
|
65
|
+
setDisplayText(text) {
|
|
66
|
+
this.internalDisplayText = text;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* @param host The SelectOption in which to attach this controller to.
|
|
70
|
+
* @param config The object that configures this controller's behavior.
|
|
71
|
+
*/
|
|
72
|
+
constructor(host, config) {
|
|
73
|
+
this.host = host;
|
|
74
|
+
this.internalDisplayText = null;
|
|
75
|
+
this.lastSelected = this.host.selected;
|
|
76
|
+
this.firstUpdate = true;
|
|
77
|
+
/**
|
|
78
|
+
* Bind this click listener to the interactive element. Handles closing the
|
|
79
|
+
* menu.
|
|
80
|
+
*/
|
|
81
|
+
this.onClick = () => {
|
|
82
|
+
this.menuItemController.onClick();
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Bind this click listener to the interactive element. Handles closing the
|
|
86
|
+
* menu.
|
|
87
|
+
*/
|
|
88
|
+
this.onKeydown = (e) => {
|
|
89
|
+
this.menuItemController.onKeydown(e);
|
|
90
|
+
};
|
|
91
|
+
this.menuItemController = new MenuItemController(host, config);
|
|
92
|
+
this.getHeadlineElements = config.getHeadlineElements;
|
|
93
|
+
host.addController(this);
|
|
94
|
+
}
|
|
95
|
+
hostUpdate() {
|
|
96
|
+
if (this.lastSelected !== this.host.selected) {
|
|
97
|
+
this.host.ariaSelected = this.host.selected ? 'true' : 'false';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
hostUpdated() {
|
|
101
|
+
// Do not dispatch event on first update / boot-up.
|
|
102
|
+
if (this.lastSelected !== this.host.selected && !this.firstUpdate) {
|
|
103
|
+
// This section is really useful for when the user sets selected on the
|
|
104
|
+
// option programmatically. Most other cases (click and keyboard) are
|
|
105
|
+
// handled by md-select because it needs to coordinate the
|
|
106
|
+
// single-selection behavior.
|
|
107
|
+
if (this.host.selected) {
|
|
108
|
+
this.host.dispatchEvent(createRequestSelectionEvent());
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
this.host.dispatchEvent(createRequestDeselectionEvent());
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
this.lastSelected = this.host.selected;
|
|
115
|
+
this.firstUpdate = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=selectOptionController.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectOptionController.js","sourceRoot":"","sources":["../../../src/selectoption/selectOptionController.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * @license\n * Copyright 2023 Google LLC\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { ReactiveController, ReactiveControllerHost } from 'lit';\n\nimport {\n MenuItem,\n MenuItemController,\n MenuItemControllerConfig,\n} from '@material/web/menu/internal/controllers/menuItemController.js';\n\n/**\n * The interface specific to a Select Option\n */\ninterface SelectOptionSelf {\n /**\n * The form value associated with the Select Option. (Note: the visual portion\n * of the SelectOption is the headline defined in ListItem)\n */\n value: string;\n /**\n * Whether or not the SelectOption is selected.\n */\n selected: boolean;\n /**\n * The text to display in the select when selected. Defaults to the\n * textContent of the Element slotted into the headline.\n */\n displayText: string;\n}\n\n/**\n * The interface to implement for a select option. Additionally, the element\n * must have `md-list-item` and `md-menu-item` attributes on the host.\n */\nexport type SelectOption = SelectOptionSelf & MenuItem;\n\n/**\n * Creates an event fired by a SelectOption to request selection from md-select.\n * Typically fired after `selected` changes from `false` to `true`.\n */\nexport function createRequestSelectionEvent() {\n return new Event('request-selection', {\n bubbles: true,\n composed: true,\n });\n}\n\n/**\n * Creates an event fired by a SelectOption to request deselection from\n * md-select. Typically fired after `selected` changes from `true` to `false`.\n */\nexport function createRequestDeselectionEvent() {\n return new Event('request-deselection', {\n bubbles: true,\n composed: true,\n });\n}\n\n/**\n * The options used to inialize SelectOptionController.\n */\nexport type SelectOptionConfig = MenuItemControllerConfig;\n\n/**\n * A controller that provides most functionality and md-select compatibility for\n * an element that implements the SelectOption interface.\n */\nexport class SelectOptionController implements ReactiveController {\n private readonly menuItemController: MenuItemController;\n\n private readonly getHeadlineElements: SelectOptionConfig['getHeadlineElements'];\n\n private internalDisplayText: string | null = null;\n\n private lastSelected = this.host.selected;\n\n private firstUpdate = true;\n\n /**\n * The recommended role of the select option.\n */\n get role() {\n return this.menuItemController.role;\n }\n\n /**\n * The text that is selectable via typeahead. If not set, defaults to the\n * innerText of the item slotted into the `\"headline\"` slot.\n */\n get typeaheadText() {\n return this.menuItemController.typeaheadText;\n }\n\n setTypeaheadText(text: string) {\n this.menuItemController.setTypeaheadText(text);\n }\n\n /**\n * The text that is displayed in the select field when selected. If not set,\n * defaults to the textContent of the item slotted into the `\"headline\"` slot.\n */\n get displayText() {\n if (this.internalDisplayText !== null) {\n return this.internalDisplayText;\n }\n\n const headlineElements = this.getHeadlineElements();\n\n const textParts: string[] = [];\n headlineElements.forEach(headlineElement => {\n if (headlineElement.textContent && headlineElement.textContent.trim()) {\n textParts.push(headlineElement.textContent.trim());\n }\n });\n\n return textParts.join(' ');\n }\n\n setDisplayText(text: string) {\n this.internalDisplayText = text;\n }\n\n /**\n * @param host The SelectOption in which to attach this controller to.\n * @param config The object that configures this controller's behavior.\n */\n constructor(\n private readonly host: ReactiveControllerHost & SelectOption,\n config: SelectOptionConfig\n ) {\n this.menuItemController = new MenuItemController(host, config);\n this.getHeadlineElements = config.getHeadlineElements;\n host.addController(this);\n }\n\n hostUpdate() {\n if (this.lastSelected !== this.host.selected) {\n this.host.ariaSelected = this.host.selected ? 'true' : 'false';\n }\n }\n\n hostUpdated() {\n // Do not dispatch event on first update / boot-up.\n if (this.lastSelected !== this.host.selected && !this.firstUpdate) {\n // This section is really useful for when the user sets selected on the\n // option programmatically. Most other cases (click and keyboard) are\n // handled by md-select because it needs to coordinate the\n // single-selection behavior.\n if (this.host.selected) {\n this.host.dispatchEvent(createRequestSelectionEvent());\n } else {\n this.host.dispatchEvent(createRequestDeselectionEvent());\n }\n }\n\n this.lastSelected = this.host.selected;\n this.firstUpdate = false;\n }\n\n /**\n * Bind this click listener to the interactive element. Handles closing the\n * menu.\n */\n onClick = () => {\n this.menuItemController.onClick();\n };\n\n /**\n * Bind this click listener to the interactive element. Handles closing the\n * menu.\n */\n onKeydown = (e: KeyboardEvent) => {\n this.menuItemController.onKeydown(e);\n };\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '../src/ix-select.js';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { html } from 'lit';
|
|
2
|
+
import { fixture, expect } from '@open-wc/testing';
|
|
3
|
+
import '../src/ix-select.js';
|
|
4
|
+
describe('IxSelect', () => {
|
|
5
|
+
it('should show the outlined field by default', async () => {
|
|
6
|
+
const el = await fixture(html `<ix-select></ix-select>`);
|
|
7
|
+
expect(el.materialRoot.tagName.toLowerCase()).to.be.string('md-outlined-select');
|
|
8
|
+
});
|
|
9
|
+
});
|
|
10
|
+
describe('IxSelect', () => {
|
|
11
|
+
it('should render the appearance specified by property', async () => {
|
|
12
|
+
const el = await fixture(html `<ix-select appearance="filled"></ix-select>`);
|
|
13
|
+
expect(el.materialRoot.tagName.toLowerCase()).to.be.string('md-filled-select');
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
describe('IxSelect', () => {
|
|
17
|
+
it('form should submit with data', async () => {
|
|
18
|
+
var _a, _b, _c;
|
|
19
|
+
let formData;
|
|
20
|
+
const select = await fixture(html `
|
|
21
|
+
<ix-select name="theForm" label="theLabel">
|
|
22
|
+
<ix-select-option value="1">
|
|
23
|
+
<div slot="headline">Test Value</div>
|
|
24
|
+
</ix-select-option>
|
|
25
|
+
</ix-select>
|
|
26
|
+
`);
|
|
27
|
+
const handleSubmit = (e) => {
|
|
28
|
+
e.preventDefault();
|
|
29
|
+
formData = new FormData(e.target);
|
|
30
|
+
};
|
|
31
|
+
const form = await fixture(html `
|
|
32
|
+
<form @submit=${handleSubmit}>
|
|
33
|
+
${select}
|
|
34
|
+
<button type="submit">Submit</button>
|
|
35
|
+
</form>
|
|
36
|
+
`);
|
|
37
|
+
form.addEventListener('submit', () => {
|
|
38
|
+
formData.forEach((value, key) => console.log(`${key}: ${value}`));
|
|
39
|
+
});
|
|
40
|
+
(_b = (_a = select.materialRoot.options[0].shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('li')) === null || _b === void 0 ? void 0 : _b.click();
|
|
41
|
+
// Wait for 'request-selection' event to propogate to select after dropdown item 'clicked'
|
|
42
|
+
// Form will not contain any data if we submit before event is received
|
|
43
|
+
// eslint-disable-next-line no-use-before-define
|
|
44
|
+
await waitForEvent(select, 'request-selection');
|
|
45
|
+
(_c = form.querySelector('button')) === null || _c === void 0 ? void 0 : _c.click();
|
|
46
|
+
expect(formData.get('theForm'), 'Form data did not contain expected result').is.string('1');
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
function waitForEvent(target, eventName) {
|
|
50
|
+
return new Promise(resolve => {
|
|
51
|
+
const handler = (event) => {
|
|
52
|
+
resolve(event);
|
|
53
|
+
target.removeEventListener(eventName, handler);
|
|
54
|
+
};
|
|
55
|
+
target.addEventListener(eventName, handler);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=ix-select.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ix-select.test.js","sourceRoot":"","sources":["../../test/ix-select.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { html } from 'lit';\nimport { fixture, expect } from '@open-wc/testing';\nimport { IxSelect } from '../src/IxSelect.js';\nimport '../src/ix-select.js';\n\ndescribe('IxSelect', () => {\n it('should show the outlined field by default', async () => {\n const el = await fixture<IxSelect>(html`<ix-select></ix-select>`);\n\n expect(el.materialRoot.tagName.toLowerCase()).to.be.string(\n 'md-outlined-select'\n );\n });\n});\n\ndescribe('IxSelect', () => {\n it('should render the appearance specified by property', async () => {\n const el = await fixture<IxSelect>(\n html`<ix-select appearance=\"filled\"></ix-select>`\n );\n\n expect(el.materialRoot.tagName.toLowerCase()).to.be.string(\n 'md-filled-select'\n );\n });\n});\n\ndescribe('IxSelect', () => {\n it('form should submit with data', async () => {\n let formData: FormData;\n\n const select = await fixture<IxSelect>(html`\n <ix-select name=\"theForm\" label=\"theLabel\">\n <ix-select-option value=\"1\">\n <div slot=\"headline\">Test Value</div>\n </ix-select-option>\n </ix-select>\n `);\n\n const handleSubmit = (e: Event & { target: HTMLFormElement }) => {\n e.preventDefault();\n formData = new FormData(e.target);\n };\n const form = await fixture<HTMLFormElement>(html`\n <form @submit=${handleSubmit}>\n ${select}\n <button type=\"submit\">Submit</button>\n </form>\n `);\n\n form.addEventListener('submit', () => {\n formData.forEach((value, key) => console.log(`${key}: ${value}`));\n });\n\n select.materialRoot.options[0].shadowRoot?.querySelector('li')?.click();\n\n // Wait for 'request-selection' event to propogate to select after dropdown item 'clicked'\n // Form will not contain any data if we submit before event is received\n // eslint-disable-next-line no-use-before-define\n await waitForEvent(select, 'request-selection');\n\n form.querySelector('button')?.click();\n\n expect(\n formData!.get('theForm'),\n 'Form data did not contain expected result'\n ).is.string('1');\n });\n});\n\nfunction waitForEvent(target: EventTarget, eventName: string): Promise<Event> {\n return new Promise(resolve => {\n const handler = (event: Event) => {\n resolve(event);\n target.removeEventListener(eventName, handler);\n };\n target.addEventListener(eventName, handler);\n });\n}\n"]}
|