@lumx/react 2.2.3-alpha-export-hook1 → 2.2.5

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 (208) hide show
  1. package/esm/_internal/AlertDialog.js +2 -3
  2. package/esm/_internal/AlertDialog.js.map +1 -1
  3. package/esm/_internal/AutocompleteMultiple.js +1 -2
  4. package/esm/_internal/AutocompleteMultiple.js.map +1 -1
  5. package/esm/_internal/Button2.js +1 -1
  6. package/esm/_internal/ButtonGroup.js +4 -0
  7. package/esm/_internal/ButtonGroup.js.map +1 -1
  8. package/esm/_internal/Checkbox2.js +2 -3
  9. package/esm/_internal/Checkbox2.js.map +1 -1
  10. package/esm/_internal/Chip2.js +1 -2
  11. package/esm/_internal/Chip2.js.map +1 -1
  12. package/esm/_internal/ChipGroup.js.map +1 -1
  13. package/esm/_internal/ClickAwayProvider.js +1 -1
  14. package/esm/_internal/ClickAwayProvider.js.map +1 -1
  15. package/esm/_internal/DatePickerField.js +5 -1
  16. package/esm/_internal/DatePickerField.js.map +1 -1
  17. package/esm/_internal/Dialog2.js.map +1 -1
  18. package/esm/_internal/DragHandle.js +1 -2
  19. package/esm/_internal/DragHandle.js.map +1 -1
  20. package/esm/_internal/Dropdown2.js +1 -1
  21. package/esm/_internal/Dropdown2.js.map +1 -1
  22. package/esm/_internal/ExpansionPanel.js +1 -1
  23. package/esm/_internal/Icon2.js +23 -3
  24. package/esm/_internal/Icon2.js.map +1 -1
  25. package/esm/_internal/IconButton.js +5 -1
  26. package/esm/_internal/IconButton.js.map +1 -1
  27. package/esm/_internal/Lightbox2.js +1 -1
  28. package/esm/_internal/Lightbox2.js.map +1 -1
  29. package/esm/_internal/Link2.js +1 -1
  30. package/esm/_internal/LinkPreview.js +1 -1
  31. package/esm/_internal/LinkPreview.js.map +1 -1
  32. package/esm/_internal/List2.js +4 -20
  33. package/esm/_internal/List2.js.map +1 -1
  34. package/esm/_internal/Message2.js +3 -3
  35. package/esm/_internal/Message2.js.map +1 -1
  36. package/esm/_internal/Notification2.js +1 -2
  37. package/esm/_internal/Notification2.js.map +1 -1
  38. package/esm/_internal/Popover2.js.map +1 -1
  39. package/esm/_internal/ProgressTrackerStepPanel.js +1 -2
  40. package/esm/_internal/ProgressTrackerStepPanel.js.map +1 -1
  41. package/esm/_internal/RadioGroup.js +1 -1
  42. package/esm/_internal/SelectMultiple.js +2 -3
  43. package/esm/_internal/SelectMultiple.js.map +1 -1
  44. package/esm/_internal/SideNavigationItem.js +2 -4
  45. package/esm/_internal/SideNavigationItem.js.map +1 -1
  46. package/esm/_internal/Slider2.js +1 -1
  47. package/esm/_internal/Slider2.js.map +1 -1
  48. package/esm/_internal/SlideshowControls.js +3 -101
  49. package/esm/_internal/SlideshowControls.js.map +1 -1
  50. package/esm/_internal/Switch2.js +1 -1
  51. package/esm/_internal/TabPanel.js +1 -1
  52. package/esm/_internal/TabPanel.js.map +1 -1
  53. package/esm/_internal/TableRow.js +2 -4
  54. package/esm/_internal/TableRow.js.map +1 -1
  55. package/esm/_internal/TextField.js +2 -3
  56. package/esm/_internal/TextField.js.map +1 -1
  57. package/esm/_internal/Thumbnail2.js +6 -3
  58. package/esm/_internal/Thumbnail2.js.map +1 -1
  59. package/esm/_internal/Tooltip2.js +145 -12
  60. package/esm/_internal/Tooltip2.js.map +1 -1
  61. package/esm/_internal/alert-dialog.js +4 -5
  62. package/esm/_internal/alert-dialog.js.map +1 -1
  63. package/esm/_internal/autocomplete.js +6 -8
  64. package/esm/_internal/autocomplete.js.map +1 -1
  65. package/esm/_internal/avatar.js +3 -3
  66. package/esm/_internal/badge.js +2 -1
  67. package/esm/_internal/badge.js.map +1 -1
  68. package/esm/_internal/button.js +5 -5
  69. package/esm/_internal/checkbox.js +4 -4
  70. package/esm/_internal/chip.js +2 -2
  71. package/esm/_internal/comment-block.js +3 -3
  72. package/esm/_internal/constants.js.map +1 -1
  73. package/esm/_internal/date-picker.js +5 -6
  74. package/esm/_internal/date-picker.js.map +1 -1
  75. package/esm/_internal/dialog.js +2 -2
  76. package/esm/_internal/divider.js +2 -1
  77. package/esm/_internal/divider.js.map +1 -1
  78. package/esm/_internal/drag-handle.js +3 -3
  79. package/esm/_internal/dropdown.js +3 -4
  80. package/esm/_internal/dropdown.js.map +1 -1
  81. package/esm/_internal/expansion-panel.js +5 -6
  82. package/esm/_internal/expansion-panel.js.map +1 -1
  83. package/esm/_internal/flag.js +3 -2
  84. package/esm/_internal/flag.js.map +1 -1
  85. package/esm/_internal/flex-box.js +2 -1
  86. package/esm/_internal/flex-box.js.map +1 -1
  87. package/esm/_internal/getRootClassName.js +166 -40
  88. package/esm/_internal/getRootClassName.js.map +1 -1
  89. package/esm/_internal/grid.js +2 -1
  90. package/esm/_internal/grid.js.map +1 -1
  91. package/esm/_internal/icon.js +3 -2
  92. package/esm/_internal/icon.js.map +1 -1
  93. package/esm/_internal/image-block.js +3 -3
  94. package/esm/_internal/input-helper.js +2 -1
  95. package/esm/_internal/input-helper.js.map +1 -1
  96. package/esm/_internal/input-label.js +2 -1
  97. package/esm/_internal/input-label.js.map +1 -1
  98. package/esm/_internal/lightbox.js +5 -6
  99. package/esm/_internal/lightbox.js.map +1 -1
  100. package/esm/_internal/link-preview.js +3 -3
  101. package/esm/_internal/link.js +3 -2
  102. package/esm/_internal/link.js.map +1 -1
  103. package/esm/_internal/list.js +3 -3
  104. package/esm/_internal/message.js +3 -3
  105. package/esm/_internal/mosaic.js +3 -3
  106. package/esm/_internal/notification.js +3 -3
  107. package/esm/_internal/popover.js +2 -2
  108. package/esm/_internal/post-block.js +3 -3
  109. package/esm/_internal/progress-tracker.js +4 -4
  110. package/esm/_internal/progress.js +2 -1
  111. package/esm/_internal/progress.js.map +1 -1
  112. package/esm/_internal/radio-button.js +3 -2
  113. package/esm/_internal/radio-button.js.map +1 -1
  114. package/esm/_internal/select.js +6 -8
  115. package/esm/_internal/select.js.map +1 -1
  116. package/esm/_internal/side-navigation.js +5 -7
  117. package/esm/_internal/side-navigation.js.map +1 -1
  118. package/esm/_internal/skeleton.js +2 -1
  119. package/esm/_internal/skeleton.js.map +1 -1
  120. package/esm/_internal/slider.js +3 -2
  121. package/esm/_internal/slider.js.map +1 -1
  122. package/esm/_internal/slideshow.js +6 -8
  123. package/esm/_internal/slideshow.js.map +1 -1
  124. package/esm/_internal/switch.js +3 -2
  125. package/esm/_internal/switch.js.map +1 -1
  126. package/esm/_internal/table.js +3 -4
  127. package/esm/_internal/table.js.map +1 -1
  128. package/esm/_internal/tabs.js +4 -3
  129. package/esm/_internal/tabs.js.map +1 -1
  130. package/esm/_internal/text-field.js +5 -6
  131. package/esm/_internal/text-field.js.map +1 -1
  132. package/esm/_internal/thumbnail.js +3 -3
  133. package/esm/_internal/toolbar.js +2 -1
  134. package/esm/_internal/toolbar.js.map +1 -1
  135. package/esm/_internal/tooltip.js +4 -4
  136. package/esm/_internal/uploader.js +3 -2
  137. package/esm/_internal/uploader.js.map +1 -1
  138. package/esm/_internal/useDelayedVisibility.js.map +1 -1
  139. package/esm/_internal/useDisableBodyScroll.js.map +1 -1
  140. package/esm/_internal/useFocusTrap.js.map +1 -1
  141. package/esm/_internal/useRovingTabIndex.js +1 -1
  142. package/esm/_internal/useRovingTabIndex.js.map +1 -1
  143. package/esm/_internal/user-block.js +3 -3
  144. package/esm/index.js +7 -10
  145. package/esm/index.js.map +1 -1
  146. package/esm/{_internal/index.js → index2.js} +1 -1
  147. package/esm/index2.js.map +1 -0
  148. package/package.json +4 -4
  149. package/src/components/autocomplete/Autocomplete.tsx +1 -1
  150. package/src/components/button/__snapshots__/IconButton.test.tsx.snap +5 -0
  151. package/src/components/chip/Chip.tsx +1 -1
  152. package/src/components/chip/ChipGroup.tsx +1 -1
  153. package/src/components/date-picker/DatePickerField.tsx +2 -2
  154. package/src/components/dialog/Dialog.test.tsx +1 -1
  155. package/src/components/dialog/Dialog.tsx +5 -5
  156. package/src/components/dropdown/Dropdown.tsx +1 -1
  157. package/src/components/icon/Icon.tsx +5 -0
  158. package/src/components/lightbox/Lightbox.tsx +4 -4
  159. package/src/components/link-preview/LinkPreview.tsx +1 -1
  160. package/src/components/link-preview/__snapshots__/LinkPreview.test.tsx.snap +2 -2
  161. package/src/components/list/List.tsx +1 -1
  162. package/src/components/message/Message.tsx +3 -1
  163. package/src/components/mosaic/Mosaic.test.tsx +1 -1
  164. package/src/components/notification/Notification.tsx +1 -1
  165. package/src/components/popover/Popover.tsx +2 -2
  166. package/src/components/progress-tracker/ProgressTracker.tsx +1 -1
  167. package/src/components/select/Select.stories.tsx +1 -1
  168. package/src/components/select/SelectMultiple.stories.tsx +1 -1
  169. package/src/components/select/WithSelectContext.tsx +1 -1
  170. package/src/components/slider/Slider.tsx +1 -1
  171. package/src/components/slideshow/Slideshow.tsx +1 -1
  172. package/src/components/slideshow/useSwipeNavigate.ts +1 -1
  173. package/src/components/tabs/TabList.tsx +4 -4
  174. package/src/components/thumbnail/Thumbnail.tsx +7 -1
  175. package/src/components/tooltip/Tooltip.tsx +4 -7
  176. package/src/components/tooltip/useTooltipOpen.tsx +112 -0
  177. package/src/constants.ts +1 -7
  178. package/src/{_internal/hooks → hooks}/useBooleanState.tsx +0 -0
  179. package/src/{_internal/hooks → hooks}/useCallbackOnEscape.ts +0 -0
  180. package/src/{_internal/hooks → hooks}/useChipGroupNavigation.tsx +0 -0
  181. package/src/{_internal/hooks → hooks}/useClickAway.tsx +0 -0
  182. package/src/{_internal/hooks → hooks}/useDelayedVisibility.tsx +0 -0
  183. package/src/{_internal/hooks → hooks}/useDisableBodyScroll.ts +0 -0
  184. package/src/{_internal/hooks → hooks}/useEventCallback.tsx +0 -0
  185. package/src/{_internal/hooks → hooks}/useFocus.tsx +0 -0
  186. package/src/{_internal/hooks → hooks}/useFocusTrap.ts +0 -0
  187. package/src/{_internal/hooks → hooks}/useInfiniteScroll.tsx +0 -0
  188. package/src/{_internal/hooks → hooks}/useIntersectionObserver.tsx +0 -0
  189. package/src/{_internal/hooks → hooks}/useInterval.tsx +1 -1
  190. package/src/{_internal/hooks → hooks}/useKeyboardListNavigation.tsx +0 -0
  191. package/src/{_internal/hooks → hooks}/useListenFocus.tsx +0 -0
  192. package/src/{_internal/hooks → hooks}/useOnResize.ts +0 -0
  193. package/src/{_internal/hooks → hooks}/useRovingTabIndex.tsx +0 -0
  194. package/src/{_internal/hooks → hooks}/useStopPropagation.ts +0 -0
  195. package/src/utils/ClickAwayProvider/ClickAwayProvider.tsx +1 -1
  196. package/types.d.ts +2 -2
  197. package/esm/_internal/index.js.map +0 -1
  198. package/esm/_internal/mdi.js +0 -22
  199. package/esm/_internal/mdi.js.map +0 -1
  200. package/esm/_internal/onEnterPressed.js +0 -20
  201. package/esm/_internal/onEnterPressed.js.map +0 -1
  202. package/esm/_internal/onEscapePressed.js +0 -20
  203. package/esm/_internal/onEscapePressed.js.map +0 -1
  204. package/esm/hooks/useOpenHoverOrLongPress.js +0 -172
  205. package/esm/hooks/useOpenHoverOrLongPress.js.map +0 -1
  206. package/src/hooks/useOpenHoverOrLongPress.ts +0 -140
  207. package/src/utils/browserDoesNotSupportHover.test.js +0 -24
  208. package/src/utils/browserDoesNotSupportHover.ts +0 -2
@@ -1,20 +0,0 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
-
3
- /**
4
- * Make sure the pressed key is the enter key before calling the callback.
5
- *
6
- * @param handler The handler to call on enter/return press.
7
- * @return The decorated function.
8
- */
9
- function onEnterPressed(handler) {
10
- return function (evt) {
11
- if (evt.key !== 'Enter') {
12
- return;
13
- }
14
-
15
- handler(evt);
16
- };
17
- }
18
-
19
- export { onEnterPressed as o };
20
- //# sourceMappingURL=onEnterPressed.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"onEnterPressed.js","sources":["../../../../lumx-core/src/js/utils/onEnterPressed.ts"],"sourcesContent":["// eslint-disable-next-line import/no-extraneous-dependencies\nimport React from 'react';\nimport { KeyboardEventHandler } from '@lumx/core/js/types';\n\n/**\n * Make sure the pressed key is the enter key before calling the callback.\n *\n * @param handler The handler to call on enter/return press.\n * @return The decorated function.\n */\nexport function onEnterPressed<E extends KeyboardEvent | React.KeyboardEvent>(\n handler: KeyboardEventHandler<E>,\n): KeyboardEventHandler<E> {\n return (evt) => {\n if (evt.key !== 'Enter') {\n return;\n }\n handler(evt);\n };\n}\n"],"names":["onEnterPressed","handler","evt","key"],"mappings":"AAAA;;AAIA;;;;;;AAMO,SAASA,cAAT,CACHC,OADG,EAEoB;AACvB,SAAO,UAACC,GAAD,EAAS;AACZ,QAAIA,GAAG,CAACC,GAAJ,KAAY,OAAhB,EAAyB;AACrB;AACH;;AACDF,IAAAA,OAAO,CAACC,GAAD,CAAP;AACH,GALD;AAMH;;;;"}
@@ -1,20 +0,0 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
-
3
- /**
4
- * Make sure the pressed key is the escape key before calling the callback.
5
- *
6
- * @param handler The handler to call on enter/return press.
7
- * @return The decorated function.
8
- */
9
- function onEscapePressed(handler) {
10
- return function (evt) {
11
- if (evt.key !== 'Escape') {
12
- return;
13
- }
14
-
15
- handler(evt);
16
- };
17
- }
18
-
19
- export { onEscapePressed as o };
20
- //# sourceMappingURL=onEscapePressed.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"onEscapePressed.js","sources":["../../../../lumx-core/src/js/utils/onEscapePressed.ts"],"sourcesContent":["// eslint-disable-next-line import/no-extraneous-dependencies\nimport React from 'react';\nimport { KeyboardEventHandler } from '@lumx/core/js/types';\n\n/**\n * Make sure the pressed key is the escape key before calling the callback.\n *\n * @param handler The handler to call on enter/return press.\n * @return The decorated function.\n */\nexport function onEscapePressed<E extends KeyboardEvent | React.KeyboardEvent>(\n handler: KeyboardEventHandler<E>,\n): KeyboardEventHandler<E> {\n return (evt) => {\n if (evt.key !== 'Escape') {\n return;\n }\n handler(evt);\n };\n}\n"],"names":["onEscapePressed","handler","evt","key"],"mappings":"AAAA;;AAIA;;;;;;AAMO,SAASA,eAAT,CACHC,OADG,EAEoB;AACvB,SAAO,UAACC,GAAD,EAAS;AACZ,QAAIA,GAAG,CAACC,GAAJ,KAAY,QAAhB,EAA0B;AACtB;AACH;;AACDF,IAAAA,OAAO,CAACC,GAAD,CAAP;AACH,GALD;AAMH;;;;"}
@@ -1,172 +0,0 @@
1
- import { d as _slicedToArray } from '../_internal/_rollupPluginBabelHelpers.js';
2
- import { useState, useEffect } from 'react';
3
- import { o as onEscapePressed } from '../_internal/onEscapePressed.js';
4
-
5
- /** Return true if the browser does not support pointer hover */
6
- var browserDoesNotSupportHover = function browserDoesNotSupportHover() {
7
- var _window$matchMedia, _window;
8
-
9
- return !!((_window$matchMedia = (_window = window).matchMedia) === null || _window$matchMedia === void 0 ? void 0 : _window$matchMedia.call(_window, '(hover: none)').matches);
10
- };
11
-
12
- var DEFAULT_CONFIG = {
13
- hover: {
14
- openDelay: 500,
15
- closeDelay: 0
16
- },
17
- longPress: {
18
- openDelay: 250,
19
- closeDelay: 3000
20
- }
21
- };
22
- /**
23
- * Hook controlling an open/close action on hover on device supporting pointer hover
24
- * and on long press on device not supporting pointer hover.
25
- *
26
- * @param anchorElement Anchor element on which the hover or longPress is watched.
27
- * @param config Open/close delay configuration.
28
- * @return true/false boolean.
29
- */
30
-
31
- function useOpenHoverOrLongPress(anchorElement) {
32
- var config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
33
-
34
- var _useState = useState(false),
35
- _useState2 = _slicedToArray(_useState, 2),
36
- isOpen = _useState2[0],
37
- setIsOpen = _useState2[1];
38
-
39
- var activation = browserDoesNotSupportHover() ? 'longPress' : 'hover';
40
- var _DEFAULT_CONFIG$activ = DEFAULT_CONFIG[activation],
41
- defaultOpenDelay = _DEFAULT_CONFIG$activ.openDelay,
42
- defaultCloseDelay = _DEFAULT_CONFIG$activ.closeDelay;
43
-
44
- var _ref = (config === null || config === void 0 ? void 0 : config[activation]) || {},
45
- _ref$openDelay = _ref.openDelay,
46
- openDelay = _ref$openDelay === void 0 ? defaultOpenDelay : _ref$openDelay,
47
- _ref$closeDelay = _ref.closeDelay,
48
- closeDelay = _ref$closeDelay === void 0 ? defaultCloseDelay : _ref$closeDelay;
49
-
50
- useEffect(function () {
51
- if (!anchorElement) {
52
- return undefined;
53
- }
54
-
55
- var timer;
56
- var openStartTime;
57
- var shouldOpen; // Run timer to defer updating the isOpen state.
58
-
59
- var deferUpdate = function deferUpdate(duration) {
60
- if (timer) clearTimeout(timer);
61
- timer = setTimeout(function () {
62
- setIsOpen(!!shouldOpen);
63
- }, duration);
64
- };
65
-
66
- var hasTouch = 'ontouchstart' in window; // Open (or/and cancel closing).
67
-
68
- var open = function open() {
69
- if (shouldOpen && !timer) return;
70
- shouldOpen = true;
71
- openStartTime = Date.now();
72
- deferUpdate(openDelay);
73
- }; // Close or cancel opening
74
-
75
-
76
- var close = function close() {
77
- var overrideDelay = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : closeDelay;
78
- if (!shouldOpen && !timer) return;
79
- shouldOpen = false;
80
- deferUpdate(overrideDelay);
81
- };
82
-
83
- var closeImmediately = function closeImmediately() {
84
- return close(0);
85
- };
86
- /**
87
- * Handle touchend event
88
- * If `touchend` comes before the open delay => cancel open (close immediate).
89
- * Else if `touchend` comes after the open delay => open takes priority, the anchor's default touch end event is prevented.
90
- */
91
-
92
-
93
- var touchEnd = function touchEnd(evt) {
94
- if (!openStartTime) return;
95
-
96
- if (Date.now() - openStartTime >= openDelay) {
97
- // Tooltip take priority, event prevented.
98
- evt.stopPropagation();
99
- evt.preventDefault();
100
- anchorElement.focus(); // Close with delay.
101
-
102
- close();
103
- } else {
104
- // Close immediately.
105
- closeImmediately();
106
- }
107
- };
108
-
109
- var events = []; // Long press activation.
110
-
111
- if (activation === 'longPress') {
112
- events.push([anchorElement, hasTouch ? 'touchstart' : 'mousedown', open], [anchorElement, hasTouch ? 'touchend' : 'mouseup', touchEnd]);
113
- } // Hover activation.
114
-
115
-
116
- if (activation === 'hover') {
117
- events.push([anchorElement, 'mouseenter', open], [anchorElement, 'mouseleave', close], [anchorElement, 'mouseup', closeImmediately]);
118
- } // Events always applied no matter the browser:
119
-
120
-
121
- events.push( // Open on focus.
122
- [anchorElement, 'focusin', open], // Close on lost focus.
123
- [anchorElement, 'focusout', closeImmediately], // Close on ESC keydown
124
- [anchorElement, 'keydown', onEscapePressed(closeImmediately)]); // Attach events
125
-
126
- for (var _i = 0, _events = events; _i < _events.length; _i++) {
127
- var _events$_i = _slicedToArray(_events[_i], 3),
128
- node = _events$_i[0],
129
- eventType = _events$_i[1],
130
- evenHandler = _events$_i[2];
131
-
132
- node.addEventListener(eventType, evenHandler);
133
- }
134
-
135
- return function () {
136
- // Detach events.
137
- var _iteratorNormalCompletion = true;
138
- var _didIteratorError = false;
139
- var _iteratorError = undefined;
140
-
141
- try {
142
- for (var _iterator = events[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
143
- var _step$value = _slicedToArray(_step.value, 3),
144
- node = _step$value[0],
145
- eventType = _step$value[1],
146
- evenHandler = _step$value[2];
147
-
148
- node.removeEventListener(eventType, evenHandler);
149
- }
150
- } catch (err) {
151
- _didIteratorError = true;
152
- _iteratorError = err;
153
- } finally {
154
- try {
155
- if (!_iteratorNormalCompletion && _iterator.return != null) {
156
- _iterator.return();
157
- }
158
- } finally {
159
- if (_didIteratorError) {
160
- throw _iteratorError;
161
- }
162
- }
163
- }
164
-
165
- closeImmediately();
166
- };
167
- }, [activation, anchorElement, closeDelay, openDelay]);
168
- return isOpen;
169
- }
170
-
171
- export { DEFAULT_CONFIG, useOpenHoverOrLongPress };
172
- //# sourceMappingURL=useOpenHoverOrLongPress.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"useOpenHoverOrLongPress.js","sources":["../../../src/utils/browserDoesNotSupportHover.ts","../../../src/hooks/useOpenHoverOrLongPress.ts"],"sourcesContent":["/** Return true if the browser does not support pointer hover */\nexport const browserDoesNotSupportHover = (): boolean => !!window.matchMedia?.('(hover: none)').matches;\n","import { onEscapePressed } from '@lumx/react/utils';\nimport { useEffect, useState } from 'react';\nimport { browserDoesNotSupportHover } from '@lumx/react/utils/browserDoesNotSupportHover';\n\ninterface OpenCloseConfig {\n openDelay: number;\n closeDelay: number;\n}\n\ninterface Config {\n hover: OpenCloseConfig;\n longPress: OpenCloseConfig;\n}\n\nexport const DEFAULT_CONFIG: Config = {\n hover: {\n openDelay: 500,\n closeDelay: 0,\n },\n longPress: {\n openDelay: 250,\n closeDelay: 3000,\n },\n};\n\n/**\n * Hook controlling an open/close action on hover on device supporting pointer hover\n * and on long press on device not supporting pointer hover.\n *\n * @param anchorElement Anchor element on which the hover or longPress is watched.\n * @param config Open/close delay configuration.\n * @return true/false boolean.\n */\nexport function useOpenHoverOrLongPress(\n anchorElement: HTMLElement | null,\n config: { hover?: Partial<OpenCloseConfig>; longPress?: Partial<OpenCloseConfig> } = {},\n): boolean {\n const [isOpen, setIsOpen] = useState(false);\n const activation = browserDoesNotSupportHover() ? 'longPress' : 'hover';\n const { openDelay: defaultOpenDelay, closeDelay: defaultCloseDelay } = DEFAULT_CONFIG[activation];\n const { openDelay = defaultOpenDelay, closeDelay = defaultCloseDelay } = config?.[activation] || {};\n\n useEffect(() => {\n if (!anchorElement) {\n return undefined;\n }\n let timer: number | undefined;\n let openStartTime: number | undefined;\n let shouldOpen: boolean | undefined;\n\n // Run timer to defer updating the isOpen state.\n const deferUpdate = (duration: number) => {\n if (timer) clearTimeout(timer);\n timer = setTimeout(() => {\n setIsOpen(!!shouldOpen);\n }, duration) as any;\n };\n\n const hasTouch = 'ontouchstart' in window;\n\n // Open (or/and cancel closing).\n const open = () => {\n if (shouldOpen && !timer) return;\n shouldOpen = true;\n openStartTime = Date.now();\n deferUpdate(openDelay);\n };\n\n // Close or cancel opening\n const close = (overrideDelay = closeDelay) => {\n if (!shouldOpen && !timer) return;\n shouldOpen = false;\n deferUpdate(overrideDelay);\n };\n const closeImmediately = () => close(0);\n\n /**\n * Handle touchend event\n * If `touchend` comes before the open delay => cancel open (close immediate).\n * Else if `touchend` comes after the open delay => open takes priority, the anchor's default touch end event is prevented.\n */\n const touchEnd = (evt: Event) => {\n if (!openStartTime) return;\n if (Date.now() - openStartTime >= openDelay) {\n // Tooltip take priority, event prevented.\n evt.stopPropagation();\n evt.preventDefault();\n anchorElement.focus();\n // Close with delay.\n close();\n } else {\n // Close immediately.\n closeImmediately();\n }\n };\n\n const events: Array<[Node, Event['type'], any]> = [];\n\n // Long press activation.\n if (activation === 'longPress') {\n events.push(\n [anchorElement, hasTouch ? 'touchstart' : 'mousedown', open],\n [anchorElement, hasTouch ? 'touchend' : 'mouseup', touchEnd],\n );\n }\n\n // Hover activation.\n if (activation === 'hover') {\n events.push(\n [anchorElement, 'mouseenter', open],\n [anchorElement, 'mouseleave', close],\n [anchorElement, 'mouseup', closeImmediately],\n );\n }\n\n // Events always applied no matter the browser:\n events.push(\n // Open on focus.\n [anchorElement, 'focusin', open],\n // Close on lost focus.\n [anchorElement, 'focusout', closeImmediately],\n // Close on ESC keydown\n [anchorElement, 'keydown', onEscapePressed(closeImmediately)],\n );\n\n // Attach events\n for (const [node, eventType, evenHandler] of events) {\n node.addEventListener(eventType, evenHandler);\n }\n return () => {\n // Detach events.\n for (const [node, eventType, evenHandler] of events) {\n node.removeEventListener(eventType, evenHandler);\n }\n closeImmediately();\n };\n }, [activation, anchorElement, closeDelay, openDelay]);\n\n return isOpen;\n}\n"],"names":["browserDoesNotSupportHover","window","matchMedia","matches","DEFAULT_CONFIG","hover","openDelay","closeDelay","longPress","useOpenHoverOrLongPress","anchorElement","config","useState","isOpen","setIsOpen","activation","defaultOpenDelay","defaultCloseDelay","useEffect","undefined","timer","openStartTime","shouldOpen","deferUpdate","duration","clearTimeout","setTimeout","hasTouch","open","Date","now","close","overrideDelay","closeImmediately","touchEnd","evt","stopPropagation","preventDefault","focus","events","push","onEscapePressed","node","eventType","evenHandler","addEventListener","removeEventListener"],"mappings":"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"}
@@ -1,140 +0,0 @@
1
- import { onEscapePressed } from '@lumx/react/utils';
2
- import { useEffect, useState } from 'react';
3
- import { browserDoesNotSupportHover } from '@lumx/react/utils/browserDoesNotSupportHover';
4
-
5
- interface OpenCloseConfig {
6
- openDelay: number;
7
- closeDelay: number;
8
- }
9
-
10
- interface Config {
11
- hover: OpenCloseConfig;
12
- longPress: OpenCloseConfig;
13
- }
14
-
15
- export const DEFAULT_CONFIG: Config = {
16
- hover: {
17
- openDelay: 500,
18
- closeDelay: 0,
19
- },
20
- longPress: {
21
- openDelay: 250,
22
- closeDelay: 3000,
23
- },
24
- };
25
-
26
- /**
27
- * Hook controlling an open/close action on hover on device supporting pointer hover
28
- * and on long press on device not supporting pointer hover.
29
- *
30
- * @param anchorElement Anchor element on which the hover or longPress is watched.
31
- * @param config Open/close delay configuration.
32
- * @return true/false boolean.
33
- */
34
- export function useOpenHoverOrLongPress(
35
- anchorElement: HTMLElement | null,
36
- config: { hover?: Partial<OpenCloseConfig>; longPress?: Partial<OpenCloseConfig> } = {},
37
- ): boolean {
38
- const [isOpen, setIsOpen] = useState(false);
39
- const activation = browserDoesNotSupportHover() ? 'longPress' : 'hover';
40
- const { openDelay: defaultOpenDelay, closeDelay: defaultCloseDelay } = DEFAULT_CONFIG[activation];
41
- const { openDelay = defaultOpenDelay, closeDelay = defaultCloseDelay } = config?.[activation] || {};
42
-
43
- useEffect(() => {
44
- if (!anchorElement) {
45
- return undefined;
46
- }
47
- let timer: number | undefined;
48
- let openStartTime: number | undefined;
49
- let shouldOpen: boolean | undefined;
50
-
51
- // Run timer to defer updating the isOpen state.
52
- const deferUpdate = (duration: number) => {
53
- if (timer) clearTimeout(timer);
54
- timer = setTimeout(() => {
55
- setIsOpen(!!shouldOpen);
56
- }, duration) as any;
57
- };
58
-
59
- const hasTouch = 'ontouchstart' in window;
60
-
61
- // Open (or/and cancel closing).
62
- const open = () => {
63
- if (shouldOpen && !timer) return;
64
- shouldOpen = true;
65
- openStartTime = Date.now();
66
- deferUpdate(openDelay);
67
- };
68
-
69
- // Close or cancel opening
70
- const close = (overrideDelay = closeDelay) => {
71
- if (!shouldOpen && !timer) return;
72
- shouldOpen = false;
73
- deferUpdate(overrideDelay);
74
- };
75
- const closeImmediately = () => close(0);
76
-
77
- /**
78
- * Handle touchend event
79
- * If `touchend` comes before the open delay => cancel open (close immediate).
80
- * Else if `touchend` comes after the open delay => open takes priority, the anchor's default touch end event is prevented.
81
- */
82
- const touchEnd = (evt: Event) => {
83
- if (!openStartTime) return;
84
- if (Date.now() - openStartTime >= openDelay) {
85
- // Tooltip take priority, event prevented.
86
- evt.stopPropagation();
87
- evt.preventDefault();
88
- anchorElement.focus();
89
- // Close with delay.
90
- close();
91
- } else {
92
- // Close immediately.
93
- closeImmediately();
94
- }
95
- };
96
-
97
- const events: Array<[Node, Event['type'], any]> = [];
98
-
99
- // Long press activation.
100
- if (activation === 'longPress') {
101
- events.push(
102
- [anchorElement, hasTouch ? 'touchstart' : 'mousedown', open],
103
- [anchorElement, hasTouch ? 'touchend' : 'mouseup', touchEnd],
104
- );
105
- }
106
-
107
- // Hover activation.
108
- if (activation === 'hover') {
109
- events.push(
110
- [anchorElement, 'mouseenter', open],
111
- [anchorElement, 'mouseleave', close],
112
- [anchorElement, 'mouseup', closeImmediately],
113
- );
114
- }
115
-
116
- // Events always applied no matter the browser:
117
- events.push(
118
- // Open on focus.
119
- [anchorElement, 'focusin', open],
120
- // Close on lost focus.
121
- [anchorElement, 'focusout', closeImmediately],
122
- // Close on ESC keydown
123
- [anchorElement, 'keydown', onEscapePressed(closeImmediately)],
124
- );
125
-
126
- // Attach events
127
- for (const [node, eventType, evenHandler] of events) {
128
- node.addEventListener(eventType, evenHandler);
129
- }
130
- return () => {
131
- // Detach events.
132
- for (const [node, eventType, evenHandler] of events) {
133
- node.removeEventListener(eventType, evenHandler);
134
- }
135
- closeImmediately();
136
- };
137
- }, [activation, anchorElement, closeDelay, openDelay]);
138
-
139
- return isOpen;
140
- }
@@ -1,24 +0,0 @@
1
- import { browserDoesNotSupportHover } from '@lumx/react/utils/browserDoesNotSupportHover';
2
-
3
- const originalMatchMedia = global.matchMedia;
4
-
5
- describe('browserDoesNotSupportHover', () => {
6
- afterAll(() => {
7
- global.matchMedia = originalMatchMedia;
8
- });
9
-
10
- it('should return `false` on browsers that do not support matchMedia', () => {
11
- global.matchMedia = undefined;
12
- expect(browserDoesNotSupportHover()).toBe(false);
13
- });
14
-
15
- it('should return `false` on browsers that support matchMedia and does support hover', () => {
16
- global.matchMedia = () => ({ matches: false });
17
- expect(browserDoesNotSupportHover()).toBe(false);
18
- });
19
-
20
- it('should return `true` on browsers that support matchMedia and does not support hover', () => {
21
- global.matchMedia = () => ({ matches: true });
22
- expect(browserDoesNotSupportHover()).toBe(true);
23
- });
24
- });
@@ -1,2 +0,0 @@
1
- /** Return true if the browser does not support pointer hover */
2
- export const browserDoesNotSupportHover = (): boolean => !!window.matchMedia?.('(hover: none)').matches;