@oscarpalmer/oui 0.38.0 → 0.40.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 (264) hide show
  1. package/README.md +1 -1
  2. package/dist/css/badge.css +11 -8
  3. package/dist/css/button.css +106 -14
  4. package/dist/css/color-picker.css +555 -73
  5. package/dist/css/color.css +86 -86
  6. package/dist/css/combobox.css +98 -4
  7. package/dist/css/content.css +7 -6
  8. package/dist/css/floatable.css +1 -3
  9. package/dist/css/form.css +99 -6
  10. package/dist/css/icon.css +99 -0
  11. package/dist/css/listbox.css +3 -0
  12. package/dist/css/message.css +4 -3
  13. package/dist/css/mixins/button.mixins.css +1 -0
  14. package/dist/css/reset.css +1 -1
  15. package/dist/css/tabs.css +95 -3
  16. package/dist/css/typography.css +90 -0
  17. package/dist/js/color-picker/color-picker.constants.d.mts +2 -0
  18. package/dist/js/color-picker/color-picker.constants.mjs +60 -0
  19. package/dist/js/color-picker/color-picker.dom.d.mts +8 -0
  20. package/dist/js/color-picker/color-picker.dom.mjs +191 -0
  21. package/dist/js/color-picker/color-picker.event.d.mts +9 -0
  22. package/dist/js/color-picker/color-picker.event.mjs +2 -0
  23. package/dist/js/color-picker/color-picker.form.d.mts +5 -0
  24. package/dist/js/color-picker/color-picker.form.mjs +27 -0
  25. package/dist/js/color-picker/color-picker.misc.d.mts +2 -0
  26. package/dist/js/color-picker/color-picker.misc.mjs +2 -0
  27. package/dist/js/color-picker/color-picker.model.d.mts +2 -0
  28. package/dist/js/color-picker/color-picker.model.mjs +24 -0
  29. package/dist/js/color-picker/color-picker.output.d.mts +8 -0
  30. package/dist/js/color-picker/color-picker.output.mjs +235 -0
  31. package/dist/js/color-picker/color-picker.state.d.mts +8 -0
  32. package/dist/js/color-picker/color-picker.state.mjs +2 -0
  33. package/dist/js/{color-picker.d.mts → color-picker/index.d.mts} +10 -43
  34. package/dist/js/color-picker/index.mjs +305 -0
  35. package/dist/js/color-picker.constants-D1mxw_Le.d.mts +179 -0
  36. package/dist/js/color-picker.event-Cksj5TvS.mjs +500 -0
  37. package/dist/js/color-picker.misc-CtsXGrOe.d.mts +27 -0
  38. package/dist/js/combobox/combobox.constants.d.mts +2 -0
  39. package/dist/js/combobox/{constants.combobox.mjs → combobox.constants.mjs} +21 -21
  40. package/dist/js/combobox/combobox.dom.d.mts +26 -0
  41. package/dist/js/combobox/{dom.combobox.mjs → combobox.dom.mjs} +44 -37
  42. package/dist/js/combobox/combobox.event.d.mts +22 -0
  43. package/dist/js/combobox/{event.combobox.mjs → combobox.event.mjs} +1 -1
  44. package/dist/js/combobox/combobox.misc.d.mts +2 -0
  45. package/dist/js/combobox/{misc.combobox.mjs → combobox.misc.mjs} +1 -1
  46. package/dist/js/combobox/combobox.model.d.mts +2 -0
  47. package/dist/js/combobox/combobox.state.d.mts +10 -0
  48. package/dist/js/combobox/combobox.state.mjs +2 -0
  49. package/dist/js/combobox/index.d.mts +163 -2
  50. package/dist/js/combobox/index.mjs +53 -52
  51. package/dist/js/combobox.constants-DZVkMP5g.d.mts +19 -0
  52. package/dist/js/combobox.misc-C1tPZZDi.d.mts +22 -0
  53. package/dist/js/{combobox/models.combobox.d.mts → combobox.model-oDV06XCN.d.mts} +6 -6
  54. package/dist/js/{state.combobox-Qm3FWzYW.mjs → combobox.state-BfJ3Hxg8.mjs} +96 -82
  55. package/dist/js/constants.listbox-C5Ap6Ag_.d.mts +9 -0
  56. package/dist/js/dialog/dialog.model.d.mts +2 -0
  57. package/dist/js/dialog/dialog.model.mjs +11 -0
  58. package/dist/js/dialog/index.d.mts +12 -0
  59. package/dist/js/dialog/index.mjs +123 -0
  60. package/dist/js/dialog.model-DX2mndMh.d.mts +45 -0
  61. package/dist/js/floatable/floatable.embedded.d.mts +2 -2
  62. package/dist/js/floatable/floatable.embedded.mjs +64 -92
  63. package/dist/js/floatable/floatable.model.d.mts +2 -0
  64. package/dist/js/floatable/floatable.model.mjs +23 -0
  65. package/dist/js/floatable/floatable.standalone.d.mts +2 -1
  66. package/dist/js/floatable.embedded-MeTyXjFn.d.mts +17 -0
  67. package/dist/js/floatable.model-DXsQgoU7.d.mts +62 -0
  68. package/dist/js/focus-trap/focus-trap.embedded.d.mts +2 -2
  69. package/dist/js/focus-trap/focus-trap.embedded.mjs +112 -134
  70. package/dist/js/focus-trap/focus-trap.model.d.mts +2 -0
  71. package/dist/js/focus-trap/focus-trap.model.mjs +15 -0
  72. package/dist/js/focus-trap/focus-trap.standalone.d.mts +2 -1
  73. package/dist/js/focus-trap.embedded-DIU05m1z.d.mts +13 -0
  74. package/dist/js/{focus-trap.embedded-DR8NpZfr.d.mts → focus-trap.model-BeX6UYlw.d.mts} +16 -18
  75. package/dist/js/index.d.mts +26 -14
  76. package/dist/js/index.mjs +18 -15
  77. package/dist/js/internal/attributable.d.mts +2 -3
  78. package/dist/js/internal/attributable.mjs +3 -2
  79. package/dist/js/internal/draggable/draggable.model.d.mts +2 -0
  80. package/dist/js/internal/draggable/draggable.model.mjs +37 -0
  81. package/dist/js/internal/draggable/index.d.mts +13 -0
  82. package/dist/js/internal/{draggable.mjs → draggable/index.mjs} +83 -114
  83. package/dist/js/internal/listbox/listbox.constants.d.mts +7 -10
  84. package/dist/js/internal/listbox/listbox.constants.mjs +15 -16
  85. package/dist/js/internal/listbox/listbox.data.d.mts +9 -10
  86. package/dist/js/internal/listbox/listbox.data.mjs +1 -1
  87. package/dist/js/internal/listbox/listbox.dom.d.mts +19 -20
  88. package/dist/js/internal/listbox/listbox.dom.mjs +1 -1
  89. package/dist/js/internal/listbox/listbox.event.d.mts +3 -4
  90. package/dist/js/internal/listbox/listbox.event.mjs +23 -20
  91. package/dist/js/internal/listbox/listbox.form.d.mts +4 -5
  92. package/dist/js/internal/listbox/listbox.form.mjs +15 -12
  93. package/dist/js/internal/listbox/listbox.misc.d.mts +10 -11
  94. package/dist/js/internal/listbox/listbox.misc.mjs +1 -1
  95. package/dist/js/internal/listbox/listbox.model.d.mts +2 -2
  96. package/dist/js/internal/listbox/listbox.state.d.mts +5 -6
  97. package/dist/js/internal/listbox/listbox.state.mjs +19 -20
  98. package/dist/js/internal/misc.d.mts +5 -4
  99. package/dist/js/internal/misc.mjs +7 -1
  100. package/dist/js/internal/navigable/index.d.mts +6 -0
  101. package/dist/js/internal/navigable/index.mjs +125 -0
  102. package/dist/js/internal/navigable/navigable.model.d.mts +2 -0
  103. package/dist/js/internal/navigable/navigable.model.mjs +18 -0
  104. package/dist/js/l10n/index.d.mts +9 -0
  105. package/dist/js/{l10n.mjs → l10n/index.mjs} +50 -23
  106. package/dist/js/l10n/l10n.model.d.mts +2 -0
  107. package/dist/js/l10n/l10n.model.mjs +9 -0
  108. package/dist/js/l10n.model-D6a9frgl.d.mts +26 -0
  109. package/dist/js/listbox/constants.listbox.d.mts +2 -2
  110. package/dist/js/listbox/constants.listbox.mjs +10 -14
  111. package/dist/js/listbox/event.listbox.d.mts +6 -7
  112. package/dist/js/listbox/event.listbox.mjs +47 -1
  113. package/dist/js/listbox/index.d.mts +8 -6
  114. package/dist/js/listbox/index.mjs +47 -49
  115. package/dist/js/listbox/misc.listbox.d.mts +1 -1
  116. package/dist/js/listbox/misc.listbox.mjs +1 -1
  117. package/dist/js/listbox/state.listbox.d.mts +8 -10
  118. package/dist/js/listbox/state.listbox.mjs +2 -2
  119. package/dist/js/{listbox.data-C7CRa5Ya.mjs → listbox.data-BQyZGKgr.mjs} +83 -66
  120. package/dist/js/{listbox.model-CRReGOmu.d.mts → listbox.model-CuBOj4qe.d.mts} +15 -11
  121. package/dist/js/menu/index.mjs +167 -0
  122. package/dist/js/menu/menu.model.d.mts +33 -0
  123. package/dist/js/menu/menu.model.mjs +15 -0
  124. package/dist/js/{misc.listbox-Cyz2CRDy.mjs → misc.listbox-CjfBUbHD.mjs} +27 -69
  125. package/dist/js/{misc.listbox-gnoJhrTr.d.mts → misc.listbox-CtoGvXQo.d.mts} +2 -2
  126. package/dist/js/movable/movable.embedded.d.mts +2 -2
  127. package/dist/js/movable/movable.embedded.mjs +60 -72
  128. package/dist/js/movable/movable.model.d.mts +2 -0
  129. package/dist/js/movable/movable.model.mjs +12 -0
  130. package/dist/js/movable/movable.standalone.d.mts +2 -1
  131. package/dist/js/movable.embedded-DoyXLegc.d.mts +11 -0
  132. package/dist/js/movable.model-BHaK_mKw.d.mts +186 -0
  133. package/dist/js/navigable.model-BPOM8DZk.d.mts +44 -0
  134. package/dist/js/popover/index.d.mts +12 -0
  135. package/dist/js/{popover.mjs → popover/index.mjs} +40 -50
  136. package/dist/js/popover/popover.model.d.mts +2 -0
  137. package/dist/js/popover/popover.model.mjs +12 -0
  138. package/dist/js/popover.model-ubKNG612.d.mts +38 -0
  139. package/dist/js/resizable/resizable.embedded.d.mts +2 -2
  140. package/dist/js/resizable/resizable.embedded.mjs +44 -59
  141. package/dist/js/resizable/resizable.model.d.mts +2 -0
  142. package/dist/js/resizable/resizable.model.mjs +21 -0
  143. package/dist/js/resizable/resizable.standalone.d.mts +2 -1
  144. package/dist/js/resizable.embedded-Bf1qBUdt.d.mts +11 -0
  145. package/dist/js/resizable.model-BwzJcTVJ.d.mts +46 -0
  146. package/dist/js/sortable/sortable.embedded.d.mts +2 -2
  147. package/dist/js/sortable/sortable.embedded.mjs +69 -82
  148. package/dist/js/sortable/sortable.model.d.mts +2 -0
  149. package/dist/js/sortable/sortable.model.mjs +24 -0
  150. package/dist/js/sortable/sortable.standalone.d.mts +2 -1
  151. package/dist/js/sortable.embedded-DzBKAwSG.d.mts +11 -0
  152. package/dist/js/{splitter.d.mts → splitter/index.d.mts} +8 -7
  153. package/dist/js/splitter/index.mjs +284 -0
  154. package/dist/js/splitter/splitter.model.d.mts +2 -0
  155. package/dist/js/splitter/splitter.model.mjs +37 -0
  156. package/dist/js/splitter.model-DOLNjLVS.d.mts +57 -0
  157. package/dist/js/{tabs.d.mts → tabs/index.d.mts} +7 -8
  158. package/dist/js/{tabs.mjs → tabs/index.mjs} +58 -58
  159. package/dist/js/tabs/tabs.model.d.mts +2 -0
  160. package/dist/js/tabs/tabs.model.mjs +18 -0
  161. package/dist/js/tabs.model-DRBX_JtI.d.mts +40 -0
  162. package/dist/js/toolbar/index.mjs +27 -0
  163. package/dist/js/toolbar/toolbar.model.d.mts +11 -0
  164. package/dist/js/toolbar/toolbar.model.mjs +7 -0
  165. package/dist/js/tooltip/index.d.mts +19 -0
  166. package/dist/js/{tooltip.mjs → tooltip/index.mjs} +60 -85
  167. package/dist/js/tooltip/tooltip.model.d.mts +2 -0
  168. package/dist/js/tooltip/tooltip.model.mjs +15 -0
  169. package/dist/js/tooltip.model-DRkY_BsL.d.mts +37 -0
  170. package/package.json +43 -37
  171. package/dist/js/color-picker.mjs +0 -924
  172. package/dist/js/combobox/constants.combobox.d.mts +0 -2
  173. package/dist/js/combobox/dom.combobox.d.mts +0 -27
  174. package/dist/js/combobox/event.combobox.d.mts +0 -23
  175. package/dist/js/combobox/misc.combobox.d.mts +0 -2
  176. package/dist/js/combobox/state.combobox.d.mts +0 -12
  177. package/dist/js/combobox/state.combobox.mjs +0 -2
  178. package/dist/js/constants.combobox-DmRAMC64.d.mts +0 -26
  179. package/dist/js/constants.listbox-DRsXUxd3.d.mts +0 -14
  180. package/dist/js/dialog.d.mts +0 -47
  181. package/dist/js/dialog.mjs +0 -131
  182. package/dist/js/draggable-a6w0J1OD.d.mts +0 -154
  183. package/dist/js/floatable.embedded-Bct4U5Dm.d.mts +0 -69
  184. package/dist/js/index-DJdFlTLm.d.mts +0 -177
  185. package/dist/js/internal/draggable.d.mts +0 -2
  186. package/dist/js/internal/navigable.d.mts +0 -37
  187. package/dist/js/internal/navigable.mjs +0 -135
  188. package/dist/js/l10n-Bn-7RcwR.d.mts +0 -20
  189. package/dist/js/l10n.d.mts +0 -2
  190. package/dist/js/menu.mjs +0 -172
  191. package/dist/js/popover.d.mts +0 -38
  192. package/dist/js/resizable.embedded-3qoR0Bjm.d.mts +0 -34
  193. package/dist/js/splitter.mjs +0 -322
  194. package/dist/js/toolbar.mjs +0 -31
  195. package/dist/js/tooltip.d.mts +0 -45
  196. package/src/css/a11y.scss +0 -13
  197. package/src/css/badge.scss +0 -62
  198. package/src/css/button.scss +0 -50
  199. package/src/css/color-picker.scss +0 -344
  200. package/src/css/color.scss +0 -113
  201. package/src/css/combobox.scss +0 -255
  202. package/src/css/content.scss +0 -181
  203. package/src/css/flex.scss +0 -107
  204. package/src/css/floatable.scss +0 -155
  205. package/src/css/form.scss +0 -575
  206. package/src/css/listbox.scss +0 -121
  207. package/src/css/message.scss +0 -74
  208. package/src/css/mixins/badge.mixins.scss +0 -53
  209. package/src/css/mixins/button.mixins.scss +0 -112
  210. package/src/css/mixins/input.mixins.scss +0 -114
  211. package/src/css/mixins/message.mixins.scss +0 -41
  212. package/src/css/mixins/misc.mixins.scss +0 -48
  213. package/src/css/mixins/shadow.mixins.scss +0 -57
  214. package/src/css/reset.scss +0 -392
  215. package/src/css/splitter.scss +0 -89
  216. package/src/css/table.scss +0 -107
  217. package/src/css/tabs.scss +0 -74
  218. package/src/js/color-picker.ts +0 -1653
  219. package/src/js/combobox/constants.combobox.ts +0 -83
  220. package/src/js/combobox/dom.combobox.ts +0 -411
  221. package/src/js/combobox/event.combobox.ts +0 -365
  222. package/src/js/combobox/index.ts +0 -382
  223. package/src/js/combobox/misc.combobox.ts +0 -104
  224. package/src/js/combobox/models.combobox.ts +0 -54
  225. package/src/js/combobox/state.combobox.ts +0 -246
  226. package/src/js/dialog.ts +0 -255
  227. package/src/js/floatable/floatable.embedded.ts +0 -336
  228. package/src/js/floatable/floatable.standalone.ts +0 -6
  229. package/src/js/focus-trap/focus-trap.embedded.ts +0 -411
  230. package/src/js/focus-trap/focus-trap.standalone.ts +0 -1
  231. package/src/js/index.ts +0 -16
  232. package/src/js/internal/attributable.ts +0 -73
  233. package/src/js/internal/draggable.ts +0 -657
  234. package/src/js/internal/listbox/listbox.constants.ts +0 -25
  235. package/src/js/internal/listbox/listbox.data.ts +0 -287
  236. package/src/js/internal/listbox/listbox.dom.ts +0 -446
  237. package/src/js/internal/listbox/listbox.event.ts +0 -129
  238. package/src/js/internal/listbox/listbox.form.ts +0 -125
  239. package/src/js/internal/listbox/listbox.misc.ts +0 -135
  240. package/src/js/internal/listbox/listbox.model.ts +0 -169
  241. package/src/js/internal/listbox/listbox.state.ts +0 -82
  242. package/src/js/internal/misc.ts +0 -27
  243. package/src/js/internal/navigable.ts +0 -317
  244. package/src/js/l10n.ts +0 -192
  245. package/src/js/listbox/constants.listbox.ts +0 -61
  246. package/src/js/listbox/event.listbox.ts +0 -106
  247. package/src/js/listbox/index.ts +0 -364
  248. package/src/js/listbox/misc.listbox.ts +0 -70
  249. package/src/js/listbox/state.listbox.ts +0 -194
  250. package/src/js/menu.ts +0 -348
  251. package/src/js/movable/movable.embedded.ts +0 -318
  252. package/src/js/movable/movable.standalone.ts +0 -2
  253. package/src/js/popover.ts +0 -229
  254. package/src/js/resizable/resizable.embedded.ts +0 -413
  255. package/src/js/resizable/resizable.standalone.ts +0 -5
  256. package/src/js/sortable/sortable.embedded.ts +0 -527
  257. package/src/js/sortable/sortable.standalone.ts +0 -2
  258. package/src/js/splitter.ts +0 -583
  259. package/src/js/tabs.ts +0 -441
  260. package/src/js/toolbar.ts +0 -63
  261. package/src/js/tooltip.ts +0 -367
  262. /package/dist/js/combobox/{models.combobox.mjs → combobox.model.mjs} +0 -0
  263. /package/dist/js/{menu.d.mts → menu/index.d.mts} +0 -0
  264. /package/dist/js/{toolbar.d.mts → toolbar/index.d.mts} +0 -0
@@ -1,129 +0,0 @@
1
- import {clamp} from '@oscarpalmer/atoms/number';
2
- import {LISTBOX_KEYS} from './listbox.constants';
3
- import {getListboxVisibleOptions} from './listbox.misc';
4
- import type {OuiListboxPreview, OuiListboxState} from './listbox.model';
5
-
6
- // #region Functions
7
-
8
- export function processListboxKeydown<State extends OuiListboxState>(
9
- event: KeyboardEvent,
10
- state: State,
11
- ): void {
12
- const ignore = state.disabled || state.readonly;
13
- const isSelect = state.type === 'select';
14
-
15
- let preventDefault = ignore;
16
-
17
- switch (true) {
18
- case event.key === ' ': {
19
- if (!state.disabled) {
20
- state.callbacks.keydown.onActivation?.(state);
21
- }
22
-
23
- break;
24
- }
25
-
26
- case event.key === 'Enter': {
27
- preventDefault = state.callbacks.keydown.preventActivation?.(state) ?? true;
28
-
29
- if (preventDefault) {
30
- state.callbacks.keydown.onEnter?.(state);
31
- } else if (!ignore && state.type === 'select') {
32
- state.callbacks.keydown.onActivation?.(state);
33
- } else if (!ignore) {
34
- state.internals.form?.requestSubmit();
35
- }
36
-
37
- break;
38
- }
39
-
40
- case event.key === 'Escape': {
41
- preventDefault = false;
42
-
43
- state.callbacks.keydown.onEscape?.(state);
44
-
45
- break;
46
- }
47
-
48
- case !isSelect && LISTBOX_KEYS.selection.has(event.key): {
49
- if (!ignore) {
50
- state.callbacks.keydown.onSelection?.(state);
51
- }
52
-
53
- break;
54
- }
55
-
56
- case LISTBOX_KEYS.navigation.has(event.key): {
57
- if (!state.disabled) {
58
- onNavigation(event, state);
59
- }
60
-
61
- break;
62
- }
63
-
64
- default: {
65
- preventDefault = false;
66
-
67
- if (event.key === 'Tab') {
68
- state.callbacks.keydown.onTab?.(state);
69
- }
70
-
71
- break;
72
- }
73
- }
74
-
75
- if (preventDefault) {
76
- event.preventDefault();
77
- event.stopPropagation();
78
- }
79
- }
80
-
81
- function onNavigation<State extends OuiListboxState>(event: KeyboardEvent, state: State): void {
82
- const skip = state.callbacks.keydown.skipNavigation?.(state) ?? false;
83
- const visible = getListboxVisibleOptions(state);
84
-
85
- if (visible.length === 0) {
86
- return;
87
- }
88
-
89
- let next: HTMLElement | undefined;
90
-
91
- if (skip || state.active == null) {
92
- next = state.active ?? visible.at(event.key === 'ArrowDown' ? 0 : -1);
93
- } else {
94
- const current = visible.findIndex(option => option.id === state.active?.id);
95
-
96
- let index: number | undefined;
97
-
98
- switch (event.key) {
99
- case 'ArrowDown':
100
- case 'ArrowUp':
101
- index = clamp(current + (event.key === 'ArrowDown' ? 1 : -1), 0, visible.length - 1, true);
102
- break;
103
-
104
- case 'PageDown':
105
- case 'PageUp':
106
- index = clamp(current + (event.key === 'PageDown' ? 10 : -10), 0, visible.length - 1);
107
- break;
108
-
109
- default:
110
- break;
111
- }
112
-
113
- if (index != null) {
114
- next = visible[index];
115
- }
116
- }
117
-
118
- let preview: OuiListboxPreview;
119
-
120
- if (state.type === 'autocomplete' && (state.autocomplete.both || state.autocomplete.inline)) {
121
- preview = 'set';
122
- } else {
123
- preview = 'none';
124
- }
125
-
126
- state.callbacks.keydown.onNavigation(preview, state, next ?? state.active ?? visible[0]);
127
- }
128
-
129
- // #endregion
@@ -1,125 +0,0 @@
1
- import {dispatch} from '@oscarpalmer/toretto/event';
2
- import {getLocalization, localize} from '../../l10n';
3
- import type {OuiListboxState} from './listbox.model';
4
-
5
- // #region Functions
6
-
7
- export function updateListboxForm<State extends OuiListboxState>(
8
- state: State,
9
- values: string[],
10
- emit?: boolean,
11
- ): void {
12
- let value: string | FormData;
13
-
14
- if (state.multiple) {
15
- const {length} = values;
16
-
17
- value = new FormData();
18
-
19
- for (let index = 0; index < length; index += 1) {
20
- (value as FormData).append(state.name, values[index]);
21
- }
22
- } else {
23
- value = values[0];
24
- }
25
-
26
- state.values.current = values;
27
-
28
- state.internals.setFormValue(value, JSON.stringify(values));
29
-
30
- state.callbacks.data.onForm(state);
31
-
32
- updateListboxValidity(state);
33
-
34
- if (emit ?? true) {
35
- dispatch(state.host, 'oui:change');
36
- }
37
- }
38
-
39
- export function updateListboxValidity(state: OuiListboxState): void {
40
- const {
41
- autocomplete,
42
- filter,
43
- host,
44
- internals,
45
- listbox,
46
- localizations,
47
- max,
48
- min,
49
- multiple,
50
- options,
51
- required,
52
- } = state;
53
-
54
- if (autocomplete.none && !listbox) {
55
- const valueMissing = required && filter.element.value.length === 0;
56
-
57
- const localization = getLocalization(
58
- localizations.global,
59
- host,
60
- 'invalid',
61
- localizations.component,
62
- );
63
-
64
- internals.setValidity({valueMissing}, localize(localization, {}, []));
65
-
66
- internals.checkValidity();
67
-
68
- return;
69
- }
70
-
71
- let data: Record<string, unknown> = {};
72
- let error: 'badInput' | 'rangeOverflow' | 'rangeUnderflow' | undefined;
73
- let key: 'input' | 'max' | 'min' | undefined;
74
- let parameters: unknown[] = [];
75
-
76
- switch (true) {
77
- case required && options.selected.length === 0: {
78
- error = 'badInput';
79
- key = 'input';
80
-
81
- break;
82
- }
83
-
84
- case multiple && typeof max === 'number' && options.selected.length > max: {
85
- data = {amount: max};
86
- error = 'rangeOverflow';
87
- key = 'max';
88
- parameters = [max];
89
-
90
- break;
91
- }
92
-
93
- case multiple && typeof min === 'number' && options.selected.length < min: {
94
- data = {amount: min};
95
- error = 'rangeUnderflow';
96
- key = 'min';
97
- parameters = [min];
98
-
99
- break;
100
- }
101
-
102
- default:
103
- break;
104
- }
105
-
106
- const localization =
107
- key == null
108
- ? undefined
109
- : getLocalization(localizations.global, host, key, localizations.component);
110
-
111
- const message = localization == null ? undefined : localize(localization, data, parameters);
112
-
113
- internals.setValidity(
114
- error == null
115
- ? {}
116
- : {
117
- [error]: true,
118
- },
119
- message,
120
- );
121
-
122
- internals.checkValidity();
123
- }
124
-
125
- // #endregion
@@ -1,135 +0,0 @@
1
- import {setAria} from '@oscarpalmer/toretto/aria';
2
- import {setAttribute} from '@oscarpalmer/toretto/attribute';
3
- import {filterListbox} from './listbox.data';
4
- import {updateListboxValidity} from './listbox.form';
5
- import type {OuiListboxState} from './listbox.model';
6
-
7
- // #region Functions
8
-
9
- export function generateListboxIds(prefix: string, select: HTMLSelectElement): void {
10
- const elements = [...select.children].flatMap(child =>
11
- child instanceof HTMLOptGroupElement
12
- ? [
13
- child,
14
- ...[...child.children].filter(groupChild => groupChild instanceof HTMLOptionElement),
15
- ]
16
- : child instanceof HTMLOptionElement
17
- ? [child]
18
- : [],
19
- );
20
-
21
- const {length} = elements;
22
-
23
- for (let index = 0; index < length; index += 1) {
24
- const element = elements[index];
25
-
26
- if (element.id === '') {
27
- element.id = `${prefix}${element instanceof HTMLOptGroupElement ? '_group_' : '_option_'}${index}`;
28
- }
29
- }
30
- }
31
-
32
- export function getListboxVisibleOptions(state: OuiListboxState): HTMLElement[] {
33
- return state.options.all.filter(option => !option.hidden);
34
- }
35
-
36
- export function setListboxDisabled<State extends OuiListboxState>(
37
- state: State,
38
- value: boolean,
39
- ): void {
40
- state.filter.element.readOnly = state.readonly || value;
41
-
42
- setProperties('disabled', state, value);
43
- }
44
-
45
- export function setListboxFilter<State extends OuiListboxState>(
46
- state: State,
47
- value: unknown,
48
- ): void {
49
- if (typeof value !== 'string') {
50
- return;
51
- }
52
-
53
- const type: InputEvent['inputType'] =
54
- value.length < state.filter.element.value.length ? 'deleteContentBackward' : 'insertText';
55
-
56
- state.filter.element.value = value;
57
-
58
- filterListbox(type, state);
59
- }
60
-
61
- export function setListboxLimit<State extends OuiListboxState>(
62
- type: 'max' | 'min',
63
- state: State,
64
- value?: unknown,
65
- ): void {
66
- let actual = value;
67
-
68
- if (typeof actual === 'string') {
69
- actual = Number.parseInt(actual, 10);
70
- }
71
-
72
- const updateLimit =
73
- typeof actual === 'number' && !Number.isNaN(actual) && actual >= 0
74
- ? actual !== state[type]
75
- : actual == null;
76
-
77
- if (updateLimit) {
78
- state[type] = actual as number | undefined;
79
-
80
- setAttribute(state.host, type, actual);
81
-
82
- updateListboxValidity(state);
83
- }
84
- }
85
-
86
- export function setListboxMultiple(element: HTMLElement, value: boolean): void {
87
- if (value) {
88
- element.setAttribute('multiple', '');
89
- } else {
90
- element.removeAttribute('multiple');
91
- }
92
- }
93
-
94
- function setProperties<State extends OuiListboxState>(
95
- key: 'disabled' | 'readonly' | 'required',
96
- state: State,
97
- value: boolean,
98
- ): void {
99
- state[key] = value;
100
-
101
- const {length} = state.elements;
102
-
103
- for (let index = 0; index < length; index += 1) {
104
- const element = state.elements[index];
105
-
106
- if (element == null) {
107
- continue;
108
- }
109
-
110
- setAria(
111
- element,
112
- key,
113
- key !== 'readonly' || !(element instanceof HTMLButtonElement) ? value : undefined,
114
- );
115
- }
116
- }
117
-
118
- export function setListboxReadonly<State extends OuiListboxState>(
119
- state: State,
120
- value: boolean,
121
- ): void {
122
- state.filter.element.readOnly = state.disabled || value;
123
-
124
- setProperties('readonly', state, value);
125
- }
126
-
127
- export function setListboxRequired<State extends OuiListboxState>(
128
- state: State,
129
- value: boolean,
130
- ): void {
131
- setProperties('required', state, value);
132
- updateListboxValidity(state);
133
- }
134
-
135
- // #endregion
@@ -1,169 +0,0 @@
1
- import type {RemovableEventListener} from '@oscarpalmer/toretto/models';
2
- import type {OuiLocalizations, OuiLocalizationsValues} from '../../l10n';
3
-
4
- // #region Types
5
-
6
- export type OuiListboxAttributes = {
7
- active: string;
8
- content: string;
9
- empty: string;
10
- filter: string;
11
- group: string;
12
- header: string;
13
- hidden: string;
14
- input: string;
15
- list: string;
16
- message: string;
17
- option: string;
18
- };
19
-
20
- export type OuiListboxAutoComplete = Record<OuiListboxAutoCompleteType, boolean> & {
21
- value?: OuiListboxAutoCompleteType;
22
- };
23
-
24
- export type OuiListboxAutoCompleteType = 'both' | 'inline' | 'list' | 'none';
25
-
26
- export type OuiListboxCallbacks<State extends OuiListboxState = OuiListboxState> = {
27
- data: OuiListboxCallbacksData<State>;
28
- keydown: OuiListboxCallbacksKeydown<State>;
29
- };
30
-
31
- type OuiListboxCallbacksData<State extends OuiListboxState = OuiListboxState> = {
32
- onApply: OuiListboxCallbacksDataOnApply<State>;
33
- onFilter: OuiListboxCallbacksDataOnFilter<State>;
34
- onForm: (state: State) => void;
35
- onPreview: OuiListboxCallbacksDataOnPreview<State>;
36
- onToggle: (state: State) => void;
37
- };
38
-
39
- type OuiListboxCallbacksDataOnApply<State extends OuiListboxState = OuiListboxState> = (
40
- state: State,
41
- option: HTMLElement | undefined,
42
- values: string[],
43
- added: boolean,
44
- selected?: HTMLElement[],
45
- emit?: boolean,
46
- ) => void;
47
-
48
- type OuiListboxCallbacksDataOnFilter<State extends OuiListboxState = OuiListboxState> = (
49
- preview: OuiListboxPreview,
50
- state: State,
51
- update: boolean,
52
- active?: HTMLElement,
53
- emit?: boolean,
54
- ) => void;
55
-
56
- type OuiListboxCallbacksDataOnPreview<State extends OuiListboxState = OuiListboxState> = (
57
- preview: OuiListboxPreview,
58
- state: State,
59
- active?: HTMLElement,
60
- ) => void;
61
-
62
- type OuiListboxCallbacksKeydown<State extends OuiListboxState = OuiListboxState> = {
63
- onActivation?: (state: State) => void;
64
- onEnter?: (state: State) => void;
65
- onEscape?: (state: State) => void;
66
- onNavigation: OuiListboxCallbacksDataOnNavigation<State>;
67
- onSelection?: (state: State) => void;
68
- onTab?: (state: State) => void;
69
- onToggle?: (state: State) => void;
70
- preventActivation?: (state: State) => boolean;
71
- skipNavigation?: (state: State) => boolean;
72
- };
73
-
74
- type OuiListboxCallbacksDataOnNavigation<State extends OuiListboxState = OuiListboxState> = (
75
- preview: OuiListboxPreview,
76
- state: State,
77
- active?: HTMLElement,
78
- ) => void;
79
-
80
- type OuiListboxFilter = {
81
- element: HTMLInputElement;
82
- value: string;
83
- };
84
-
85
- type OuiListboxFooter = {
86
- container: HTMLElement;
87
- message: HTMLElement;
88
- };
89
-
90
- export type OuiListboxGroup = {
91
- element: HTMLElement;
92
- header: HTMLElement;
93
- options: HTMLElement[];
94
- };
95
-
96
- type OuiListboxLabel = {
97
- element: HTMLLabelElement;
98
- id: string;
99
- };
100
-
101
- type OuiListboxLocalization<Localizations extends OuiLocalizationsValues> = {
102
- component: Record<string, Partial<Localizations>>;
103
- global: OuiLocalizations<Localizations>;
104
- };
105
-
106
- export type OuiListboxLocalizations = {
107
- empty: string | (() => string);
108
- input: string | (() => string);
109
- invalid: string | (() => string);
110
- max: string | ((max: number) => string);
111
- min: string | ((min: number) => string);
112
- remove: string | ((label: string, value: string) => string);
113
- results: string | ((amount: number) => string);
114
- selected: string | ((amount: number) => string);
115
- };
116
-
117
- export type OuiListboxOptions = {
118
- all: HTMLElement[];
119
- selected: HTMLElement[];
120
- };
121
-
122
- export type OuiListboxPreview = 'none' | 'set' | 'typed';
123
-
124
- export type OuiListboxState = {
125
- active?: HTMLElement;
126
- attributes: OuiListboxAttributes;
127
- autocomplete: OuiListboxAutoComplete;
128
- callbacks: OuiListboxCallbacks;
129
- content: HTMLDivElement;
130
- disabled: boolean;
131
- elements: Array<HTMLElement | undefined>;
132
- filter: OuiListboxFilter;
133
- footer?: OuiListboxFooter;
134
- groups?: OuiListboxGroup[];
135
- host: HTMLElement;
136
- id: string;
137
- internals: ElementInternals;
138
- label: OuiListboxLabel;
139
- list: HTMLUListElement;
140
- listbox: boolean;
141
- listeners: RemovableEventListener[];
142
- localizations: OuiListboxLocalization<OuiListboxLocalizations>;
143
- max?: number;
144
- min?: number;
145
- message: HTMLElement;
146
- multiple: boolean;
147
- name: string;
148
- options: OuiListboxOptions;
149
- readonly: boolean;
150
- required: boolean;
151
- select: HTMLSelectElement;
152
- type: OuiListboxType;
153
- values: OuiListboxValues;
154
- };
155
-
156
- export type OuiListboxStates<State extends OuiListboxState = OuiListboxState> = {
157
- map: WeakMap<HTMLElement, State>;
158
- set: Set<State>;
159
- };
160
-
161
- export type OuiListboxType = 'autocomplete' | 'select';
162
-
163
- type OuiListboxValues = {
164
- current: string[];
165
- initial: string[];
166
- label: HTMLElement;
167
- };
168
-
169
- // #endregion
@@ -1,82 +0,0 @@
1
- import {getAttribute} from '@oscarpalmer/toretto/attribute';
2
- import {filterListboxOptions} from './listbox.data';
3
- import {updateListboxMessage, updateListboxPreview, updateListboxValueLabel} from './listbox.dom';
4
- import {updateListboxForm} from './listbox.form';
5
- import {
6
- setListboxDisabled,
7
- setListboxLimit,
8
- setListboxMultiple,
9
- setListboxReadonly,
10
- setListboxRequired,
11
- } from './listbox.misc';
12
- import type {OuiListboxState, OuiListboxStates} from './listbox.model';
13
-
14
- // #region Functions
15
-
16
- export function attachListbox<State extends OuiListboxState>(
17
- state: State,
18
- states: OuiListboxStates<State>,
19
- onAttach: (state: State) => void,
20
- ): void {
21
- const {filter, host, id, label} = state;
22
-
23
- label.element.htmlFor = filter.element.id;
24
- label.element.id = `${id}_label`;
25
-
26
- onAttach(state);
27
-
28
- states.map.set(host, state);
29
- states.set.add(state);
30
- }
31
-
32
- export function detachListbox<State extends OuiListboxState>(
33
- state: State,
34
- states: OuiListboxStates<State>,
35
- onDetach: (state: State) => void,
36
- ): void {
37
- const {host, label, select} = state;
38
-
39
- const listeners = state.listeners.splice(0);
40
- const {length} = listeners;
41
-
42
- for (let index = 0; index < length; index += 1) {
43
- listeners[index]();
44
- }
45
-
46
- label.element.htmlFor = select.id;
47
- label.element.id = label.id;
48
-
49
- onDetach(state);
50
-
51
- states.map.delete(host);
52
- states.set.delete(state);
53
- }
54
-
55
- export function initializeListboxState<State extends OuiListboxState>(
56
- state: State,
57
- states: OuiListboxStates<State>,
58
- onAttach: (state: State) => void,
59
- ): State {
60
- attachListbox(state, states, onAttach);
61
-
62
- setListboxDisabled(state, state.disabled);
63
- setListboxLimit('max', state, getAttribute(state.host, 'max'));
64
- setListboxLimit('min', state, getAttribute(state.host, 'min'));
65
- setListboxMultiple(state.host, state.multiple);
66
- setListboxReadonly(state, state.readonly);
67
- setListboxRequired(state, state.required);
68
-
69
- filterListboxOptions(state);
70
-
71
- updateListboxForm(state, state.values.current, false);
72
- updateListboxMessage(state);
73
- updateListboxValueLabel(state);
74
-
75
- if (state.options.selected.length > 0) {
76
- updateListboxPreview('none', state, state.options.selected[0], false);
77
- }
78
-
79
- return state;
80
- }
81
-
82
- // #endregion
@@ -1,27 +0,0 @@
1
- import {getAria} from '@oscarpalmer/toretto/aria';
2
- import {getAttribute} from '@oscarpalmer/toretto/attribute';
3
- import type {AnyAriaBooleanAttribute} from '@oscarpalmer/toretto/models';
4
-
5
- // #region Functions
6
-
7
- export function getAttributeValue<Value>(
8
- element: HTMLElement,
9
- attribute: string,
10
- possible: Set<Value>,
11
- defaultValue: Value,
12
- ): Value {
13
- const value = getAttribute(element, attribute);
14
-
15
- return possible.has(value as Value) ? (value as Value) : defaultValue;
16
- }
17
-
18
- export function getBooleanAriaValue(
19
- element: HTMLElement,
20
- attribute: AnyAriaBooleanAttribute,
21
- ): boolean {
22
- const value = getAria(element, attribute);
23
-
24
- return value === true || value === 'true';
25
- }
26
-
27
- // #endregion