@oscarpalmer/oui 0.34.0 → 0.35.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.
Files changed (32) hide show
  1. package/dist/js/combobox/constants.combobox.d.mts +1 -1
  2. package/dist/js/combobox/data.combobox.d.mts +1 -1
  3. package/dist/js/combobox/data.combobox.mjs +1 -1
  4. package/dist/js/combobox/dom.combobox.d.mts +1 -1
  5. package/dist/js/combobox/dom.combobox.mjs +1 -1
  6. package/dist/js/combobox/event.combobox.d.mts +1 -1
  7. package/dist/js/combobox/event.combobox.mjs +1 -1
  8. package/dist/js/combobox/form.combobox.d.mts +1 -1
  9. package/dist/js/combobox/form.combobox.mjs +1 -1
  10. package/dist/js/combobox/index.d.mts +1 -1
  11. package/dist/js/combobox/index.mjs +3 -2
  12. package/dist/js/combobox/misc.combobox.d.mts +2 -14
  13. package/dist/js/combobox/misc.combobox.mjs +2 -2
  14. package/dist/js/combobox/models.combobox.d.mts +1 -1
  15. package/dist/js/combobox/state.combobox.d.mts +4 -2
  16. package/dist/js/combobox/state.combobox.mjs +2 -2
  17. package/dist/js/{constants.combobox-DqNUGBLS.d.mts → constants.combobox-h_kyDegw.d.mts} +12 -7
  18. package/dist/js/{data.combobox-8RwBv5ey.mjs → data.combobox-B8HMkDOh.mjs} +245 -292
  19. package/dist/js/index.d.mts +1 -1
  20. package/dist/js/index.mjs +1 -1
  21. package/dist/js/l10n.d.mts +20 -0
  22. package/dist/js/l10n.mjs +80 -0
  23. package/package.json +1 -1
  24. package/src/js/combobox/dom.combobox.ts +57 -26
  25. package/src/js/combobox/form.combobox.ts +26 -25
  26. package/src/js/combobox/index.ts +10 -4
  27. package/src/js/combobox/misc.combobox.ts +50 -0
  28. package/src/js/combobox/state.combobox.ts +13 -1
  29. package/src/js/l10n.ts +192 -0
  30. package/dist/js/combobox/i18n.combobox.d.mts +0 -2
  31. package/dist/js/combobox/i18n.combobox.mjs +0 -2
  32. package/src/js/combobox/i18n.combobox.ts +0 -179
@@ -1,4 +1,5 @@
1
1
  import { createEmbeddedFloatable } from "./floatable/floatable.embedded.mjs";
2
+ import { getLocalization, getLocalizations, localize, updateLocalizations } from "./l10n.mjs";
2
3
  import { COMBOBOX_ATTRIBUTE_ANCHOR, COMBOBOX_ATTRIBUTE_CONTENT, COMBOBOX_ATTRIBUTE_FILTER, COMBOBOX_ATTRIBUTE_FILTER_INPUT, COMBOBOX_ATTRIBUTE_HEADER, COMBOBOX_ATTRIBUTE_HIDDEN, COMBOBOX_ATTRIBUTE_LIST, COMBOBOX_ATTRIBUTE_MESSAGE, COMBOBOX_ATTRIBUTE_OPTION, COMBOBOX_ATTRIBUTE_OPTION_ACTIVE, COMBOBOX_ATTRIBUTE_SELECTION, COMBOBOX_ATTRIBUTE_SELECTION_ITEM, COMBOBOX_AUTOCOMPLETES, COMBOBOX_KEYS_ACTIVATION, COMBOBOX_KEYS_NAVIGATION, COMBOBOX_KEYS_SELECTION, COMBOBOX_MESSAGE_LABEL, COMBOBOX_MESSAGE_SELECT, COMBOBOX_SELECTOR_ANCHOR, COMBOBOX_SELECTOR_OPTION, COMBOBOX_SELECTOR_SELECTION_ITEM, COMBOBOX_TAGNAME, COMBOBOX_TYPES, comboboxScrollOptions } from "./combobox/constants.combobox.mjs";
3
4
  import { getAria, setAria } from "@oscarpalmer/toretto/aria";
4
5
  import { dispatch, on } from "@oscarpalmer/toretto/event";
@@ -8,145 +9,70 @@ import { getString } from "@oscarpalmer/atoms/string";
8
9
  import { getData } from "@oscarpalmer/toretto/data";
9
10
  import { createElement } from "@oscarpalmer/toretto/create";
10
11
  import { dispatch as dispatch$1, findAncestor, getData as getData$1 } from "@oscarpalmer/toretto";
11
- //#region src/js/combobox/state.combobox.ts
12
- function attachCombobox(state) {
13
- const { anchor, content, filter, label, listeners, select } = state;
14
- label.element.htmlFor = filter.element.id;
15
- label.element.id = `${state.id}_label`;
16
- select.hidden = true;
17
- select.insertAdjacentElement("afterend", anchor.container ?? anchor.element);
18
- (anchor.container ?? anchor.element).insertAdjacentElement("afterend", content);
19
- select.remove();
20
- state.floatable = createEmbeddedFloatable(anchor.container ?? anchor.element, content, {
21
- position: "below-start",
22
- reusable: false
23
- });
24
- state.floatable.update();
25
- listeners.push(on(state.host, "focusout", () => {
26
- setTimeout(() => {
27
- onComboboxFocusout(state);
28
- });
29
- }), on(content, "click", (event) => {
30
- onComboboxClickContent(event, content);
31
- }), on(content, "toggle", () => {
32
- setAria(anchor.element, "expanded", state.floatable.open);
33
- setAria(filter.element, "activedescendant", state.floatable.open ? state.active?.id : void 0);
34
- if (state.floatable.open) filter.element.focus();
35
- }));
36
- comboboxStates.map.set(state.host, state);
37
- comboboxStates.map.set(state.content, state);
38
- comboboxStates.set.add(state);
12
+ //#region src/js/combobox/misc.combobox.ts
13
+ function generateComboboxIds(prefix, select) {
14
+ const elements = [...select.children].flatMap((child) => child instanceof HTMLOptGroupElement ? [child, ...[...child.children].filter((groupChild) => groupChild instanceof HTMLOptionElement)] : child instanceof HTMLOptionElement ? [child] : []);
15
+ const { length } = elements;
16
+ for (let index = 0; index < length; index += 1) {
17
+ const element = elements[index];
18
+ if (element.id === "") element.id = `${prefix}${element instanceof HTMLOptGroupElement ? "_group_" : "_option_"}${index}`;
19
+ }
39
20
  }
40
- function createComboboxState(element, internals) {
41
- const select = element.querySelector("select");
42
- if (select == null || select.id === "") throw new Error(COMBOBOX_MESSAGE_SELECT);
43
- const label = element.querySelector(`label[for="${select.id}"]`);
44
- if (label == null) throw new Error(COMBOBOX_MESSAGE_LABEL);
45
- element.id = select.id;
46
- setAttribute(element, "name", select.name === "" ? select.id : select.name);
47
- const disabled = getComboboxBooleanAria(element, "disabled") || select.disabled;
48
- const multiple = element.multiple || select.multiple;
49
- const readonly = getComboboxBooleanAria(element, "readonly");
50
- const required = getComboboxBooleanAria(element, "required") || select.required;
51
- const id = getComboboxId();
52
- const type = multiple ? "select" : getComboboxAttributeValue(element, "type", COMBOBOX_TYPES, "select");
53
- const autocomplete = getComboboxAutoComplete(element, type === "select");
54
- const labelId = label.id;
55
- label.htmlFor = id;
56
- label.id = `${id}_label`;
57
- generateComboboxIds(id, select);
58
- const anchor = createComboboxAnchor({
59
- autocomplete,
60
- id,
61
- label,
62
- multiple,
63
- select,
64
- type
65
- });
66
- const content = createComboboxContent({
67
- autocomplete,
68
- id,
69
- label,
70
- multiple,
71
- select,
72
- type
73
- });
74
- const values = content.list.selected.length === 0 ? [""] : content.list.selected.map((option) => getData(option, "value", false) ?? "");
75
- const state = {
76
- autocomplete,
77
- disabled,
78
- id,
79
- internals,
80
- multiple,
81
- readonly,
82
- required,
83
- select,
84
- type,
85
- anchor: {
86
- container: anchor.container,
87
- element: anchor.element
88
- },
89
- active: content.list.selected[0],
90
- content: content.element,
91
- filter: {
92
- element: content.filter?.element ?? anchor.element,
93
- value: ""
94
- },
95
- floatable: void 0,
96
- groups: content.list.groups,
97
- host: element,
98
- label: {
99
- element: label,
100
- id: labelId
101
- },
102
- listeners: [],
103
- localizations: {},
104
- message: content.message,
105
- name: element.name,
106
- options: {
107
- all: content.list.options,
108
- selected: content.list.selected
109
- },
110
- selection: anchor.selection,
111
- values: {
112
- current: values.slice(),
113
- initial: values.slice()
114
- }
21
+ function getComboboxAttributeValue(element, attribute, possible, defaultValue) {
22
+ const value = getAttribute(element, attribute);
23
+ return possible.has(value) ? value : defaultValue;
24
+ }
25
+ function getComboboxAutoComplete(element, select) {
26
+ let value;
27
+ if (select) value = "list";
28
+ else value = getComboboxAttributeValue(element, "autocomplete", COMBOBOX_AUTOCOMPLETES, "none");
29
+ return {
30
+ value,
31
+ both: value === "both",
32
+ inline: value === "inline",
33
+ list: value === "list",
34
+ none: value === "none"
115
35
  };
116
- attachCombobox(state);
117
- setComboboxDisabled(state, disabled);
118
- setComboboxLimit("max", state, getAttribute(element, "max"));
119
- setComboboxLimit("min", state, getAttribute(element, "min"));
120
- setComboboxReadonly(state, readonly);
121
- setComboboxRequired(state, required);
122
- filterComboboxOptions(state);
123
- if (content.list.selected.length > 0) updateComboboxPreview("set", state, content.list.selected[0]);
124
- updateComboboxForm(state, state.values.current, false);
125
- updateComboboxMessage(state, getComboboxVisibleOptions(state).length);
126
- updateComboboxSelectionItems(state);
127
- return state;
128
36
  }
129
- function detachCombobox(state) {
130
- const { content, floatable, host, label, select } = state;
131
- const listeners = state.listeners.splice(0);
132
- const { length } = listeners;
133
- for (let index = 0; index < length; index += 1) listeners[index]();
134
- floatable.destroy();
135
- const anchor = state.anchor.container ?? state.anchor.element;
136
- anchor.insertAdjacentElement("beforebegin", select);
137
- anchor.remove();
138
- content.remove();
139
- label.element.htmlFor = select.id;
140
- label.element.id = state.label.id;
141
- select.hidden = false;
142
- comboboxStates.map.delete(host);
143
- comboboxStates.map.delete(content);
144
- comboboxStates.set.delete(state);
37
+ function getComboboxBooleanAria(element, attribute) {
38
+ const value = getAria(element, attribute);
39
+ return value === true || value === "true";
145
40
  }
146
- const comboboxStates = {
147
- map: /* @__PURE__ */ new WeakMap(),
148
- set: /* @__PURE__ */ new Set()
149
- };
41
+ function getComboboxId() {
42
+ index += 1;
43
+ return `oui_combobox_${index}`;
44
+ }
45
+ function getComboboxVisibleOptions(state) {
46
+ return state.options.all.filter((option) => !option.hidden);
47
+ }
48
+ function hasTextSelection(element) {
49
+ return element instanceof HTMLInputElement && element.selectionStart !== element.selectionEnd;
50
+ }
51
+ function setComboboxFilter(state, value) {
52
+ if (typeof value !== "string") return;
53
+ const type = value.length < state.filter.element.value.length ? "deleteContentBackward" : "insertText";
54
+ state.filter.element.value = value;
55
+ onComboboxFilter(type, state);
56
+ }
57
+ function setComboboxLimit(type, state, value) {
58
+ let actual = value;
59
+ if (typeof actual === "string") actual = Number.parseInt(actual, 10);
60
+ if (typeof actual === "number" && !Number.isNaN(actual) && actual >= 0 ? actual !== state[type] : actual == null) {
61
+ state[type] = actual;
62
+ setAttribute(state.host, type, actual);
63
+ updateComboboxValidity(state);
64
+ }
65
+ }
66
+ function setComboboxLocalizations(first, second) {
67
+ updateLocalizations(comboboxLocalizations, typeof first === "string" ? { [first]: second } : first, comboboxLocalizations.values, () => {
68
+ for (const state of comboboxStates.set) {
69
+ updateComboboxAnchor(state);
70
+ updateComboboxMessage(state, getComboboxVisibleOptions(state).length);
71
+ updateComboboxSelectionItems(state);
72
+ }
73
+ });
74
+ }
75
+ let index = 0;
150
76
  //#endregion
151
77
  //#region src/js/combobox/event.combobox.ts
152
78
  function onComboboxClickContent(event, content) {
@@ -355,139 +281,154 @@ on(document, "click", onComboboxClickDocument);
355
281
  on(document, "input", onComboboxInput, { passive: false });
356
282
  on(document, "keydown", onComboboxKeydown, { passive: false });
357
283
  //#endregion
358
- //#region src/js/combobox/misc.combobox.ts
359
- function generateComboboxIds(prefix, select) {
360
- const elements = [...select.children].flatMap((child) => child instanceof HTMLOptGroupElement ? [child, ...[...child.children].filter((groupChild) => groupChild instanceof HTMLOptionElement)] : child instanceof HTMLOptionElement ? [child] : []);
361
- const { length } = elements;
362
- for (let index = 0; index < length; index += 1) {
363
- const element = elements[index];
364
- if (element.id === "") element.id = `${prefix}${element instanceof HTMLOptGroupElement ? "_group_" : "_option_"}${index}`;
365
- }
366
- }
367
- function getComboboxAttributeValue(element, attribute, possible, defaultValue) {
368
- const value = getAttribute(element, attribute);
369
- return possible.has(value) ? value : defaultValue;
284
+ //#region src/js/combobox/state.combobox.ts
285
+ function attachCombobox(state) {
286
+ const { anchor, content, filter, label, listeners, select } = state;
287
+ label.element.htmlFor = filter.element.id;
288
+ label.element.id = `${state.id}_label`;
289
+ select.hidden = true;
290
+ select.insertAdjacentElement("afterend", anchor.container ?? anchor.element);
291
+ (anchor.container ?? anchor.element).insertAdjacentElement("afterend", content);
292
+ select.remove();
293
+ state.floatable = createEmbeddedFloatable(anchor.container ?? anchor.element, content, {
294
+ position: "below-start",
295
+ reusable: false
296
+ });
297
+ state.floatable.update();
298
+ listeners.push(on(state.host, "focusout", () => {
299
+ setTimeout(() => {
300
+ onComboboxFocusout(state);
301
+ });
302
+ }), on(content, "click", (event) => {
303
+ onComboboxClickContent(event, content);
304
+ }), on(content, "toggle", () => {
305
+ setAria(anchor.element, "expanded", state.floatable.open);
306
+ setAria(filter.element, "activedescendant", state.floatable.open ? state.active?.id : void 0);
307
+ if (state.floatable.open) filter.element.focus();
308
+ }));
309
+ comboboxStates.map.set(state.host, state);
310
+ comboboxStates.map.set(state.content, state);
311
+ comboboxStates.set.add(state);
370
312
  }
371
- function getComboboxAutoComplete(element, select) {
372
- let value;
373
- if (select) value = "list";
374
- else value = getComboboxAttributeValue(element, "autocomplete", COMBOBOX_AUTOCOMPLETES, "none");
375
- return {
376
- value,
377
- both: value === "both",
378
- inline: value === "inline",
379
- list: value === "list",
380
- none: value === "none"
313
+ function createComboboxState(element, internals) {
314
+ const select = element.querySelector("select");
315
+ if (select == null || select.id === "") throw new Error(COMBOBOX_MESSAGE_SELECT);
316
+ const label = element.querySelector(`label[for="${select.id}"]`);
317
+ if (label == null) throw new Error(COMBOBOX_MESSAGE_LABEL);
318
+ element.id = select.id;
319
+ setAttribute(element, "name", select.name === "" ? select.id : select.name);
320
+ const disabled = getComboboxBooleanAria(element, "disabled") || select.disabled;
321
+ const multiple = element.multiple || select.multiple;
322
+ const readonly = getComboboxBooleanAria(element, "readonly");
323
+ const required = getComboboxBooleanAria(element, "required") || select.required;
324
+ const id = getComboboxId();
325
+ const type = multiple ? "select" : getComboboxAttributeValue(element, "type", COMBOBOX_TYPES, "select");
326
+ const autocomplete = getComboboxAutoComplete(element, type === "select");
327
+ const labelId = label.id;
328
+ label.htmlFor = id;
329
+ label.id = `${id}_label`;
330
+ generateComboboxIds(id, select);
331
+ const anchor = createComboboxAnchor({
332
+ autocomplete,
333
+ id,
334
+ label,
335
+ multiple,
336
+ select,
337
+ type
338
+ });
339
+ const content = createComboboxContent({
340
+ autocomplete,
341
+ id,
342
+ label,
343
+ multiple,
344
+ select,
345
+ type
346
+ });
347
+ const values = content.list.selected.length === 0 ? [""] : content.list.selected.map((option) => getData(option, "value", false) ?? "");
348
+ const state = {
349
+ autocomplete,
350
+ disabled,
351
+ id,
352
+ internals,
353
+ multiple,
354
+ readonly,
355
+ required,
356
+ select,
357
+ type,
358
+ anchor: {
359
+ container: anchor.container,
360
+ element: anchor.element
361
+ },
362
+ active: content.list.selected[0],
363
+ content: content.element,
364
+ filter: {
365
+ element: content.filter?.element ?? anchor.element,
366
+ value: ""
367
+ },
368
+ floatable: void 0,
369
+ groups: content.list.groups,
370
+ host: element,
371
+ label: {
372
+ element: label,
373
+ id: labelId
374
+ },
375
+ listeners: [],
376
+ localizations: {},
377
+ message: content.message,
378
+ name: element.name,
379
+ options: {
380
+ all: content.list.options,
381
+ selected: content.list.selected
382
+ },
383
+ selection: anchor.selection,
384
+ values: {
385
+ current: values.slice(),
386
+ initial: values.slice()
387
+ }
381
388
  };
389
+ attachCombobox(state);
390
+ setComboboxDisabled(state, disabled);
391
+ setComboboxLimit("max", state, getAttribute(element, "max"));
392
+ setComboboxLimit("min", state, getAttribute(element, "min"));
393
+ setComboboxReadonly(state, readonly);
394
+ setComboboxRequired(state, required);
395
+ filterComboboxOptions(state);
396
+ if (content.list.selected.length > 0) updateComboboxPreview("set", state, content.list.selected[0]);
397
+ updateComboboxForm(state, state.values.current, false);
398
+ updateComboboxMessage(state, getComboboxVisibleOptions(state).length);
399
+ updateComboboxSelectionItems(state);
400
+ return state;
382
401
  }
383
- function getComboboxBooleanAria(element, attribute) {
384
- const value = getAria(element, attribute);
385
- return value === true || value === "true";
386
- }
387
- function getComboboxId() {
388
- index += 1;
389
- return `oui_combobox_${index}`;
390
- }
391
- function getComboboxVisibleOptions(state) {
392
- return state.options.all.filter((option) => !option.hidden);
393
- }
394
- function hasTextSelection(element) {
395
- return element instanceof HTMLInputElement && element.selectionStart !== element.selectionEnd;
396
- }
397
- function setComboboxFilter(state, value) {
398
- if (typeof value !== "string") return;
399
- const type = value.length < state.filter.element.value.length ? "deleteContentBackward" : "insertText";
400
- state.filter.element.value = value;
401
- onComboboxFilter(type, state);
402
- }
403
- function setComboboxLimit(type, state, value) {
404
- let actual = value;
405
- if (typeof actual === "string") actual = Number.parseInt(actual, 10);
406
- if (typeof actual === "number" && !Number.isNaN(actual) && actual >= 0 ? actual !== state[type] : actual == null) {
407
- state[type] = actual;
408
- setAttribute(state.host, type, actual);
409
- updateComboboxValidity(state);
410
- }
411
- }
412
- let index = 0;
413
- //#endregion
414
- //#region src/js/combobox/i18n.combobox.ts
415
- function getComboboxLanguage(state) {
416
- return (state.host.closest("[lang]")?.getAttribute("lang") ?? document.documentElement.lang).toLowerCase();
417
- }
418
- function getComboboxLocalization(key, state) {
419
- const language = getComboboxLanguage(state);
420
- const allLocalizations = [state.localizations, LOCALIZATIONS.globals];
421
- const { length } = allLocalizations;
422
- let localization;
423
- let shortLanguage;
424
- for (let index = 0; index < length; index += 1) {
425
- const localizations = allLocalizations[index];
426
- localization = localizations?.[language]?.[key];
427
- if (localization != null) break;
428
- shortLanguage ??= language.split("-")[0];
429
- if (shortLanguage === language) continue;
430
- localization = localizations?.[shortLanguage]?.[key];
431
- if (localization != null) break;
432
- }
433
- return localization ?? LOCALIZATIONS.defaults[key];
434
- }
435
- function setComboboxLocalizations(first, second) {
436
- updateComboboxLocalizations(typeof first === "string" ? { [first]: second } : first);
437
- }
438
- function updateComboboxLocalizations(values, destination) {
439
- if (typeof values !== "object" || values == null) return;
440
- const localizations = destination ?? LOCALIZATIONS.globals;
441
- const languages = Object.keys(values);
442
- const languagesLength = languages.length;
443
- let updated = false;
444
- for (let languagesIndex = 0; languagesIndex < languagesLength; languagesIndex += 1) {
445
- const language = languages[languagesIndex];
446
- const languageValue = values[language];
447
- if (typeof languageValue !== "object" || languageValue == null) continue;
448
- const normalizedLanguage = language.toLowerCase();
449
- localizations[normalizedLanguage] ??= {};
450
- const keys = Object.keys(languageValue);
451
- const keysLength = keys.length;
452
- for (let keysIndex = 0; keysIndex < keysLength; keysIndex += 1) {
453
- const key = keys[keysIndex];
454
- const keyValue = languageValue[key];
455
- const normalizedKey = key.toLowerCase();
456
- if (LOCALIZATIONS.keys.has(normalizedKey) && (typeof keyValue === "string" || typeof keyValue === "function")) {
457
- updated = true;
458
- localizations[normalizedLanguage][normalizedKey] = keyValue;
459
- }
460
- }
461
- }
462
- if (!updated) return;
463
- for (const state of comboboxStates.set) {
464
- updateComboboxAnchor(state);
465
- updateComboboxMessage(state, getComboboxVisibleOptions(state).length);
466
- updateComboboxSelectionItems(state);
467
- }
402
+ function detachCombobox(state) {
403
+ const { content, floatable, host, label, select } = state;
404
+ const listeners = state.listeners.splice(0);
405
+ const { length } = listeners;
406
+ for (let index = 0; index < length; index += 1) listeners[index]();
407
+ floatable.destroy();
408
+ const anchor = state.anchor.container ?? state.anchor.element;
409
+ anchor.insertAdjacentElement("beforebegin", select);
410
+ anchor.remove();
411
+ content.remove();
412
+ label.element.htmlFor = select.id;
413
+ label.element.id = state.label.id;
414
+ select.hidden = false;
415
+ comboboxStates.map.delete(host);
416
+ comboboxStates.map.delete(content);
417
+ comboboxStates.set.delete(state);
468
418
  }
469
- const LOCALIZATIONS = {
470
- defaults: {
471
- empty: "No results found",
472
- input: "Please enter a value",
473
- invalid: "Please select an option from the list",
474
- max: (max) => `Please select fewer options (maximum is ${max})`,
475
- min: (min) => `Please select more options (minimum is ${min})`,
476
- remove: (label) => `Remove ${label}`,
477
- results: (amount) => `${amount} results available`,
478
- selected: (amount) => `${amount} selected`
479
- },
480
- globals: {},
481
- keys: /* @__PURE__ */ new Set([
482
- "empty",
483
- "input",
484
- "invalid",
485
- "max",
486
- "min",
487
- "remove",
488
- "results",
489
- "selected"
490
- ])
419
+ const comboboxLocalizations = getLocalizations({
420
+ empty: "No results found",
421
+ input: "Please enter a value",
422
+ invalid: "Please select an option from the list",
423
+ max: (max) => `Please select fewer options (maximum is ${max})`,
424
+ min: (min) => `Please select more options (minimum is ${min})`,
425
+ remove: (label) => `Remove ${label}`,
426
+ results: (amount) => `${amount} results available`,
427
+ selected: (amount) => `${amount} selected`
428
+ });
429
+ const comboboxStates = {
430
+ map: /* @__PURE__ */ new WeakMap(),
431
+ set: /* @__PURE__ */ new Set()
491
432
  };
492
433
  //#endregion
493
434
  //#region src/js/combobox/form.combobox.ts
@@ -507,33 +448,34 @@ function updateComboboxForm(state, values, emit) {
507
448
  function updateComboboxValidity(state) {
508
449
  if (state.autocomplete.none) {
509
450
  const valueMissing = state.required && state.filter.element.value.length === 0;
510
- const localization = getComboboxLocalization("invalid", state);
511
- state.internals.setValidity({ valueMissing }, typeof localization === "function" ? localization() : localization);
451
+ const localization = getLocalization(comboboxLocalizations, state.host, "invalid", state.localizations);
452
+ state.internals.setValidity({ valueMissing }, localize(localization, {}, []));
512
453
  state.internals.checkValidity();
513
454
  return;
514
455
  }
456
+ let data = {};
515
457
  let error;
516
- let message;
458
+ let key;
459
+ let parameters = [];
517
460
  switch (true) {
518
- case state.required && state.options.selected.length === 0: {
461
+ case state.required && state.options.selected.length === 0:
519
462
  error = "badInput";
520
- const localization = getComboboxLocalization("input", state);
521
- message = typeof localization === "function" ? localization() : localization;
463
+ key = "input";
522
464
  break;
523
- }
524
- case state.multiple && typeof state.max === "number" && state.options.selected.length > state.max: {
465
+ case state.multiple && typeof state.max === "number" && state.options.selected.length > state.max:
466
+ data = { amount: state.max };
525
467
  error = "rangeOverflow";
526
- const localization = getComboboxLocalization("max", state);
527
- message = typeof localization === "function" ? localization(state.max) : localization.replace("{max}", state.max.toString());
468
+ key = "max";
469
+ parameters = [state.max];
528
470
  break;
529
- }
530
- case state.multiple && typeof state.min === "number" && state.options.selected.length < state.min: {
471
+ case state.multiple && typeof state.min === "number" && state.options.selected.length < state.min:
472
+ data = { amount: state.min };
531
473
  error = "rangeUnderflow";
532
- const localization = getComboboxLocalization("min", state);
533
- message = typeof localization === "function" ? localization(state.min) : localization.replace("{min}", state.min.toString());
534
- break;
535
- }
474
+ key = "min";
475
+ parameters = [state.min];
536
476
  }
477
+ const localization = key == null ? void 0 : getLocalization(comboboxLocalizations, state.host, key, state.localizations);
478
+ const message = localization == null ? void 0 : localize(localization, data, parameters);
537
479
  state.internals.setValidity(error == null ? {} : { [error]: true }, message);
538
480
  state.internals.checkValidity();
539
481
  }
@@ -805,10 +747,15 @@ function createComboboxSelection(id, select) {
805
747
  };
806
748
  }
807
749
  function createComboboxSelectionItem(option, state) {
750
+ const optionLabel = option.textContent;
751
+ const optionValue = getData(option, "value", false) ?? "";
808
752
  const element = createElement("li");
809
- const localization = state == null ? option.textContent : getComboboxLocalization("remove", state);
753
+ const localization = state == null ? option.textContent : getLocalization(comboboxLocalizations, state.host, "remove", state.localizations);
810
754
  const button = createElement("button", {
811
- aria: { label: typeof localization === "function" ? localization(option.textContent ?? "", getData(option, "value", false) ?? "") : localization },
755
+ aria: { label: localize(localization, {
756
+ label: optionLabel,
757
+ value: optionValue
758
+ }, [optionLabel, optionValue]) },
812
759
  attribute: {
813
760
  [COMBOBOX_ATTRIBUTE_SELECTION_ITEM]: "",
814
761
  tabindex: -1
@@ -875,8 +822,9 @@ function updateComboboxTabindices(state, active) {
875
822
  }
876
823
  function updateComboboxAnchor(state) {
877
824
  if (!state.multiple) return;
878
- const localization = getComboboxLocalization("selected", state);
879
- setAria(state.anchor.element, "label", typeof localization === "function" ? localization(state.options.selected.length) : localization.replace("{amount}", state.options.selected.length.toString()));
825
+ const localization = getLocalization(comboboxLocalizations, state.host, "selected", state.localizations);
826
+ const { length } = state.options.selected;
827
+ setAria(state.anchor.element, "label", localize(localization, { amount: length }, [length]));
880
828
  }
881
829
  function updateComboboxAutocomplete(preview, state, active) {
882
830
  if (state.multiple) return;
@@ -894,11 +842,11 @@ function updateComboboxAutocomplete(preview, state, active) {
894
842
  function updateComboboxMessage(state, visible) {
895
843
  setAttribute(state.message, COMBOBOX_ATTRIBUTE_HIDDEN, visible > 0 ? "" : void 0);
896
844
  if (visible === 0) {
897
- const localization = getComboboxLocalization("empty", state);
898
- state.message.textContent = typeof localization === "function" ? localization() : localization;
845
+ const localization = getLocalization(comboboxLocalizations, state.host, "empty", state.localizations);
846
+ state.message.textContent = localize(localization, {}, []);
899
847
  } else {
900
- const localization = getComboboxLocalization("results", state);
901
- state.message.textContent = typeof localization === "function" ? localization(visible) : localization.replace("{amount}", visible.toString());
848
+ const localization = getLocalization(comboboxLocalizations, state.host, "results", state.localizations);
849
+ state.message.textContent = localize(localization, { amount: visible }, [visible]);
902
850
  }
903
851
  state.message.hidden = false;
904
852
  }
@@ -916,7 +864,7 @@ function updateComboboxPreview(preview, state, active) {
916
864
  function updateComboboxSelection(state, active, added, selected) {
917
865
  if (state.selection == null) return;
918
866
  let options = active == null ? [] : [active];
919
- if (selected != null) {
867
+ if (added && selected != null) {
920
868
  options = selected;
921
869
  const { length } = state.selection.items;
922
870
  for (let index = 0; index < length; index += 1) state.selection.items[index].element.remove();
@@ -950,13 +898,18 @@ function updateComboboxSelection(state, active, added, selected) {
950
898
  }
951
899
  function updateComboboxSelectionItems(state) {
952
900
  if (state.selection == null) return;
953
- const localization = getComboboxLocalization("remove", state);
901
+ const localization = getLocalization(comboboxLocalizations, state.host, "remove", state.localizations);
954
902
  const { length } = state.selection.items;
955
903
  for (let index = 0; index < length; index += 1) {
956
904
  const item = state.selection.items[index];
957
905
  const option = state.options.selected.find((option) => option.id === getData(item.button, "option", false));
958
906
  if (option == null) continue;
959
- setAria(item.button, "label", typeof localization === "function" ? localization(option?.textContent ?? "", getData(option, "value", false) ?? "") : localization.replace("{label}", option?.textContent ?? ""));
907
+ const optionLabel = option.textContent;
908
+ const optionValue = getData(option, "value", false) ?? "";
909
+ setAria(item.button, "label", localize(localization, {
910
+ label: optionLabel,
911
+ value: optionValue
912
+ }, [optionLabel, optionValue]));
960
913
  }
961
914
  }
962
915
  //#endregion
@@ -1074,4 +1027,4 @@ function toggleComboboxOption(state, option) {
1074
1027
  if (!state.multiple) state.floatable.hide();
1075
1028
  }
1076
1029
  //#endregion
1077
- export { onComboboxKeydown as $, updateComboboxTabindices as A, getComboboxBooleanAria as B, setComboboxRequired as C, updateComboboxPreview as D, updateComboboxMessage as E, setComboboxLocalizations as F, setComboboxLimit as G, getComboboxVisibleOptions as H, updateComboboxLocalizations as I, onComboboxEnter as J, onComboboxClickContent as K, generateComboboxIds as L, updateComboboxValidity as M, getComboboxLanguage as N, updateComboboxSelection as O, getComboboxLocalization as P, onComboboxInput as Q, getComboboxAttributeValue as R, setComboboxReadonly as S, updateComboboxAutocomplete as T, hasTextSelection as U, getComboboxId as V, setComboboxFilter as W, onComboboxFilter as X, onComboboxEscape as Y, onComboboxFocusout as Z, createComboboxOptions as _, setComboboxValues as a, attachCombobox as at, createComboboxSelectionItems as b, createComboboxButton as c, detachCombobox as ct, createComboboxGroup as d, onComboboxKeydownSelection as et, createComboboxHeader as f, createComboboxOption as g, createComboboxMessage as h, setComboboxValue as i, onComboboxTab as it, updateComboboxForm as j, updateComboboxSelectionItems as k, createComboboxContent as l, createComboboxList as m, filterComboboxOption as n, onComboboxRemoveSelection as nt, toggleComboboxOption as o, comboboxStates as ot, createComboboxInput as p, onComboboxClickDocument as q, filterComboboxOptions as r, onComboboxSelection as rt, createComboboxAnchor as s, createComboboxState as st, applyComboboxSelection as t, onComboboxNavigation as tt, createComboboxFilter as u, createComboboxSelection as v, updateComboboxAnchor as w, setComboboxDisabled as x, createComboboxSelectionItem as y, getComboboxAutoComplete as z };
1030
+ export { getComboboxAutoComplete as $, updateComboboxTabindices as A, onComboboxEnter as B, setComboboxRequired as C, updateComboboxPreview as D, updateComboboxMessage as E, comboboxStates as F, onComboboxKeydown as G, onComboboxFilter as H, createComboboxState as I, onComboboxRemoveSelection as J, onComboboxKeydownSelection as K, detachCombobox as L, updateComboboxValidity as M, attachCombobox as N, updateComboboxSelection as O, comboboxLocalizations as P, getComboboxAttributeValue as Q, onComboboxClickContent as R, setComboboxReadonly as S, updateComboboxAutocomplete as T, onComboboxFocusout as U, onComboboxEscape as V, onComboboxInput as W, onComboboxTab as X, onComboboxSelection as Y, generateComboboxIds as Z, createComboboxOptions as _, setComboboxValues as a, setComboboxLimit as at, createComboboxSelectionItems as b, createComboboxButton as c, createComboboxGroup as d, getComboboxBooleanAria as et, createComboboxHeader as f, createComboboxOption as g, createComboboxMessage as h, setComboboxValue as i, setComboboxFilter as it, updateComboboxForm as j, updateComboboxSelectionItems as k, createComboboxContent as l, createComboboxList as m, filterComboboxOption as n, getComboboxVisibleOptions as nt, toggleComboboxOption as o, setComboboxLocalizations as ot, createComboboxInput as p, onComboboxNavigation as q, filterComboboxOptions as r, hasTextSelection as rt, createComboboxAnchor as s, applyComboboxSelection as t, getComboboxId as tt, createComboboxFilter as u, createComboboxSelection as v, updateComboboxAnchor as w, setComboboxDisabled as x, createComboboxSelectionItem as y, onComboboxClickDocument as z };
@@ -1,5 +1,5 @@
1
1
  import { a as OuiFloatablePosition, n as CreateOuiFloatableOptions, r as OuiFloatable, s as createFloatable } from "./floatable.embedded-Bct4U5Dm.mjs";
2
- import { H as setComboboxLocalizations, z as OuiComboboxElement } from "./constants.combobox-DqNUGBLS.mjs";
2
+ import { Y as setComboboxLocalizations, z as OuiComboboxElement } from "./constants.combobox-h_kyDegw.mjs";
3
3
  import { d as OuiSortable, f as createSortable, g as createMovable, h as OuiMovable, t as CreateOuiDraggableOptions } from "./draggable-a6w0J1OD.mjs";
4
4
  import "./movable/movable.standalone.mjs";
5
5
  import { a as createResizable, n as OuiResizable, t as CreateOuiResizableOptions } from "./resizable.embedded-3qoR0Bjm.mjs";
package/dist/js/index.mjs CHANGED
@@ -5,7 +5,7 @@ import { createResizable } from "./resizable/resizable.embedded.mjs";
5
5
  import { getDialog } from "./dialog.mjs";
6
6
  import "./menu.mjs";
7
7
  import "./toolbar.mjs";
8
- import { F as setComboboxLocalizations } from "./data.combobox-8RwBv5ey.mjs";
8
+ import { ot as setComboboxLocalizations } from "./data.combobox-B8HMkDOh.mjs";
9
9
  import { OuiComboboxElement } from "./combobox/index.mjs";
10
10
  import "./floatable/floatable.standalone.mjs";
11
11
  import { createFocusTrap } from "./focus-trap/focus-trap.embedded.mjs";