@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
package/src/js/popover.ts DELETED
@@ -1,229 +0,0 @@
1
- import {getAria, setAria} from '@oscarpalmer/toretto/aria';
2
- import {setAttribute} from '@oscarpalmer/toretto/attribute';
3
- import {on} from '@oscarpalmer/toretto/event';
4
- import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
5
- import type {RemovableEventListener} from '@oscarpalmer/toretto/models';
6
- import {
7
- ATTRIBUTE_FLOATABLE,
8
- createEmbeddedFloatable,
9
- getOnBeforeToggleListener,
10
- type OuiFloatable,
11
- type OuiFloatableOptions,
12
- } from './floatable/floatable.embedded';
13
- import {createFocusTrap, type OuiFocusTrap} from './focus-trap/focus-trap.embedded';
14
- import {attributable} from './internal/attributable';
15
-
16
- // #region Types
17
-
18
- class OuiPopover {
19
- readonly #state: OuiPopoverState;
20
-
21
- /**
22
- * Is the popover open?
23
- */
24
- get open(): boolean {
25
- return this.#state.content.checkVisibility();
26
- }
27
-
28
- set open(value: boolean) {
29
- if (value === true) {
30
- this.show();
31
- } else if (value === false) {
32
- this.hide();
33
- }
34
- }
35
-
36
- constructor(state: OuiPopoverState) {
37
- this.#state = state;
38
-
39
- initialize(state);
40
-
41
- this.#state.floatable.update();
42
- }
43
-
44
- /**
45
- * Closes the popover
46
- */
47
- hide(): void {
48
- this.#state.floatable.hide();
49
- }
50
-
51
- /**
52
- * Opens the popover
53
- */
54
- show(): void {
55
- this.#state.floatable.show();
56
- }
57
- }
58
-
59
- type OuiPopoverState = {
60
- anchor: HTMLElement;
61
- content: HTMLElement;
62
- floatable: OuiFloatable;
63
- focusTrap?: OuiFocusTrap;
64
- listeners: RemovableEventListener[];
65
- popover: OuiPopover;
66
- };
67
-
68
- // #endregion
69
-
70
- // #region Functions
71
-
72
- function addPopover(element: HTMLElement): void {
73
- if (states.has(element) || element.hasAttribute(ATTRIBUTE_FLOATABLE)) {
74
- return;
75
- }
76
-
77
- const anchor = element.ownerDocument.querySelector(`[popovertarget="${element.id}"]`);
78
-
79
- if (isHTMLOrSVGElement(anchor)) {
80
- states.set(element, getState(anchor, element));
81
- }
82
- }
83
-
84
- function destroyPopover(state: OuiPopoverState): void {
85
- state.floatable.destroy();
86
- state.focusTrap?.destroy();
87
-
88
- for (const listener of state.listeners) {
89
- listener();
90
- }
91
-
92
- state.anchor = undefined as never;
93
- state.content = undefined as never;
94
- state.floatable = undefined as never;
95
- state.focusTrap = undefined as never;
96
- state.listeners = undefined as never;
97
- state.popover = undefined as never;
98
- }
99
-
100
- function getId(element: HTMLElement, value?: string): string {
101
- let {id} = element;
102
-
103
- if (id == null || id.trim().length === 0) {
104
- id = value == null ? `oui_popover_${++index}` : `${value}_toggle`;
105
-
106
- element.id = id;
107
- }
108
-
109
- return id;
110
- }
111
-
112
- /**
113
- * Get the _OuiPopover_ for an element
114
- *
115
- * @param element Element to get _OuiPopover_ for
116
- * @returns _OuiPopover_ instance
117
- */
118
- function getPopover(element: HTMLElement): OuiPopover | undefined {
119
- return states.get(element)?.popover;
120
- }
121
-
122
- function getState(anchor: HTMLElement, content: HTMLElement): OuiPopoverState {
123
- const state: OuiPopoverState = {
124
- anchor,
125
- content,
126
- floatable: createEmbeddedFloatable(anchor, content, options),
127
- focusTrap:
128
- getAria(content, 'modal') === true
129
- ? createFocusTrap(content, {
130
- noescape: true,
131
- })
132
- : undefined,
133
- listeners: [
134
- getOnBeforeToggleListener(content),
135
- on(content, 'toggle', event => {
136
- const expanded = event.newState === 'open';
137
-
138
- if (expanded) {
139
- ignoreFocus = false;
140
-
141
- state.floatable?.update();
142
-
143
- content.focus();
144
- } else {
145
- if (!ignoreFocus) {
146
- anchor?.focus();
147
- }
148
- }
149
-
150
- setAria(anchor, 'expanded', expanded);
151
- setAttribute(content, ATTRIBUTE_OPEN, expanded ? '' : undefined);
152
- }),
153
- ],
154
- popover: undefined as never,
155
- };
156
-
157
- state.popover = new OuiPopover(state);
158
-
159
- return state;
160
- }
161
-
162
- function initialize(state: OuiPopoverState): void {
163
- const id = getId(state.content);
164
-
165
- setAria(state.anchor, {
166
- controls: id,
167
- expanded: 'false',
168
- });
169
-
170
- const label = getAria(state.content, 'label') ?? getAria(state.content, 'labelledby');
171
-
172
- if (label == null) {
173
- setAria(state.content, 'labelledby', getId(state.anchor, id));
174
- }
175
- }
176
-
177
- function onPointerdown(): void {
178
- ignoreFocus = true;
179
- }
180
-
181
- function removePopover(element: HTMLElement): void {
182
- const state = states.get(element);
183
-
184
- if (state == null) {
185
- return;
186
- }
187
-
188
- destroyPopover(state);
189
-
190
- states.delete(element);
191
- }
192
-
193
- // #endregion
194
-
195
- // #region Variables
196
-
197
- const ATTRIBUTE = 'oui-popover';
198
-
199
- const ATTRIBUTE_OPEN = `${ATTRIBUTE}-open`;
200
-
201
- const options: OuiFloatableOptions = {
202
- attribute: `${ATTRIBUTE}-position`,
203
- position: 'below-start',
204
- reusable: false,
205
- };
206
-
207
- const states = new WeakMap<HTMLElement, OuiPopoverState>();
208
-
209
- let ignoreFocus = false;
210
-
211
- let index = 0;
212
-
213
- // #endregion
214
-
215
- // #region Initialization
216
-
217
- on(document, 'pointerdown', onPointerdown, {
218
- capture: true,
219
- });
220
-
221
- attributable(ATTRIBUTE, addPopover, removePopover);
222
-
223
- // #endregion
224
-
225
- // #region Exports
226
-
227
- export {getPopover, type OuiPopover};
228
-
229
- // #endregion
@@ -1,413 +0,0 @@
1
- import {isPlainObject} from '@oscarpalmer/atoms/is';
2
- import type {EventPosition} from '@oscarpalmer/atoms/models';
3
- import {getNumber} from '@oscarpalmer/atoms/number';
4
- import {getAttribute, setAttribute} from '@oscarpalmer/toretto/attribute';
5
- import {dispatch, getEventPosition, on} from '@oscarpalmer/toretto/event';
6
- import {findAncestor} from '@oscarpalmer/toretto/find';
7
- import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
8
- import {setStyles, toggleStyles, type StyleToggler} from '@oscarpalmer/toretto/style';
9
- import supportsTouch from '@oscarpalmer/toretto/touch';
10
- import {attributable} from '../internal/attributable';
11
-
12
- // #region Types
13
-
14
- export type CreateOuiResizableOptions = {
15
- maximumHeight?: number;
16
- maximumWidth?: number;
17
- minimumHeight?: number;
18
- minimumWidth?: number;
19
- };
20
-
21
- export class OuiResizable {
22
- readonly #state: OuiResizableState;
23
-
24
- constructor(state: OuiResizableState) {
25
- this.#state = state;
26
- }
27
-
28
- destroy(): void {
29
- destroyResizable(this.#state);
30
- }
31
-
32
- set(): void {
33
- const [width, height] = getAndSetDimensions(this.#state.element, this.#state.options);
34
-
35
- this.#state.width = width;
36
- this.#state.height = height;
37
- }
38
-
39
- reset(): void {
40
- setStyles(this.#state.element, {
41
- height: '',
42
- width: '',
43
- });
44
- }
45
- }
46
-
47
- type OuiResizableItem = {
48
- instance: OuiResizable;
49
- state: OuiResizableState;
50
- };
51
-
52
- type OuiResizableState = {
53
- element: HTMLElement;
54
- handle: HTMLElement;
55
- height: number;
56
- options: Required<CreateOuiResizableOptions>;
57
- styles: StyleToggler;
58
- width: number;
59
- };
60
-
61
- // #endregion
62
-
63
- // #region Functions
64
-
65
- function addResizable(
66
- element: HTMLElement,
67
- options?: CreateOuiResizableOptions,
68
- ): OuiResizable | undefined {
69
- let item = items.get(element);
70
-
71
- if (item == null) {
72
- const handle = element.querySelector(SELECTOR_HANDLE_SCOPED);
73
-
74
- if (!isHTMLOrSVGElement(handle)) {
75
- return;
76
- }
77
-
78
- const state = getState(element, handle, options);
79
- const instance = new OuiResizable(state);
80
-
81
- item = {
82
- instance,
83
- state,
84
- };
85
-
86
- items.set(element, item);
87
- }
88
-
89
- return item?.instance;
90
- }
91
-
92
- function cancelResize(item?: OuiResizableItem): void {
93
- if (item == null) {
94
- return;
95
- }
96
-
97
- setStyles(item.state.element, {
98
- height: `${item.state.height}px`,
99
- width: `${item.state.width}px`,
100
- });
101
-
102
- resetResizable();
103
-
104
- dispatch(item.state.element, 'oui:resizable:cancel');
105
- }
106
-
107
- /**
108
- * Creates _(or retrieves)_ a _OuiResizable_ instance for an element
109
- *
110
- * @param element Element to make resizable
111
- * @returns _OuiResizable_ instance
112
- */
113
- export function createResizable(
114
- element: HTMLElement,
115
- options?: CreateOuiResizableOptions,
116
- ): OuiResizable {
117
- if (!isHTMLOrSVGElement(element)) {
118
- throw new TypeError(MESSAGE_ELEMENT);
119
- }
120
-
121
- if (!isHTMLOrSVGElement(element.querySelector(SELECTOR_HANDLE_SCOPED))) {
122
- throw new Error(MESSAGE_HANDLE);
123
- }
124
-
125
- return addResizable(element, options ?? {})!;
126
- }
127
-
128
- function destroyResizable(state: OuiResizableState): void {
129
- state.element = undefined as never;
130
- state.handle = undefined as never;
131
- }
132
-
133
- function getAndSetDimensions(
134
- element: HTMLElement,
135
- options: Required<CreateOuiResizableOptions>,
136
- input?: Pick<DOMRect, 'height' | 'width'>,
137
- ): [number, number] {
138
- let {height, width} = input ?? element.getBoundingClientRect();
139
-
140
- if (options.maximumWidth > -1 && width > options.maximumWidth) {
141
- width = options.maximumWidth;
142
- } else if (options.minimumWidth > -1 && width < options.minimumWidth) {
143
- width = options.minimumWidth;
144
- }
145
-
146
- if (options.maximumHeight > -1 && height > options.maximumHeight) {
147
- height = options.maximumHeight;
148
- } else if (options.minimumHeight > -1 && height < options.minimumHeight) {
149
- height = options.minimumHeight;
150
- }
151
-
152
- if (element.checkVisibility()) {
153
- setStyles(element, {
154
- height: `${height}px`,
155
- width: `${width}px`,
156
- });
157
- }
158
-
159
- return [width, height];
160
- }
161
-
162
- function getProperties(
163
- element: HTMLElement,
164
- widthProperty: 'maxWidth' | 'minWidth',
165
- heightProperty: 'maxHeight' | 'minHeight',
166
- ): [string, string] {
167
- const computed = getComputedStyle(element);
168
-
169
- return [computed[widthProperty], computed[heightProperty]];
170
- }
171
-
172
- function getRestrictions(
173
- maximum: string | [unknown, unknown],
174
- minimum: string | [unknown, unknown],
175
- ): Required<CreateOuiResizableOptions> {
176
- const [maximumWidth, maximumHeight] = getXAndY.apply(
177
- null,
178
- typeof maximum === 'string' ? [maximum] : maximum,
179
- );
180
-
181
- const [minimumWidth, minimumHeight] = getXAndY.apply(
182
- null,
183
- typeof minimum === 'string' ? [minimum] : minimum,
184
- );
185
-
186
- if (maximumWidth > -1 && minimumWidth > -1 && maximumWidth <= minimumWidth) {
187
- throw new Error(MESSAGE_WIDTH);
188
- }
189
-
190
- if (maximumHeight > -1 && minimumHeight > -1 && maximumHeight <= minimumHeight) {
191
- throw new Error(MESSAGE_HEIGHT);
192
- }
193
-
194
- return {
195
- maximumHeight,
196
- maximumWidth,
197
- minimumHeight,
198
- minimumWidth,
199
- };
200
- }
201
-
202
- function getState(
203
- element: HTMLElement,
204
- handle: HTMLElement,
205
- input?: CreateOuiResizableOptions,
206
- ): OuiResizableState {
207
- setAttribute(element, RESIZABLE_ATTRIBUTE, '');
208
-
209
- const options = getValidOptions(element, input);
210
-
211
- const [width, height] = getAndSetDimensions(element, options);
212
-
213
- return {
214
- element,
215
- handle,
216
- height,
217
- options,
218
- width,
219
- styles: toggleStyles(element, styles),
220
- };
221
- }
222
-
223
- function getValidOptions(
224
- element: HTMLElement,
225
- input?: CreateOuiResizableOptions,
226
- ): Required<CreateOuiResizableOptions> {
227
- const original = isPlainObject(input) ? input : {};
228
-
229
- return {
230
- ...getRestrictions(
231
- input == null
232
- ? (getAttribute(element, ATTRIBUTE_MAXIMUM) ??
233
- getProperties(element, 'maxWidth', 'maxHeight'))
234
- : [original.maximumWidth, original.maximumHeight],
235
- input == null
236
- ? (getAttribute(element, ATTRIBUTE_MINIMUM) ??
237
- getProperties(element, 'minWidth', 'minHeight'))
238
- : [original.minimumWidth, original.minimumHeight],
239
- ),
240
- };
241
- }
242
-
243
- function getXAndY(first: unknown, second?: unknown): [number, number] {
244
- const [x, y] = typeof first === 'string' && second == null ? first.split(',') : [first, second];
245
-
246
- let xAsNumber = typeof x === 'string' ? Number.parseFloat(x) : getNumber(x);
247
- let yAsNumber = typeof y === 'string' ? Number.parseFloat(y) : getNumber(y);
248
-
249
- if (Number.isNaN(xAsNumber) || xAsNumber <= 0) {
250
- xAsNumber = -1;
251
- }
252
-
253
- if (Number.isNaN(yAsNumber) || yAsNumber <= 0) {
254
- yAsNumber = -1;
255
- }
256
-
257
- return [xAsNumber, yAsNumber];
258
- }
259
-
260
- function onKeydown(event: KeyboardEvent): void {
261
- if (current != null && event.key === 'Escape') {
262
- cancelResize(current);
263
- }
264
- }
265
-
266
- function onPointerdown(event: MouseEvent | TouchEvent): void {
267
- if (
268
- event.altKey ||
269
- event.ctrlKey ||
270
- event.metaKey ||
271
- event.shiftKey ||
272
- (supportsTouch.value
273
- ? event.type === 'mousedown'
274
- : event.type === 'touchstart' || (event as MouseEvent).button !== 0)
275
- ) {
276
- return;
277
- }
278
-
279
- const handle = findAncestor(event, SELECTOR_HANDLE);
280
- const element = handle && findAncestor(handle, SELECTOR);
281
- const stored = element && items.get(element as HTMLElement);
282
- const position = getEventPosition(event);
283
-
284
- if (stored == null || position == null) {
285
- return;
286
- }
287
-
288
- if (supportsTouch.value) {
289
- event.preventDefault();
290
- }
291
-
292
- if (dispatch(element!, 'oui:resizable:begin').defaultPrevented) {
293
- return;
294
- }
295
-
296
- current = stored;
297
- start = position;
298
-
299
- current.state.styles.set();
300
- styleToggler.set();
301
- }
302
-
303
- function onPointermove(event: MouseEvent | TouchEvent): void {
304
- if (current == null) {
305
- return;
306
- }
307
-
308
- const {x, y} = getEventPosition(event) ?? {};
309
-
310
- if (x == null || y == null) {
311
- return;
312
- }
313
-
314
- const width = current.state.width + (x - (start?.x ?? 0));
315
- const height = current.state.height + (y - (start?.y ?? 0));
316
-
317
- getAndSetDimensions(current.state.element, current.state.options, {height, width});
318
-
319
- if (
320
- dispatch(current.state.element, 'oui:resizable:resize', {
321
- detail: {
322
- height,
323
- width,
324
- },
325
- }).defaultPrevented
326
- ) {
327
- cancelResize(current);
328
- }
329
- }
330
-
331
- function onPointerup(): void {
332
- if (current == null || dispatch(current.state.element, 'oui:resizable:end').defaultPrevented) {
333
- cancelResize(current);
334
-
335
- return;
336
- }
337
-
338
- const {height, width} = current.state.element.getBoundingClientRect();
339
-
340
- current.state.height = height;
341
- current.state.width = width;
342
-
343
- resetResizable();
344
- }
345
-
346
- function removeResizable(element: HTMLElement): void {
347
- items.get(element)?.instance.destroy();
348
-
349
- items.delete(element);
350
- }
351
-
352
- function resetResizable(): void {
353
- current?.state.styles.remove();
354
- styleToggler.remove();
355
-
356
- current = undefined;
357
- start = undefined;
358
- }
359
-
360
- // #endregion
361
-
362
- // #region Variables
363
-
364
- export const RESIZABLE_ATTRIBUTE = 'oui-resizable';
365
-
366
- export const RESIZABLE_ATTRIBUTE_HANDLE = `${RESIZABLE_ATTRIBUTE}-handle`;
367
-
368
- const ATTRIBUTE_MAXIMUM = `${RESIZABLE_ATTRIBUTE}-maximum`;
369
-
370
- const ATTRIBUTE_MINIMUM = `${RESIZABLE_ATTRIBUTE}-minimum`;
371
-
372
- const MESSAGE_ELEMENT = 'The element must be an instance of HTMLElement or SVGElement';
373
-
374
- const MESSAGE_HEIGHT = 'The maximum height must be greater than the minimum height';
375
-
376
- const MESSAGE_HANDLE = `The element must contain a child with the attribute "${RESIZABLE_ATTRIBUTE_HANDLE}"`;
377
-
378
- const MESSAGE_WIDTH = 'The maximum width must be greater than the minimum width';
379
-
380
- const SELECTOR = `[${RESIZABLE_ATTRIBUTE}]`;
381
-
382
- const SELECTOR_HANDLE = `[${RESIZABLE_ATTRIBUTE_HANDLE}]`;
383
-
384
- const SELECTOR_HANDLE_SCOPED = `:scope > ${SELECTOR_HANDLE}`;
385
-
386
- const items = new WeakMap<HTMLElement, OuiResizableItem>();
387
-
388
- const styles = {
389
- touchAction: 'none',
390
- userSelect: 'none',
391
- webkitUserSelect: 'none',
392
- };
393
-
394
- const styleToggler = toggleStyles(document.body, styles);
395
-
396
- let current: OuiResizableItem | undefined;
397
-
398
- let start: EventPosition | undefined;
399
-
400
- // #endregion
401
-
402
- // #region Initialization
403
-
404
- on(document, 'keydown', onKeydown);
405
- on(document, 'mousedown', onPointerdown);
406
- on(document, 'pointermove', onPointermove);
407
- on(document, 'pointerup', onPointerup);
408
- on(document, 'touchcancel', onPointerup);
409
- on(document, 'touchstart', onPointerdown, {passive: false});
410
-
411
- attributable(RESIZABLE_ATTRIBUTE, addResizable, removeResizable);
412
-
413
- // #endregion
@@ -1,5 +0,0 @@
1
- export {
2
- createResizable as createOuiResizable,
3
- type CreateOuiResizableOptions,
4
- type OuiResizable,
5
- } from './resizable.embedded';