@oscarpalmer/oui 0.37.0 → 0.39.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 (183) hide show
  1. package/dist/css/a11y.css +1 -0
  2. package/dist/css/badge.css +12 -8
  3. package/dist/css/button.css +111 -14
  4. package/dist/css/color-picker.css +859 -0
  5. package/dist/css/color.css +86 -87
  6. package/dist/css/combobox.css +105 -4
  7. package/dist/css/content.css +8 -6
  8. package/dist/css/floatable.css +3 -3
  9. package/dist/css/form.css +106 -6
  10. package/dist/css/icon.css +99 -0
  11. package/dist/css/listbox.css +5 -0
  12. package/dist/css/message.css +6 -3
  13. package/dist/css/mixins/badge.mixins.css +2 -0
  14. package/dist/css/mixins/button.mixins.css +3 -0
  15. package/dist/css/mixins/message.mixins.css +1 -0
  16. package/dist/css/mixins/misc.mixins.css +2 -0
  17. package/dist/css/mixins/shadow.mixins.css +1 -0
  18. package/dist/css/reset.css +3 -3
  19. package/dist/css/splitter.css +1 -1
  20. package/dist/css/tabs.css +115 -23
  21. package/dist/css/typography.css +90 -0
  22. package/dist/js/color-picker/constants.color-picker.d.mts +2 -0
  23. package/dist/js/color-picker/constants.color-picker.mjs +59 -0
  24. package/dist/js/color-picker/dom.color-picker.d.mts +8 -0
  25. package/dist/js/color-picker/dom.color-picker.mjs +191 -0
  26. package/dist/js/color-picker/event.color-picker.d.mts +9 -0
  27. package/dist/js/color-picker/event.color-picker.mjs +2 -0
  28. package/dist/js/color-picker/form.color-picker.d.mts +5 -0
  29. package/dist/js/color-picker/form.color-picker.mjs +24 -0
  30. package/dist/js/color-picker/index.d.mts +2 -0
  31. package/dist/js/color-picker/index.mjs +303 -0
  32. package/dist/js/color-picker/misc.color-picker.d.mts +2 -0
  33. package/dist/js/color-picker/misc.color-picker.mjs +2 -0
  34. package/dist/js/color-picker/models.color-picker.d.mts +2 -0
  35. package/dist/js/color-picker/models.color-picker.mjs +24 -0
  36. package/dist/js/color-picker/output.color-picker.d.mts +8 -0
  37. package/dist/js/color-picker/output.color-picker.mjs +233 -0
  38. package/dist/js/color-picker/state.color-picker.d.mts +8 -0
  39. package/dist/js/color-picker/state.color-picker.mjs +2 -0
  40. package/dist/js/combobox/constants.combobox.d.mts +1 -1
  41. package/dist/js/combobox/dom.combobox.d.mts +12 -13
  42. package/dist/js/combobox/dom.combobox.mjs +12 -5
  43. package/dist/js/combobox/event.combobox.d.mts +20 -21
  44. package/dist/js/combobox/event.combobox.mjs +1 -1
  45. package/dist/js/combobox/index.d.mts +1 -1
  46. package/dist/js/combobox/index.mjs +56 -2
  47. package/dist/js/combobox/misc.combobox.d.mts +1 -1
  48. package/dist/js/combobox/misc.combobox.mjs +1 -1
  49. package/dist/js/combobox/models.combobox.d.mts +12 -13
  50. package/dist/js/combobox/state.combobox.d.mts +8 -9
  51. package/dist/js/combobox/state.combobox.mjs +1 -1
  52. package/dist/js/constants.color-picker-B-gFjL8m.d.mts +364 -0
  53. package/dist/js/constants.combobox-8EMRmv09.d.mts +18 -0
  54. package/dist/js/constants.listbox-DGnX32kv.d.mts +8 -0
  55. package/dist/js/dialog.d.mts +2 -2
  56. package/dist/js/dialog.mjs +1 -1
  57. package/dist/js/{draggable-a6w0J1OD.d.mts → draggable-B5-70SZm.d.mts} +5 -4
  58. package/dist/js/event.color-picker-BEpq0Adu.mjs +485 -0
  59. package/dist/js/floatable/floatable.embedded.d.mts +1 -1
  60. package/dist/js/floatable/floatable.embedded.mjs +11 -8
  61. package/dist/js/floatable/floatable.standalone.d.mts +1 -1
  62. package/dist/js/{floatable.embedded-Bct4U5Dm.d.mts → floatable.embedded-DQYkXt8X.d.mts} +1 -1
  63. package/dist/js/focus-trap/focus-trap.embedded.d.mts +1 -1
  64. package/dist/js/focus-trap/focus-trap.standalone.d.mts +1 -1
  65. package/dist/js/{focus-trap.embedded-DR8NpZfr.d.mts → focus-trap.embedded-CjyFQYow.d.mts} +2 -2
  66. package/dist/js/{index-EfkUSals.d.mts → index-C5D3-oiI.d.mts} +41 -3
  67. package/dist/js/index.d.mts +8 -7
  68. package/dist/js/index.mjs +6 -3
  69. package/dist/js/internal/attributable.d.mts +2 -3
  70. package/dist/js/internal/draggable.d.mts +1 -1
  71. package/dist/js/internal/draggable.mjs +1 -1
  72. package/dist/js/internal/listbox/listbox.constants.d.mts +7 -10
  73. package/dist/js/internal/listbox/listbox.constants.mjs +15 -16
  74. package/dist/js/internal/listbox/listbox.data.d.mts +9 -10
  75. package/dist/js/internal/listbox/listbox.data.mjs +1 -1
  76. package/dist/js/internal/listbox/listbox.dom.d.mts +19 -20
  77. package/dist/js/internal/listbox/listbox.dom.mjs +1 -1
  78. package/dist/js/internal/listbox/listbox.event.d.mts +3 -4
  79. package/dist/js/internal/listbox/listbox.event.mjs +4 -4
  80. package/dist/js/internal/listbox/listbox.form.d.mts +4 -5
  81. package/dist/js/internal/listbox/listbox.form.mjs +16 -15
  82. package/dist/js/internal/listbox/listbox.misc.d.mts +10 -11
  83. package/dist/js/internal/listbox/listbox.misc.mjs +1 -1
  84. package/dist/js/internal/listbox/listbox.model.d.mts +1 -1
  85. package/dist/js/internal/listbox/listbox.state.d.mts +5 -6
  86. package/dist/js/internal/listbox/listbox.state.mjs +3 -3
  87. package/dist/js/internal/misc.d.mts +4 -4
  88. package/dist/js/internal/misc.mjs +9 -1
  89. package/dist/js/internal/navigable.d.mts +9 -10
  90. package/dist/js/internal/navigable.mjs +1 -0
  91. package/dist/js/listbox/constants.listbox.d.mts +1 -1
  92. package/dist/js/listbox/event.listbox.d.mts +6 -7
  93. package/dist/js/listbox/event.listbox.mjs +1 -1
  94. package/dist/js/listbox/index.d.mts +43 -5
  95. package/dist/js/listbox/index.mjs +56 -2
  96. package/dist/js/listbox/misc.listbox.d.mts +1 -1
  97. package/dist/js/listbox/misc.listbox.mjs +1 -1
  98. package/dist/js/listbox/state.listbox.d.mts +7 -8
  99. package/dist/js/listbox/state.listbox.mjs +1 -1
  100. package/dist/js/{listbox.data-BWd0PCy7.mjs → listbox.data-DQ7-x2uY.mjs} +8 -7
  101. package/dist/js/{listbox.model-CRReGOmu.d.mts → listbox.model-BHPA7GM4.d.mts} +3 -3
  102. package/dist/js/menu.mjs +1 -1
  103. package/dist/js/{misc.listbox-BI-XsTOf.mjs → misc.listbox-DKB-j0UK.mjs} +4 -5
  104. package/dist/js/{misc.listbox-gnoJhrTr.d.mts → misc.listbox-mZMuYOxg.d.mts} +1 -1
  105. package/dist/js/movable/movable.embedded.d.mts +1 -1
  106. package/dist/js/movable/movable.standalone.d.mts +1 -1
  107. package/dist/js/popover.d.mts +2 -2
  108. package/dist/js/popover.mjs +1 -1
  109. package/dist/js/resizable/resizable.embedded.d.mts +1 -1
  110. package/dist/js/resizable/resizable.embedded.mjs +1 -1
  111. package/dist/js/resizable/resizable.standalone.d.mts +1 -1
  112. package/dist/js/{resizable.embedded-3qoR0Bjm.d.mts → resizable.embedded-dvhdfQgt.d.mts} +1 -1
  113. package/dist/js/sortable/sortable.embedded.d.mts +1 -1
  114. package/dist/js/sortable/sortable.standalone.d.mts +1 -1
  115. package/dist/js/splitter.d.mts +2 -3
  116. package/dist/js/splitter.mjs +2 -2
  117. package/dist/js/{state.combobox-4xq0FPCF.mjs → state.combobox-BWDFHwoi.mjs} +9 -9
  118. package/dist/js/tabs.d.mts +4 -5
  119. package/dist/js/tabs.mjs +4 -7
  120. package/dist/js/tooltip.d.mts +1 -1
  121. package/package.json +24 -22
  122. package/dist/js/constants.combobox-DmRAMC64.d.mts +0 -26
  123. package/dist/js/constants.listbox-DRsXUxd3.d.mts +0 -14
  124. package/src/css/a11y.scss +0 -13
  125. package/src/css/badge.scss +0 -62
  126. package/src/css/button.scss +0 -50
  127. package/src/css/color.scss +0 -115
  128. package/src/css/combobox.scss +0 -252
  129. package/src/css/content.scss +0 -180
  130. package/src/css/flex.scss +0 -107
  131. package/src/css/floatable.scss +0 -152
  132. package/src/css/form.scss +0 -573
  133. package/src/css/listbox.scss +0 -120
  134. package/src/css/message.scss +0 -73
  135. package/src/css/mixins.scss +0 -419
  136. package/src/css/reset.scss +0 -392
  137. package/src/css/splitter.scss +0 -89
  138. package/src/css/table.scss +0 -107
  139. package/src/css/tabs.scss +0 -85
  140. package/src/js/combobox/constants.combobox.ts +0 -83
  141. package/src/js/combobox/dom.combobox.ts +0 -407
  142. package/src/js/combobox/event.combobox.ts +0 -365
  143. package/src/js/combobox/index.ts +0 -320
  144. package/src/js/combobox/misc.combobox.ts +0 -104
  145. package/src/js/combobox/models.combobox.ts +0 -54
  146. package/src/js/combobox/state.combobox.ts +0 -246
  147. package/src/js/dialog.ts +0 -255
  148. package/src/js/floatable/floatable.embedded.ts +0 -332
  149. package/src/js/floatable/floatable.standalone.ts +0 -6
  150. package/src/js/focus-trap/focus-trap.embedded.ts +0 -411
  151. package/src/js/focus-trap/focus-trap.standalone.ts +0 -1
  152. package/src/js/index.ts +0 -15
  153. package/src/js/internal/attributable.ts +0 -73
  154. package/src/js/internal/draggable.ts +0 -657
  155. package/src/js/internal/listbox/listbox.constants.ts +0 -25
  156. package/src/js/internal/listbox/listbox.data.ts +0 -287
  157. package/src/js/internal/listbox/listbox.dom.ts +0 -445
  158. package/src/js/internal/listbox/listbox.event.ts +0 -129
  159. package/src/js/internal/listbox/listbox.form.ts +0 -115
  160. package/src/js/internal/listbox/listbox.misc.ts +0 -135
  161. package/src/js/internal/listbox/listbox.model.ts +0 -169
  162. package/src/js/internal/listbox/listbox.state.ts +0 -82
  163. package/src/js/internal/misc.ts +0 -27
  164. package/src/js/internal/navigable.ts +0 -315
  165. package/src/js/l10n.ts +0 -192
  166. package/src/js/listbox/constants.listbox.ts +0 -61
  167. package/src/js/listbox/event.listbox.ts +0 -106
  168. package/src/js/listbox/index.ts +0 -302
  169. package/src/js/listbox/misc.listbox.ts +0 -70
  170. package/src/js/listbox/state.listbox.ts +0 -196
  171. package/src/js/menu.ts +0 -348
  172. package/src/js/movable/movable.embedded.ts +0 -318
  173. package/src/js/movable/movable.standalone.ts +0 -2
  174. package/src/js/popover.ts +0 -229
  175. package/src/js/resizable/resizable.embedded.ts +0 -413
  176. package/src/js/resizable/resizable.standalone.ts +0 -5
  177. package/src/js/sortable/sortable.embedded.ts +0 -527
  178. package/src/js/sortable/sortable.standalone.ts +0 -2
  179. package/src/js/splitter.ts +0 -583
  180. package/src/js/tabs.ts +0 -447
  181. package/src/js/toolbar.ts +0 -63
  182. package/src/js/tooltip.ts +0 -367
  183. /package/dist/css/{mixins.css → mixins/input.mixins.css} +0 -0
@@ -1,287 +0,0 @@
1
- import {getString} from '@oscarpalmer/atoms/string';
2
- import {setAria} from '@oscarpalmer/toretto/aria';
3
- import {setAttribute} from '@oscarpalmer/toretto/attribute';
4
- import {getData} from '@oscarpalmer/toretto/data';
5
- import {dispatch} from '@oscarpalmer/toretto/event';
6
- import {updateListboxMessage, updateListboxPreview, updateListboxValueLabel} from './listbox.dom';
7
- import {updateListboxForm} from './listbox.form';
8
- import {setListboxFilter} from './listbox.misc';
9
- import type {OuiListboxPreview, OuiListboxState} from './listbox.model';
10
-
11
- // #region Types
12
-
13
- type ApplySelectionParameters<State extends OuiListboxState = OuiListboxState> = {
14
- added: boolean;
15
- emit?: boolean;
16
- option?: HTMLElement;
17
- scroll?: boolean;
18
- selected?: HTMLElement[];
19
- state: State;
20
- values?: string[];
21
- };
22
-
23
- // #endregion
24
-
25
- // #region Functions
26
-
27
- export function applyListboxSelection<State extends OuiListboxState>(
28
- parameters: ApplySelectionParameters<State>,
29
- ): void {
30
- const {added, emit, option, scroll, selected, state} = parameters;
31
- const {length} = state.options.all;
32
-
33
- for (let index = 0; index < length; index += 1) {
34
- const option = state.options.all[index];
35
-
36
- setAria(
37
- option,
38
- 'selected',
39
- (state.type === 'select' || !state.autocomplete.none) &&
40
- (selected ?? state.options.selected).includes(option),
41
- );
42
- }
43
-
44
- const values =
45
- parameters.values ??
46
- (state.autocomplete.none && !state.listbox
47
- ? [state.filter.element.value]
48
- : (selected ?? state.options.selected).map(option => getData(option, 'value', false) ?? ''));
49
-
50
- if (values.length === 0) {
51
- values.push('');
52
- }
53
-
54
- if (selected != null) {
55
- state.options.selected = selected;
56
- }
57
-
58
- const update =
59
- values.length === state.values.current.length
60
- ? values.some(value => !state.values.current.includes(value))
61
- : true;
62
-
63
- if (!update) {
64
- return;
65
- }
66
-
67
- updateListboxForm(state, values, emit);
68
- updateListboxMessage(state);
69
- updateListboxPreview('set', state, option, scroll);
70
- updateListboxValueLabel(state);
71
-
72
- state.callbacks.data.onApply(state, option, values, added, selected, emit);
73
- }
74
-
75
- export function filterListbox(type: InputEvent['inputType'], state: OuiListboxState): void {
76
- if (state.disabled || state.readonly) {
77
- return;
78
- }
79
-
80
- const update = state.filter.element.value !== state.filter.value;
81
-
82
- const option = filterListboxOptions(state);
83
-
84
- let preview: OuiListboxPreview | undefined;
85
-
86
- if (type.includes('delete')) {
87
- preview = 'none';
88
- } else if (type.includes('insert')) {
89
- preview = 'typed';
90
- }
91
-
92
- if (preview != null) {
93
- state.callbacks.data.onFilter(preview, state, update, option);
94
- }
95
-
96
- if (update) {
97
- state.filter.value = state.filter.element.value;
98
-
99
- dispatch(state.host, 'input');
100
- }
101
- }
102
-
103
- export function filterListboxOption(
104
- state: OuiListboxState,
105
- value: unknown,
106
- textContent?: boolean,
107
- ): HTMLElement | undefined {
108
- const filterTextContent = textContent ?? false;
109
-
110
- const filter = getString(value).toLocaleLowerCase();
111
-
112
- filterListboxOptions(state);
113
-
114
- const {length} = state.options.all;
115
-
116
- let match: HTMLElement | undefined;
117
-
118
- for (let index = 0; index < length; index += 1) {
119
- const option = state.options.all[index];
120
-
121
- const value = (
122
- filterTextContent ? option.textContent : (getData(option, 'value', false) ?? '')
123
- ).toLocaleLowerCase();
124
-
125
- if (value === filter) {
126
- match = option;
127
-
128
- break;
129
- }
130
- }
131
-
132
- return match;
133
- }
134
-
135
- export function filterListboxOptions(state: OuiListboxState): HTMLElement | undefined {
136
- function filter(options: HTMLElement[]): boolean {
137
- const {length} = options;
138
-
139
- let count = 0;
140
-
141
- for (let index = 0; index < length; index += 1) {
142
- const option = options[index];
143
-
144
- option.hidden =
145
- (state.type === 'select' || !state.autocomplete.none) &&
146
- !option.textContent.toLocaleLowerCase().includes(value);
147
-
148
- if (!option.hidden) {
149
- count += 1;
150
-
151
- visible.push(option);
152
- }
153
- }
154
-
155
- return count === 0;
156
- }
157
-
158
- const value = state.filter.element.value.toLocaleLowerCase();
159
-
160
- const visible: HTMLElement[] = [];
161
-
162
- if (state.groups == null) {
163
- filter(state.options.all);
164
- } else {
165
- const groupsLength = state.groups.length;
166
-
167
- for (let groupIndex = 0; groupIndex < groupsLength; groupIndex += 1) {
168
- const {element, options} = state.groups[groupIndex];
169
-
170
- element.hidden = filter(options);
171
- }
172
- }
173
-
174
- setAttribute(state.list, state.attributes.empty, visible.length === 0 ? '' : undefined);
175
-
176
- updateListboxMessage(state);
177
-
178
- return state.active != null && visible.includes(state.active) ? state.active : visible[0];
179
- }
180
-
181
- export function setListboxValue<State extends OuiListboxState>(
182
- state: State,
183
- value: unknown,
184
- emit?: boolean,
185
- ): void {
186
- if (state.autocomplete.none && !state.listbox) {
187
- setListboxFilter(state, getString(value));
188
-
189
- return;
190
- }
191
-
192
- const option = filterListboxOption(state, value);
193
-
194
- if (option != null) {
195
- setListboxValues(state, [value], emit);
196
- }
197
- }
198
-
199
- export function setListboxValues<State extends OuiListboxState>(
200
- state: State,
201
- value: unknown[],
202
- emit?: boolean,
203
- ): void {
204
- if (!Array.isArray(value)) {
205
- return;
206
- }
207
-
208
- const values = (state.multiple ? value : value.slice(0, 1)).map(value =>
209
- getString(value).toLocaleLowerCase(),
210
- );
211
-
212
- if (values.length === 0) {
213
- values.push('');
214
- }
215
-
216
- if (state.autocomplete.none && !state.listbox) {
217
- setListboxValue(state, values[0], emit);
218
-
219
- return;
220
- }
221
-
222
- const {length} = state.options.all;
223
-
224
- const selected: HTMLElement[] = [];
225
-
226
- for (let index = 0; index < length; index += 1) {
227
- const option = state.options.all[index];
228
-
229
- if (values.includes(getData(option, 'value', false)?.toLocaleLowerCase() ?? '')) {
230
- selected.push(option);
231
- }
232
- }
233
-
234
- applyListboxSelection({
235
- emit,
236
- selected,
237
- state,
238
- added: true,
239
- option: selected[0] ?? state.options.all[0],
240
- values: state.autocomplete.none && !state.listbox ? values : undefined,
241
- });
242
- }
243
-
244
- export function toggleListboxOption<State extends OuiListboxState>(
245
- state: State,
246
- option?: HTMLElement,
247
- ): void {
248
- if (option == null || (!state.multiple && state.options.selected.includes(option))) {
249
- state.callbacks.data.onToggle(state);
250
-
251
- return;
252
- }
253
-
254
- const selected = state.options.selected.slice();
255
-
256
- let added = true;
257
-
258
- if (state.multiple) {
259
- const index = selected.indexOf(option);
260
-
261
- if (index === -1) {
262
- selected.push(option);
263
- } else {
264
- added = false;
265
-
266
- selected.splice(index, 1);
267
- }
268
- } else {
269
- selected.splice(0, selected.length, option);
270
- }
271
-
272
- applyListboxSelection({
273
- added,
274
- option,
275
- selected,
276
- state,
277
- scroll: false,
278
- values:
279
- state.autocomplete.none && !state.listbox && option != null
280
- ? [option.textContent]
281
- : undefined,
282
- });
283
-
284
- state.callbacks.data.onToggle(state);
285
- }
286
-
287
- // #endregion
@@ -1,445 +0,0 @@
1
- import {createElement, setAria, setAttribute} from '@oscarpalmer/toretto';
2
- import {getLocalization, localize} from '../../l10n';
3
- import {listboxScrollOptions} from './listbox.constants';
4
- import {getListboxVisibleOptions} from './listbox.misc';
5
- import type {
6
- OuiListboxAttributes,
7
- OuiListboxAutoComplete,
8
- OuiListboxGroup,
9
- OuiListboxLocalizations,
10
- OuiListboxOptions,
11
- OuiListboxPreview,
12
- OuiListboxState,
13
- OuiListboxType,
14
- } from './listbox.model';
15
-
16
- // #region Types
17
-
18
- export type CreateListboxContent = {
19
- element: HTMLDivElement;
20
- filter?: CreateListboxFilter;
21
- list: CreateListboxList;
22
- message: HTMLDivElement;
23
- value: HTMLSpanElement;
24
- };
25
-
26
- export type CreateListboxContentParameters = {
27
- attributes: OuiListboxAttributes;
28
- autocomplete: OuiListboxAutoComplete;
29
- element: HTMLElement;
30
- id: string;
31
- label: HTMLLabelElement;
32
- listbox: boolean;
33
- multiple: boolean;
34
- select: HTMLSelectElement;
35
- type: OuiListboxType;
36
- };
37
-
38
- export type CreateListboxFilter = {
39
- container: HTMLElement;
40
- element: HTMLInputElement;
41
- };
42
-
43
- type CreateListboxGroupParameters = {
44
- group: HTMLOptGroupElement;
45
- groupOptions: HTMLOptionElement[];
46
- original: CreateListboxContentParameters;
47
- selected: HTMLElement[];
48
- type: OuiListboxType;
49
- };
50
-
51
- export type CreateListboxList = {
52
- element: HTMLUListElement;
53
- groups?: OuiListboxGroup[];
54
- options: OuiListboxOptions;
55
- };
56
-
57
- type CreateListboxOptionParameters = {
58
- group?: string;
59
- index: number;
60
- option: HTMLOptionElement;
61
- original: CreateListboxContentParameters;
62
- type: OuiListboxType;
63
- };
64
-
65
- type CreateListboxOptionsParameters = {
66
- group?: string;
67
- list: HTMLElement;
68
- options: HTMLOptionElement[];
69
- original: CreateListboxContentParameters;
70
- selected: HTMLElement[];
71
- type: OuiListboxType;
72
- };
73
-
74
- // #endregion
75
-
76
- // #region Functions
77
-
78
- export function createListboxContent(
79
- parameters: CreateListboxContentParameters,
80
- ): CreateListboxContent {
81
- const element = createElement('div', {
82
- attribute: {
83
- [parameters.attributes.content]: '',
84
- },
85
- });
86
-
87
- const filter = createListboxFilter(parameters);
88
- const list = createListboxList(parameters);
89
- const message = createListboxMessage(parameters.attributes.message);
90
- const value = createListboxValueLabel(parameters.id);
91
-
92
- if (filter != null) {
93
- element.append(filter.container);
94
- }
95
-
96
- element.append(list.element, message, value);
97
-
98
- return {
99
- element,
100
- filter,
101
- list,
102
- message,
103
- value,
104
- };
105
- }
106
-
107
- export function createListboxFilter(
108
- parameters: CreateListboxContentParameters,
109
- ): CreateListboxFilter | undefined {
110
- if (parameters.type === 'autocomplete') {
111
- return;
112
- }
113
-
114
- const container = createElement('div', {
115
- attribute: {
116
- [parameters.attributes.filter]: '',
117
- },
118
- });
119
-
120
- const element = createListboxInput(parameters, '');
121
-
122
- setAttribute(element, parameters.attributes.input, '');
123
-
124
- container.append(element);
125
-
126
- return {container, element};
127
- }
128
-
129
- export function createListboxGroup(parameters: CreateListboxGroupParameters): OuiListboxGroup {
130
- const {group, groupOptions, selected, type} = parameters;
131
-
132
- const element = createElement('li', {
133
- aria: {
134
- label: group.label,
135
- },
136
- property: {
137
- role: 'group',
138
- },
139
- });
140
-
141
- const list = createElement('ul', {
142
- property: {
143
- role: 'none',
144
- },
145
- });
146
-
147
- const header = createListboxHeader(parameters, group);
148
-
149
- element.append(header, list);
150
-
151
- return {
152
- element,
153
- header,
154
- options: createListboxOptions({
155
- list,
156
- selected,
157
- type,
158
- group: header.id,
159
- options: groupOptions,
160
- original: parameters.original,
161
- }),
162
- };
163
- }
164
-
165
- export function createListboxHeader(
166
- parameters: CreateListboxGroupParameters,
167
- group: HTMLOptGroupElement,
168
- ): HTMLElement {
169
- return createElement('div', {
170
- aria: {
171
- hidden: true,
172
- },
173
- attribute: {
174
- [parameters.original.attributes.header]: '',
175
- },
176
- property: {
177
- id: group.id,
178
- textContent: group.label,
179
- },
180
- });
181
- }
182
-
183
- export function createListboxInput(
184
- parameters: CreateListboxContentParameters,
185
- value: string,
186
- ): HTMLInputElement {
187
- const {autocomplete, id, label, listbox, type} = parameters;
188
-
189
- const isAutocomplete = type === 'autocomplete';
190
-
191
- const input = createElement('input', {
192
- aria: {
193
- autocomplete: autocomplete.value,
194
- controls: `${id}_list`,
195
- haspopup: isAutocomplete ? 'listbox' : undefined,
196
- labelledby: label.id,
197
- },
198
- attribute: {
199
- autocorrect: 'off',
200
- autocomplete: 'off',
201
- form: '',
202
- spellcheck: 'false',
203
- type: 'text',
204
- },
205
- property: {
206
- id,
207
- value,
208
- role: isAutocomplete || listbox ? 'combobox' : 'searchbox',
209
- },
210
- });
211
-
212
- if (isAutocomplete || listbox) {
213
- setAria(input, 'expanded', listbox);
214
- }
215
-
216
- return input;
217
- }
218
-
219
- export function createListboxList(parameters: CreateListboxContentParameters): CreateListboxList {
220
- const {attributes, id, label, multiple, select, type} = parameters;
221
-
222
- const element = createElement('ul', {
223
- aria: {
224
- labelledby: label.id,
225
- multiselectable: multiple,
226
- },
227
- attribute: {
228
- [attributes.list]: '',
229
- tabindex: -1,
230
- },
231
- property: {
232
- id: `${id}_list`,
233
- role: 'listbox',
234
- },
235
- });
236
-
237
- const children = [...select.children];
238
- const childrenLength = children.length;
239
-
240
- const options: HTMLElement[] = [];
241
- const selected: HTMLElement[] = [];
242
-
243
- let groups: OuiListboxGroup[] | undefined;
244
-
245
- for (let childIndex = 0; childIndex < childrenLength; childIndex += 1) {
246
- const child = children[childIndex];
247
-
248
- if (child instanceof HTMLOptionElement) {
249
- const option = createListboxOption({
250
- type,
251
- option: child,
252
- original: parameters,
253
- index: childIndex,
254
- });
255
-
256
- element.append(option);
257
- options.push(option);
258
-
259
- if (child.selected) {
260
- selected.push(option);
261
- }
262
-
263
- continue;
264
- }
265
-
266
- if (!(child instanceof HTMLOptGroupElement)) {
267
- continue;
268
- }
269
-
270
- const group = createListboxGroup({
271
- selected,
272
- type,
273
- group: child,
274
- groupOptions: [...child.children] as HTMLOptionElement[],
275
- original: parameters,
276
- });
277
-
278
- groups ??= [];
279
-
280
- element.append(group.element);
281
- groups.push(group);
282
- options.push(...group.options);
283
- }
284
-
285
- return {
286
- element,
287
- groups,
288
- options: {
289
- selected,
290
- all: options,
291
- },
292
- };
293
- }
294
-
295
- export function createListboxMessage(attribute: string): HTMLDivElement {
296
- return createElement('div', {
297
- aria: {
298
- live: 'polite',
299
- },
300
- attribute: {
301
- [attribute]: '',
302
- },
303
- property: {
304
- hidden: true,
305
- role: 'status',
306
- },
307
- });
308
- }
309
-
310
- export function createListboxOption(parameters: CreateListboxOptionParameters): HTMLElement {
311
- const {group, option, original} = parameters;
312
-
313
- return createElement('li', {
314
- aria: {
315
- selected: (parameters.type === 'select' || !original.autocomplete.none) && option.selected,
316
- },
317
- attribute: {
318
- [original.attributes.option]: '',
319
- },
320
- data: {
321
- group,
322
- value: option.value,
323
- },
324
- property: {
325
- id: option.id,
326
- role: 'option',
327
- textContent: option.textContent,
328
- },
329
- });
330
- }
331
-
332
- export function createListboxOptions(parameters: CreateListboxOptionsParameters): HTMLElement[] {
333
- const {group, list, options, original, selected, type} = parameters;
334
-
335
- const items: HTMLElement[] = [];
336
-
337
- for (let index = 0; index < options.length; index += 1) {
338
- const option = options[index];
339
-
340
- const item = createListboxOption({group, index, option, original, type});
341
-
342
- items.push(item);
343
-
344
- if (option.selected) {
345
- selected.push(item);
346
- }
347
-
348
- list.append(item);
349
- }
350
-
351
- return items;
352
- }
353
-
354
- export function createListboxValueLabel(id: string): HTMLSpanElement {
355
- return createElement('span', {
356
- property: {
357
- hidden: true,
358
- id: `${id}_value`,
359
- },
360
- });
361
- }
362
-
363
- export function updateListboxMessage(state: OuiListboxState): void {
364
- const {attributes, host, localizations, message} = state;
365
-
366
- const visible = getListboxVisibleOptions(state).length;
367
-
368
- setAttribute(message, attributes.hidden, visible > 0 ? '' : undefined);
369
-
370
- let data: Record<string, unknown> = {};
371
- let parameters: unknown[] = [];
372
-
373
- let key: keyof OuiListboxLocalizations | undefined;
374
-
375
- if (visible === 0) {
376
- key = 'empty';
377
- } else {
378
- data = {amount: visible};
379
- key = 'results';
380
- parameters = [visible];
381
- }
382
-
383
- const localization = getLocalization(localizations.global, host, key, localizations.component);
384
-
385
- message.textContent = localize(localization, data, parameters);
386
-
387
- message.hidden = false;
388
- }
389
-
390
- export function updateListboxPreview<State extends OuiListboxState>(
391
- preview: OuiListboxPreview,
392
- state: State,
393
- active?: HTMLElement,
394
- scroll?: boolean,
395
- ): void {
396
- const {length} = state.options.all;
397
-
398
- for (let index = 0; index < length; index += 1) {
399
- const option = state.options.all[index];
400
-
401
- setAttribute(option, state.attributes.active, option === active ? '' : undefined);
402
- }
403
-
404
- state.active = active;
405
-
406
- setAria(
407
- state.filter.element,
408
- 'activedescendant',
409
- state.content.checkVisibility() ? active?.id : undefined,
410
- );
411
-
412
- if (scroll ?? true) {
413
- active?.scrollIntoView(listboxScrollOptions);
414
- }
415
-
416
- if (preview !== 'none') {
417
- state.callbacks.data.onPreview(preview, state, active);
418
- }
419
- }
420
-
421
- export function updateListboxValueLabel<State extends OuiListboxState>(state: State): void {
422
- let label: string;
423
-
424
- if (state.multiple) {
425
- const localization = getLocalization(
426
- state.localizations.global,
427
- state.host,
428
- 'selected',
429
- state.localizations.component,
430
- );
431
-
432
- const {length} = state.options.selected;
433
-
434
- label = localize(localization, {amount: length}, [length]);
435
- } else {
436
- label =
437
- state.autocomplete.none && !state.listbox
438
- ? state.filter.element.value
439
- : (state.options.selected[0]?.textContent ?? '');
440
- }
441
-
442
- state.values.label.textContent = label;
443
- }
444
-
445
- // #endregion