@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,411 +0,0 @@
1
- import {isPlainObject} from '@oscarpalmer/atoms/is';
2
- import {clamp} from '@oscarpalmer/atoms/number';
3
- import {setAttribute} from '@oscarpalmer/toretto/attribute';
4
- import {dispatch, on} from '@oscarpalmer/toretto/event';
5
- import {findAncestor} from '@oscarpalmer/toretto/find';
6
- import {getFocusable} from '@oscarpalmer/toretto/focusable';
7
- import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
8
- import {attributable} from '../internal/attributable';
9
-
10
- // #region Types
11
-
12
- export class OuiFocusTrap {
13
- #destroyed = false;
14
- #tabIndex: number;
15
-
16
- readonly #state: OuiFocusTrapState;
17
-
18
- /**
19
- * Is focused maintained within the _focus trap_ when clicking outside of it?
20
- */
21
- get contain(): boolean {
22
- return this.#state.element.hasAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN);
23
- }
24
-
25
- /**
26
- * Should focus be maintained within the _focus trap_ when clicking outside of it?
27
- */
28
- set contain(value: boolean) {
29
- if (value === true) {
30
- setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_CONTAIN, '');
31
- } else if (value === false) {
32
- setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_CONTAIN, undefined);
33
- }
34
- }
35
-
36
- /**
37
- * Is the _focus trap_ disabled?
38
- */
39
- get disabled(): boolean {
40
- return this.#state.disabled;
41
- }
42
-
43
- /**
44
- * Should the _focus trap_ be disabled?
45
- */
46
- set disabled(value: boolean) {
47
- if (value === true) {
48
- this.disable();
49
- } else if (value === false) {
50
- this.enable();
51
- }
52
- }
53
-
54
- /**
55
- * Is focus allowed to escape when pressing _Escape_ within the _focus trap_?
56
- */
57
- get noescape(): boolean {
58
- return this.#state.element.hasAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE);
59
- }
60
-
61
- /**
62
- * Should the _focus trap_ allow focus to escape when pressing _Escape_?
63
- */
64
- set noescape(value: boolean) {
65
- if (value === true) {
66
- setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_NOESCAPE, '');
67
- } else if (value === false) {
68
- setAttribute(this.#state.element, ATTRIBUTE_FOCUSTRAP_NOESCAPE, undefined);
69
- }
70
- }
71
-
72
- constructor(state: OuiFocusTrapState) {
73
- this.#state = state;
74
- this.#tabIndex = state.element.tabIndex;
75
-
76
- state.element.tabIndex = -1;
77
-
78
- setAttribute(state.element, ATTRIBUTE_FOCUSTRAP, '');
79
-
80
- this.contain = state.options.contain;
81
- this.noescape = state.options.noescape;
82
-
83
- states.set(this, state);
84
- }
85
-
86
- /**
87
- * Destroys the _focus trap_
88
- */
89
- destroy(): void {
90
- if (this.#destroyed) {
91
- return;
92
- }
93
-
94
- this.#destroyed = true;
95
-
96
- disabled.delete(this);
97
- instances.delete(this.#state.element);
98
- states.delete(this);
99
-
100
- this.#state.element.tabIndex = this.#tabIndex;
101
-
102
- this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP);
103
- this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN);
104
- this.#state.element.removeAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE);
105
-
106
- this.#state.element = undefined as never;
107
- }
108
-
109
- /**
110
- * Disables the _focus trap_
111
- */
112
- disable(): void {
113
- if (!this.#destroyed && !(this.disabled || this.#state.options.noescape)) {
114
- setDisabled(this, this.#state, true);
115
- }
116
- }
117
-
118
- /**
119
- * Enables the _focus trap_
120
- */
121
- enable(): void {
122
- if (!this.#destroyed && this.disabled) {
123
- setDisabled(this, this.#state, false);
124
- }
125
- }
126
-
127
- /**
128
- * Focuses the _focus trap_
129
- *
130
- * @param last When `true`, focuses the last focusable element within the _focus trap_ instead of the first
131
- */
132
- focus(last: boolean): void {
133
- if (!this.#destroyed && !this.disabled) {
134
- tabToTrap(this, getFocusable(this.#state.element), this.#state.element, last ? -1 : 0);
135
- }
136
- }
137
- }
138
-
139
- export type OuiFocusTrapOptions = {
140
- /**
141
- * Should focus be maintained within the _focus trap_ when clicking outside of it?
142
- */
143
- contain?: boolean;
144
- /**
145
- * Should the _focus trap_ allow focus to escape when pressing _Escape_?
146
- */
147
- noescape?: boolean;
148
- };
149
-
150
- type OuiFocusTrapState = {
151
- disabled: boolean;
152
- element: HTMLElement;
153
- options: Required<OuiFocusTrapOptions>;
154
- };
155
-
156
- // #endregion
157
-
158
- // #region Functions
159
-
160
- /**
161
- * Creates _(or retrieves)_ a _focus trap_ for an element
162
- *
163
- * @param element Element to trap focus within
164
- * @param options _Focus trap_ options
165
- * @returns _Focus trap_ instance
166
- */
167
- export function createFocusTrap(element: HTMLElement, options?: OuiFocusTrapOptions): OuiFocusTrap {
168
- if (!isHTMLOrSVGElement(element)) {
169
- throw new TypeError(MESSAGE);
170
- }
171
-
172
- let instance = instances.get(element);
173
-
174
- if (instance == null) {
175
- instance = new OuiFocusTrap(getState(element, options));
176
-
177
- instances.set(element, instance);
178
- }
179
-
180
- return instance;
181
- }
182
-
183
- function getOptions(
184
- element: HTMLElement,
185
- input?: OuiFocusTrapOptions,
186
- ): Required<OuiFocusTrapOptions> {
187
- const options = isPlainObject(input) ? input : {};
188
-
189
- return {
190
- contain:
191
- typeof options.contain === 'boolean'
192
- ? options.contain
193
- : element.hasAttribute(ATTRIBUTE_FOCUSTRAP_CONTAIN),
194
- noescape:
195
- typeof options.noescape === 'boolean'
196
- ? options.noescape
197
- : element.hasAttribute(ATTRIBUTE_FOCUSTRAP_NOESCAPE),
198
- };
199
- }
200
-
201
- function getState(element: HTMLElement, options?: OuiFocusTrapOptions): OuiFocusTrapState {
202
- return {
203
- element,
204
- disabled: false,
205
- options: getOptions(element, options),
206
- };
207
- }
208
-
209
- function onEscape(event: KeyboardEvent): void {
210
- let element = findAncestor(event, SELECTOR) as HTMLElement;
211
-
212
- let instance = instances.get(element);
213
- let state = states.get(instance!);
214
-
215
- if (element == null || instance == null || state == null) {
216
- return;
217
- }
218
-
219
- while (state.disabled) {
220
- element = findAncestor(state.element.parentElement as HTMLElement, SELECTOR) as HTMLElement;
221
-
222
- instance = instances.get(element);
223
- state = states.get(instance!);
224
-
225
- if (element == null || instance == null || state == null) {
226
- return;
227
- }
228
-
229
- if (!state.disabled) {
230
- break;
231
- }
232
- }
233
-
234
- instance?.disable();
235
- }
236
-
237
- function onFocusIn(event: Event): void {
238
- const focusTrap = instances.get(findAncestor(event, SELECTOR) as HTMLElement);
239
-
240
- lastTarget = focusTrap == null ? undefined : (event.target as HTMLElement);
241
- }
242
-
243
- function onKeydown(event: KeyboardEvent): void {
244
- switch (event.key) {
245
- case 'Escape':
246
- onEscape(event);
247
- break;
248
-
249
- case 'Tab':
250
- onTab(event);
251
- break;
252
-
253
- default:
254
- return;
255
- }
256
- }
257
-
258
- function onPointerdown(event: MouseEvent | TouchEvent): void {
259
- const last = findAncestor(lastTarget as HTMLElement, SELECTOR) as HTMLElement;
260
- const next = findAncestor(event, SELECTOR) as HTMLElement;
261
-
262
- if (last != null && next !== last) {
263
- if (states.get(instances.get(last)!)?.options.contain ?? false) {
264
- event.preventDefault();
265
-
266
- lastTarget?.focus();
267
- }
268
- }
269
-
270
- if (disabled.size === 0) {
271
- return;
272
- }
273
-
274
- for (const focusTrap of disabled) {
275
- const state = states.get(focusTrap);
276
-
277
- if (state != null && state.element !== next) {
278
- focusTrap.enable();
279
- }
280
- }
281
- }
282
-
283
- function onTab(event: KeyboardEvent): void {
284
- const element = findAncestor(event, SELECTOR) as HTMLElement;
285
-
286
- const instance = instances.get(element);
287
-
288
- if (instance == null || dispatch(element, 'oui:focus-trap').defaultPrevented) {
289
- return;
290
- }
291
-
292
- if (!instance.disabled) {
293
- event.preventDefault();
294
- }
295
-
296
- const elements = getFocusable(element);
297
-
298
- const index = elements.indexOf(event.target as HTMLElement);
299
-
300
- if (index === -1 || elements.length === 0) {
301
- tabToTrap(instance, elements, element);
302
- } else {
303
- tabToElement(instance, elements, index, event.shiftKey ? -1 : 1);
304
- }
305
- }
306
-
307
- export function removeFocusTrap(element: HTMLElement): void {
308
- instances.get(element)?.destroy();
309
-
310
- instances.delete(element);
311
- }
312
-
313
- function setDisabled(focusTrap: OuiFocusTrap, state: OuiFocusTrapState, value: boolean): void {
314
- state.disabled = value;
315
-
316
- if (value) {
317
- disabled.add(focusTrap);
318
- } else {
319
- disabled.delete(focusTrap);
320
- }
321
- }
322
-
323
- function tabToElement(
324
- instance: OuiFocusTrap,
325
- elements: Element[],
326
- index: number,
327
- modifier: number,
328
- ): void {
329
- const {length} = elements;
330
- const next = clamp(index + modifier, 0, length - 1, true);
331
-
332
- if (instance.disabled) {
333
- if ((index === length - 1 && next === 0) || (index === 0 && next === length - 1)) {
334
- lastTarget = undefined;
335
-
336
- instance.enable();
337
- }
338
-
339
- return;
340
- }
341
-
342
- const element = elements[next] as HTMLElement;
343
- const elementFocusTrap = instances.get(element);
344
-
345
- if (elementFocusTrap != null) {
346
- elementFocusTrap.focus(modifier === -1);
347
- } else {
348
- (elements[next] as HTMLElement).focus();
349
-
350
- lastTarget = elements[next] as HTMLElement;
351
- }
352
- }
353
-
354
- function tabToTrap(
355
- instance: OuiFocusTrap,
356
- elements: Element[],
357
- element: HTMLElement,
358
- index?: number,
359
- ): void {
360
- if (instance.disabled) {
361
- lastTarget = undefined;
362
-
363
- instance.enable();
364
- } else {
365
- const next = elements.length === 0 ? element : elements.at(index ?? 0);
366
-
367
- (next as HTMLElement).focus();
368
-
369
- lastTarget = next as HTMLElement;
370
- }
371
- }
372
-
373
- // #endregion
374
-
375
- // #region Variables
376
-
377
- export const ATTRIBUTE_FOCUSTRAP = 'oui-focus-trap';
378
-
379
- export const ATTRIBUTE_FOCUSTRAP_CONTAIN = `${ATTRIBUTE_FOCUSTRAP}-contain`;
380
-
381
- export const ATTRIBUTE_FOCUSTRAP_NOESCAPE = `${ATTRIBUTE_FOCUSTRAP}-noescape`;
382
-
383
- const EVENT_OPTIONS: AddEventListenerOptions = {
384
- capture: true,
385
- passive: false,
386
- };
387
-
388
- const MESSAGE = 'Element must be an HTMLElement or SVGElement';
389
-
390
- const SELECTOR = `[${ATTRIBUTE_FOCUSTRAP}]`;
391
-
392
- const disabled = new Set<OuiFocusTrap>();
393
-
394
- const instances = new WeakMap<HTMLElement, OuiFocusTrap>();
395
-
396
- const states = new WeakMap<OuiFocusTrap, OuiFocusTrapState>();
397
-
398
- let lastTarget: HTMLElement | undefined;
399
-
400
- // #endregion
401
-
402
- // #region Initialization
403
-
404
- attributable(ATTRIBUTE_FOCUSTRAP, createFocusTrap, removeFocusTrap);
405
-
406
- on(document, 'focusin', onFocusIn, EVENT_OPTIONS);
407
- on(document, 'keydown', onKeydown, EVENT_OPTIONS);
408
- on(document, 'mousedown', onPointerdown, EVENT_OPTIONS);
409
- on(document, 'touchstart', onPointerdown, EVENT_OPTIONS);
410
-
411
- // #endregion
@@ -1 +0,0 @@
1
- export {createFocusTrap, type OuiFocusTrap, type OuiFocusTrapOptions} from './focus-trap.embedded';
package/src/js/index.ts DELETED
@@ -1,16 +0,0 @@
1
- import './menu';
2
- import './toolbar';
3
-
4
- export * from './color-picker';
5
- export * from './combobox/index';
6
- export * from './dialog';
7
- export * from './floatable/floatable.standalone';
8
- export * from './focus-trap/focus-trap.standalone';
9
- export * from './listbox/index';
10
- export * from './movable/movable.standalone';
11
- export * from './popover';
12
- export * from './resizable/resizable.standalone';
13
- export * from './sortable/sortable.standalone';
14
- export * from './splitter';
15
- export * from './tabs';
16
- export * from './tooltip';
@@ -1,73 +0,0 @@
1
- export function attributable(
2
- attribute: string,
3
- add: (element: HTMLElement) => void,
4
- remove: (element: HTMLElement) => void,
5
- ): void {
6
- const observer = new MutationObserver(entries => {
7
- const {length} = entries;
8
-
9
- for (let index = 0; index < length; index += 1) {
10
- const entry = entries[index];
11
-
12
- if (entry.type === 'attributes' && entry.target instanceof Element) {
13
- if (entry.target.hasAttribute(attribute)) {
14
- handleAdded(attribute, [entry.target], add);
15
- } else {
16
- handleRemoved([entry.target], remove);
17
- }
18
- } else if (entry.type === 'childList') {
19
- handleAdded(attribute, entry.addedNodes, add);
20
- handleRemoved(entry.removedNodes, remove);
21
- }
22
- }
23
- });
24
-
25
- observer.observe(document, {
26
- attributeFilter: [attribute],
27
- attributes: true,
28
- childList: true,
29
- subtree: true,
30
- });
31
-
32
- requestAnimationFrame(() => {
33
- handleAdded(attribute, document.querySelectorAll(`[${attribute}]`), add);
34
- });
35
- }
36
-
37
- function handleAdded(
38
- attribute: string,
39
- nodes: Node[] | NodeList,
40
- add: (element: HTMLElement) => void,
41
- ): void {
42
- const elements = [...nodes].filter(node => node instanceof Element) as HTMLElement[];
43
-
44
- const {length} = elements;
45
-
46
- for (let index = 0; index < length; index += 1) {
47
- const element = elements[index];
48
-
49
- if (element.hasAttribute(attribute)) {
50
- add(element);
51
- }
52
-
53
- if (element.hasChildNodes()) {
54
- handleAdded(attribute, element.childNodes, add);
55
- }
56
- }
57
- }
58
-
59
- function handleRemoved(nodes: Node[] | NodeList, remove: (element: HTMLElement) => void): void {
60
- const elements = [...nodes].filter(node => node instanceof Element) as HTMLElement[];
61
-
62
- const {length} = elements;
63
-
64
- for (let index = 0; index < length; index += 1) {
65
- const element = elements[index];
66
-
67
- remove(element);
68
-
69
- if (element.hasChildNodes()) {
70
- handleRemoved(element.childNodes, remove);
71
- }
72
- }
73
- }