@oscarpalmer/oui 0.34.0 → 0.36.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/dist/css/combobox.css +1 -1
- package/dist/css/listbox.css +152 -0
- package/dist/js/combobox/constants.combobox.d.mts +2 -2
- package/dist/js/combobox/constants.combobox.mjs +40 -33
- package/dist/js/combobox/dom.combobox.d.mts +8 -91
- package/dist/js/combobox/dom.combobox.mjs +204 -2
- package/dist/js/combobox/event.combobox.d.mts +14 -8
- package/dist/js/combobox/event.combobox.mjs +2 -2
- package/dist/js/combobox/index.d.mts +1 -1
- package/dist/js/combobox/index.mjs +21 -18
- package/dist/js/combobox/misc.combobox.d.mts +2 -14
- package/dist/js/combobox/misc.combobox.mjs +2 -2
- package/dist/js/combobox/models.combobox.d.mts +44 -2
- package/dist/js/combobox/state.combobox.d.mts +9 -8
- package/dist/js/combobox/state.combobox.mjs +2 -2
- package/dist/js/constants.combobox-DmRAMC64.d.mts +26 -0
- package/dist/js/constants.listbox-DRsXUxd3.d.mts +14 -0
- package/dist/js/index-EfkUSals.d.mts +139 -0
- package/dist/js/index.d.mts +4 -2
- package/dist/js/index.mjs +4 -2
- package/dist/js/internal/attributable.mjs +4 -3
- package/dist/js/internal/listbox/listbox.constants.d.mts +11 -0
- package/dist/js/internal/listbox/listbox.constants.mjs +23 -0
- package/dist/js/internal/listbox/listbox.data.d.mts +20 -0
- package/dist/js/internal/listbox/listbox.data.mjs +2 -0
- package/dist/js/internal/listbox/listbox.dom.d.mts +66 -0
- package/dist/js/internal/listbox/listbox.dom.mjs +2 -0
- package/dist/js/internal/listbox/listbox.event.d.mts +5 -0
- package/dist/js/internal/listbox/listbox.event.mjs +63 -0
- package/dist/js/internal/listbox/listbox.form.d.mts +6 -0
- package/dist/js/internal/listbox/listbox.form.mjs +52 -0
- package/dist/js/internal/listbox/listbox.misc.d.mts +12 -0
- package/dist/js/internal/listbox/listbox.misc.mjs +2 -0
- package/dist/js/internal/listbox/listbox.model.d.mts +2 -0
- package/dist/js/internal/listbox/listbox.model.mjs +1 -0
- package/dist/js/internal/listbox/listbox.state.d.mts +7 -0
- package/dist/js/internal/listbox/listbox.state.mjs +40 -0
- package/dist/js/internal/misc.d.mts +6 -0
- package/dist/js/internal/misc.mjs +13 -0
- package/dist/js/l10n-Bn-7RcwR.d.mts +20 -0
- package/dist/js/l10n.d.mts +2 -0
- package/dist/js/l10n.mjs +80 -0
- package/dist/js/listbox/constants.listbox.d.mts +2 -0
- package/dist/js/listbox/constants.listbox.mjs +40 -0
- package/dist/js/listbox/event.listbox.d.mts +8 -0
- package/dist/js/listbox/event.listbox.mjs +2 -0
- package/dist/js/listbox/index.d.mts +116 -0
- package/dist/js/listbox/index.mjs +189 -0
- package/dist/js/listbox/misc.listbox.d.mts +2 -0
- package/dist/js/listbox/misc.listbox.mjs +2 -0
- package/dist/js/listbox/state.listbox.d.mts +11 -0
- package/dist/js/listbox/state.listbox.mjs +2 -0
- package/dist/js/listbox.data-BWd0PCy7.mjs +424 -0
- package/dist/js/listbox.model-CRReGOmu.d.mts +125 -0
- package/dist/js/misc.listbox-BI-XsTOf.mjs +197 -0
- package/dist/js/misc.listbox-gnoJhrTr.d.mts +20 -0
- package/dist/js/sortable/sortable.embedded.mjs +4 -2
- package/dist/js/state.combobox-4xq0FPCF.mjs +365 -0
- package/package.json +7 -3
- package/src/css/combobox.scss +1 -1
- package/src/css/listbox.scss +149 -0
- package/src/js/combobox/constants.combobox.ts +46 -25
- package/src/js/combobox/dom.combobox.ts +65 -452
- package/src/js/combobox/event.combobox.ts +129 -218
- package/src/js/combobox/index.ts +43 -30
- package/src/js/combobox/misc.combobox.ts +60 -94
- package/src/js/combobox/models.combobox.ts +7 -47
- package/src/js/combobox/state.combobox.ts +136 -125
- package/src/js/index.ts +1 -0
- package/src/js/internal/listbox/listbox.constants.ts +25 -0
- package/src/js/{combobox/data.combobox.ts → internal/listbox/listbox.data.ts} +94 -43
- package/src/js/internal/listbox/listbox.dom.ts +445 -0
- package/src/js/internal/listbox/listbox.event.ts +129 -0
- package/src/js/{combobox/form.combobox.ts → internal/listbox/listbox.form.ts} +33 -33
- package/src/js/internal/listbox/listbox.misc.ts +135 -0
- package/src/js/internal/listbox/listbox.model.ts +169 -0
- package/src/js/internal/listbox/listbox.state.ts +82 -0
- package/src/js/internal/misc.ts +27 -0
- package/src/js/l10n.ts +192 -0
- package/src/js/listbox/constants.listbox.ts +61 -0
- package/src/js/listbox/event.listbox.ts +106 -0
- package/src/js/listbox/index.ts +302 -0
- package/src/js/listbox/misc.listbox.ts +70 -0
- package/src/js/listbox/state.listbox.ts +196 -0
- package/dist/js/combobox/data.combobox.d.mts +0 -18
- package/dist/js/combobox/data.combobox.mjs +0 -2
- package/dist/js/combobox/form.combobox.d.mts +0 -6
- package/dist/js/combobox/form.combobox.mjs +0 -2
- package/dist/js/combobox/i18n.combobox.d.mts +0 -2
- package/dist/js/combobox/i18n.combobox.mjs +0 -2
- package/dist/js/constants.combobox-DqNUGBLS.d.mts +0 -243
- package/dist/js/data.combobox-8RwBv5ey.mjs +0 -1077
- package/src/js/combobox/i18n.combobox.ts +0 -179
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { C as setListboxDisabled, D as setListboxReadonly, O as setListboxRequired, T as setListboxLimit, a as setListboxValue, o as setListboxValues, w as setListboxFilter } from "../listbox.data-BWd0PCy7.mjs";
|
|
2
|
+
import { attachListbox, detachListbox } from "../internal/listbox/listbox.state.mjs";
|
|
3
|
+
import { LISTBOX_TAGNAME } from "./constants.listbox.mjs";
|
|
4
|
+
import { c as onDetachListbox, i as createListboxState, n as setListboxLocalizations, o as listboxStates, r as updateListboxLocalizations, s as onAttachListbox } from "../misc.listbox-BI-XsTOf.mjs";
|
|
5
|
+
import { getAttribute } from "@oscarpalmer/toretto/attribute";
|
|
6
|
+
import { parse } from "@oscarpalmer/atoms/string";
|
|
7
|
+
//#region src/js/listbox/index.ts
|
|
8
|
+
var OuiListboxElement = class extends HTMLElement {
|
|
9
|
+
static formAssociated = true;
|
|
10
|
+
static observedAttributes = [
|
|
11
|
+
"max",
|
|
12
|
+
"min",
|
|
13
|
+
"required",
|
|
14
|
+
"value"
|
|
15
|
+
];
|
|
16
|
+
#internals;
|
|
17
|
+
#restored;
|
|
18
|
+
#state;
|
|
19
|
+
/**
|
|
20
|
+
* Is the listbox disabled?
|
|
21
|
+
*/
|
|
22
|
+
get disabled() {
|
|
23
|
+
return this.#state?.disabled ?? false;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Should the listbox be disabled?
|
|
27
|
+
*/
|
|
28
|
+
set disabled(value) {
|
|
29
|
+
if (typeof value === "boolean" && value !== this.disabled) setListboxDisabled(this.#state, value);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Current filter value
|
|
33
|
+
*/
|
|
34
|
+
get filter() {
|
|
35
|
+
return this.#state.filter.element.value;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Set the filter value
|
|
39
|
+
*/
|
|
40
|
+
set filter(value) {
|
|
41
|
+
setListboxFilter(this.#state, value);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Maximum number of selected options
|
|
45
|
+
*/
|
|
46
|
+
get max() {
|
|
47
|
+
return this.#state?.max;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Set the maximum number of selected options
|
|
51
|
+
*/
|
|
52
|
+
set max(value) {
|
|
53
|
+
setListboxLimit("max", this.#state, value);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Minimum number of selected options
|
|
57
|
+
*/
|
|
58
|
+
get min() {
|
|
59
|
+
return this.#state?.min;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Set the minimum number of selected options
|
|
63
|
+
*/
|
|
64
|
+
set min(value) {
|
|
65
|
+
setListboxLimit("min", this.#state, value);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Does the listbox allow multiple values?
|
|
69
|
+
*/
|
|
70
|
+
get multiple() {
|
|
71
|
+
return this.hasAttribute("multiple");
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Name of the listbox
|
|
75
|
+
*/
|
|
76
|
+
get name() {
|
|
77
|
+
return getAttribute(this, "name") ?? "";
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Is the listbox readonly?
|
|
81
|
+
*/
|
|
82
|
+
get readonly() {
|
|
83
|
+
return this.#state?.readonly ?? false;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Should the listbox be readonly?
|
|
87
|
+
*/
|
|
88
|
+
set readonly(value) {
|
|
89
|
+
if (typeof value === "boolean" && value !== this.readonly) setListboxReadonly(this.#state, value);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Is the listbox required?
|
|
93
|
+
*/
|
|
94
|
+
get required() {
|
|
95
|
+
return this.#state?.required ?? false;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Should the listbox be required?
|
|
99
|
+
*/
|
|
100
|
+
set required(value) {
|
|
101
|
+
if (typeof value === "boolean" && value !== this.required) setListboxRequired(this.#state, value);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Selected options
|
|
105
|
+
*/
|
|
106
|
+
get selected() {
|
|
107
|
+
return this.#state.options.selected.slice();
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Current value
|
|
111
|
+
*/
|
|
112
|
+
get value() {
|
|
113
|
+
return this.#state.values.current[0];
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Set the value
|
|
117
|
+
*/
|
|
118
|
+
set value(value) {
|
|
119
|
+
setListboxValue(this.#state, value);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Current values
|
|
123
|
+
*/
|
|
124
|
+
get values() {
|
|
125
|
+
return this.#state.values.current.slice();
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Set the values
|
|
129
|
+
*/
|
|
130
|
+
set values(values) {
|
|
131
|
+
setListboxValues(this.#state, values);
|
|
132
|
+
}
|
|
133
|
+
constructor() {
|
|
134
|
+
super();
|
|
135
|
+
this.#internals = this.attachInternals();
|
|
136
|
+
}
|
|
137
|
+
attributeChangedCallback(name, _, value) {
|
|
138
|
+
if (this.#state == null) return;
|
|
139
|
+
switch (name) {
|
|
140
|
+
case "required":
|
|
141
|
+
this[name] = this.hasAttribute(name);
|
|
142
|
+
break;
|
|
143
|
+
case "max":
|
|
144
|
+
case "min":
|
|
145
|
+
setListboxLimit(name, this.#state, value);
|
|
146
|
+
break;
|
|
147
|
+
case "value": this.value = value ?? "";
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Clear all selected options
|
|
152
|
+
*/
|
|
153
|
+
clear() {
|
|
154
|
+
setListboxValues(this.#state, []);
|
|
155
|
+
}
|
|
156
|
+
connectedCallback() {
|
|
157
|
+
if (this.#state == null) this.#initialize();
|
|
158
|
+
else attachListbox(this.#state, listboxStates, onAttachListbox);
|
|
159
|
+
}
|
|
160
|
+
disconnectedCallback() {
|
|
161
|
+
if (this.#state != null) detachListbox(this.#state, listboxStates, onDetachListbox);
|
|
162
|
+
}
|
|
163
|
+
formDisabledCallback(disabled) {
|
|
164
|
+
this.disabled = disabled;
|
|
165
|
+
}
|
|
166
|
+
formResetCallback() {
|
|
167
|
+
setListboxValues(this.#state, this.#state.values.initial);
|
|
168
|
+
}
|
|
169
|
+
formStateRestoreCallback(state, reason) {
|
|
170
|
+
if (reason !== "restore") return;
|
|
171
|
+
const parsed = typeof state === "string" ? parse(state) : void 0;
|
|
172
|
+
if (!Array.isArray(parsed)) return;
|
|
173
|
+
if (this.#state == null) this.#restored = parsed;
|
|
174
|
+
else setListboxValues(this.#state, parsed);
|
|
175
|
+
}
|
|
176
|
+
setLocalizations(first, second) {
|
|
177
|
+
updateListboxLocalizations(this.#state.localizations.global, this.#state.localizations.component, first, second);
|
|
178
|
+
}
|
|
179
|
+
#initialize() {
|
|
180
|
+
this.#state = createListboxState(this, this.#internals);
|
|
181
|
+
if (this.#restored != null) {
|
|
182
|
+
setListboxValues(this.#state, this.#restored);
|
|
183
|
+
this.#restored = void 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
customElements.define(LISTBOX_TAGNAME, OuiListboxElement);
|
|
188
|
+
//#endregion
|
|
189
|
+
export { OuiListboxElement, setListboxLocalizations };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { t as OuiLocalizations } from "../l10n-Bn-7RcwR.mjs";
|
|
2
|
+
import { l as OuiListboxState, o as OuiListboxLocalizations, u as OuiListboxStates } from "../listbox.model-CRReGOmu.mjs";
|
|
3
|
+
import { OuiListboxElement } from "./index.mjs";
|
|
4
|
+
//#region src/js/listbox/state.listbox.d.ts
|
|
5
|
+
declare function createListboxState(element: OuiListboxElement, internals: ElementInternals): OuiListboxState;
|
|
6
|
+
declare function onAttachListbox(state: OuiListboxState): void;
|
|
7
|
+
declare function onDetachListbox(state: OuiListboxState): void;
|
|
8
|
+
declare const listboxLocalizations: OuiLocalizations<OuiListboxLocalizations>;
|
|
9
|
+
declare const listboxStates: OuiListboxStates;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { createListboxState, listboxLocalizations, listboxStates, onAttachListbox, onDetachListbox };
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
import { getLocalization, localize } from "./l10n.mjs";
|
|
2
|
+
import { listboxScrollOptions } from "./internal/listbox/listbox.constants.mjs";
|
|
3
|
+
import { updateListboxForm, updateListboxValidity } from "./internal/listbox/listbox.form.mjs";
|
|
4
|
+
import { setAria } from "@oscarpalmer/toretto/aria";
|
|
5
|
+
import { dispatch } from "@oscarpalmer/toretto/event";
|
|
6
|
+
import { setAttribute } from "@oscarpalmer/toretto/attribute";
|
|
7
|
+
import { getString } from "@oscarpalmer/atoms/string";
|
|
8
|
+
import { getData } from "@oscarpalmer/toretto/data";
|
|
9
|
+
import { createElement, setAria as setAria$1, setAttribute as setAttribute$1 } from "@oscarpalmer/toretto";
|
|
10
|
+
//#region src/js/internal/listbox/listbox.misc.ts
|
|
11
|
+
function generateListboxIds(prefix, select) {
|
|
12
|
+
const elements = [...select.children].flatMap((child) => child instanceof HTMLOptGroupElement ? [child, ...[...child.children].filter((groupChild) => groupChild instanceof HTMLOptionElement)] : child instanceof HTMLOptionElement ? [child] : []);
|
|
13
|
+
const { length } = elements;
|
|
14
|
+
for (let index = 0; index < length; index += 1) {
|
|
15
|
+
const element = elements[index];
|
|
16
|
+
if (element.id === "") element.id = `${prefix}${element instanceof HTMLOptGroupElement ? "_group_" : "_option_"}${index}`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
function getListboxVisibleOptions(state) {
|
|
20
|
+
return state.options.all.filter((option) => !option.hidden);
|
|
21
|
+
}
|
|
22
|
+
function setListboxDisabled(state, value) {
|
|
23
|
+
state.filter.element.readOnly = state.readonly || value;
|
|
24
|
+
setProperties("disabled", state, value);
|
|
25
|
+
}
|
|
26
|
+
function setListboxFilter(state, value) {
|
|
27
|
+
if (typeof value !== "string") return;
|
|
28
|
+
const type = value.length < state.filter.element.value.length ? "deleteContentBackward" : "insertText";
|
|
29
|
+
state.filter.element.value = value;
|
|
30
|
+
filterListbox(type, state);
|
|
31
|
+
}
|
|
32
|
+
function setListboxLimit(type, state, value) {
|
|
33
|
+
let actual = value;
|
|
34
|
+
if (typeof actual === "string") actual = Number.parseInt(actual, 10);
|
|
35
|
+
if (typeof actual === "number" && !Number.isNaN(actual) && actual >= 0 ? actual !== state[type] : actual == null) {
|
|
36
|
+
state[type] = actual;
|
|
37
|
+
setAttribute(state.host, type, actual);
|
|
38
|
+
updateListboxValidity(state);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function setListboxMultiple(element, value) {
|
|
42
|
+
if (value) element.setAttribute("multiple", "");
|
|
43
|
+
else element.removeAttribute("multiple");
|
|
44
|
+
}
|
|
45
|
+
function setProperties(key, state, value) {
|
|
46
|
+
state[key] = value;
|
|
47
|
+
const { length } = state.elements;
|
|
48
|
+
for (let index = 0; index < length; index += 1) {
|
|
49
|
+
const element = state.elements[index];
|
|
50
|
+
if (element == null) continue;
|
|
51
|
+
setAria(element, key, key !== "readonly" || !(element instanceof HTMLButtonElement) ? value : void 0);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function setListboxReadonly(state, value) {
|
|
55
|
+
state.filter.element.readOnly = state.disabled || value;
|
|
56
|
+
setProperties("readonly", state, value);
|
|
57
|
+
}
|
|
58
|
+
function setListboxRequired(state, value) {
|
|
59
|
+
setProperties("required", state, value);
|
|
60
|
+
updateListboxValidity(state);
|
|
61
|
+
}
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/js/internal/listbox/listbox.dom.ts
|
|
64
|
+
function createListboxContent(parameters) {
|
|
65
|
+
const element = createElement("div", { attribute: { [parameters.attributes.content]: "" } });
|
|
66
|
+
const filter = createListboxFilter(parameters);
|
|
67
|
+
const list = createListboxList(parameters);
|
|
68
|
+
const message = createListboxMessage(parameters.attributes.message);
|
|
69
|
+
const value = createListboxValueLabel(parameters.id);
|
|
70
|
+
if (filter != null) element.append(filter.container);
|
|
71
|
+
element.append(list.element, message, value);
|
|
72
|
+
return {
|
|
73
|
+
element,
|
|
74
|
+
filter,
|
|
75
|
+
list,
|
|
76
|
+
message,
|
|
77
|
+
value
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function createListboxFilter(parameters) {
|
|
81
|
+
if (parameters.type === "autocomplete") return;
|
|
82
|
+
const container = createElement("div", { attribute: { [parameters.attributes.filter]: "" } });
|
|
83
|
+
const element = createListboxInput(parameters, "");
|
|
84
|
+
setAttribute$1(element, parameters.attributes.input, "");
|
|
85
|
+
container.append(element);
|
|
86
|
+
return {
|
|
87
|
+
container,
|
|
88
|
+
element
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function createListboxGroup(parameters) {
|
|
92
|
+
const { group, groupOptions, selected, type } = parameters;
|
|
93
|
+
const element = createElement("li", {
|
|
94
|
+
aria: { label: group.label },
|
|
95
|
+
property: { role: "group" }
|
|
96
|
+
});
|
|
97
|
+
const list = createElement("ul", { property: { role: "none" } });
|
|
98
|
+
const header = createListboxHeader(parameters, group);
|
|
99
|
+
element.append(header, list);
|
|
100
|
+
return {
|
|
101
|
+
element,
|
|
102
|
+
header,
|
|
103
|
+
options: createListboxOptions({
|
|
104
|
+
list,
|
|
105
|
+
selected,
|
|
106
|
+
type,
|
|
107
|
+
group: header.id,
|
|
108
|
+
options: groupOptions,
|
|
109
|
+
original: parameters.original
|
|
110
|
+
})
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function createListboxHeader(parameters, group) {
|
|
114
|
+
return createElement("div", {
|
|
115
|
+
aria: { hidden: true },
|
|
116
|
+
attribute: { [parameters.original.attributes.header]: "" },
|
|
117
|
+
property: {
|
|
118
|
+
id: group.id,
|
|
119
|
+
textContent: group.label
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function createListboxInput(parameters, value) {
|
|
124
|
+
const { autocomplete, id, label, listbox, type } = parameters;
|
|
125
|
+
const isAutocomplete = type === "autocomplete";
|
|
126
|
+
const input = createElement("input", {
|
|
127
|
+
aria: {
|
|
128
|
+
autocomplete: autocomplete.value,
|
|
129
|
+
controls: `${id}_list`,
|
|
130
|
+
haspopup: isAutocomplete ? "listbox" : void 0,
|
|
131
|
+
labelledby: label.id
|
|
132
|
+
},
|
|
133
|
+
attribute: {
|
|
134
|
+
autocorrect: "off",
|
|
135
|
+
autocomplete: "off",
|
|
136
|
+
form: "",
|
|
137
|
+
spellcheck: "false",
|
|
138
|
+
type: "text"
|
|
139
|
+
},
|
|
140
|
+
property: {
|
|
141
|
+
id,
|
|
142
|
+
value,
|
|
143
|
+
role: isAutocomplete || listbox ? "combobox" : "searchbox"
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
if (isAutocomplete || listbox) setAria$1(input, "expanded", listbox);
|
|
147
|
+
return input;
|
|
148
|
+
}
|
|
149
|
+
function createListboxList(parameters) {
|
|
150
|
+
const { attributes, id, label, multiple, select, type } = parameters;
|
|
151
|
+
const element = createElement("ul", {
|
|
152
|
+
aria: {
|
|
153
|
+
labelledby: label.id,
|
|
154
|
+
multiselectable: multiple
|
|
155
|
+
},
|
|
156
|
+
attribute: {
|
|
157
|
+
[attributes.list]: "",
|
|
158
|
+
tabindex: -1
|
|
159
|
+
},
|
|
160
|
+
property: {
|
|
161
|
+
id: `${id}_list`,
|
|
162
|
+
role: "listbox"
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
const children = [...select.children];
|
|
166
|
+
const childrenLength = children.length;
|
|
167
|
+
const options = [];
|
|
168
|
+
const selected = [];
|
|
169
|
+
let groups;
|
|
170
|
+
for (let childIndex = 0; childIndex < childrenLength; childIndex += 1) {
|
|
171
|
+
const child = children[childIndex];
|
|
172
|
+
if (child instanceof HTMLOptionElement) {
|
|
173
|
+
const option = createListboxOption({
|
|
174
|
+
type,
|
|
175
|
+
option: child,
|
|
176
|
+
original: parameters,
|
|
177
|
+
index: childIndex
|
|
178
|
+
});
|
|
179
|
+
element.append(option);
|
|
180
|
+
options.push(option);
|
|
181
|
+
if (child.selected) selected.push(option);
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
if (!(child instanceof HTMLOptGroupElement)) continue;
|
|
185
|
+
const group = createListboxGroup({
|
|
186
|
+
selected,
|
|
187
|
+
type,
|
|
188
|
+
group: child,
|
|
189
|
+
groupOptions: [...child.children],
|
|
190
|
+
original: parameters
|
|
191
|
+
});
|
|
192
|
+
groups ??= [];
|
|
193
|
+
element.append(group.element);
|
|
194
|
+
groups.push(group);
|
|
195
|
+
options.push(...group.options);
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
element,
|
|
199
|
+
groups,
|
|
200
|
+
options: {
|
|
201
|
+
selected,
|
|
202
|
+
all: options
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
function createListboxMessage(attribute) {
|
|
207
|
+
return createElement("div", {
|
|
208
|
+
aria: { live: "polite" },
|
|
209
|
+
attribute: { [attribute]: "" },
|
|
210
|
+
property: {
|
|
211
|
+
hidden: true,
|
|
212
|
+
role: "status"
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
function createListboxOption(parameters) {
|
|
217
|
+
const { group, option, original } = parameters;
|
|
218
|
+
return createElement("li", {
|
|
219
|
+
aria: { selected: (parameters.type === "select" || !original.autocomplete.none) && option.selected },
|
|
220
|
+
attribute: { [original.attributes.option]: "" },
|
|
221
|
+
data: {
|
|
222
|
+
group,
|
|
223
|
+
value: option.value
|
|
224
|
+
},
|
|
225
|
+
property: {
|
|
226
|
+
id: option.id,
|
|
227
|
+
role: "option",
|
|
228
|
+
textContent: option.textContent
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function createListboxOptions(parameters) {
|
|
233
|
+
const { group, list, options, original, selected, type } = parameters;
|
|
234
|
+
const items = [];
|
|
235
|
+
for (let index = 0; index < options.length; index += 1) {
|
|
236
|
+
const option = options[index];
|
|
237
|
+
const item = createListboxOption({
|
|
238
|
+
group,
|
|
239
|
+
index,
|
|
240
|
+
option,
|
|
241
|
+
original,
|
|
242
|
+
type
|
|
243
|
+
});
|
|
244
|
+
items.push(item);
|
|
245
|
+
if (option.selected) selected.push(item);
|
|
246
|
+
list.append(item);
|
|
247
|
+
}
|
|
248
|
+
return items;
|
|
249
|
+
}
|
|
250
|
+
function createListboxValueLabel(id) {
|
|
251
|
+
return createElement("span", { property: {
|
|
252
|
+
hidden: true,
|
|
253
|
+
id: `${id}_value`
|
|
254
|
+
} });
|
|
255
|
+
}
|
|
256
|
+
function updateListboxMessage(state) {
|
|
257
|
+
const { attributes, host, localizations, message } = state;
|
|
258
|
+
const visible = getListboxVisibleOptions(state).length;
|
|
259
|
+
setAttribute$1(message, attributes.hidden, visible > 0 ? "" : void 0);
|
|
260
|
+
let data = {};
|
|
261
|
+
let parameters = [];
|
|
262
|
+
let key;
|
|
263
|
+
if (visible === 0) key = "empty";
|
|
264
|
+
else {
|
|
265
|
+
data = { amount: visible };
|
|
266
|
+
key = "results";
|
|
267
|
+
parameters = [visible];
|
|
268
|
+
}
|
|
269
|
+
const localization = getLocalization(localizations.global, host, key, localizations.component);
|
|
270
|
+
message.textContent = localize(localization, data, parameters);
|
|
271
|
+
message.hidden = false;
|
|
272
|
+
}
|
|
273
|
+
function updateListboxPreview(preview, state, active, scroll) {
|
|
274
|
+
const { length } = state.options.all;
|
|
275
|
+
for (let index = 0; index < length; index += 1) {
|
|
276
|
+
const option = state.options.all[index];
|
|
277
|
+
setAttribute$1(option, state.attributes.active, option === active ? "" : void 0);
|
|
278
|
+
}
|
|
279
|
+
state.active = active;
|
|
280
|
+
setAria$1(state.filter.element, "activedescendant", state.content.checkVisibility() ? active?.id : void 0);
|
|
281
|
+
if (scroll ?? true) active?.scrollIntoView(listboxScrollOptions);
|
|
282
|
+
if (preview !== "none") state.callbacks.data.onPreview(preview, state, active);
|
|
283
|
+
}
|
|
284
|
+
function updateListboxValueLabel(state) {
|
|
285
|
+
let label;
|
|
286
|
+
if (state.multiple) {
|
|
287
|
+
const localization = getLocalization(state.localizations.global, state.host, "selected", state.localizations.component);
|
|
288
|
+
const { length } = state.options.selected;
|
|
289
|
+
label = localize(localization, { amount: length }, [length]);
|
|
290
|
+
} else label = state.autocomplete.none && !state.listbox ? state.filter.element.value : state.options.selected[0]?.textContent ?? "";
|
|
291
|
+
state.values.label.textContent = label;
|
|
292
|
+
}
|
|
293
|
+
//#endregion
|
|
294
|
+
//#region src/js/internal/listbox/listbox.data.ts
|
|
295
|
+
function applyListboxSelection(parameters) {
|
|
296
|
+
const { added, emit, option, scroll, selected, state } = parameters;
|
|
297
|
+
const { length } = state.options.all;
|
|
298
|
+
for (let index = 0; index < length; index += 1) {
|
|
299
|
+
const option = state.options.all[index];
|
|
300
|
+
setAria(option, "selected", (state.type === "select" || !state.autocomplete.none) && (selected ?? state.options.selected).includes(option));
|
|
301
|
+
}
|
|
302
|
+
const values = parameters.values ?? (state.autocomplete.none && !state.listbox ? [state.filter.element.value] : (selected ?? state.options.selected).map((option) => getData(option, "value", false) ?? ""));
|
|
303
|
+
if (values.length === 0) values.push("");
|
|
304
|
+
if (selected != null) state.options.selected = selected;
|
|
305
|
+
if (!(values.length === state.values.current.length ? values.some((value) => !state.values.current.includes(value)) : true)) return;
|
|
306
|
+
updateListboxForm(state, values, emit);
|
|
307
|
+
updateListboxMessage(state);
|
|
308
|
+
updateListboxPreview("set", state, option, scroll);
|
|
309
|
+
updateListboxValueLabel(state);
|
|
310
|
+
state.callbacks.data.onApply(state, option, values, added, selected, emit);
|
|
311
|
+
}
|
|
312
|
+
function filterListbox(type, state) {
|
|
313
|
+
if (state.disabled || state.readonly) return;
|
|
314
|
+
const update = state.filter.element.value !== state.filter.value;
|
|
315
|
+
const option = filterListboxOptions(state);
|
|
316
|
+
let preview;
|
|
317
|
+
if (type.includes("delete")) preview = "none";
|
|
318
|
+
else if (type.includes("insert")) preview = "typed";
|
|
319
|
+
if (preview != null) state.callbacks.data.onFilter(preview, state, update, option);
|
|
320
|
+
if (update) {
|
|
321
|
+
state.filter.value = state.filter.element.value;
|
|
322
|
+
dispatch(state.host, "input");
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
function filterListboxOption(state, value, textContent) {
|
|
326
|
+
const filterTextContent = textContent ?? false;
|
|
327
|
+
const filter = getString(value).toLocaleLowerCase();
|
|
328
|
+
filterListboxOptions(state);
|
|
329
|
+
const { length } = state.options.all;
|
|
330
|
+
let match;
|
|
331
|
+
for (let index = 0; index < length; index += 1) {
|
|
332
|
+
const option = state.options.all[index];
|
|
333
|
+
if ((filterTextContent ? option.textContent : getData(option, "value", false) ?? "").toLocaleLowerCase() === filter) {
|
|
334
|
+
match = option;
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return match;
|
|
339
|
+
}
|
|
340
|
+
function filterListboxOptions(state) {
|
|
341
|
+
function filter(options) {
|
|
342
|
+
const { length } = options;
|
|
343
|
+
let count = 0;
|
|
344
|
+
for (let index = 0; index < length; index += 1) {
|
|
345
|
+
const option = options[index];
|
|
346
|
+
option.hidden = (state.type === "select" || !state.autocomplete.none) && !option.textContent.toLocaleLowerCase().includes(value);
|
|
347
|
+
if (!option.hidden) {
|
|
348
|
+
count += 1;
|
|
349
|
+
visible.push(option);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return count === 0;
|
|
353
|
+
}
|
|
354
|
+
const value = state.filter.element.value.toLocaleLowerCase();
|
|
355
|
+
const visible = [];
|
|
356
|
+
if (state.groups == null) filter(state.options.all);
|
|
357
|
+
else {
|
|
358
|
+
const groupsLength = state.groups.length;
|
|
359
|
+
for (let groupIndex = 0; groupIndex < groupsLength; groupIndex += 1) {
|
|
360
|
+
const { element, options } = state.groups[groupIndex];
|
|
361
|
+
element.hidden = filter(options);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
setAttribute(state.list, state.attributes.empty, visible.length === 0 ? "" : void 0);
|
|
365
|
+
updateListboxMessage(state);
|
|
366
|
+
return state.active != null && visible.includes(state.active) ? state.active : visible[0];
|
|
367
|
+
}
|
|
368
|
+
function setListboxValue(state, value, emit) {
|
|
369
|
+
if (state.autocomplete.none && !state.listbox) {
|
|
370
|
+
setListboxFilter(state, getString(value));
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (filterListboxOption(state, value) != null) setListboxValues(state, [value], emit);
|
|
374
|
+
}
|
|
375
|
+
function setListboxValues(state, value, emit) {
|
|
376
|
+
if (!Array.isArray(value)) return;
|
|
377
|
+
const values = (state.multiple ? value : value.slice(0, 1)).map((value) => getString(value).toLocaleLowerCase());
|
|
378
|
+
if (values.length === 0) values.push("");
|
|
379
|
+
if (state.autocomplete.none && !state.listbox) {
|
|
380
|
+
setListboxValue(state, values[0], emit);
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
const { length } = state.options.all;
|
|
384
|
+
const selected = [];
|
|
385
|
+
for (let index = 0; index < length; index += 1) {
|
|
386
|
+
const option = state.options.all[index];
|
|
387
|
+
if (values.includes(getData(option, "value", false)?.toLocaleLowerCase() ?? "")) selected.push(option);
|
|
388
|
+
}
|
|
389
|
+
applyListboxSelection({
|
|
390
|
+
emit,
|
|
391
|
+
selected,
|
|
392
|
+
state,
|
|
393
|
+
added: true,
|
|
394
|
+
option: selected[0] ?? state.options.all[0],
|
|
395
|
+
values: state.autocomplete.none && !state.listbox ? values : void 0
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
function toggleListboxOption(state, option) {
|
|
399
|
+
if (option == null || !state.multiple && state.options.selected.includes(option)) {
|
|
400
|
+
state.callbacks.data.onToggle(state);
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
const selected = state.options.selected.slice();
|
|
404
|
+
let added = true;
|
|
405
|
+
if (state.multiple) {
|
|
406
|
+
const index = selected.indexOf(option);
|
|
407
|
+
if (index === -1) selected.push(option);
|
|
408
|
+
else {
|
|
409
|
+
added = false;
|
|
410
|
+
selected.splice(index, 1);
|
|
411
|
+
}
|
|
412
|
+
} else selected.splice(0, selected.length, option);
|
|
413
|
+
applyListboxSelection({
|
|
414
|
+
added,
|
|
415
|
+
option,
|
|
416
|
+
selected,
|
|
417
|
+
state,
|
|
418
|
+
scroll: false,
|
|
419
|
+
values: state.autocomplete.none && !state.listbox && option != null ? [option.textContent] : void 0
|
|
420
|
+
});
|
|
421
|
+
state.callbacks.data.onToggle(state);
|
|
422
|
+
}
|
|
423
|
+
//#endregion
|
|
424
|
+
export { setListboxDisabled as C, setListboxReadonly as D, setListboxMultiple as E, setListboxRequired as O, getListboxVisibleOptions as S, setListboxLimit as T, createListboxValueLabel as _, setListboxValue as a, updateListboxValueLabel as b, createListboxContent as c, createListboxHeader as d, createListboxInput as f, createListboxOptions as g, createListboxOption as h, filterListboxOptions as i, createListboxFilter as l, createListboxMessage as m, filterListbox as n, setListboxValues as o, createListboxList as p, filterListboxOption as r, toggleListboxOption as s, applyListboxSelection as t, createListboxGroup as u, updateListboxMessage as v, setListboxFilter as w, generateListboxIds as x, updateListboxPreview as y };
|