@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,317 +0,0 @@
1
- import {clamp} from '@oscarpalmer/atoms/number';
2
- import {getAria, setAria, setRole} from '@oscarpalmer/toretto/aria';
3
- import {getAttribute} from '@oscarpalmer/toretto/attribute';
4
- import {on} from '@oscarpalmer/toretto/event';
5
- import {findAncestor} from '@oscarpalmer/toretto/find';
6
- import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
7
- import type {AriaRole, RemovableEventListener} from '@oscarpalmer/toretto/models';
8
-
9
- // #region Types
10
-
11
- export class OuiNavigable {
12
- active: OuiNavigableActive = {
13
- index: 0,
14
- };
15
-
16
- element: HTMLElement;
17
-
18
- listeners: RemovableEventListener[];
19
-
20
- options: OuiNavigableOptions;
21
-
22
- orientation: OuiNavigableOrientation;
23
-
24
- constructor(element: HTMLElement, options: OuiNavigableOptions) {
25
- this.element = element;
26
- this.options = options;
27
-
28
- this.listeners = [
29
- on(
30
- element,
31
- 'click',
32
- event => {
33
- onClick(this, event);
34
- },
35
- {
36
- passive: false,
37
- },
38
- ),
39
- on(element, 'focusin', event => {
40
- onFocusin(this, event);
41
- }),
42
- on(
43
- element,
44
- 'keydown',
45
- event => {
46
- onKeydown(this, event);
47
- },
48
- {
49
- passive: false,
50
- },
51
- ),
52
- ];
53
-
54
- this.orientation = options?.orientation ?? getNavigableOrientation(element, options.vertical);
55
-
56
- setAria(element, 'orientation', this.orientation);
57
-
58
- if (options.role != null) {
59
- setRole(element, options.role);
60
- }
61
- }
62
-
63
- destroy(): void {
64
- const listeners = this.listeners.splice(0);
65
-
66
- for (const listener of listeners) {
67
- listener();
68
- }
69
-
70
- this.active.element = undefined;
71
- this.element = undefined as never;
72
- }
73
-
74
- navigate(index: number, focus?: boolean): void {
75
- const items = getItems(this.element, this.options.selector);
76
-
77
- if (index >= 0 && index < items.length) {
78
- onNavigate(this, index, items, focus ?? false);
79
- }
80
- }
81
- }
82
-
83
- type OuiNavigableActive = {
84
- element?: HTMLElement;
85
- index: number;
86
- };
87
-
88
- type OuiNavigableCallback<ReturnType> = (
89
- event: KeyboardEvent,
90
- navigable: OuiNavigable,
91
- ) => ReturnType;
92
-
93
- export type OuiNavigableOptions = {
94
- orientation?: OuiNavigableOrientation;
95
- role?: AriaRole;
96
- selector: string;
97
- vertical: boolean;
98
- onActivate?: (navigable: OuiNavigable) => void;
99
- onDeactivate?: OuiNavigableCallback<void>;
100
- onNavigation?: (navigable: OuiNavigable) => void;
101
- onPreventNavigation?: OuiNavigableCallback<boolean>;
102
- onShouldActivate?: OuiNavigableCallback<boolean>;
103
- onShouldDeactivate?: OuiNavigableCallback<boolean | undefined>;
104
- };
105
-
106
- export type OuiNavigableOrientation = 'horizontal' | 'vertical';
107
-
108
- // #endregion
109
-
110
- // #region Functions
111
-
112
- function getItems(container: HTMLElement, selector: string): HTMLElement[] {
113
- return [...container.querySelectorAll(selector)].filter(isValidItem);
114
- }
115
-
116
- export function getNavigable(element: HTMLElement, options: OuiNavigableOptions): OuiNavigable {
117
- return new OuiNavigable(element, options);
118
- }
119
-
120
- export function getNavigableOrientation(
121
- element: HTMLElement,
122
- vertical: boolean,
123
- aria?: boolean,
124
- ): OuiNavigableOrientation {
125
- const attribute =
126
- (aria ?? true) ? getAria(element, 'orientation') : getAttribute(element, 'orientation');
127
-
128
- return ORIENTATIONS.has(attribute as OuiNavigableOrientation)
129
- ? (attribute as OuiNavigableOrientation)
130
- : vertical
131
- ? ORIENTATION_VERTICAL
132
- : ORIENTATION_HORIZONTAL;
133
- }
134
-
135
- function isValidItem(element: Element): element is HTMLElement {
136
- return 'disabled' in element ? element.disabled !== true : true;
137
- }
138
-
139
- function onClick(navigable: OuiNavigable, event: Event): void {
140
- const item = findAncestor(event, navigable.options.selector) as HTMLElement;
141
- const items = getItems(navigable.element, navigable.options.selector);
142
-
143
- const index = items.indexOf(item);
144
-
145
- if (index === -1) {
146
- return;
147
- }
148
-
149
- if (index !== navigable.active.index) {
150
- onNavigate(navigable, index, items, false);
151
- }
152
-
153
- navigable.options.onActivate?.(navigable);
154
-
155
- item.focus();
156
- }
157
-
158
- function onNavigate(
159
- navigable: OuiNavigable,
160
- index: number,
161
- items: HTMLElement[],
162
- focus: boolean,
163
- ): void {
164
- navigable.active.element = items[index];
165
- navigable.active.index = index;
166
-
167
- updateNavigableFocus(navigable, focus, items);
168
-
169
- navigable.options.onNavigation?.(navigable);
170
- }
171
-
172
- function onFocusin(navigable: OuiNavigable, event: FocusEvent): void {
173
- const item = findAncestor(event, navigable.options.selector);
174
-
175
- if (!isHTMLOrSVGElement(item) || !isValidItem(item)) {
176
- return;
177
- }
178
-
179
- const items = getItems(navigable.element, navigable.options.selector);
180
- const index = items.indexOf(item);
181
-
182
- if (index === -1) {
183
- return;
184
- }
185
-
186
- navigable.active.element = item;
187
- navigable.active.index = index;
188
-
189
- updateNavigableFocus(navigable, false, items);
190
- }
191
-
192
- function onKeydown(navigable: OuiNavigable, event: KeyboardEvent): void {
193
- const escaped = event.key === 'Escape';
194
- const stopPropagation = navigable.options.onShouldDeactivate?.(event, navigable);
195
-
196
- if (escaped || stopPropagation != null) {
197
- if (escaped || stopPropagation) {
198
- event.stopPropagation();
199
- }
200
-
201
- navigable.options.onDeactivate?.(event, navigable);
202
-
203
- return;
204
- }
205
-
206
- if (!KEYS_ALL.has(event.key)) {
207
- return;
208
- }
209
-
210
- const mustActivate = KEYS_ACTIVATE.has(event.key);
211
- const shouldActivate = navigable.options.onShouldActivate?.(event, navigable) === true;
212
-
213
- if (
214
- mustActivate ||
215
- shouldActivate ||
216
- navigable.options.onPreventNavigation?.(event, navigable) === true
217
- ) {
218
- event.stopPropagation();
219
- }
220
-
221
- if (mustActivate || shouldActivate) {
222
- navigable.options.onActivate?.(navigable);
223
-
224
- return;
225
- }
226
-
227
- const items = getItems(navigable.element, navigable.options.selector);
228
- const {length} = items;
229
-
230
- if (length === 0) {
231
- return;
232
- }
233
-
234
- event.preventDefault();
235
-
236
- let index: number | undefined;
237
-
238
- if (KEYS_ABSOLUTE.has(event.key)) {
239
- index = event.key === 'Home' ? 0 : items.length - 1;
240
- } else {
241
- const direction = NAVIGABLE_KEYS_HORIZONTAL.has(event.key)
242
- ? ORIENTATION_HORIZONTAL
243
- : ORIENTATION_VERTICAL;
244
-
245
- if (navigable.orientation === direction) {
246
- if (navigable.active.element instanceof HTMLSelectElement) {
247
- event.preventDefault();
248
- }
249
-
250
- index = clamp(
251
- navigable.active.index + (KEYS_NEXT.has(event.key) ? 1 : -1),
252
- 0,
253
- length - 1,
254
- true,
255
- );
256
- }
257
- }
258
-
259
- if (index != null && index !== navigable.active.index) {
260
- onNavigate(navigable, index, items, true);
261
- }
262
- }
263
-
264
- export function updateNavigableFocus(
265
- navigable: OuiNavigable,
266
- focus: boolean,
267
- items?: HTMLElement[],
268
- ): void {
269
- const updated = items ?? getItems(navigable.element, navigable.options.selector);
270
- const {length} = updated;
271
-
272
- if (length === 0) {
273
- return;
274
- }
275
-
276
- for (let index = 0; index < length; index += 1) {
277
- updated[index].tabIndex = index === navigable.active.index ? 0 : -1;
278
- }
279
-
280
- navigable.active.element ??= updated[navigable.active.index];
281
-
282
- if (focus) {
283
- navigable.active.element?.focus();
284
- }
285
- }
286
-
287
- // #endregion
288
-
289
- // #region Variables
290
-
291
- const KEYS_ABSOLUTE = new Set(['End', 'Home']);
292
-
293
- const KEYS_ACTIVATE = new Set(['Enter', ' ']);
294
-
295
- export const NAVIGABLE_KEYS_HORIZONTAL = new Set(['ArrowRight', 'ArrowLeft']);
296
-
297
- export const NAVIGABLE_KEYS_VERTICAL = new Set(['ArrowDown', 'ArrowUp']);
298
-
299
- const KEYS_ALL = new Set([
300
- ...KEYS_ABSOLUTE,
301
- ...KEYS_ACTIVATE,
302
- ...NAVIGABLE_KEYS_HORIZONTAL,
303
- ...NAVIGABLE_KEYS_VERTICAL,
304
- ]);
305
-
306
- const KEYS_NEXT = new Set(['ArrowDown', 'ArrowRight']);
307
-
308
- const ORIENTATION_HORIZONTAL: OuiNavigableOrientation = 'horizontal';
309
-
310
- const ORIENTATION_VERTICAL: OuiNavigableOrientation = 'vertical';
311
-
312
- const ORIENTATIONS = new Set<OuiNavigableOrientation>([
313
- ORIENTATION_HORIZONTAL,
314
- ORIENTATION_VERTICAL,
315
- ]);
316
-
317
- // #endregion
package/src/js/l10n.ts DELETED
@@ -1,192 +0,0 @@
1
- import type {GenericCallback} from '@oscarpalmer/atoms/models';
2
- import {getString} from '@oscarpalmer/atoms/string';
3
-
4
- // #region Types
5
-
6
- type LocalizationParameters<Localization> = Localization extends GenericCallback
7
- ? Parameters<Localization>
8
- : never;
9
-
10
- export class OuiLocalizations<Localizations extends OuiLocalizationsValues> {
11
- readonly defaults: Localizations;
12
-
13
- readonly keys: Set<keyof Localizations>;
14
-
15
- readonly values: Record<string, Partial<Localizations>> = {};
16
-
17
- constructor(defaults: Localizations) {
18
- this.defaults = defaults;
19
- this.keys = new Set(Object.keys(defaults) as Array<keyof Localizations>);
20
- }
21
-
22
- get<Key extends keyof Localizations>(
23
- element: Element,
24
- key: Key,
25
- localizations: Record<string, Partial<Localizations>>,
26
- ): string | GenericCallback {
27
- return getLocalization(this, element, key, localizations);
28
- }
29
-
30
- set(language: string, localizations: Partial<Localizations>): void;
31
-
32
- set(localizations: Record<string, Partial<Localizations>>): void;
33
-
34
- set(
35
- first: string | Record<string, Partial<Localizations>>,
36
- second?: Partial<Localizations>,
37
- ): void {
38
- updateLocalizations(
39
- this,
40
- typeof first === 'string'
41
- ? {
42
- [first]: second!,
43
- }
44
- : first,
45
- this.values,
46
- );
47
- }
48
- }
49
-
50
- export type OuiLocalizationsValues = Record<string, string | GenericCallback>;
51
-
52
- // #endregion
53
-
54
- // #region Functions
55
-
56
- export function getLanguage(element: Element): string {
57
- return (
58
- element.closest('[lang]')?.getAttribute('lang') ?? document.documentElement.lang
59
- ).toLowerCase();
60
- }
61
-
62
- export function getLocalization<
63
- Localizations extends OuiLocalizationsValues,
64
- Key extends keyof Localizations,
65
- >(
66
- localizations: OuiLocalizations<Localizations>,
67
- element: Element,
68
- key: Key,
69
- value: Record<string, Partial<Localizations>>,
70
- ): Localizations[Key] | GenericCallback {
71
- const language = getLanguage(element);
72
-
73
- const values = [value, localizations.values];
74
- const {length} = values;
75
-
76
- let localization: Localizations[Key] | undefined;
77
- let shortLanguage: string | undefined;
78
-
79
- for (let index = 0; index < length; index += 1) {
80
- const value = values[index];
81
-
82
- localization = value?.[language]?.[key];
83
-
84
- if (localization != null) {
85
- break;
86
- }
87
-
88
- shortLanguage ??= language.split('-')[0];
89
-
90
- if (shortLanguage === language) {
91
- continue;
92
- }
93
-
94
- localization = value?.[shortLanguage]?.[key];
95
-
96
- if (localization != null) {
97
- break;
98
- }
99
- }
100
-
101
- return localization ?? localizations.defaults[key];
102
- }
103
-
104
- export function getLocalizations<Localizations extends OuiLocalizationsValues>(
105
- defaults: Localizations,
106
- ): OuiLocalizations<Localizations> {
107
- return new OuiLocalizations(defaults);
108
- }
109
-
110
- export function localize<
111
- Localizations extends OuiLocalizationsValues,
112
- Key extends keyof Localizations,
113
- Localization extends Localizations[Key],
114
- >(
115
- localization: Localization,
116
- data: Record<string, unknown>,
117
- parameters: LocalizationParameters<Localization>,
118
- ): string {
119
- if (typeof localization === 'function') {
120
- return localization(...parameters);
121
- }
122
-
123
- const keys = Object.keys(data);
124
- const {length} = keys;
125
-
126
- let localized = localization as string;
127
-
128
- for (let index = 0; index < length; index += 1) {
129
- const key = keys[index];
130
- const value = data[key];
131
-
132
- localized = localized.replaceAll(`{${key}}`, getString(value));
133
- }
134
-
135
- return localized;
136
- }
137
-
138
- export function updateLocalizations<Localizations extends OuiLocalizationsValues>(
139
- instance: OuiLocalizations<Localizations>,
140
- values: Record<string, Partial<Localizations>>,
141
- destination: Record<string, Partial<Localizations>>,
142
- onAfter?: () => void,
143
- ): void {
144
- if (typeof values !== 'object' || values == null) {
145
- return;
146
- }
147
-
148
- const localizations = destination ?? instance.values;
149
-
150
- const languages = Object.keys(values);
151
- const languagesLength = languages.length;
152
-
153
- let updated = false;
154
-
155
- for (let languagesIndex = 0; languagesIndex < languagesLength; languagesIndex += 1) {
156
- const language = languages[languagesIndex];
157
- const languageValue = values[language];
158
-
159
- if (typeof languageValue !== 'object' || languageValue == null) {
160
- continue;
161
- }
162
-
163
- const normalizedLanguage = language.toLowerCase();
164
-
165
- localizations[normalizedLanguage] ??= {};
166
-
167
- const keys = Object.keys(languageValue);
168
- const keysLength = keys.length;
169
-
170
- for (let keysIndex = 0; keysIndex < keysLength; keysIndex += 1) {
171
- const key = keys[keysIndex];
172
- const keyValue = languageValue[key];
173
-
174
- const normalizedKey = key.toLowerCase() as keyof Localizations;
175
-
176
- if (
177
- instance.keys.has(normalizedKey) &&
178
- (typeof keyValue === 'string' || typeof keyValue === 'function')
179
- ) {
180
- updated = true;
181
-
182
- localizations[normalizedLanguage][normalizedKey] = keyValue as never;
183
- }
184
- }
185
- }
186
-
187
- if (updated && typeof onAfter === 'function') {
188
- onAfter();
189
- }
190
- }
191
-
192
- // #endregion
@@ -1,61 +0,0 @@
1
- import type {OuiListboxAttributes} from '../internal/listbox/listbox.model';
2
-
3
- // #region Variables
4
-
5
- export const LISTBOX_TAGNAME = 'oui-listbox';
6
-
7
- const attributeContent = `${LISTBOX_TAGNAME}-content`;
8
-
9
- const attributeFilter = `${LISTBOX_TAGNAME}-filter`;
10
-
11
- const attributeFilterInput = `${attributeFilter}-input`;
12
-
13
- const attributeGroup = `${LISTBOX_TAGNAME}-group`;
14
-
15
- const attributeHeader = `${LISTBOX_TAGNAME}-header`;
16
-
17
- const attributeHidden = `${LISTBOX_TAGNAME}-hidden`;
18
-
19
- const attributeList = `${LISTBOX_TAGNAME}-list`;
20
-
21
- const attributeListEmpty = `${attributeList}-empty`;
22
-
23
- const attributeMessage = `${LISTBOX_TAGNAME}-message`;
24
-
25
- const attributeOption = `${LISTBOX_TAGNAME}-option`;
26
-
27
- const attributeOptionActive = `${LISTBOX_TAGNAME}-option-active`;
28
-
29
- const messageLabel = `<${LISTBOX_TAGNAME}> must contain a <label> element for the <select> element`;
30
-
31
- const messageSelect = `<${LISTBOX_TAGNAME}> must contain a valid <select> element`;
32
-
33
- const selectorFilter = `[${attributeFilterInput}]`;
34
-
35
- const selectorOption = `[${attributeOption}]`;
36
-
37
- export const LISTBOX_ATTRIBUTES: OuiListboxAttributes = {
38
- active: attributeOptionActive,
39
- content: attributeContent,
40
- empty: attributeListEmpty,
41
- filter: attributeFilter,
42
- group: attributeGroup,
43
- header: attributeHeader,
44
- hidden: attributeHidden,
45
- input: attributeFilterInput,
46
- list: attributeList,
47
- message: attributeMessage,
48
- option: attributeOption,
49
- };
50
-
51
- export const LISTBOX_MESSAGES = {
52
- label: messageLabel,
53
- select: messageSelect,
54
- };
55
-
56
- export const LISTBOX_SELECTORS = {
57
- filter: selectorFilter,
58
- option: selectorOption,
59
- };
60
-
61
- // #endregion
@@ -1,106 +0,0 @@
1
- import {on} from '@oscarpalmer/toretto/event';
2
- import {findAncestor} from '@oscarpalmer/toretto/find';
3
- import {
4
- applyListboxSelection,
5
- filterListbox,
6
- toggleListboxOption,
7
- } from '../internal/listbox/listbox.data';
8
- import {updateListboxPreview} from '../internal/listbox/listbox.dom';
9
- import {processListboxKeydown} from '../internal/listbox/listbox.event';
10
- import type {OuiListboxPreview, OuiListboxState} from '../internal/listbox/listbox.model';
11
- import {LISTBOX_SELECTORS, LISTBOX_TAGNAME} from './constants.listbox';
12
- import {listboxStates} from './state.listbox';
13
-
14
- // #region Types
15
-
16
- // #region Functions
17
-
18
- function onListboxClick(event: Event): void {
19
- const listbox = findAncestor(event, LISTBOX_TAGNAME);
20
- const state = listboxStates.map.get(listbox!);
21
-
22
- if (listbox == null || state == null) {
23
- return;
24
- }
25
-
26
- const option = findAncestor(event, LISTBOX_SELECTORS.option) as HTMLElement | null;
27
-
28
- if (option == null) {
29
- return;
30
- }
31
-
32
- if (state.disabled) {
33
- state.filter.element.focus();
34
- } else if (state.readonly) {
35
- updateListboxPreview('none', state, option, false);
36
- } else {
37
- toggleListboxOption(state, option);
38
- }
39
- }
40
-
41
- export function onListboxEnter(state: OuiListboxState): void {
42
- if (!state.disabled && !state.readonly) {
43
- toggleListboxOption(state, state.active);
44
- }
45
- }
46
-
47
- export function onListboxFilter(
48
- preview: OuiListboxPreview,
49
- state: OuiListboxState,
50
- _: boolean,
51
- active?: HTMLElement,
52
- ): void {
53
- updateListboxPreview(preview, state, active);
54
- }
55
-
56
- function onListboxInput(event: InputEvent): void {
57
- const listbox = findAncestor(event, LISTBOX_TAGNAME);
58
- const state = listboxStates.map.get(listbox!);
59
-
60
- if (state?.filter.element === event.target) {
61
- filterListbox(event.inputType, state);
62
- }
63
- }
64
-
65
- function onListboxKeydown(event: KeyboardEvent): void {
66
- const listbox = findAncestor(event, LISTBOX_TAGNAME);
67
- const state = listboxStates.map.get(listbox!);
68
-
69
- if (state?.filter.element === event.target) {
70
- processListboxKeydown(event, state);
71
- }
72
- }
73
-
74
- export function onListboxNavigation(
75
- preview: OuiListboxPreview,
76
- state: OuiListboxState,
77
- active?: HTMLElement,
78
- ): void {
79
- if (state.multiple || state.readonly) {
80
- updateListboxPreview(preview, state, active);
81
- } else {
82
- applyListboxSelection({
83
- state,
84
- option: active,
85
- added: true,
86
- selected: active == null ? [] : [active],
87
- });
88
- }
89
- }
90
-
91
- export function onListboxToggle(state: OuiListboxState): void {
92
- state.filter.element.focus();
93
- }
94
-
95
- // #endregion
96
-
97
- // #region Initialization
98
-
99
- on(document, 'click', onListboxClick);
100
- on(document, 'input', onListboxInput);
101
-
102
- on(document, 'keydown', onListboxKeydown, {
103
- passive: false,
104
- });
105
-
106
- // #endregion