@box/blueprint-web 13.19.0 → 14.0.1

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 (54) hide show
  1. package/THIRD_PARTY_LICENSES +206 -27
  2. package/dist/lib-esm/button/button.d.ts +0 -2
  3. package/dist/lib-esm/button/button.js +2 -4
  4. package/dist/lib-esm/button/types.d.ts +0 -4
  5. package/dist/lib-esm/card-tooltip/card-tooltip.d.ts +3 -6
  6. package/dist/lib-esm/card-tooltip/card-tooltip.js +96 -42
  7. package/dist/lib-esm/card-tooltip/card-tooltip.module.js +1 -1
  8. package/dist/lib-esm/card-tooltip/types.d.ts +21 -36
  9. package/dist/lib-esm/combobox/chips-group.js +1 -5
  10. package/dist/lib-esm/combobox/combobox.js +64 -55
  11. package/dist/lib-esm/combobox/combobox.module.js +1 -1
  12. package/dist/lib-esm/combobox/types.d.ts +2 -2
  13. package/dist/lib-esm/combobox-group/combobox-group-combobox.js +0 -1
  14. package/dist/lib-esm/data-table/data-table-wrapper.js +2 -0
  15. package/dist/lib-esm/data-table/use-table-scroll-correction.d.ts +15 -0
  16. package/dist/lib-esm/data-table/use-table-scroll-correction.js +211 -0
  17. package/dist/lib-esm/empty-state/empty-state.d.ts +0 -2
  18. package/dist/lib-esm/guided-tooltip/guided-tooltip-footer.d.ts +0 -4
  19. package/dist/lib-esm/guided-tooltip/guided-tooltip.d.ts +0 -4
  20. package/dist/lib-esm/index.css +105 -289
  21. package/dist/lib-esm/index.d.ts +0 -3
  22. package/dist/lib-esm/index.js +0 -3
  23. package/dist/lib-esm/list-item/table-header-dropdown.js +1 -1
  24. package/dist/lib-esm/modal/alert-modal.d.ts +0 -4
  25. package/dist/lib-esm/modal/modal-footer.d.ts +0 -4
  26. package/dist/lib-esm/modal/modal.d.ts +0 -4
  27. package/dist/lib-esm/primitives/context-menu/context-menu.module.js +1 -1
  28. package/dist/lib-esm/primitives/select-menu-grid/select-menu-grid-option.js +0 -1
  29. package/dist/lib-esm/side-panel/side-panel-footer.d.ts +0 -4
  30. package/dist/lib-esm/side-panel/side-panel.d.ts +0 -4
  31. package/dist/lib-esm/tooltip/tooltip.d.ts +3 -2
  32. package/dist/lib-esm/tooltip/tooltip.js +2 -36
  33. package/dist/lib-esm/tooltip/types.d.ts +0 -9
  34. package/dist/lib-esm/util-components/base-grid-list-item/types.d.ts +2 -2
  35. package/dist/lib-esm/utils/useMedia.js +13 -1
  36. package/package.json +14 -14
  37. package/dist/lib-esm/card-tooltip-v2/card-tooltip-v2.d.ts +0 -10
  38. package/dist/lib-esm/card-tooltip-v2/card-tooltip-v2.js +0 -119
  39. package/dist/lib-esm/card-tooltip-v2/card-tooltip-v2.module.js +0 -4
  40. package/dist/lib-esm/card-tooltip-v2/index.d.ts +0 -2
  41. package/dist/lib-esm/card-tooltip-v2/types.d.ts +0 -30
  42. package/dist/lib-esm/content-field/content-field.d.ts +0 -4
  43. package/dist/lib-esm/content-field/content-field.js +0 -126
  44. package/dist/lib-esm/content-field/content-field.module.js +0 -4
  45. package/dist/lib-esm/content-field/index.d.ts +0 -2
  46. package/dist/lib-esm/content-field/messages.d.ts +0 -7
  47. package/dist/lib-esm/content-field/messages.js +0 -8
  48. package/dist/lib-esm/content-field/types.d.ts +0 -35
  49. package/dist/lib-esm/util-components/focus-trap/focus-trap.d.ts +0 -2
  50. package/dist/lib-esm/util-components/focus-trap/focus-trap.js +0 -52
  51. package/dist/lib-esm/util-components/focus-trap/index.d.ts +0 -1
  52. package/dist/lib-esm/util-components/focus-trap/types.d.ts +0 -8
  53. package/dist/lib-esm/utils/useIsTriggerInteractive.d.ts +0 -4
  54. package/dist/lib-esm/utils/useIsTriggerInteractive.js +0 -21
@@ -356,63 +356,68 @@ const RootInner = ({
356
356
  hideLabel: hideLabel
357
357
  }), jsx(PopoverAnchor, {
358
358
  store: comboboxStore,
359
- children: jsxs("div", {
359
+ children: jsx("div", {
360
360
  ref: comboboxContainerRef,
361
361
  className: clsx(styles.comboboxContainer, {
362
362
  [styles.error]: hasError,
363
363
  [styles.withChips]: showChipsGroup || showSingleSelectChip,
364
364
  [styles.withComboboxButtons]: showComboboxCancelButton || Boolean(endComboboxIcon)
365
365
  }),
366
- "data-testid": "combobox-container",
367
366
  onClick: handleFocusInputOnEvent,
368
- children: [showChipsGroup && jsx(ChipsGroup, {
367
+ "data-testid": "combobox-container",
368
+ children: jsxs("div", {
369
+ className: styles.comboboxContainerInner,
369
370
  onClick: handleFocusInputOnEvent,
370
- children: selectedValue.map(selected => jsx(InputChip, {
371
- avatar: getDisplayAvatarFromOptionValue(selected, options, displayAvatar),
372
- label: getDisplayValueFromOptionValue(selected, options, displayValue),
373
- onDelete: () => removeMultiSelectInputChip(selected),
374
- tooltip: getTooltipValueFromOptionValue(selected, options, displayTooltip),
375
- variant: getDisplayChipVariantFromOptionValue(selected, options, displayChipVariant)
376
- }, selected))
377
- }), showSingleSelectChip && jsx(InputChip, {
378
- label: getDisplayValueFromOptionValue(selectedValue, options, displayValue),
379
- onDelete: showComboboxCancelButton ? undefined : removeSingleSelectInputChip,
380
- tooltip: getTooltipValueFromOptionValue(selectedValue, options, displayTooltip),
381
- variant: getDisplayChipVariantFromOptionValue(selectedValue, options, displayChipVariant)
382
- }), jsxs("div", {
383
- className: styles.textInputWrapper,
384
- children: [jsx(Combobox$1, {
385
- ...comboboxProps,
386
- ref: reference,
387
- "aria-describedby": ariaDescribedBy,
388
- ...(hasError && {
389
- 'aria-invalid': 'true'
390
- }),
391
- "aria-required": required,
392
- autoSelect: false,
393
- className: styles.textInput,
394
- disabled: disabled,
395
- id: comboboxId,
396
- onBlur: composeEventHandlers(onBlur, handleOnBlur),
397
- onFocus: handleOnFocus,
398
- onKeyDown: handleKeyDown,
399
- required: required,
400
- store: comboboxStore
401
- }), jsx("div", {
402
- className: styles.comboboxButtons,
403
- children: showComboboxCancelButton ? jsx(ComboboxCancel, {
404
- onClick: resetSelectedValue,
405
- // eslint-disable-next-line react/jsx-no-bind
406
- render: cancelProps => jsx(IconButton, {
407
- ...cancelProps,
408
- "aria-label": clearButtonAriaLabel,
409
- icon: enableModernizedComponents ? XMark : XMark$1,
410
- size: "x-small"
371
+ role: "presentation",
372
+ children: [showChipsGroup && jsx(ChipsGroup, {
373
+ onClick: handleFocusInputOnEvent,
374
+ children: selectedValue.map(selected => jsx(InputChip, {
375
+ avatar: getDisplayAvatarFromOptionValue(selected, options, displayAvatar),
376
+ label: getDisplayValueFromOptionValue(selected, options, displayValue),
377
+ onDelete: () => removeMultiSelectInputChip(selected),
378
+ tooltip: getTooltipValueFromOptionValue(selected, options, displayTooltip),
379
+ variant: getDisplayChipVariantFromOptionValue(selected, options, displayChipVariant)
380
+ }, selected))
381
+ }), showSingleSelectChip && jsx(InputChip, {
382
+ label: getDisplayValueFromOptionValue(selectedValue, options, displayValue),
383
+ onDelete: showComboboxCancelButton ? undefined : removeSingleSelectInputChip,
384
+ tooltip: getTooltipValueFromOptionValue(selectedValue, options, displayTooltip),
385
+ variant: getDisplayChipVariantFromOptionValue(selectedValue, options, displayChipVariant)
386
+ }), jsxs("div", {
387
+ className: styles.textInputWrapper,
388
+ children: [jsx(Combobox$1, {
389
+ ...comboboxProps,
390
+ ref: reference,
391
+ "aria-describedby": ariaDescribedBy,
392
+ ...(hasError && {
393
+ 'aria-invalid': 'true'
411
394
  }),
395
+ "aria-required": required,
396
+ autoSelect: false,
397
+ className: styles.textInput,
398
+ disabled: disabled,
399
+ id: comboboxId,
400
+ onBlur: composeEventHandlers(onBlur, handleOnBlur),
401
+ onFocus: handleOnFocus,
402
+ onKeyDown: handleKeyDown,
403
+ required: required,
412
404
  store: comboboxStore
413
- }) : endComboboxIcon
405
+ }), jsx("div", {
406
+ className: styles.comboboxButtons,
407
+ children: showComboboxCancelButton ? jsx(ComboboxCancel, {
408
+ onClick: resetSelectedValue,
409
+ // eslint-disable-next-line react/jsx-no-bind
410
+ render: cancelProps => jsx(IconButton, {
411
+ ...cancelProps,
412
+ "aria-label": clearButtonAriaLabel,
413
+ icon: enableModernizedComponents ? XMark : XMark$1,
414
+ size: "x-small"
415
+ }),
416
+ store: comboboxStore
417
+ }) : endComboboxIcon
418
+ })]
414
419
  })]
415
- })]
420
+ })
416
421
  })
417
422
  }), jsx(InlineError, {
418
423
  className: styles.inlineError,
@@ -470,15 +475,19 @@ const RootInner = ({
470
475
  sameWidth: true,
471
476
  store: comboboxStore,
472
477
  unmountOnHide: unmountOnHide,
473
- children: jsx(Collection, {
474
- experimentalVirtualization: experimentalVirtualization,
475
- inputValue: inputValue,
476
- loadingAriaLabel: loadingAriaLabel,
477
- noResultMessage: noResultMessage,
478
- options: filteredOptions,
479
- overscan: 2,
480
- renderOptionFn: renderOptionFn,
481
- showLoading: showLoading
478
+ children: jsx("div", {
479
+ className: styles.popoverInner,
480
+ role: "presentation",
481
+ children: jsx(Collection, {
482
+ experimentalVirtualization: experimentalVirtualization,
483
+ inputValue: inputValue,
484
+ loadingAriaLabel: loadingAriaLabel,
485
+ noResultMessage: noResultMessage,
486
+ options: filteredOptions,
487
+ overscan: 2,
488
+ renderOptionFn: renderOptionFn,
489
+ showLoading: showLoading
490
+ })
482
491
  })
483
492
  }) : null]
484
493
  });
@@ -1,4 +1,4 @@
1
1
  import '../index.css';
2
- var styles = {"container":"bp_combobox_module_container--355f7","label":"bp_combobox_module_label--355f7","textInput":"bp_combobox_module_textInput--355f7","popover":"bp_combobox_module_popover--355f7","disabled":"bp_combobox_module_disabled--355f7","hiddenLabel":"bp_combobox_module_hiddenLabel--355f7","comboboxContainer":"bp_combobox_module_comboboxContainer--355f7","withComboboxButtons":"bp_combobox_module_withComboboxButtons--355f7","error":"bp_combobox_module_error--355f7","textInputWrapper":"bp_combobox_module_textInputWrapper--355f7","comboboxButtons":"bp_combobox_module_comboboxButtons--355f7","withChips":"bp_combobox_module_withChips--355f7","inlineError":"bp_combobox_module_inlineError--355f7","option":"bp_combobox_module_option--355f7","indicator":"bp_combobox_module_indicator--355f7","indicatorIcon":"bp_combobox_module_indicatorIcon--355f7","optionWithIndicator":"bp_combobox_module_optionWithIndicator--355f7","loadingIndicator":"bp_combobox_module_loadingIndicator--355f7"};
2
+ var styles = {"container":"bp_combobox_module_container--c4fe7","label":"bp_combobox_module_label--c4fe7","textInput":"bp_combobox_module_textInput--c4fe7","popover":"bp_combobox_module_popover--c4fe7","disabled":"bp_combobox_module_disabled--c4fe7","hiddenLabel":"bp_combobox_module_hiddenLabel--c4fe7","comboboxContainer":"bp_combobox_module_comboboxContainer--c4fe7","comboboxContainerInner":"bp_combobox_module_comboboxContainerInner--c4fe7","withChips":"bp_combobox_module_withChips--c4fe7","error":"bp_combobox_module_error--c4fe7","withComboboxButtons":"bp_combobox_module_withComboboxButtons--c4fe7","textInputWrapper":"bp_combobox_module_textInputWrapper--c4fe7","comboboxButtons":"bp_combobox_module_comboboxButtons--c4fe7","inlineError":"bp_combobox_module_inlineError--c4fe7","popoverInner":"bp_combobox_module_popoverInner--c4fe7","option":"bp_combobox_module_option--c4fe7","indicator":"bp_combobox_module_indicator--c4fe7","indicatorIcon":"bp_combobox_module_indicatorIcon--c4fe7","optionWithIndicator":"bp_combobox_module_optionWithIndicator--c4fe7","loadingIndicator":"bp_combobox_module_loadingIndicator--c4fe7"};
3
3
 
4
4
  export { styles as default };
@@ -15,7 +15,7 @@ export interface ComboboxBaseProps<Multiple extends boolean, FreeInput extends b
15
15
  /**
16
16
  * The list of values for the combobox items.
17
17
  */
18
- options: T[];
18
+ options: ReadonlyArray<T>;
19
19
  /**
20
20
  * If set to `true`, the combobox input can contain any arbitrary value.
21
21
  * In other words, options just behave as suggestions and the user input
@@ -291,7 +291,7 @@ export interface ComboboxOptionProps extends Pick<SelectItemProps, 'hideOnClick'
291
291
  className?: string;
292
292
  }
293
293
  export interface CollectionProps<T> {
294
- options: Array<T>;
294
+ options: ReadonlyArray<T>;
295
295
  experimentalVirtualization: boolean;
296
296
  inputValue: string;
297
297
  renderOptionFn: (option: T) => React.ReactElement;
@@ -3,7 +3,6 @@ import clsx from 'clsx';
3
3
  import { forwardRef, useCallback, useEffect } from 'react';
4
4
  import '@box/blueprint-web-assets/tokens/px-tokens';
5
5
  import '@radix-ui/react-tooltip';
6
- import 'tabbable';
7
6
  import { Combobox } from '../combobox/combobox.js';
8
7
  import { useComboboxGroupContext } from './combobox-group-context.js';
9
8
  import styles from './combobox-group.module.js';
@@ -4,6 +4,7 @@ import { forwardRef, useRef } from 'react';
4
4
  import { useScroll, ScrollContext } from '../util-components/scrollable-container/scrollable-container.js';
5
5
  import { useForkRef } from '../utils/useForkRef.js';
6
6
  import styles from './data-table.module.js';
7
+ import { useTableScrollCorrection } from './use-table-scroll-correction.js';
7
8
 
8
9
  const hideActionWrapperRightOffsetPx = 30;
9
10
  const DataTableWrapper = /*#__PURE__*/forwardRef((props, forwardedRef) => {
@@ -17,6 +18,7 @@ const DataTableWrapper = /*#__PURE__*/forwardRef((props, forwardedRef) => {
17
18
  value,
18
19
  onScrollThrottled
19
20
  } = useScroll(localRef);
21
+ useTableScrollCorrection(localRef);
20
22
  const {
21
23
  offsetTillEndX,
22
24
  isScrolledX,
@@ -0,0 +1,15 @@
1
+ import { type RefObject } from 'react';
2
+ export declare function getScrollableAncestors(element: HTMLElement): HTMLElement[];
3
+ /**
4
+ * corrects the scroll position of the ancestor element to make the element visible
5
+ */
6
+ export declare function scrollElementIntoAncestor(ancestor: HTMLElement, element: HTMLElement): void;
7
+ /**
8
+ * Attaches a corrective scroll listener to the container referenced by
9
+ * `containerRef`. When keyboard focus moves to a descendant element,
10
+ * react-aria's Chrome-specific scroll path may leave the focused element
11
+ * partially or fully out of view. This hook schedules a corrective
12
+ * `scrollBy` in the animation frame after react-aria's own frame, ensuring
13
+ * the focused element is visible.
14
+ */
15
+ export declare function useTableScrollCorrection(containerRef: RefObject<HTMLDivElement | null>): void;
@@ -0,0 +1,211 @@
1
+ import { getInteractionModality } from '@react-aria/interactions';
2
+ import { useEffect } from 'react';
3
+
4
+ const getElementPadding = element => {
5
+ const style = getComputedStyle(element);
6
+ return {
7
+ paddingTop: parseFloat(style.paddingTop) || 0,
8
+ paddingRight: parseFloat(style.paddingRight) || 0,
9
+ paddingBottom: parseFloat(style.paddingBottom) || 0,
10
+ paddingLeft: parseFloat(style.paddingLeft) || 0
11
+ };
12
+ };
13
+ const getViewportDimensions = () => {
14
+ const {
15
+ visualViewport
16
+ } = window;
17
+ if (!visualViewport) {
18
+ return {
19
+ top: 0,
20
+ right: window.innerWidth,
21
+ bottom: window.innerHeight,
22
+ left: 0
23
+ };
24
+ }
25
+ return {
26
+ top: 0,
27
+ right: visualViewport.width,
28
+ bottom: visualViewport.height,
29
+ left: 0
30
+ };
31
+ };
32
+ function getScrollableAncestors(element) {
33
+ const ancestors = [];
34
+ let node = element.parentElement;
35
+ while (node) {
36
+ const {
37
+ overflowY,
38
+ overflowX
39
+ } = getComputedStyle(node);
40
+ const isScrollableY = /(auto|scroll|overlay)/.test(overflowY) && node.scrollHeight > node.clientHeight;
41
+ const isScrollableX = /(auto|scroll|overlay)/.test(overflowX) && node.scrollWidth > node.clientWidth;
42
+ if (isScrollableY || isScrollableX) {
43
+ ancestors.push(node);
44
+ }
45
+ node = node.parentElement;
46
+ }
47
+ const root = document.scrollingElement;
48
+ if (root && root instanceof HTMLElement) {
49
+ ancestors.push(root);
50
+ }
51
+ return ancestors;
52
+ }
53
+ /**
54
+ * corrects the scroll position of the ancestor element to make the element visible
55
+ */
56
+ function scrollElementIntoAncestor(ancestor, element) {
57
+ const {
58
+ paddingTop,
59
+ paddingRight,
60
+ paddingBottom,
61
+ paddingLeft
62
+ } = getElementPadding(ancestor);
63
+ const eRect = element.getBoundingClientRect();
64
+ const isRootScroller = ancestor === document.scrollingElement;
65
+ const aRect = isRootScroller ? getViewportDimensions() : ancestor.getBoundingClientRect();
66
+ let dy = 0;
67
+ if (eRect.top < aRect.top + paddingTop) {
68
+ dy = eRect.top - aRect.top - paddingTop;
69
+ } else if (eRect.bottom > aRect.bottom - paddingBottom) {
70
+ dy = eRect.bottom - aRect.bottom + paddingBottom;
71
+ }
72
+ let dx = 0;
73
+ if (eRect.left < aRect.left + paddingLeft) {
74
+ dx = eRect.left - aRect.left - paddingLeft;
75
+ } else if (eRect.right > aRect.right - paddingRight) {
76
+ dx = eRect.right - aRect.right + paddingRight;
77
+ }
78
+ if (dx !== 0 || dy !== 0) {
79
+ ancestor.scrollBy({
80
+ left: dx,
81
+ top: dy,
82
+ behavior: 'instant'
83
+ });
84
+ }
85
+ }
86
+ /**
87
+ * Scrolls `element` into the visible area of `container`, respecting the
88
+ * container's CSS `scroll-padding`. Uses manual `scrollBy` instead of native
89
+ * `element.scrollIntoView` to work around Chromium bug #40074749, which causes
90
+ * `scrollIntoView` on `<td>` elements to skip the real scroll container.
91
+ *
92
+ * Horizontal correction is skipped for `<tr>` elements because rows span the
93
+ * full table width and would cause erroneous horizontal scrolling.
94
+ */
95
+ function scrollElementIntoContainer(container, element) {
96
+ const {
97
+ paddingTop,
98
+ paddingRight,
99
+ paddingBottom,
100
+ paddingLeft
101
+ } = getElementPadding(container);
102
+ const cRect = container.getBoundingClientRect();
103
+ const eRect = element.getBoundingClientRect();
104
+ const stickyHeader = container.querySelector('table > thead > tr');
105
+ const stickyHeaderRect = stickyHeader instanceof HTMLElement ? stickyHeader.getBoundingClientRect() : null;
106
+ // Get the viewport dimensions to check if the element is completely visible
107
+ const {
108
+ top: viewportTop,
109
+ right: viewportRight,
110
+ bottom: viewportBottom,
111
+ left: viewportLeft
112
+ } = getViewportDimensions();
113
+ const visibleTop = Math.max(cRect.top, viewportTop);
114
+ const visibleRight = Math.min(cRect.right, viewportRight);
115
+ const visibleBottom = Math.min(cRect.bottom, viewportBottom);
116
+ const visibleLeft = Math.max(cRect.left, viewportLeft);
117
+ const isRow = element.tagName === 'TR';
118
+ const isInsideTableHead = element.closest('thead') !== null;
119
+ const stickyHeaderOverlayTopInset = stickyHeaderRect && !isInsideTableHead ? Math.max(0, stickyHeaderRect.bottom - visibleTop) : 0;
120
+ const topInset = paddingTop + stickyHeaderOverlayTopInset;
121
+ const row = element.closest('tr');
122
+ const firstRowCell = row?.firstElementChild instanceof HTMLElement ? row.firstElementChild : null;
123
+ const firstRowCellRect = firstRowCell?.getBoundingClientRect();
124
+ const firstRowCellStyle = firstRowCell ? getComputedStyle(firstRowCell) : null;
125
+ const isFirstCellSticky = firstRowCellStyle?.position === 'sticky';
126
+ const isWithinStickyFirstCell = Boolean(isFirstCellSticky && firstRowCell && (firstRowCell === element || firstRowCell.contains(element)));
127
+ const stickyFirstCellOverlayLeftInset = firstRowCellRect && isFirstCellSticky ? Math.max(0, firstRowCellRect.right - visibleLeft) : 0;
128
+ const leftInset = isWithinStickyFirstCell ? paddingLeft : paddingLeft + stickyFirstCellOverlayLeftInset;
129
+ let dy = 0;
130
+ if (eRect.top < visibleTop + topInset) {
131
+ dy = eRect.top - visibleTop - topInset;
132
+ } else if (eRect.bottom > visibleBottom - paddingBottom) {
133
+ dy = eRect.bottom - visibleBottom + paddingBottom;
134
+ }
135
+ let dx = 0;
136
+ if (!isRow) {
137
+ if (eRect.left < visibleLeft + leftInset) {
138
+ dx = eRect.left - visibleLeft - leftInset;
139
+ } else if (eRect.right > visibleRight - paddingRight) {
140
+ dx = eRect.right - visibleRight + paddingRight;
141
+ }
142
+ }
143
+ if (dx !== 0 || dy !== 0) {
144
+ const prevScrollTop = container.scrollTop;
145
+ const prevScrollLeft = container.scrollLeft;
146
+ container.scrollBy({
147
+ left: dx,
148
+ top: dy,
149
+ behavior: 'instant'
150
+ });
151
+ const actualDy = container.scrollTop - prevScrollTop;
152
+ const actualDx = container.scrollLeft - prevScrollLeft;
153
+ const didNotFullyApply = Math.abs(actualDy - dy) > 0.5 || Math.abs(actualDx - dx) > 0.5;
154
+ // Check if scroll wrapper was able to correctly show focused element
155
+ // If not, change scroll position of the ancestor elements to make element visible
156
+ if (didNotFullyApply) {
157
+ const outerAncestors = getScrollableAncestors(container);
158
+ outerAncestors.forEach(ancestor => {
159
+ scrollElementIntoAncestor(ancestor, element);
160
+ });
161
+ }
162
+ }
163
+ }
164
+ /**
165
+ * Attaches a corrective scroll listener to the container referenced by
166
+ * `containerRef`. When keyboard focus moves to a descendant element,
167
+ * react-aria's Chrome-specific scroll path may leave the focused element
168
+ * partially or fully out of view. This hook schedules a corrective
169
+ * `scrollBy` in the animation frame after react-aria's own frame, ensuring
170
+ * the focused element is visible.
171
+ */
172
+ function useTableScrollCorrection(containerRef) {
173
+ useEffect(() => {
174
+ const container = containerRef.current;
175
+ if (!container) {
176
+ return;
177
+ }
178
+ let raf1 = 0;
179
+ let raf2 = 0;
180
+ const onFocusIn = e => {
181
+ const modality = getInteractionModality();
182
+ const target = e.target;
183
+ const containsTarget = container.contains(target);
184
+ if (modality !== 'keyboard') {
185
+ return;
186
+ }
187
+ if (!containsTarget) {
188
+ return;
189
+ }
190
+ cancelAnimationFrame(raf1);
191
+ cancelAnimationFrame(raf2);
192
+ // react-aria schedules its (broken) scroll in one rAF; we run in
193
+ // the following frame to override the incorrect final position.
194
+ raf1 = requestAnimationFrame(() => {
195
+ raf2 = requestAnimationFrame(() => {
196
+ scrollElementIntoContainer(container, target);
197
+ });
198
+ });
199
+ };
200
+ container.addEventListener('focusin', onFocusIn);
201
+ // eslint-disable-next-line consistent-return
202
+ return () => {
203
+ container.removeEventListener('focusin', onFocusIn);
204
+ cancelAnimationFrame(raf1);
205
+ cancelAnimationFrame(raf2);
206
+ };
207
+ // since it is a ref, it will not trigger a re-render, however eslint still warns to add it to the dependency array
208
+ }, [containerRef]);
209
+ }
210
+
211
+ export { getScrollableAncestors, scrollElementIntoAncestor, useTableScrollCorrection };
@@ -11,12 +11,10 @@ export declare const EmptyState: import("react").ForwardRefExoticComponent<Empty
11
11
  */
12
12
  PrimaryAction: import("react").ForwardRefExoticComponent<(Omit<import("../primitives/base-button").BaseButtonInterface & Required<Pick<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
13
13
  children?: string | string[];
14
- icon?: import("../button/types").SvgIconComponent;
15
14
  endIcon?: import("../button/types").SvgIconComponent;
16
15
  startIcon?: import("../button/types").SvgIconComponent;
17
16
  }, "ref"> | Omit<import("../primitives/base-button").BaseButtonInterface & Partial<Record<keyof import("../primitives/base-button").Loading, never>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
18
17
  children?: string | string[];
19
- icon?: import("../button/types").SvgIconComponent;
20
18
  endIcon?: import("../button/types").SvgIconComponent;
21
19
  startIcon?: import("../button/types").SvgIconComponent;
22
20
  }, "ref">) & import("react").RefAttributes<HTMLButtonElement>>;
@@ -11,23 +11,19 @@ export declare const GuidedTooltipFooter: (({ children, className, ...rest }: Gu
11
11
  ActionsContainer: ({ children, className, ...rest }: GuidedTooltipActionsContainerProps) => import("react/jsx-runtime").JSX.Element;
12
12
  PrimaryAction: import("react").ForwardRefExoticComponent<(Omit<import("../primitives/base-button").BaseButtonInterface & Required<Pick<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
13
13
  children?: string | string[];
14
- icon?: import("../button/types").SvgIconComponent;
15
14
  endIcon?: import("../button/types").SvgIconComponent;
16
15
  startIcon?: import("../button/types").SvgIconComponent;
17
16
  }, "ref"> | Omit<import("../primitives/base-button").BaseButtonInterface & Partial<Record<keyof import("../primitives/base-button").Loading, never>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
18
17
  children?: string | string[];
19
- icon?: import("../button/types").SvgIconComponent;
20
18
  endIcon?: import("../button/types").SvgIconComponent;
21
19
  startIcon?: import("../button/types").SvgIconComponent;
22
20
  }, "ref">) & import("react").RefAttributes<HTMLButtonElement>>;
23
21
  SecondaryAction: import("react").ForwardRefExoticComponent<(Omit<import("../primitives/base-button").BaseButtonInterface & Required<Pick<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
24
22
  children?: string | string[];
25
- icon?: import("../button/types").SvgIconComponent;
26
23
  endIcon?: import("../button/types").SvgIconComponent;
27
24
  startIcon?: import("../button/types").SvgIconComponent;
28
25
  }, "ref"> | Omit<import("../primitives/base-button").BaseButtonInterface & Partial<Record<keyof import("../primitives/base-button").Loading, never>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
29
26
  children?: string | string[];
30
- icon?: import("../button/types").SvgIconComponent;
31
27
  endIcon?: import("../button/types").SvgIconComponent;
32
28
  startIcon?: import("../button/types").SvgIconComponent;
33
29
  }, "ref">) & import("react").RefAttributes<HTMLButtonElement>>;
@@ -5,23 +5,19 @@ export declare const GuidedTooltip: (({ children, onOpenChange, open, container,
5
5
  ActionsContainer: ({ children, className, ...rest }: import("./types").GuidedTooltipActionsContainerProps) => import("react/jsx-runtime").JSX.Element;
6
6
  PrimaryAction: import("react").ForwardRefExoticComponent<(Omit<import("../primitives/base-button").BaseButtonInterface & Required<Pick<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
7
7
  children?: string | string[];
8
- icon?: import("../button/types").SvgIconComponent;
9
8
  endIcon?: import("../button/types").SvgIconComponent;
10
9
  startIcon?: import("../button/types").SvgIconComponent;
11
10
  }, "ref"> | Omit<import("../primitives/base-button").BaseButtonInterface & Partial<Record<keyof import("../primitives/base-button").Loading, never>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
12
11
  children?: string | string[];
13
- icon?: import("../button/types").SvgIconComponent;
14
12
  endIcon?: import("../button/types").SvgIconComponent;
15
13
  startIcon?: import("../button/types").SvgIconComponent;
16
14
  }, "ref">) & import("react").RefAttributes<HTMLButtonElement>>;
17
15
  SecondaryAction: import("react").ForwardRefExoticComponent<(Omit<import("../primitives/base-button").BaseButtonInterface & Required<Pick<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
18
16
  children?: string | string[];
19
- icon?: import("../button/types").SvgIconComponent;
20
17
  endIcon?: import("../button/types").SvgIconComponent;
21
18
  startIcon?: import("../button/types").SvgIconComponent;
22
19
  }, "ref"> | Omit<import("../primitives/base-button").BaseButtonInterface & Partial<Record<keyof import("../primitives/base-button").Loading, never>> & Omit<import("../primitives/base-button").Loading, keyof import("../primitives/base-button").Loading> & {
23
20
  children?: string | string[];
24
- icon?: import("../button/types").SvgIconComponent;
25
21
  endIcon?: import("../button/types").SvgIconComponent;
26
22
  startIcon?: import("../button/types").SvgIconComponent;
27
23
  }, "ref">) & import("react").RefAttributes<HTMLButtonElement>>;