@stack-spot/portal-components 2.27.1 → 2.27.2

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 (246) hide show
  1. package/CHANGELOG.md +635 -628
  2. package/dist/components/AnimatedHeight.d.ts +1 -1
  3. package/dist/components/AnimatedHeight.js +26 -26
  4. package/dist/components/AsyncContent.d.ts +1 -1
  5. package/dist/components/AsyncContent.js +1 -1
  6. package/dist/components/BannerWarning.d.ts +1 -1
  7. package/dist/components/BannerWarning.js +1 -1
  8. package/dist/components/Breadcrumb/index.d.ts +2 -2
  9. package/dist/components/Breadcrumb/index.js +1 -1
  10. package/dist/components/Breadcrumb/styled.js +31 -31
  11. package/dist/components/ButtonLoading.d.ts +1 -1
  12. package/dist/components/ButtonLoading.js +1 -1
  13. package/dist/components/ChatBot.d.ts +1 -1
  14. package/dist/components/ChatBot.js +1 -1
  15. package/dist/components/ContentValidateFilter.d.ts +1 -1
  16. package/dist/components/ContentValidateFilter.js +1 -1
  17. package/dist/components/FadingOverflow.d.ts +1 -1
  18. package/dist/components/FadingOverflow.js +69 -69
  19. package/dist/components/FileTreeView/More.d.ts +1 -1
  20. package/dist/components/FileTreeView/More.js +1 -1
  21. package/dist/components/FileTreeView/index.d.ts +1 -1
  22. package/dist/components/FileTreeView/index.js +1 -1
  23. package/dist/components/InfiniteScroll.d.ts +1 -1
  24. package/dist/components/InfiniteScroll.js +1 -1
  25. package/dist/components/InfoMaintenanceBanner.d.ts +1 -1
  26. package/dist/components/InfoMaintenanceBanner.js +2 -2
  27. package/dist/components/LazyMarkdown/BlockquoteMd.d.ts +1 -1
  28. package/dist/components/LazyMarkdown/BlockquoteMd.js +1 -1
  29. package/dist/components/LazyMarkdown/CodeViewer.d.ts +1 -1
  30. package/dist/components/LazyMarkdown/CodeViewer.js +76 -76
  31. package/dist/components/LazyMarkdown/Markdown.d.ts +1 -1
  32. package/dist/components/LazyMarkdown/Markdown.js +1 -1
  33. package/dist/components/LazyMarkdown/MarkdownButton.d.ts +1 -1
  34. package/dist/components/LazyMarkdown/MarkdownButton.js +1 -1
  35. package/dist/components/LazyMarkdown/Video.d.ts +1 -1
  36. package/dist/components/LazyMarkdown/Video.js +1 -1
  37. package/dist/components/LazyMarkdown/index.d.ts +1 -1
  38. package/dist/components/LazyMarkdown/index.js +1 -1
  39. package/dist/components/Placeholder.d.ts +7 -3
  40. package/dist/components/Placeholder.d.ts.map +1 -1
  41. package/dist/components/Placeholder.js +3 -3
  42. package/dist/components/Placeholder.js.map +1 -1
  43. package/dist/components/ScrollView.js +16 -16
  44. package/dist/components/Select/BadgeItem.d.ts +1 -1
  45. package/dist/components/Select/BadgeItem.js +1 -1
  46. package/dist/components/Select/ClearInput.d.ts +1 -1
  47. package/dist/components/Select/ClearInput.js +1 -1
  48. package/dist/components/Select/CloseItem.d.ts +1 -1
  49. package/dist/components/Select/CloseItem.js +1 -1
  50. package/dist/components/Select/CreatableSelect.js +1 -1
  51. package/dist/components/Select/CustomMenu.d.ts +1 -1
  52. package/dist/components/Select/CustomMenu.js +1 -1
  53. package/dist/components/Select/LabelItem.d.ts +1 -1
  54. package/dist/components/Select/LabelItem.js +1 -1
  55. package/dist/components/Select/MultiValue.d.ts +1 -1
  56. package/dist/components/Select/MultiValue.js +1 -1
  57. package/dist/components/Select/SelectInfiniteScroll.d.ts +1 -1
  58. package/dist/components/Select/SelectInfiniteScroll.js +1 -1
  59. package/dist/components/Select/SelectSearch.d.ts +1 -1
  60. package/dist/components/Select/SelectSearch.js +1 -1
  61. package/dist/components/SelectionList.d.ts +1 -1
  62. package/dist/components/SelectionList.js +61 -61
  63. package/dist/components/StatusCircle.d.ts +1 -1
  64. package/dist/components/StatusCircle.js +6 -6
  65. package/dist/components/Stepper/Navigation.js +4 -4
  66. package/dist/components/Stepper/Step.js +3 -3
  67. package/dist/components/Stepper/Stepper.js +6 -6
  68. package/dist/components/Stepper/headers.js +22 -22
  69. package/dist/components/Table/HeaderItem.js +1 -1
  70. package/dist/components/Table/SettingsVerticalMenu.d.ts +1 -1
  71. package/dist/components/Table/SettingsVerticalMenu.js +1 -1
  72. package/dist/components/Table/StyledLinkTable.d.ts +1 -1
  73. package/dist/components/Table/StyledLinkTable.js +5 -5
  74. package/dist/components/Table/TableData.d.ts +1 -1
  75. package/dist/components/Table/TableData.js +25 -25
  76. package/dist/components/TimelineSection.d.ts +1 -1
  77. package/dist/components/TimelineSection.js +14 -14
  78. package/dist/components/error/ErrorFeedback.d.ts +1 -1
  79. package/dist/components/error/ErrorFeedback.js +35 -35
  80. package/dist/components/error/NotFound.d.ts +1 -1
  81. package/dist/components/error/NotFound.js +1 -1
  82. package/dist/components/error/UnderMaintenance.d.ts +1 -1
  83. package/dist/components/error/UnderMaintenance.js +1 -1
  84. package/dist/components/form/Form/Form.d.ts +1 -1
  85. package/dist/components/form/Form/Form.js +1 -1
  86. package/dist/components/form/Form/FormGroup.d.ts +2 -2
  87. package/dist/components/form/Form/FormGroup.js +1 -1
  88. package/dist/components/form/SearchInput.d.ts +1 -1
  89. package/dist/components/form/SearchInput.js +1 -1
  90. package/dist/components/form/Select/CustomSelect.d.ts +1 -1
  91. package/dist/components/form/Select/CustomSelect.js +1 -1
  92. package/dist/components/form/Select/DetailedSelect.d.ts +1 -1
  93. package/dist/components/form/Select/DetailedSelect.js +1 -1
  94. package/dist/components/form/Select/Select.d.ts +1 -1
  95. package/dist/components/form/Select/Select.js +1 -1
  96. package/dist/components/form/Select/styled.js +161 -161
  97. package/dist/components/form/Select/utils.js +1 -1
  98. package/dist/components/notification/NotificationComponent.d.ts +1 -1
  99. package/dist/components/notification/NotificationComponent.js +54 -54
  100. package/dist/components/notification/NotificationItem.d.ts +1 -1
  101. package/dist/components/notification/NotificationItem.d.ts.map +1 -1
  102. package/dist/components/notification/NotificationItem.js +8 -2
  103. package/dist/components/notification/NotificationItem.js.map +1 -1
  104. package/dist/components/notification/NotificationList.d.ts +1 -1
  105. package/dist/components/notification/NotificationList.d.ts.map +1 -1
  106. package/dist/components/notification/NotificationList.js +44 -44
  107. package/dist/components/notification/NotificationList.js.map +1 -1
  108. package/dist/components/notification/NotificationPlaceholder.d.ts +1 -1
  109. package/dist/components/notification/NotificationPlaceholder.d.ts.map +1 -1
  110. package/dist/components/notification/NotificationPlaceholder.js +2 -2
  111. package/dist/components/notification/NotificationPlaceholder.js.map +1 -1
  112. package/dist/containers/NotificationsPage.d.ts +1 -1
  113. package/dist/containers/NotificationsPage.js +10 -10
  114. package/dist/context/anchor.d.ts +1 -1
  115. package/dist/context/anchor.js +1 -1
  116. package/dist/context/loading.d.ts +1 -1
  117. package/dist/context/loading.js +1 -1
  118. package/dist/context/notification/context.d.ts +1 -1
  119. package/dist/context/notification/context.js +1 -1
  120. package/dist/hooks/date.js +1 -1
  121. package/dist/hooks/service-now.js +28 -28
  122. package/dist/svg/AI.d.ts +1 -1
  123. package/dist/svg/AI.js +1 -1
  124. package/dist/svg/CS.d.ts +1 -1
  125. package/dist/svg/CS.js +1 -1
  126. package/dist/svg/EDP.d.ts +1 -1
  127. package/dist/svg/EDP.js +1 -1
  128. package/dist/svg/Forbidden.d.ts +1 -1
  129. package/dist/svg/Forbidden.js +1 -1
  130. package/dist/svg/GenericPlaceholder.d.ts +4 -2
  131. package/dist/svg/GenericPlaceholder.d.ts.map +1 -1
  132. package/dist/svg/GenericPlaceholder.js +2 -2
  133. package/dist/svg/GenericPlaceholder.js.map +1 -1
  134. package/dist/svg/HUB.d.ts +1 -1
  135. package/dist/svg/HUB.js +1 -1
  136. package/dist/svg/Logo.d.ts +1 -1
  137. package/dist/svg/Logo.js +1 -1
  138. package/dist/svg/MiniLogo.d.ts +1 -1
  139. package/dist/svg/MiniLogo.js +1 -1
  140. package/dist/svg/NotFound.d.ts +1 -1
  141. package/dist/svg/NotFound.js +1 -1
  142. package/dist/svg/ServerError.d.ts +1 -1
  143. package/dist/svg/ServerError.js +1 -1
  144. package/dist/svg/Unauthenticated.d.ts +1 -1
  145. package/dist/svg/Unauthenticated.js +1 -1
  146. package/package.json +80 -80
  147. package/readme.md +66 -66
  148. package/src/components/AnimatedHeight.tsx +174 -174
  149. package/src/components/AsyncContent.tsx +78 -78
  150. package/src/components/BannerWarning.tsx +91 -91
  151. package/src/components/Breadcrumb/index.tsx +76 -76
  152. package/src/components/Breadcrumb/styled.ts +37 -37
  153. package/src/components/ButtonLoading.tsx +29 -29
  154. package/src/components/ChatBot.tsx +82 -82
  155. package/src/components/ContentValidateFilter.tsx +15 -15
  156. package/src/components/FadingOverflow.tsx +265 -265
  157. package/src/components/FileTreeView/More.tsx +114 -114
  158. package/src/components/FileTreeView/index.tsx +186 -186
  159. package/src/components/InfiniteScroll.tsx +24 -24
  160. package/src/components/InfoMaintenanceBanner.tsx +29 -29
  161. package/src/components/LazyMarkdown/BlockquoteMd.tsx +107 -107
  162. package/src/components/LazyMarkdown/CodeViewer.tsx +161 -161
  163. package/src/components/LazyMarkdown/Markdown.tsx +122 -122
  164. package/src/components/LazyMarkdown/MarkdownButton.tsx +24 -24
  165. package/src/components/LazyMarkdown/Video.tsx +13 -13
  166. package/src/components/LazyMarkdown/index.tsx +21 -21
  167. package/src/components/Placeholder.tsx +123 -118
  168. package/src/components/ScrollView.tsx +57 -57
  169. package/src/components/Select/BadgeItem.tsx +58 -58
  170. package/src/components/Select/ClearInput.tsx +24 -24
  171. package/src/components/Select/CloseItem.tsx +38 -38
  172. package/src/components/Select/CreatableSelect.tsx +155 -155
  173. package/src/components/Select/CustomMenu.tsx +16 -16
  174. package/src/components/Select/LabelItem.tsx +8 -8
  175. package/src/components/Select/MultiValue.tsx +49 -49
  176. package/src/components/Select/SelectInfiniteScroll.tsx +82 -82
  177. package/src/components/Select/SelectSearch.tsx +195 -195
  178. package/src/components/Select/index.tsx +7 -7
  179. package/src/components/Select/types.ts +8 -8
  180. package/src/components/SelectionList.tsx +427 -427
  181. package/src/components/StatusCircle.tsx +67 -67
  182. package/src/components/Stepper/Navigation.tsx +97 -97
  183. package/src/components/Stepper/Step.tsx +30 -30
  184. package/src/components/Stepper/Stepper.tsx +113 -113
  185. package/src/components/Stepper/headers.tsx +64 -64
  186. package/src/components/Stepper/index.ts +3 -3
  187. package/src/components/Table/HeaderItem.tsx +52 -52
  188. package/src/components/Table/SettingsVerticalMenu.tsx +50 -50
  189. package/src/components/Table/StyledLinkTable.tsx +22 -22
  190. package/src/components/Table/TableData.tsx +251 -251
  191. package/src/components/Table/index.tsx +2 -2
  192. package/src/components/TimelineSection.tsx +66 -66
  193. package/src/components/error/ErrorFeedback.tsx +217 -217
  194. package/src/components/error/NotFound.tsx +24 -24
  195. package/src/components/error/UnderMaintenance.tsx +30 -30
  196. package/src/components/error/index.ts +4 -4
  197. package/src/components/form/Form/Form.tsx +101 -101
  198. package/src/components/form/Form/FormGroup.tsx +221 -221
  199. package/src/components/form/Form/index.ts +2 -2
  200. package/src/components/form/SearchInput.tsx +69 -69
  201. package/src/components/form/Select/CustomSelect.tsx +232 -232
  202. package/src/components/form/Select/DetailedSelect.tsx +85 -85
  203. package/src/components/form/Select/Select.tsx +67 -67
  204. package/src/components/form/Select/index.ts +4 -4
  205. package/src/components/form/Select/styled.ts +165 -165
  206. package/src/components/form/Select/types.ts +112 -112
  207. package/src/components/form/Select/utils.tsx +28 -28
  208. package/src/components/notification/NotificationComponent.tsx +340 -340
  209. package/src/components/notification/NotificationItem.tsx +345 -337
  210. package/src/components/notification/NotificationList.tsx +179 -178
  211. package/src/components/notification/NotificationPlaceholder.tsx +44 -43
  212. package/src/components/notification/types.ts +72 -72
  213. package/src/containers/NotificationsPage.tsx +119 -119
  214. package/src/context/anchor.tsx +37 -37
  215. package/src/context/loading.tsx +36 -36
  216. package/src/context/notification/LazyNotificationList.ts +103 -103
  217. package/src/context/notification/NotificationController.ts +104 -104
  218. package/src/context/notification/context.tsx +23 -23
  219. package/src/context/notification/hooks.ts +98 -98
  220. package/src/context/notification/types.ts +66 -66
  221. package/src/hooks/date.ts +31 -31
  222. package/src/hooks/keyboard.tsx +128 -128
  223. package/src/hooks/manual-render.tsx +10 -10
  224. package/src/hooks/service-now.tsx +233 -233
  225. package/src/hooks/text.tsx +30 -30
  226. package/src/hooks/title.tsx +28 -28
  227. package/src/hooks/use-effect-once.tsx +43 -43
  228. package/src/index.ts +19 -19
  229. package/src/notifications.ts +11 -11
  230. package/src/svg/AI.tsx +41 -41
  231. package/src/svg/CS.tsx +48 -48
  232. package/src/svg/EDP.tsx +31 -31
  233. package/src/svg/Forbidden.tsx +22 -22
  234. package/src/svg/GenericPlaceholder.tsx +20 -20
  235. package/src/svg/HUB.tsx +48 -48
  236. package/src/svg/Logo.tsx +16 -16
  237. package/src/svg/MiniLogo.tsx +12 -12
  238. package/src/svg/NotFound.tsx +16 -16
  239. package/src/svg/ServerError.tsx +33 -33
  240. package/src/svg/Unauthenticated.tsx +16 -16
  241. package/src/svg/index.ts +11 -11
  242. package/src/utils/accessibility.ts +135 -135
  243. package/src/utils/cookie.ts +73 -73
  244. package/src/utils/promise.ts +5 -5
  245. package/src/utils/read-file.ts +16 -16
  246. package/tsconfig.json +10 -10
@@ -1,128 +1,128 @@
1
- import { useCallback, useEffect, useRef } from 'react'
2
-
3
- interface Options<T extends HTMLElement = HTMLDivElement> {
4
- /**
5
- * A query selector that returns every html element that must be navigable through the keyboard.
6
- */
7
- querySelectors: string,
8
- /**
9
- * Function to call when ESC is pressed. or when TAB is pressed at the last item in the list of items returned by the query selector.
10
- */
11
- onPressEscape?: () => void,
12
- /**
13
- * Function to call when TAB is pressed at the last item in the list of items returned by the query selector. Will be the same as
14
- * onPressEscape if not specified.
15
- *
16
- * Attention: has no effect if `disableTabBehavior` is true.
17
- */
18
- onPressLastTab?: () => void,
19
- /**
20
- * Pass this function if you want any behavior when the user presses the arrow left.
21
- */
22
- onPressArrowLeft?: () => void,
23
- /**
24
- * Pass this function if you want any behavior when the user presses the arrow right.
25
- */
26
- onPressArrowRight?: () => void,
27
- /**
28
- * Disables any alteration to the tab key.
29
- * @default false
30
- */
31
- disableTabBehavior?: boolean,
32
- /**
33
- * If you already have a ref to the element you want to attach the events to, you can pass it in this prop.
34
- *
35
- * If you pass a ref. The events won't be attached to the document, instead, they will be attached to the element referred by the ref.
36
- */
37
- ref?: React.RefObject<T>,
38
- }
39
-
40
- /**
41
- * Creates listeners for controlling a Menu UI through the keyboard.
42
- * - Arrow down: next element in the iterator returned by the query selectors. First element, if the current element is the last.
43
- * - Arrow up: previous element in the iterator returned by the query selectors. Last element, if the current element is the first.
44
- * - Tab: same as Arrow down, but has a different behavior if the element is the last (see onPressLastTab).
45
- * - Esc: determined by onPressEscape.
46
- * @param props {@link Options}.
47
- * @returns an object with the element controlled by the keyboard (useRef); a function to attach the keyboard events and a function to
48
- * detach the keyboard events.
49
- */
50
- export function useKeyboardControls<T extends HTMLElement = HTMLDivElement>(
51
- /**
52
- * Options for the keyboard controls.
53
- */
54
- {
55
- querySelectors, onPressEscape, onPressLastTab = onPressEscape, onPressArrowLeft, onPressArrowRight, disableTabBehavior, ref,
56
- }: Options<T>,
57
- /**
58
- * Calls `attachKeyboardListeners` (mount) and `detachKeyboardListeners` (unmount) whenever the deps passed as parameter changes.
59
- *
60
- * If deps are undefined, this component doesn't automatically add these listeners and you have to use the functions returned in the
61
- * result.
62
- */
63
- deps?: any[],
64
- ) {
65
- const localRef = useRef<T>(null)
66
- const keyboardControlledElement = ref ?? localRef
67
- const listeners = useRef<Pick<Options, 'onPressEscape' | 'onPressLastTab'>>({})
68
- listeners.current = { onPressEscape, onPressLastTab }
69
-
70
- const keyboardControls = useCallback((event: Event) => {
71
- const eventKey = (event as KeyboardEvent).key
72
- const target = event?.target as HTMLElement | null
73
-
74
- function getSelectableAnchors() {
75
- return keyboardControlledElement.current?.querySelectorAll(querySelectors) ?? []
76
- }
77
-
78
- function handleArrows(key = eventKey) {
79
- const anchors = getSelectableAnchors()
80
- let i = 0
81
- while (i < anchors.length && document.activeElement !== anchors[i]) i++
82
- const next: any = key === 'ArrowDown' ? (anchors[i + 1] ?? anchors[0]) : (anchors[i - 1] ?? anchors[anchors.length - 1])
83
- next?.focus?.()
84
- }
85
-
86
- const handlers: Record<string, (() => void) | undefined> = {
87
- Escape: () => {
88
- listeners.current.onPressEscape?.()
89
- event.stopPropagation()
90
- event.preventDefault()
91
- },
92
- Enter: () => {
93
- target?.click()
94
- },
95
- Tab: () => {
96
- if (disableTabBehavior) return
97
- const anchors = getSelectableAnchors()
98
- if (document.activeElement === anchors[anchors.length - 1]) listeners.current.onPressLastTab?.()
99
- else handleArrows('ArrowDown')
100
- event.preventDefault()
101
- },
102
- ArrowUp: handleArrows,
103
- ArrowDown: handleArrows,
104
- ArrowLeft: onPressArrowLeft,
105
- ArrowRight: onPressArrowRight,
106
- }
107
-
108
- handlers[eventKey]?.()
109
- }, [])
110
-
111
- const attachKeyboardListeners = useCallback(() => {
112
- const element = ref?.current ?? document
113
- element.addEventListener('keydown', keyboardControls)
114
- }, [])
115
-
116
- const detachKeyboardListeners = useCallback(() => {
117
- const element = ref?.current ?? document
118
- element.removeEventListener('keydown', keyboardControls)
119
- }, [])
120
-
121
- useEffect(() => {
122
- if (!deps) return
123
- attachKeyboardListeners()
124
- return detachKeyboardListeners
125
- }, deps)
126
-
127
- return { keyboardControlledElement, attachKeyboardListeners, detachKeyboardListeners }
128
- }
1
+ import { useCallback, useEffect, useRef } from 'react'
2
+
3
+ interface Options<T extends HTMLElement = HTMLDivElement> {
4
+ /**
5
+ * A query selector that returns every html element that must be navigable through the keyboard.
6
+ */
7
+ querySelectors: string,
8
+ /**
9
+ * Function to call when ESC is pressed. or when TAB is pressed at the last item in the list of items returned by the query selector.
10
+ */
11
+ onPressEscape?: () => void,
12
+ /**
13
+ * Function to call when TAB is pressed at the last item in the list of items returned by the query selector. Will be the same as
14
+ * onPressEscape if not specified.
15
+ *
16
+ * Attention: has no effect if `disableTabBehavior` is true.
17
+ */
18
+ onPressLastTab?: () => void,
19
+ /**
20
+ * Pass this function if you want any behavior when the user presses the arrow left.
21
+ */
22
+ onPressArrowLeft?: () => void,
23
+ /**
24
+ * Pass this function if you want any behavior when the user presses the arrow right.
25
+ */
26
+ onPressArrowRight?: () => void,
27
+ /**
28
+ * Disables any alteration to the tab key.
29
+ * @default false
30
+ */
31
+ disableTabBehavior?: boolean,
32
+ /**
33
+ * If you already have a ref to the element you want to attach the events to, you can pass it in this prop.
34
+ *
35
+ * If you pass a ref. The events won't be attached to the document, instead, they will be attached to the element referred by the ref.
36
+ */
37
+ ref?: React.RefObject<T>,
38
+ }
39
+
40
+ /**
41
+ * Creates listeners for controlling a Menu UI through the keyboard.
42
+ * - Arrow down: next element in the iterator returned by the query selectors. First element, if the current element is the last.
43
+ * - Arrow up: previous element in the iterator returned by the query selectors. Last element, if the current element is the first.
44
+ * - Tab: same as Arrow down, but has a different behavior if the element is the last (see onPressLastTab).
45
+ * - Esc: determined by onPressEscape.
46
+ * @param props {@link Options}.
47
+ * @returns an object with the element controlled by the keyboard (useRef); a function to attach the keyboard events and a function to
48
+ * detach the keyboard events.
49
+ */
50
+ export function useKeyboardControls<T extends HTMLElement = HTMLDivElement>(
51
+ /**
52
+ * Options for the keyboard controls.
53
+ */
54
+ {
55
+ querySelectors, onPressEscape, onPressLastTab = onPressEscape, onPressArrowLeft, onPressArrowRight, disableTabBehavior, ref,
56
+ }: Options<T>,
57
+ /**
58
+ * Calls `attachKeyboardListeners` (mount) and `detachKeyboardListeners` (unmount) whenever the deps passed as parameter changes.
59
+ *
60
+ * If deps are undefined, this component doesn't automatically add these listeners and you have to use the functions returned in the
61
+ * result.
62
+ */
63
+ deps?: any[],
64
+ ) {
65
+ const localRef = useRef<T>(null)
66
+ const keyboardControlledElement = ref ?? localRef
67
+ const listeners = useRef<Pick<Options, 'onPressEscape' | 'onPressLastTab'>>({})
68
+ listeners.current = { onPressEscape, onPressLastTab }
69
+
70
+ const keyboardControls = useCallback((event: Event) => {
71
+ const eventKey = (event as KeyboardEvent).key
72
+ const target = event?.target as HTMLElement | null
73
+
74
+ function getSelectableAnchors() {
75
+ return keyboardControlledElement.current?.querySelectorAll(querySelectors) ?? []
76
+ }
77
+
78
+ function handleArrows(key = eventKey) {
79
+ const anchors = getSelectableAnchors()
80
+ let i = 0
81
+ while (i < anchors.length && document.activeElement !== anchors[i]) i++
82
+ const next: any = key === 'ArrowDown' ? (anchors[i + 1] ?? anchors[0]) : (anchors[i - 1] ?? anchors[anchors.length - 1])
83
+ next?.focus?.()
84
+ }
85
+
86
+ const handlers: Record<string, (() => void) | undefined> = {
87
+ Escape: () => {
88
+ listeners.current.onPressEscape?.()
89
+ event.stopPropagation()
90
+ event.preventDefault()
91
+ },
92
+ Enter: () => {
93
+ target?.click()
94
+ },
95
+ Tab: () => {
96
+ if (disableTabBehavior) return
97
+ const anchors = getSelectableAnchors()
98
+ if (document.activeElement === anchors[anchors.length - 1]) listeners.current.onPressLastTab?.()
99
+ else handleArrows('ArrowDown')
100
+ event.preventDefault()
101
+ },
102
+ ArrowUp: handleArrows,
103
+ ArrowDown: handleArrows,
104
+ ArrowLeft: onPressArrowLeft,
105
+ ArrowRight: onPressArrowRight,
106
+ }
107
+
108
+ handlers[eventKey]?.()
109
+ }, [])
110
+
111
+ const attachKeyboardListeners = useCallback(() => {
112
+ const element = ref?.current ?? document
113
+ element.addEventListener('keydown', keyboardControls)
114
+ }, [])
115
+
116
+ const detachKeyboardListeners = useCallback(() => {
117
+ const element = ref?.current ?? document
118
+ element.removeEventListener('keydown', keyboardControls)
119
+ }, [])
120
+
121
+ useEffect(() => {
122
+ if (!deps) return
123
+ attachKeyboardListeners()
124
+ return detachKeyboardListeners
125
+ }, deps)
126
+
127
+ return { keyboardControlledElement, attachKeyboardListeners, detachKeyboardListeners }
128
+ }
@@ -1,10 +1,10 @@
1
- import { useCallback, useState } from 'react'
2
-
3
- /**
4
- * Use this hook to manually trigger a re-render from React.
5
- * @returns an object with a function to re-render the component.
6
- */
7
- export function useManualRender() {
8
- const [, setCount] = useState(0)
9
- return { repaint: useCallback(() => setCount(v => v + 1), []) }
10
- }
1
+ import { useCallback, useState } from 'react'
2
+
3
+ /**
4
+ * Use this hook to manually trigger a re-render from React.
5
+ * @returns an object with a function to re-render the component.
6
+ */
7
+ export function useManualRender() {
8
+ const [, setCount] = useState(0)
9
+ return { repaint: useCallback(() => setCount(v => v + 1), []) }
10
+ }