@wordpress/components 28.7.0 → 28.8.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 (240) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/build/box-control/all-input-control.js +1 -2
  3. package/build/box-control/all-input-control.js.map +1 -1
  4. package/build/box-control/utils.js +1 -1
  5. package/build/box-control/utils.js.map +1 -1
  6. package/build/card/card/component.js +2 -2
  7. package/build/card/card/component.js.map +1 -1
  8. package/build/card/styles.js +18 -18
  9. package/build/card/styles.js.map +1 -1
  10. package/build/combobox-control/index.js +3 -1
  11. package/build/combobox-control/index.js.map +1 -1
  12. package/build/combobox-control/types.js.map +1 -1
  13. package/build/composite/context.js +1 -1
  14. package/build/composite/context.js.map +1 -1
  15. package/build/composite/group-label.js +1 -1
  16. package/build/composite/group-label.js.map +1 -1
  17. package/build/composite/group.js +1 -1
  18. package/build/composite/group.js.map +1 -1
  19. package/build/composite/hover.js +1 -1
  20. package/build/composite/hover.js.map +1 -1
  21. package/build/composite/index.js +17 -26
  22. package/build/composite/index.js.map +1 -1
  23. package/build/composite/item.js +1 -1
  24. package/build/composite/item.js.map +1 -1
  25. package/build/composite/legacy/index.js +59 -8
  26. package/build/composite/legacy/index.js.map +1 -1
  27. package/build/composite/row.js +1 -1
  28. package/build/composite/row.js.map +1 -1
  29. package/build/composite/typeahead.js +1 -1
  30. package/build/composite/typeahead.js.map +1 -1
  31. package/build/composite/types.js.map +1 -1
  32. package/build/custom-select-control-v2/styles.js +9 -9
  33. package/build/custom-select-control-v2/styles.js.map +1 -1
  34. package/build/date-time/date/index.js +1 -1
  35. package/build/date-time/date/index.js.map +1 -1
  36. package/build/date-time/date/styles.js +35 -24
  37. package/build/date-time/date/styles.js.map +1 -1
  38. package/build/date-time/date/use-lilius/index.js +163 -0
  39. package/build/date-time/date/use-lilius/index.js.map +1 -0
  40. package/build/dropdown-menu-v2/styles.js +17 -17
  41. package/build/dropdown-menu-v2/styles.js.map +1 -1
  42. package/build/index.js +7 -0
  43. package/build/index.js.map +1 -1
  44. package/build/modal/index.js +27 -12
  45. package/build/modal/index.js.map +1 -1
  46. package/build/modal/types.js.map +1 -1
  47. package/build/modal/use-modal-exit-animation.js +75 -0
  48. package/build/modal/use-modal-exit-animation.js.map +1 -0
  49. package/build/navigator/navigator-screen/component.js +5 -0
  50. package/build/navigator/navigator-screen/component.js.map +1 -1
  51. package/build/private-apis.js +0 -9
  52. package/build/private-apis.js.map +1 -1
  53. package/build/range-control/styles/range-control-styles.js +28 -28
  54. package/build/range-control/styles/range-control-styles.js.map +1 -1
  55. package/build/slot-fill/index.js +1 -0
  56. package/build/slot-fill/index.js.map +1 -1
  57. package/build/tabs/styles.js +3 -3
  58. package/build/tabs/styles.js.map +1 -1
  59. package/build/tabs/tablist.js +5 -4
  60. package/build/tabs/tablist.js.map +1 -1
  61. package/build/utils/config-values.js +4 -5
  62. package/build/utils/config-values.js.map +1 -1
  63. package/build/utils/element-rect.js +73 -105
  64. package/build/utils/element-rect.js.map +1 -1
  65. package/build-module/box-control/all-input-control.js +2 -2
  66. package/build-module/box-control/all-input-control.js.map +1 -1
  67. package/build-module/box-control/utils.js +1 -1
  68. package/build-module/box-control/utils.js.map +1 -1
  69. package/build-module/card/card/component.js +2 -2
  70. package/build-module/card/card/component.js.map +1 -1
  71. package/build-module/card/styles.js +18 -18
  72. package/build-module/card/styles.js.map +1 -1
  73. package/build-module/combobox-control/index.js +3 -1
  74. package/build-module/combobox-control/index.js.map +1 -1
  75. package/build-module/combobox-control/types.js.map +1 -1
  76. package/build-module/composite/context.js +1 -1
  77. package/build-module/composite/context.js.map +1 -1
  78. package/build-module/composite/group-label.js +1 -1
  79. package/build-module/composite/group-label.js.map +1 -1
  80. package/build-module/composite/group.js +1 -1
  81. package/build-module/composite/group.js.map +1 -1
  82. package/build-module/composite/hover.js +1 -1
  83. package/build-module/composite/hover.js.map +1 -1
  84. package/build-module/composite/index.js +17 -26
  85. package/build-module/composite/index.js.map +1 -1
  86. package/build-module/composite/item.js +1 -1
  87. package/build-module/composite/item.js.map +1 -1
  88. package/build-module/composite/legacy/index.js +56 -8
  89. package/build-module/composite/legacy/index.js.map +1 -1
  90. package/build-module/composite/row.js +1 -1
  91. package/build-module/composite/row.js.map +1 -1
  92. package/build-module/composite/typeahead.js +1 -1
  93. package/build-module/composite/typeahead.js.map +1 -1
  94. package/build-module/composite/types.js.map +1 -1
  95. package/build-module/custom-select-control-v2/styles.js +9 -9
  96. package/build-module/custom-select-control-v2/styles.js.map +1 -1
  97. package/build-module/date-time/date/index.js +1 -2
  98. package/build-module/date-time/date/index.js.map +1 -1
  99. package/build-module/date-time/date/styles.js +31 -24
  100. package/build-module/date-time/date/styles.js.map +1 -1
  101. package/build-module/date-time/date/use-lilius/index.js +158 -0
  102. package/build-module/date-time/date/use-lilius/index.js.map +1 -0
  103. package/build-module/dropdown-menu-v2/styles.js +17 -17
  104. package/build-module/dropdown-menu-v2/styles.js.map +1 -1
  105. package/build-module/index.js +1 -0
  106. package/build-module/index.js.map +1 -1
  107. package/build-module/modal/index.js +29 -12
  108. package/build-module/modal/index.js.map +1 -1
  109. package/build-module/modal/types.js.map +1 -1
  110. package/build-module/modal/use-modal-exit-animation.js +68 -0
  111. package/build-module/modal/use-modal-exit-animation.js.map +1 -0
  112. package/build-module/navigator/navigator-screen/component.js +4 -0
  113. package/build-module/navigator/navigator-screen/component.js.map +1 -1
  114. package/build-module/private-apis.js +0 -9
  115. package/build-module/private-apis.js.map +1 -1
  116. package/build-module/range-control/styles/range-control-styles.js +28 -28
  117. package/build-module/range-control/styles/range-control-styles.js.map +1 -1
  118. package/build-module/slot-fill/index.js +1 -0
  119. package/build-module/slot-fill/index.js.map +1 -1
  120. package/build-module/tabs/styles.js +3 -3
  121. package/build-module/tabs/styles.js.map +1 -1
  122. package/build-module/tabs/tablist.js +5 -4
  123. package/build-module/tabs/tablist.js.map +1 -1
  124. package/build-module/utils/config-values.js +4 -5
  125. package/build-module/utils/config-values.js.map +1 -1
  126. package/build-module/utils/element-rect.js +74 -105
  127. package/build-module/utils/element-rect.js.map +1 -1
  128. package/build-style/style-rtl.css +51 -10
  129. package/build-style/style.css +51 -10
  130. package/build-types/box-control/all-input-control.d.ts.map +1 -1
  131. package/build-types/box-control/utils.d.ts +1 -1
  132. package/build-types/box-control/utils.d.ts.map +1 -1
  133. package/build-types/button-group/stories/index.story.d.ts +2 -2
  134. package/build-types/button-group/stories/index.story.d.ts.map +1 -1
  135. package/build-types/combobox-control/index.d.ts.map +1 -1
  136. package/build-types/combobox-control/stories/index.story.d.ts +4 -0
  137. package/build-types/combobox-control/stories/index.story.d.ts.map +1 -1
  138. package/build-types/combobox-control/types.d.ts +4 -0
  139. package/build-types/combobox-control/types.d.ts.map +1 -1
  140. package/build-types/composite/context.d.ts.map +1 -1
  141. package/build-types/composite/index.d.ts +36 -24
  142. package/build-types/composite/index.d.ts.map +1 -1
  143. package/build-types/composite/legacy/index.d.ts +25 -2
  144. package/build-types/composite/legacy/index.d.ts.map +1 -1
  145. package/build-types/composite/legacy/stories/index.story.d.ts.map +1 -1
  146. package/build-types/composite/stories/index.story.d.ts +9 -9
  147. package/build-types/composite/stories/index.story.d.ts.map +1 -1
  148. package/build-types/composite/types.d.ts +11 -10
  149. package/build-types/composite/types.d.ts.map +1 -1
  150. package/build-types/custom-select-control-v2/styles.d.ts.map +1 -1
  151. package/build-types/date-time/date/index.d.ts +0 -3
  152. package/build-types/date-time/date/index.d.ts.map +1 -1
  153. package/build-types/date-time/date/styles.d.ts.map +1 -1
  154. package/build-types/date-time/date/test/use-lilius.d.ts +2 -0
  155. package/build-types/date-time/date/test/use-lilius.d.ts.map +1 -0
  156. package/build-types/date-time/date/use-lilius/index.d.ts +169 -0
  157. package/build-types/date-time/date/use-lilius/index.d.ts.map +1 -0
  158. package/build-types/index.d.ts +1 -0
  159. package/build-types/index.d.ts.map +1 -1
  160. package/build-types/modal/index.d.ts.map +1 -1
  161. package/build-types/modal/stories/index.story.d.ts +3 -0
  162. package/build-types/modal/stories/index.story.d.ts.map +1 -1
  163. package/build-types/modal/types.d.ts +6 -10
  164. package/build-types/modal/types.d.ts.map +1 -1
  165. package/build-types/modal/use-modal-exit-animation.d.ts +9 -0
  166. package/build-types/modal/use-modal-exit-animation.d.ts.map +1 -0
  167. package/build-types/navigator/navigator-screen/component.d.ts.map +1 -1
  168. package/build-types/private-apis.d.ts.map +1 -1
  169. package/build-types/range-control/styles/range-control-styles.d.ts.map +1 -1
  170. package/build-types/slot-fill/index.d.ts +3 -0
  171. package/build-types/slot-fill/index.d.ts.map +1 -1
  172. package/build-types/tabs/styles.d.ts.map +1 -1
  173. package/build-types/tabs/tablist.d.ts.map +1 -1
  174. package/build-types/utils/config-values.d.ts +0 -1
  175. package/build-types/utils/element-rect.d.ts +32 -74
  176. package/build-types/utils/element-rect.d.ts.map +1 -1
  177. package/package.json +19 -20
  178. package/src/box-control/README.md +7 -0
  179. package/src/box-control/all-input-control.tsx +2 -3
  180. package/src/box-control/utils.ts +1 -1
  181. package/src/button-group/stories/index.story.tsx +10 -15
  182. package/src/card/card/component.tsx +1 -1
  183. package/src/card/styles.ts +1 -1
  184. package/src/card/test/__snapshots__/index.tsx.snap +54 -54
  185. package/src/combobox-control/README.md +7 -0
  186. package/src/combobox-control/index.tsx +2 -0
  187. package/src/combobox-control/test/index.tsx +40 -0
  188. package/src/combobox-control/types.ts +4 -0
  189. package/src/composite/README.md +5 -24
  190. package/src/composite/{context.ts → context.tsx} +1 -2
  191. package/src/composite/group-label.tsx +1 -1
  192. package/src/composite/group.tsx +1 -1
  193. package/src/composite/hover.tsx +1 -1
  194. package/src/composite/index.tsx +17 -28
  195. package/src/composite/item.tsx +1 -1
  196. package/src/composite/legacy/index.tsx +72 -11
  197. package/src/composite/legacy/stories/index.story.tsx +2 -1
  198. package/src/composite/legacy/test/index.tsx +57 -1
  199. package/src/composite/row.tsx +1 -1
  200. package/src/composite/stories/index.story.tsx +185 -169
  201. package/src/composite/typeahead.tsx +1 -1
  202. package/src/composite/types.ts +13 -15
  203. package/src/custom-select-control-v2/styles.ts +1 -0
  204. package/src/date-time/date/index.tsx +1 -1
  205. package/src/date-time/date/styles.ts +31 -11
  206. package/src/date-time/date/test/use-lilius.ts +417 -0
  207. package/src/date-time/date/use-lilius/index.ts +394 -0
  208. package/src/dropdown-menu-v2/styles.ts +1 -1
  209. package/src/form-toggle/style.scss +1 -0
  210. package/src/index.ts +1 -0
  211. package/src/modal/index.tsx +42 -19
  212. package/src/modal/stories/index.story.tsx +8 -14
  213. package/src/modal/style.scss +30 -8
  214. package/src/modal/types.ts +6 -18
  215. package/src/modal/use-modal-exit-animation.ts +99 -0
  216. package/src/navigator/navigator-screen/component.tsx +7 -0
  217. package/src/navigator/test/index.tsx +8 -0
  218. package/src/popover/style.scss +3 -2
  219. package/src/private-apis.ts +0 -9
  220. package/src/range-control/styles/range-control-styles.ts +1 -0
  221. package/src/resizable-box/style.scss +1 -1
  222. package/src/select-control/README.md +2 -2
  223. package/src/slot-fill/index.tsx +1 -0
  224. package/src/snackbar/style.scss +1 -1
  225. package/src/tabs/styles.ts +40 -11
  226. package/src/tabs/tablist.tsx +5 -4
  227. package/src/tooltip/style.scss +1 -0
  228. package/src/utils/config-values.js +4 -5
  229. package/src/utils/element-rect.ts +93 -130
  230. package/tsconfig.tsbuildinfo +1 -1
  231. package/build/composite/store.js +0 -54
  232. package/build/composite/store.js.map +0 -1
  233. package/build-module/composite/store.js +0 -46
  234. package/build-module/composite/store.js.map +0 -1
  235. package/build-types/composite/store.d.ts +0 -25
  236. package/build-types/composite/store.d.ts.map +0 -1
  237. package/build-types/composite/stories/utils.d.ts +0 -29
  238. package/build-types/composite/stories/utils.d.ts.map +0 -1
  239. package/src/composite/store.ts +0 -46
  240. package/src/composite/stories/utils.tsx +0 -76
@@ -2,134 +2,37 @@
2
2
  /**
3
3
  * WordPress dependencies
4
4
  */
5
- import { useRef, useEffect, useState } from '@wordpress/element';
5
+ import { useLayoutEffect, useRef, useState } from '@wordpress/element';
6
+ import { useResizeObserver } from '@wordpress/compose';
6
7
  /**
7
8
  * Internal dependencies
8
9
  */
9
10
  import { useEvent } from './hooks/use-event';
10
11
 
11
12
  /**
12
- * `useTrackElementRectUpdates` options.
13
+ * The position and dimensions of an element, relative to its offset parent.
13
14
  */
14
- export type UseTrackElementRectUpdatesOptions = {
15
+ export type ElementOffsetRect = {
15
16
  /**
16
- * Whether to trigger the callback when an element's ResizeObserver is
17
- * first set up, including when the target element changes.
18
- *
19
- * @default true
17
+ * The distance from the top edge of the offset parent to the top edge of
18
+ * the element.
20
19
  */
21
- fireOnElementInit?: boolean;
22
- };
23
-
24
- /**
25
- * Tracks an element's "rect" (size and position) and fires `onRect` for all
26
- * of its discrete values. The element can be changed dynamically and **it
27
- * must not be stored in a ref**. Instead, it should be stored in a React
28
- * state or equivalent.
29
- *
30
- * By default, `onRect` is called initially for the target element (including
31
- * when the target element changes), not only on size or position updates.
32
- * This allows consumers of the hook to always be in sync with all rect values
33
- * of the target element throughout its lifetime. This behavior can be
34
- * disabled by setting the `fireOnElementInit` option to `false`.
35
- *
36
- * Under the hood, it sets up a `ResizeObserver` that tracks the element. The
37
- * target element can be changed dynamically, and the observer will be
38
- * updated accordingly.
39
- *
40
- * @example
41
- *
42
- * ```tsx
43
- * const [ targetElement, setTargetElement ] = useState< HTMLElement | null >();
44
- *
45
- * useTrackElementRectUpdates( targetElement, ( element ) => {
46
- * console.log( 'Element resized:', element );
47
- * } );
48
- *
49
- * <div ref={ setTargetElement } />;
50
- * ```
51
- */
52
- export function useTrackElementRectUpdates(
20
+ top: number;
53
21
  /**
54
- * The target element to observe. It can be changed dynamically.
22
+ * The distance from the right edge of the offset parent to the right edge
23
+ * of the element.
55
24
  */
56
- targetElement: HTMLElement | undefined | null,
25
+ right: number;
57
26
  /**
58
- * Callback to fire when the element is resized. It will also be
59
- * called when the observer is set up, unless `fireOnElementInit` is
60
- * set to `false`.
27
+ * The distance from the bottom edge of the offset parent to the bottom edge
28
+ * of the element.
61
29
  */
62
- onRect: (
63
- /**
64
- * The element being tracked at the time of this update.
65
- */
66
- element: HTMLElement,
67
- /**
68
- * The list of
69
- * [`ResizeObserverEntry`](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry)
70
- * objects passed to the `ResizeObserver.observe` callback. This list
71
- * won't be available when the observer is set up, and only on updates.
72
- */
73
- resizeObserverEntries?: ResizeObserverEntry[]
74
- ) => void,
75
- { fireOnElementInit = true }: UseTrackElementRectUpdatesOptions = {}
76
- ) {
77
- const onRectEvent = useEvent( onRect );
78
-
79
- const observedElementRef = useRef< HTMLElement | null >();
80
- const resizeObserverRef = useRef< ResizeObserver >();
81
-
82
- // TODO: could this be a layout effect?
83
- useEffect( () => {
84
- if ( targetElement === observedElementRef.current ) {
85
- return;
86
- }
87
-
88
- observedElementRef.current = targetElement;
89
-
90
- // Set up a ResizeObserver.
91
- if ( ! resizeObserverRef.current ) {
92
- resizeObserverRef.current = new ResizeObserver( ( entries ) => {
93
- if ( observedElementRef.current ) {
94
- onRectEvent( observedElementRef.current, entries );
95
- }
96
- } );
97
- }
98
- const { current: resizeObserver } = resizeObserverRef;
99
-
100
- // Observe new element.
101
- if ( targetElement ) {
102
- if ( fireOnElementInit ) {
103
- // TODO: investigate if this can be removed,
104
- // see: https://stackoverflow.com/a/60026394
105
- onRectEvent( targetElement );
106
- }
107
- resizeObserver.observe( targetElement );
108
- }
109
-
110
- return () => {
111
- // Unobserve previous element.
112
- if ( observedElementRef.current ) {
113
- resizeObserver.unobserve( observedElementRef.current );
114
- }
115
- };
116
- }, [ fireOnElementInit, onRectEvent, targetElement ] );
117
- }
118
-
119
- /**
120
- * The position and dimensions of an element, relative to its offset parent.
121
- */
122
- export type ElementOffsetRect = {
30
+ bottom: number;
123
31
  /**
124
32
  * The distance from the left edge of the offset parent to the left edge of
125
33
  * the element.
126
34
  */
127
35
  left: number;
128
- /**
129
- * The distance from the top edge of the offset parent to the top edge of
130
- * the element.
131
- */
132
- top: number;
133
36
  /**
134
37
  * The width of the element.
135
38
  */
@@ -144,51 +47,111 @@ export type ElementOffsetRect = {
144
47
  * An `ElementOffsetRect` object with all values set to zero.
145
48
  */
146
49
  export const NULL_ELEMENT_OFFSET_RECT = {
147
- left: 0,
148
50
  top: 0,
51
+ right: 0,
52
+ bottom: 0,
53
+ left: 0,
149
54
  width: 0,
150
55
  height: 0,
151
56
  } satisfies ElementOffsetRect;
152
57
 
153
58
  /**
154
59
  * Returns the position and dimensions of an element, relative to its offset
155
- * parent. This is useful in contexts where `getBoundingClientRect` is not
156
- * suitable, such as when the element is transformed.
60
+ * parent, with subpixel precision. Values reflect the real measures before any
61
+ * potential scaling distortions along the X and Y axes.
157
62
  *
158
- * **Note:** the `left` and `right` values are adjusted due to a limitation
159
- * in the way the browser calculates the offset position of the element,
160
- * which can cause unwanted scrollbars to appear. This adjustment makes the
161
- * values potentially inaccurate within a range of 1 pixel.
63
+ * Useful in contexts where plain `getBoundingClientRect` calls or `ResizeObserver`
64
+ * entries are not suitable, such as when the element is transformed, and when
65
+ * `element.offset<Top|Left|Width|Height>` methods are not precise enough.
66
+ *
67
+ * **Note:** in some contexts, like when the scale is 0, this method will fail
68
+ * because it's impossible to calculate a scaling ratio. When that happens, it
69
+ * will return `undefined`.
162
70
  */
163
71
  export function getElementOffsetRect(
164
72
  element: HTMLElement
165
- ): ElementOffsetRect {
73
+ ): ElementOffsetRect | undefined {
74
+ // Position and dimension values computed with `getBoundingClientRect` have
75
+ // subpixel precision, but are affected by distortions since they represent
76
+ // the "real" measures, or in other words, the actual final values as rendered
77
+ // by the browser.
78
+ const rect = element.getBoundingClientRect();
79
+ if ( rect.width === 0 || rect.height === 0 ) {
80
+ return;
81
+ }
82
+ const offsetParentRect =
83
+ element.offsetParent?.getBoundingClientRect() ??
84
+ NULL_ELEMENT_OFFSET_RECT;
85
+
86
+ // Computed widths and heights have subpixel precision, and are not affected
87
+ // by distortions.
88
+ const computedWidth = parseFloat( getComputedStyle( element ).width );
89
+ const computedHeight = parseFloat( getComputedStyle( element ).height );
90
+
91
+ // We can obtain the current scale factor for the element by comparing "computed"
92
+ // dimensions with the "real" ones.
93
+ const scaleX = computedWidth / rect.width;
94
+ const scaleY = computedHeight / rect.height;
95
+
166
96
  return {
167
- // The adjustments mentioned in the documentation above are necessary
168
- // because `offsetLeft` and `offsetTop` are rounded to the nearest pixel,
169
- // which can result in a position mismatch that causes unwanted overflow.
170
- // For context, see: https://github.com/WordPress/gutenberg/pull/61979
171
- left: Math.max( element.offsetLeft - 1, 0 ),
172
- top: Math.max( element.offsetTop - 1, 0 ),
173
- // This is a workaround to obtain these values with a sub-pixel precision,
174
- // since `offsetWidth` and `offsetHeight` are rounded to the nearest pixel.
175
- width: parseFloat( getComputedStyle( element ).width ),
176
- height: parseFloat( getComputedStyle( element ).height ),
97
+ // To obtain the adjusted values for the position:
98
+ // 1. Compute the element's position relative to the offset parent.
99
+ // 2. Correct for the scale factor.
100
+ top: ( rect.top - offsetParentRect?.top ) * scaleY,
101
+ right: ( offsetParentRect?.right - rect.right ) * scaleX,
102
+ bottom: ( offsetParentRect?.bottom - rect.bottom ) * scaleY,
103
+ left: ( rect.left - offsetParentRect?.left ) * scaleX,
104
+ // Computed dimensions don't need any adjustments.
105
+ width: computedWidth,
106
+ height: computedHeight,
177
107
  };
178
108
  }
179
109
 
110
+ const POLL_RATE = 100;
111
+
180
112
  /**
181
113
  * Tracks the position and dimensions of an element, relative to its offset
182
114
  * parent. The element can be changed dynamically.
115
+ *
116
+ * **Note:** sometimes, the measurement will fail (see `getElementOffsetRect`'s
117
+ * documentation for more details). When that happens, this hook will attempt
118
+ * to measure again after a frame, and if that fails, it will poll every 100
119
+ * milliseconds until it succeeds.
183
120
  */
184
121
  export function useTrackElementOffsetRect(
185
122
  targetElement: HTMLElement | undefined | null
186
123
  ) {
187
124
  const [ indicatorPosition, setIndicatorPosition ] =
188
125
  useState< ElementOffsetRect >( NULL_ELEMENT_OFFSET_RECT );
126
+ const intervalRef = useRef< ReturnType< typeof setInterval > >();
127
+
128
+ const measure = useEvent( () => {
129
+ if ( targetElement ) {
130
+ const elementOffsetRect = getElementOffsetRect( targetElement );
131
+ if ( elementOffsetRect ) {
132
+ setIndicatorPosition( elementOffsetRect );
133
+ clearInterval( intervalRef.current );
134
+ return true;
135
+ }
136
+ } else {
137
+ clearInterval( intervalRef.current );
138
+ }
139
+ return false;
140
+ } );
141
+
142
+ const setElement = useResizeObserver( () => {
143
+ if ( ! measure() ) {
144
+ requestAnimationFrame( () => {
145
+ if ( ! measure() ) {
146
+ intervalRef.current = setInterval( measure, POLL_RATE );
147
+ }
148
+ } );
149
+ }
150
+ } );
189
151
 
190
- useTrackElementRectUpdates( targetElement, ( element ) =>
191
- setIndicatorPosition( getElementOffsetRect( element ) )
152
+ useLayoutEffect(
153
+ () => setElement( targetElement ),
154
+ [ setElement, targetElement ]
192
155
  );
193
156
 
194
157
  return indicatorPosition;