@navikt/ds-react 7.32.1 → 7.32.3

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 (221) hide show
  1. package/cjs/copybutton/CopyButton.js +4 -9
  2. package/cjs/copybutton/CopyButton.js.map +1 -1
  3. package/cjs/form/combobox/Combobox.js +1 -3
  4. package/cjs/form/combobox/Combobox.js.map +1 -1
  5. package/cjs/form/combobox/ComboboxWrapper.d.ts +1 -2
  6. package/cjs/form/combobox/ComboboxWrapper.js +1 -2
  7. package/cjs/form/combobox/ComboboxWrapper.js.map +1 -1
  8. package/cjs/form/combobox/FilteredOptions/FilteredOptions.js +28 -19
  9. package/cjs/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
  10. package/cjs/form/combobox/FilteredOptions/FilteredOptionsItem.js +4 -0
  11. package/cjs/form/combobox/FilteredOptions/FilteredOptionsItem.js.map +1 -1
  12. package/cjs/form/combobox/FilteredOptions/useVirtualFocus.js.map +1 -1
  13. package/cjs/form/combobox/Input/Input.context.d.ts +2 -0
  14. package/cjs/form/combobox/Input/Input.context.js +4 -1
  15. package/cjs/form/combobox/Input/Input.context.js.map +1 -1
  16. package/cjs/form/combobox/Input/InputController.js +2 -2
  17. package/cjs/form/combobox/Input/InputController.js.map +1 -1
  18. package/cjs/form/switch/Switch.js +3 -3
  19. package/cjs/form/switch/Switch.js.map +1 -1
  20. package/cjs/help-text/HelpText.js +3 -3
  21. package/cjs/help-text/HelpText.js.map +1 -1
  22. package/cjs/help-text/HelpTextIcon.d.ts +1 -2
  23. package/cjs/help-text/HelpTextIcon.js +3 -7
  24. package/cjs/help-text/HelpTextIcon.js.map +1 -1
  25. package/cjs/layout/page/parts/PageBlock.d.ts +9 -6
  26. package/cjs/layout/page/parts/PageBlock.js.map +1 -1
  27. package/cjs/modal/ModalUtils.js +6 -4
  28. package/cjs/modal/ModalUtils.js.map +1 -1
  29. package/cjs/overlays/dismissablelayer/DismissableLayer.js +9 -19
  30. package/cjs/overlays/dismissablelayer/DismissableLayer.js.map +1 -1
  31. package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.js +5 -4
  32. package/cjs/overlays/dismissablelayer/util/usePointerDownOutside.js.map +1 -1
  33. package/cjs/overlays/floating-menu/Menu.d.ts +4 -4
  34. package/cjs/overlays/floating-menu/Menu.js +7 -4
  35. package/cjs/overlays/floating-menu/Menu.js.map +1 -1
  36. package/cjs/overlays/floating-menu/parts/RovingFocus.js +3 -3
  37. package/cjs/overlays/floating-menu/parts/RovingFocus.js.map +1 -1
  38. package/cjs/overlays/overlay/hooks/useAnimationsFinished.js +1 -1
  39. package/cjs/overlays/overlay/hooks/useAnimationsFinished.js.map +1 -1
  40. package/cjs/overlays/overlay/hooks/useOpenChangeAnimationComplete.js +2 -2
  41. package/cjs/overlays/overlay/hooks/useOpenChangeAnimationComplete.js.map +1 -1
  42. package/cjs/popover/Popover.js +1 -1
  43. package/cjs/popover/Popover.js.map +1 -1
  44. package/cjs/progress-bar/ProgressBar.js +9 -6
  45. package/cjs/progress-bar/ProgressBar.js.map +1 -1
  46. package/cjs/table/AnimateHeight.js +12 -13
  47. package/cjs/table/AnimateHeight.js.map +1 -1
  48. package/cjs/tabs/parts/tablist/useScrollButtons.d.ts +1 -1
  49. package/cjs/tabs/parts/tablist/useScrollButtons.js +4 -4
  50. package/cjs/tabs/parts/tablist/useScrollButtons.js.map +1 -1
  51. package/cjs/util/TextareaAutoSize.js +3 -10
  52. package/cjs/util/TextareaAutoSize.js.map +1 -1
  53. package/cjs/util/create-context.d.ts +0 -1
  54. package/cjs/util/create-context.js.map +1 -1
  55. package/cjs/util/debounce.d.ts +1 -1
  56. package/cjs/util/debounce.js +5 -8
  57. package/cjs/util/debounce.js.map +1 -1
  58. package/cjs/util/detectBrowser.d.ts +2 -0
  59. package/cjs/util/detectBrowser.js +7 -0
  60. package/cjs/util/detectBrowser.js.map +1 -0
  61. package/cjs/util/focus-boundary/FocusBoundary.d.ts +44 -0
  62. package/cjs/util/focus-boundary/FocusBoundary.js +365 -0
  63. package/cjs/util/focus-boundary/FocusBoundary.js.map +1 -0
  64. package/cjs/util/focus-guards/FocusGuards.d.ts +8 -0
  65. package/cjs/util/focus-guards/FocusGuards.js +36 -0
  66. package/cjs/util/focus-guards/FocusGuards.js.map +1 -0
  67. package/cjs/util/hooks/descendants/useDescendant.js +3 -0
  68. package/cjs/util/hooks/descendants/useDescendant.js.map +1 -1
  69. package/cjs/util/hooks/useEventCallback.js.map +1 -0
  70. package/cjs/{overlays/overlay → util}/hooks/useLatestRef.js +3 -2
  71. package/cjs/util/hooks/useLatestRef.js.map +1 -0
  72. package/cjs/util/hooks/useRefWithInit.js.map +1 -0
  73. package/cjs/util/hooks/useTimeout.d.ts +16 -0
  74. package/cjs/util/hooks/useTimeout.js +49 -0
  75. package/cjs/util/hooks/useTimeout.js.map +1 -0
  76. package/cjs/util/link-anchor/LinkAnchor.js +6 -7
  77. package/cjs/util/link-anchor/LinkAnchor.js.map +1 -1
  78. package/cjs/util/owner.d.ts +29 -0
  79. package/cjs/util/owner.js +38 -0
  80. package/cjs/util/owner.js.map +1 -0
  81. package/esm/copybutton/CopyButton.js +5 -10
  82. package/esm/copybutton/CopyButton.js.map +1 -1
  83. package/esm/form/combobox/Combobox.js +1 -3
  84. package/esm/form/combobox/Combobox.js.map +1 -1
  85. package/esm/form/combobox/ComboboxWrapper.d.ts +1 -2
  86. package/esm/form/combobox/ComboboxWrapper.js +1 -2
  87. package/esm/form/combobox/ComboboxWrapper.js.map +1 -1
  88. package/esm/form/combobox/FilteredOptions/FilteredOptions.js +29 -20
  89. package/esm/form/combobox/FilteredOptions/FilteredOptions.js.map +1 -1
  90. package/esm/form/combobox/FilteredOptions/FilteredOptionsItem.js +4 -0
  91. package/esm/form/combobox/FilteredOptions/FilteredOptionsItem.js.map +1 -1
  92. package/esm/form/combobox/FilteredOptions/useVirtualFocus.js.map +1 -1
  93. package/esm/form/combobox/Input/Input.context.d.ts +2 -0
  94. package/esm/form/combobox/Input/Input.context.js +4 -1
  95. package/esm/form/combobox/Input/Input.context.js.map +1 -1
  96. package/esm/form/combobox/Input/InputController.js +2 -2
  97. package/esm/form/combobox/Input/InputController.js.map +1 -1
  98. package/esm/form/switch/Switch.js +3 -3
  99. package/esm/form/switch/Switch.js.map +1 -1
  100. package/esm/help-text/HelpText.js +3 -3
  101. package/esm/help-text/HelpText.js.map +1 -1
  102. package/esm/help-text/HelpTextIcon.d.ts +1 -2
  103. package/esm/help-text/HelpTextIcon.js +3 -7
  104. package/esm/help-text/HelpTextIcon.js.map +1 -1
  105. package/esm/layout/page/parts/PageBlock.d.ts +9 -6
  106. package/esm/layout/page/parts/PageBlock.js.map +1 -1
  107. package/esm/modal/ModalUtils.js +6 -4
  108. package/esm/modal/ModalUtils.js.map +1 -1
  109. package/esm/overlays/dismissablelayer/DismissableLayer.js +9 -19
  110. package/esm/overlays/dismissablelayer/DismissableLayer.js.map +1 -1
  111. package/esm/overlays/dismissablelayer/util/usePointerDownOutside.js +5 -4
  112. package/esm/overlays/dismissablelayer/util/usePointerDownOutside.js.map +1 -1
  113. package/esm/overlays/floating-menu/Menu.d.ts +4 -4
  114. package/esm/overlays/floating-menu/Menu.js +7 -4
  115. package/esm/overlays/floating-menu/Menu.js.map +1 -1
  116. package/esm/overlays/floating-menu/parts/RovingFocus.js +3 -3
  117. package/esm/overlays/floating-menu/parts/RovingFocus.js.map +1 -1
  118. package/esm/overlays/overlay/hooks/useAnimationsFinished.js +1 -1
  119. package/esm/overlays/overlay/hooks/useAnimationsFinished.js.map +1 -1
  120. package/esm/overlays/overlay/hooks/useOpenChangeAnimationComplete.js +2 -2
  121. package/esm/overlays/overlay/hooks/useOpenChangeAnimationComplete.js.map +1 -1
  122. package/esm/popover/Popover.js +1 -1
  123. package/esm/popover/Popover.js.map +1 -1
  124. package/esm/progress-bar/ProgressBar.js +10 -7
  125. package/esm/progress-bar/ProgressBar.js.map +1 -1
  126. package/esm/table/AnimateHeight.js +12 -13
  127. package/esm/table/AnimateHeight.js.map +1 -1
  128. package/esm/tabs/parts/tablist/useScrollButtons.d.ts +1 -1
  129. package/esm/tabs/parts/tablist/useScrollButtons.js +4 -4
  130. package/esm/tabs/parts/tablist/useScrollButtons.js.map +1 -1
  131. package/esm/util/TextareaAutoSize.js +1 -8
  132. package/esm/util/TextareaAutoSize.js.map +1 -1
  133. package/esm/util/create-context.d.ts +0 -1
  134. package/esm/util/create-context.js.map +1 -1
  135. package/esm/util/debounce.d.ts +1 -1
  136. package/esm/util/debounce.js +5 -8
  137. package/esm/util/debounce.js.map +1 -1
  138. package/esm/util/detectBrowser.d.ts +2 -0
  139. package/esm/util/detectBrowser.js +4 -0
  140. package/esm/util/detectBrowser.js.map +1 -0
  141. package/esm/util/focus-boundary/FocusBoundary.d.ts +44 -0
  142. package/esm/util/focus-boundary/FocusBoundary.js +329 -0
  143. package/esm/util/focus-boundary/FocusBoundary.js.map +1 -0
  144. package/esm/util/focus-guards/FocusGuards.d.ts +8 -0
  145. package/esm/util/focus-guards/FocusGuards.js +31 -0
  146. package/esm/util/focus-guards/FocusGuards.js.map +1 -0
  147. package/esm/util/hooks/descendants/useDescendant.js +3 -0
  148. package/esm/util/hooks/descendants/useDescendant.js.map +1 -1
  149. package/esm/util/hooks/useEventCallback.js.map +1 -0
  150. package/esm/{overlays/overlay → util}/hooks/useLatestRef.js +2 -1
  151. package/esm/util/hooks/useLatestRef.js.map +1 -0
  152. package/esm/util/hooks/useRefWithInit.js.map +1 -0
  153. package/esm/util/hooks/useTimeout.d.ts +16 -0
  154. package/esm/util/hooks/useTimeout.js +45 -0
  155. package/esm/util/hooks/useTimeout.js.map +1 -0
  156. package/esm/util/link-anchor/LinkAnchor.js +6 -7
  157. package/esm/util/link-anchor/LinkAnchor.js.map +1 -1
  158. package/esm/util/owner.d.ts +29 -0
  159. package/esm/util/owner.js +35 -0
  160. package/esm/util/owner.js.map +1 -0
  161. package/package.json +8 -8
  162. package/src/copybutton/CopyButton.tsx +5 -17
  163. package/src/form/combobox/Combobox.tsx +0 -4
  164. package/src/form/combobox/ComboboxWrapper.tsx +0 -3
  165. package/src/form/combobox/FilteredOptions/FilteredOptions.tsx +65 -45
  166. package/src/form/combobox/FilteredOptions/FilteredOptionsItem.tsx +4 -0
  167. package/src/form/combobox/FilteredOptions/useVirtualFocus.ts +1 -0
  168. package/src/form/combobox/Input/Input.context.tsx +5 -0
  169. package/src/form/combobox/Input/InputController.tsx +2 -1
  170. package/src/form/file-upload/parts/item/utils/format-file-size.test.ts +2 -2
  171. package/src/form/switch/Switch.tsx +4 -4
  172. package/src/help-text/HelpText.tsx +3 -2
  173. package/src/help-text/HelpTextIcon.tsx +2 -12
  174. package/src/layout/page/parts/PageBlock.tsx +9 -6
  175. package/src/modal/ModalUtils.ts +7 -4
  176. package/src/overlays/dismissablelayer/DismissableLayer.tsx +9 -18
  177. package/src/overlays/dismissablelayer/util/usePointerDownOutside.ts +5 -4
  178. package/src/overlays/floating-menu/Menu.tsx +13 -9
  179. package/src/overlays/floating-menu/parts/RovingFocus.tsx +3 -3
  180. package/src/overlays/overlay/hooks/useAnimationsFinished.ts +1 -1
  181. package/src/overlays/overlay/hooks/useOpenChangeAnimationComplete.ts +2 -2
  182. package/src/popover/Popover.tsx +1 -1
  183. package/src/progress-bar/ProgressBar.tsx +12 -10
  184. package/src/table/AnimateHeight.tsx +12 -15
  185. package/src/tabs/parts/tablist/useScrollButtons.ts +4 -3
  186. package/src/util/TextareaAutoSize.tsx +1 -9
  187. package/src/util/create-context.tsx +0 -1
  188. package/src/util/debounce.ts +7 -8
  189. package/src/util/detectBrowser.ts +5 -0
  190. package/src/util/focus-boundary/FocusBoundary.tsx +453 -0
  191. package/src/util/focus-guards/FocusGuards.tsx +56 -0
  192. package/src/util/hooks/descendants/useDescendant.tsx +3 -0
  193. package/src/{overlays/overlay → util}/hooks/useLatestRef.ts +2 -1
  194. package/src/util/hooks/useTimeout.ts +54 -0
  195. package/src/util/link-anchor/LinkAnchor.tsx +7 -6
  196. package/src/util/owner.ts +35 -0
  197. package/cjs/overlays/floating-menu/parts/FocusScope.d.ts +0 -22
  198. package/cjs/overlays/floating-menu/parts/FocusScope.js +0 -98
  199. package/cjs/overlays/floating-menu/parts/FocusScope.js.map +0 -1
  200. package/cjs/overlays/overlay/hooks/useEventCallback.js.map +0 -1
  201. package/cjs/overlays/overlay/hooks/useLatestRef.js.map +0 -1
  202. package/cjs/overlays/overlay/hooks/useRefWithInit.js.map +0 -1
  203. package/esm/overlays/floating-menu/parts/FocusScope.d.ts +0 -22
  204. package/esm/overlays/floating-menu/parts/FocusScope.js +0 -62
  205. package/esm/overlays/floating-menu/parts/FocusScope.js.map +0 -1
  206. package/esm/overlays/overlay/hooks/useEventCallback.js.map +0 -1
  207. package/esm/overlays/overlay/hooks/useLatestRef.js.map +0 -1
  208. package/esm/overlays/overlay/hooks/useRefWithInit.js.map +0 -1
  209. package/src/overlays/floating-menu/parts/FocusScope.tsx +0 -83
  210. /package/cjs/{overlays/overlay → util}/hooks/useEventCallback.d.ts +0 -0
  211. /package/cjs/{overlays/overlay → util}/hooks/useEventCallback.js +0 -0
  212. /package/cjs/{overlays/overlay → util}/hooks/useLatestRef.d.ts +0 -0
  213. /package/cjs/{overlays/overlay → util}/hooks/useRefWithInit.d.ts +0 -0
  214. /package/cjs/{overlays/overlay → util}/hooks/useRefWithInit.js +0 -0
  215. /package/esm/{overlays/overlay → util}/hooks/useEventCallback.d.ts +0 -0
  216. /package/esm/{overlays/overlay → util}/hooks/useEventCallback.js +0 -0
  217. /package/esm/{overlays/overlay → util}/hooks/useLatestRef.d.ts +0 -0
  218. /package/esm/{overlays/overlay → util}/hooks/useRefWithInit.d.ts +0 -0
  219. /package/esm/{overlays/overlay → util}/hooks/useRefWithInit.js +0 -0
  220. /package/src/{overlays/overlay → util}/hooks/useEventCallback.ts +0 -0
  221. /package/src/{overlays/overlay → util}/hooks/useRefWithInit.ts +0 -0
@@ -3,11 +3,11 @@ import ReactDOM from "react-dom";
3
3
  import { Portal } from "../../portal";
4
4
  import { composeEventHandlers } from "../../util/composeEventHandlers";
5
5
  import { createContext } from "../../util/create-context";
6
+ import { FocusBoundary } from "../../util/focus-boundary/FocusBoundary";
6
7
  import { useCallbackRef, useId, useMergeRefs } from "../../util/hooks";
7
8
  import { createDescendantContext } from "../../util/hooks/descendants/useDescendant";
8
9
  import { DismissableLayer } from "../dismissablelayer/DismissableLayer";
9
10
  import { Floating } from "../floating/Floating";
10
- import { FocusScope } from "./parts/FocusScope";
11
11
  import { RovingFocus, RovingFocusProps } from "./parts/RovingFocus";
12
12
  import {
13
13
  SlottedDivElement,
@@ -237,13 +237,13 @@ const MenuRootContentModal = forwardRef<
237
237
 
238
238
  /* -------------------------- Menu content internals ------------------------- */
239
239
  type MenuContentInternalElement = React.ElementRef<typeof Floating.Content>;
240
- type FocusScopeProps = React.ComponentPropsWithoutRef<typeof FocusScope>;
240
+ type FocusScopeProps = React.ComponentPropsWithoutRef<typeof FocusBoundary>;
241
241
  type DismissableLayerProps = React.ComponentPropsWithoutRef<
242
242
  typeof DismissableLayer
243
243
  >;
244
244
 
245
245
  type MenuContentInternalPrivateProps = {
246
- onOpenAutoFocus?: FocusScopeProps["onMountHandler"];
246
+ onOpenAutoFocus?: FocusScopeProps["onMountAutoFocus"];
247
247
  onDismiss?: DismissableLayerProps["onDismiss"];
248
248
  disableOutsidePointerEvents?: DismissableLayerProps["disableOutsidePointerEvents"];
249
249
  };
@@ -258,7 +258,7 @@ interface MenuContentInternalProps
258
258
  * Event handler called when auto-focusing after close.
259
259
  * Can be prevented.
260
260
  */
261
- onCloseAutoFocus?: FocusScopeProps["onUnmountHandler"];
261
+ onCloseAutoFocus?: FocusScopeProps["onUnmountAutoFocus"];
262
262
  onEntryFocus?: RovingFocusProps["onEntryFocus"];
263
263
  onEscapeKeyDown?: DismissableLayerProps["onEscapeKeyDown"];
264
264
  onPointerDownOutside?: DismissableLayerProps["onPointerDownOutside"];
@@ -300,14 +300,17 @@ const MenuContentInternal = forwardRef<
300
300
  );
301
301
 
302
302
  return (
303
- <FocusScope
304
- onMountHandler={composeEventHandlers(onOpenAutoFocus, (event) => {
303
+ <FocusBoundary
304
+ onMountAutoFocus={composeEventHandlers(onOpenAutoFocus, (event) => {
305
305
  // when opening, explicitly focus the content area only and leave
306
306
  // `onEntryFocus` in control of focusing first item
307
307
  event.preventDefault();
308
308
  contentRef.current?.focus({ preventScroll: true });
309
309
  })}
310
- onUnmountHandler={onCloseAutoFocus}
310
+ onUnmountAutoFocus={onCloseAutoFocus}
311
+ /* Focus trapping is handled in `Floating.Content: onKeyDown */
312
+ trapped={false}
313
+ loop={false}
311
314
  >
312
315
  <DismissableLayer
313
316
  asChild
@@ -324,8 +327,9 @@ const MenuContentInternal = forwardRef<
324
327
  descendants={descendants}
325
328
  onEntryFocus={composeEventHandlers(onEntryFocus, (event) => {
326
329
  // only focus first item when using keyboard
327
- if (!rootContext.isUsingKeyboardRef.current)
330
+ if (!rootContext.isUsingKeyboardRef.current) {
328
331
  event.preventDefault();
332
+ }
329
333
  })}
330
334
  >
331
335
  <Floating.Content
@@ -363,7 +367,7 @@ const MenuContentInternal = forwardRef<
363
367
  />
364
368
  </RovingFocus>
365
369
  </DismissableLayer>
366
- </FocusScope>
370
+ </FocusBoundary>
367
371
  );
368
372
  },
369
373
  );
@@ -3,6 +3,7 @@ import { Slot } from "../../../slot/Slot";
3
3
  import { composeEventHandlers } from "../../../util/composeEventHandlers";
4
4
  import { useCallbackRef, useMergeRefs } from "../../../util/hooks";
5
5
  import { DescendantsManager } from "../../../util/hooks/descendants/descendant";
6
+ import { ownerDocument } from "../../../util/owner";
6
7
 
7
8
  interface RovingFocusProps
8
9
  extends Omit<React.HTMLAttributes<HTMLDivElement>, "tabIndex"> {
@@ -46,12 +47,11 @@ const RovingFocus = forwardRef<HTMLDivElement, RovingFocusProps>(
46
47
  (event: React.KeyboardEvent) => {
47
48
  const loop = false;
48
49
 
49
- const ownerDocument =
50
- _ref?.current?.ownerDocument ?? globalThis?.document;
50
+ const ownerDoc = ownerDocument(_ref?.current);
51
51
 
52
52
  const idx = descendants
53
53
  .values()
54
- .findIndex((x) => x.node.isSameNode(ownerDocument.activeElement));
54
+ .findIndex((x) => x.node.isSameNode(ownerDoc.activeElement));
55
55
 
56
56
  const nextItem = () => {
57
57
  const next = descendants.nextEnabled(idx, loop);
@@ -2,7 +2,7 @@
2
2
 
3
3
  import React, { useCallback, useEffect } from "react";
4
4
  import ReactDOM from "react-dom";
5
- import { useEventCallback } from "./useEventCallback";
5
+ import { useEventCallback } from "../../../util/hooks/useEventCallback";
6
6
 
7
7
  /**
8
8
  * Returns a stable function that, when invoked, waits for all current CSS/Web Animations
@@ -1,9 +1,9 @@
1
1
  "use client";
2
2
 
3
3
  import React, { useEffect } from "react";
4
+ import { useEventCallback } from "../../../util/hooks/useEventCallback";
5
+ import { useLatestRef } from "../../../util/hooks/useLatestRef";
4
6
  import { useAnimationsFinished } from "./useAnimationsFinished";
5
- import { useEventCallback } from "./useEventCallback";
6
- import { useLatestRef } from "./useLatestRef";
7
7
 
8
8
  interface useOpenChangeAnimationCompleteParameters {
9
9
  /**
@@ -148,7 +148,7 @@ export const Popover = forwardRef<HTMLDivElement, PopoverProps>(
148
148
 
149
149
  useClientLayoutEffect(() => {
150
150
  refs.setReference(anchorEl);
151
- }, [anchorEl]);
151
+ }, [anchorEl, refs]);
152
152
 
153
153
  const floatingRef = useMergeRefs(refs.setFloating, ref);
154
154
 
@@ -1,5 +1,7 @@
1
- import React, { HTMLAttributes, forwardRef, useEffect, useRef } from "react";
1
+ import React, { HTMLAttributes, forwardRef, useEffect } from "react";
2
2
  import { useRenameCSS } from "../theme/Theme";
3
+ import { useLatestRef } from "../util/hooks/useLatestRef";
4
+ import { useTimeout } from "../util/hooks/useTimeout";
3
5
  import { useI18n } from "../util/i18n/i18n.hooks";
4
6
 
5
7
  interface ProgressBarPropsBase
@@ -95,19 +97,19 @@ export const ProgressBar = forwardRef<HTMLDivElement, ProgressBarProps>(
95
97
  ) => {
96
98
  const { cn } = useRenameCSS();
97
99
  const translateX = 100 - (Math.round(value) / valueMax) * 100;
98
- const onTimeoutRef = useRef<() => void>(undefined);
99
- onTimeoutRef.current = simulated?.onTimeout;
100
+ const onTimeoutRef = useLatestRef(simulated?.onTimeout);
101
+
100
102
  const translate = useI18n("ProgressBar");
103
+ const timeout = useTimeout();
101
104
 
102
105
  useEffect(() => {
103
- if (simulated?.seconds && onTimeoutRef.current) {
104
- const timeout = setTimeout(
105
- onTimeoutRef.current,
106
- simulated.seconds * 1000,
107
- );
108
- return () => clearTimeout(timeout);
106
+ if (!simulated?.seconds || !onTimeoutRef.current) {
107
+ return;
109
108
  }
110
- }, [simulated?.seconds]);
109
+
110
+ timeout.start(simulated.seconds * 1000, onTimeoutRef.current);
111
+ return timeout.clear;
112
+ }, [onTimeoutRef, simulated?.seconds, timeout]);
111
113
 
112
114
  return (
113
115
  /* biome-ignore lint/a11y/useFocusableInteractive: Progressbar is not interactive. */
@@ -1,11 +1,11 @@
1
1
  /* https://github.com/Stanko/react-animate-height/blob/v3/src/index.tsx */
2
2
  import React, { CSSProperties, useEffect, useRef, useState } from "react";
3
3
  import { useRenameCSS } from "../theme/Theme";
4
+ import { useTimeout } from "../util/hooks/useTimeout";
4
5
 
5
6
  // ------------------ Types
6
7
 
7
8
  export type Height = "auto" | number | `${number}%`;
8
- type Timeout = ReturnType<typeof setTimeout>;
9
9
  type Overflow = "auto" | "visible" | "hidden" | undefined;
10
10
 
11
11
  // ------------------ Helpers
@@ -73,8 +73,8 @@ const AnimateHeight: React.FC<AnimateHeightProps> = ({
73
73
  const prevHeight = useRef<Height>(height);
74
74
  const contentElement = useRef<HTMLDivElement>(null);
75
75
 
76
- const animationClassesTimeoutID = useRef<Timeout>(undefined);
77
- const timeoutID = useRef<Timeout>(undefined);
76
+ const animationClassTimeout = useTimeout();
77
+ const animationTimeout = useTimeout();
78
78
 
79
79
  const initialHeight = useRef<Height>(height);
80
80
  const initialOverflow = useRef<Overflow>("visible");
@@ -157,33 +157,29 @@ const AnimateHeight: React.FC<AnimateHeightProps> = ({
157
157
  setOverflow("hidden");
158
158
  setUseTransitions(!isCurrentHeightAuto);
159
159
 
160
- // Clear timeouts
161
- clearTimeout(timeoutID.current as Timeout);
162
- clearTimeout(animationClassesTimeoutID.current as Timeout);
163
-
164
160
  if (isCurrentHeightAuto) {
165
161
  // When animating from 'auto' we use a short timeout to start animation
166
162
  // after setting fixed height above
167
163
  timeoutUseTransitions = true;
168
164
 
169
165
  // Short timeout to allow rendering of the initial animation state first
170
- timeoutID.current = setTimeout(() => {
166
+ animationTimeout.start(50, () => {
171
167
  setCurrentHeight(timeoutHeight);
172
168
  setOverflow(timeoutOverflow);
173
169
  setUseTransitions(timeoutUseTransitions);
174
- }, 50);
170
+ });
175
171
 
176
172
  // Set static classes and remove transitions when animation ends
177
- animationClassesTimeoutID.current = setTimeout(() => {
173
+ animationClassTimeout.start(totalDuration, () => {
178
174
  setUseTransitions(false);
179
175
 
180
176
  // ANIMATION ENDS
181
177
  // Hide content if height is 0 (to prevent tabbing into it)
182
178
  hideContent(contentElement.current, timeoutHeight);
183
- }, totalDuration);
179
+ });
184
180
  } else {
185
181
  // Set end height, classes and remove transitions when animation is complete
186
- timeoutID.current = setTimeout(() => {
182
+ animationTimeout.start(totalDuration, () => {
187
183
  setCurrentHeight(timeoutHeight);
188
184
  setOverflow(timeoutOverflow);
189
185
  setUseTransitions(false);
@@ -195,15 +191,16 @@ const AnimateHeight: React.FC<AnimateHeightProps> = ({
195
191
  // Hide content if height is 0 (to prevent tabbing into it)
196
192
  hideContent(contentElement.current, newHeight); // TODO solve newHeight = 0
197
193
  }
198
- }, totalDuration);
194
+ });
199
195
  }
200
196
  }
201
197
 
202
198
  prevHeight.current = height;
203
199
 
200
+ /* We need to manually clear here since we cant guarantee the `.start()` getting called after `height` changes */
204
201
  return () => {
205
- clearTimeout(timeoutID.current as Timeout);
206
- clearTimeout(animationClassesTimeoutID.current as Timeout);
202
+ animationTimeout.clear();
203
+ animationClassTimeout.clear();
207
204
  };
208
205
 
209
206
  // This should be explicitly run only on height change
@@ -1,5 +1,6 @@
1
1
  import { useEffect, useMemo, useState } from "react";
2
2
  import { debounce } from "../../../util";
3
+ import { ownerDocument } from "../../../util/owner";
3
4
 
4
5
  export function useScrollButtons(
5
6
  listRef: React.RefObject<HTMLDivElement | null>,
@@ -31,8 +32,8 @@ export function useScrollButtons(
31
32
 
32
33
  useEffect(() => {
33
34
  const handleResize = () => updateScrollButtonState();
34
- const win = listRef.current?.ownerDocument ?? document ?? window;
35
- win.addEventListener("resize", handleResize);
35
+ const ownerDoc = ownerDocument(listRef.current);
36
+ ownerDoc.addEventListener("resize", handleResize);
36
37
 
37
38
  let resizeObserver: ResizeObserver;
38
39
 
@@ -42,7 +43,7 @@ export function useScrollButtons(
42
43
  }
43
44
 
44
45
  return () => {
45
- win.removeEventListener("resize", handleResize);
46
+ ownerDoc.removeEventListener("resize", handleResize);
46
47
  resizeObserver?.disconnect();
47
48
  updateScrollButtonState.clear();
48
49
  };
@@ -4,6 +4,7 @@ import ReactDOM from "react-dom";
4
4
  import { useClientLayoutEffect } from "../util/hooks";
5
5
  import debounce from "./debounce";
6
6
  import { useMergeRefs } from "./hooks/useMergeRefs";
7
+ import { ownerWindow } from "./owner";
7
8
 
8
9
  type State = {
9
10
  outerHeightStyle: number;
@@ -35,15 +36,6 @@ const checkState = (
35
36
  return prevState;
36
37
  };
37
38
 
38
- /**
39
- * https://github.com/mui/material-ui/blob/master/packages/mui-utils/src/ownerDocument/ownerDocument.ts
40
- * https://github.com/mui/material-ui/blob/master/packages/mui-utils/src/ownerWindow/ownerWindow.ts
41
- */
42
- const ownerWindow = (node: Node | undefined): Window => {
43
- const doc = node?.ownerDocument || document;
44
- return doc.defaultView || window;
45
- };
46
-
47
39
  function getStyleValue(value: string) {
48
40
  return parseInt(value, 10) || 0;
49
41
  }
@@ -16,7 +16,6 @@ export interface CreateContextOptions<T> {
16
16
  errorMessage?: string;
17
17
  name?: string;
18
18
  defaultValue?: T;
19
- strict?: boolean;
20
19
  }
21
20
 
22
21
  type ProviderProps<T> = T & { children: React.ReactNode };
@@ -1,26 +1,25 @@
1
1
  "use client";
2
+
3
+ import { Timeout } from "./hooks/useTimeout";
4
+
2
5
  // https://github.com/mui/material-ui/blob/master/packages/mui-utils/src/debounce.js
3
6
  export default function debounce<T extends unknown[]>(
4
7
  func: (...args: T) => void,
5
8
  wait = 166,
6
9
  leading = false,
7
10
  ) {
8
- let timeout: ReturnType<typeof setTimeout> | undefined;
11
+ const timeout = new Timeout();
9
12
  function debounced(this: any, ...args: T) {
10
13
  const later = () => {
11
- timeout = undefined;
12
14
  func.apply(this, args);
13
15
  };
14
- if (!timeout && leading) {
16
+ if (!timeout.isStarted() && leading) {
15
17
  later();
16
18
  }
17
- clearTimeout(timeout);
18
- timeout = setTimeout(later, wait);
19
+ timeout.start(wait, later);
19
20
  }
20
21
 
21
- debounced.clear = () => {
22
- clearTimeout(timeout);
23
- };
22
+ debounced.clear = timeout.clear;
24
23
 
25
24
  return debounced;
26
25
  }
@@ -0,0 +1,5 @@
1
+ const hasNavigator = typeof navigator !== "undefined";
2
+
3
+ const isSafari = hasNavigator && /apple/i.test(navigator.vendor);
4
+
5
+ export { isSafari };