@westpac/ui 0.57.4 → 0.59.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 (110) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/component-type.json +1 -1
  3. package/dist/components/compacta/compacta.component.d.ts +1 -1
  4. package/dist/components/compacta/compacta.component.js +21 -1
  5. package/dist/components/compacta/compacta.types.d.ts +12 -0
  6. package/dist/components/index.d.ts +1 -0
  7. package/dist/components/index.js +1 -0
  8. package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.component.d.ts +2 -0
  9. package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.component.js +20 -0
  10. package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.styles.d.ts +37 -0
  11. package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.styles.js +8 -0
  12. package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.types.d.ts +5 -0
  13. package/dist/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.types.js +1 -0
  14. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.component.d.ts +2 -0
  15. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.component.js +31 -0
  16. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.styles.d.ts +25 -0
  17. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.styles.js +6 -0
  18. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.types.d.ts +4 -0
  19. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.types.js +1 -0
  20. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.component.d.ts +2 -0
  21. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.component.js +62 -0
  22. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.styles.d.ts +82 -0
  23. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.styles.js +32 -0
  24. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.types.d.ts +8 -0
  25. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.types.js +1 -0
  26. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-select-all-option/multi-select-select-all-option.component.d.ts +1 -0
  27. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-select-all-option/multi-select-select-all-option.component.js +93 -0
  28. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-select-all-option/multi-select-select-all-option.styles.d.ts +64 -0
  29. package/dist/components/multi-select/components/multi-select-list-box/components/multi-select-select-all-option/multi-select-select-all-option.styles.js +26 -0
  30. package/dist/components/multi-select/components/multi-select-list-box/multi-select-list-box.component.d.ts +2 -0
  31. package/dist/components/multi-select/components/multi-select-list-box/multi-select-list-box.component.js +35 -0
  32. package/dist/components/multi-select/components/multi-select-list-box/multi-select-list-box.styles.d.ts +43 -0
  33. package/dist/components/multi-select/components/multi-select-list-box/multi-select-list-box.styles.js +9 -0
  34. package/dist/components/multi-select/components/multi-select-list-box/multi-select-list-box.types.d.ts +5 -0
  35. package/dist/components/multi-select/components/multi-select-list-box/multi-select-list-box.types.js +1 -0
  36. package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.component.d.ts +2 -0
  37. package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.component.js +118 -0
  38. package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.d.ts +263 -0
  39. package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.js +99 -0
  40. package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.d.ts +15 -0
  41. package/dist/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.js +1 -0
  42. package/dist/components/multi-select/components/multi-select-popover/multi-select-popover.component.d.ts +2 -0
  43. package/dist/components/multi-select/components/multi-select-popover/multi-select-popover.component.js +52 -0
  44. package/dist/components/multi-select/components/multi-select-popover/multi-select-popover.styles.d.ts +31 -0
  45. package/dist/components/multi-select/components/multi-select-popover/multi-select-popover.styles.js +7 -0
  46. package/dist/components/multi-select/components/multi-select-popover/multi-select-popover.types.d.ts +6 -0
  47. package/dist/components/multi-select/components/multi-select-popover/multi-select-popover.types.js +1 -0
  48. package/dist/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.component.d.ts +2 -0
  49. package/dist/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.component.js +74 -0
  50. package/dist/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.styles.d.ts +31 -0
  51. package/dist/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.styles.js +7 -0
  52. package/dist/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.types.d.ts +6 -0
  53. package/dist/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.types.js +1 -0
  54. package/dist/components/multi-select/index.d.ts +2 -0
  55. package/dist/components/multi-select/index.js +1 -0
  56. package/dist/components/multi-select/multi-select.component.d.ts +7 -0
  57. package/dist/components/multi-select/multi-select.component.js +95 -0
  58. package/dist/components/multi-select/multi-select.styles.d.ts +25 -0
  59. package/dist/components/multi-select/multi-select.styles.js +6 -0
  60. package/dist/components/multi-select/multi-select.types.d.ts +61 -0
  61. package/dist/components/multi-select/multi-select.types.js +1 -0
  62. package/dist/components/multi-select/utils/filter-nodes.d.ts +2 -0
  63. package/dist/components/multi-select/utils/filter-nodes.js +25 -0
  64. package/dist/components/tooltip/components/tooltip-content/tooltip-content.component.d.ts +1 -1
  65. package/dist/components/tooltip/components/tooltip-content/tooltip-content.component.js +4 -2
  66. package/dist/components/tooltip/components/tooltip-content/tooltip-content.styles.d.ts +16 -1
  67. package/dist/components/tooltip/components/tooltip-content/tooltip-content.styles.js +7 -1
  68. package/dist/components/tooltip/components/tooltip-content/tooltip-content.types.d.ts +1 -0
  69. package/dist/components/tooltip/tooltip.component.d.ts +1 -1
  70. package/dist/components/tooltip/tooltip.component.js +4 -3
  71. package/dist/components/tooltip/tooltip.types.d.ts +3 -0
  72. package/dist/css/westpac-ui.css +366 -0
  73. package/dist/css/westpac-ui.min.css +366 -0
  74. package/package.json +4 -1
  75. package/src/components/compacta/compacta.component.tsx +21 -0
  76. package/src/components/compacta/compacta.types.ts +10 -0
  77. package/src/components/index.ts +1 -0
  78. package/src/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.component.tsx +26 -0
  79. package/src/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.styles.ts +9 -0
  80. package/src/components/multi-select/components/multi-select-dropdown/multi-select-dropdown.types.ts +6 -0
  81. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.component.tsx +42 -0
  82. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.styles.ts +7 -0
  83. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-list-box-section/multi-select-list-box-section.types.ts +5 -0
  84. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.component.tsx +66 -0
  85. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.styles.ts +33 -0
  86. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-option/multi-select-option.types.ts +7 -0
  87. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-select-all-option/multi-select-select-all-option.component.tsx +105 -0
  88. package/src/components/multi-select/components/multi-select-list-box/components/multi-select-select-all-option/multi-select-select-all-option.styles.ts +22 -0
  89. package/src/components/multi-select/components/multi-select-list-box/multi-select-list-box.component.tsx +42 -0
  90. package/src/components/multi-select/components/multi-select-list-box/multi-select-list-box.styles.ts +10 -0
  91. package/src/components/multi-select/components/multi-select-list-box/multi-select-list-box.types.ts +6 -0
  92. package/src/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.component.tsx +136 -0
  93. package/src/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.styles.ts +74 -0
  94. package/src/components/multi-select/components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.ts +19 -0
  95. package/src/components/multi-select/components/multi-select-popover/multi-select-popover.component.tsx +64 -0
  96. package/src/components/multi-select/components/multi-select-popover/multi-select-popover.styles.ts +8 -0
  97. package/src/components/multi-select/components/multi-select-popover/multi-select-popover.types.ts +8 -0
  98. package/src/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.component.tsx +81 -0
  99. package/src/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.styles.ts +8 -0
  100. package/src/components/multi-select/components/multi-select-searchbar/multi-select-searchbar.types.ts +7 -0
  101. package/src/components/multi-select/index.ts +2 -0
  102. package/src/components/multi-select/multi-select.component.tsx +116 -0
  103. package/src/components/multi-select/multi-select.styles.ts +7 -0
  104. package/src/components/multi-select/multi-select.types.ts +60 -0
  105. package/src/components/multi-select/utils/filter-nodes.ts +29 -0
  106. package/src/components/tooltip/components/tooltip-content/tooltip-content.component.tsx +2 -2
  107. package/src/components/tooltip/components/tooltip-content/tooltip-content.styles.ts +6 -0
  108. package/src/components/tooltip/components/tooltip-content/tooltip-content.types.ts +1 -0
  109. package/src/components/tooltip/tooltip.component.tsx +7 -3
  110. package/src/components/tooltip/tooltip.types.ts +4 -0
@@ -0,0 +1,8 @@
1
+ import { tv } from 'tailwind-variants';
2
+
3
+ export const styles = tv({
4
+ slots: {
5
+ underlay: 'fixed inset-0 bg-black/5',
6
+ overlay: 'z-10 flex flex-col overflow-hidden rounded border border-border bg-white shadow-lg',
7
+ },
8
+ });
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+
3
+ import type { AriaPopoverProps } from 'react-aria';
4
+
5
+ export type MultiSelectPopoverProps = {
6
+ children: React.ReactNode;
7
+ className?: string;
8
+ } & Omit<AriaPopoverProps, 'popoverRef' | 'triggerRef'>;
@@ -0,0 +1,81 @@
1
+ import React, { useContext, useCallback, KeyboardEvent } from 'react';
2
+
3
+ import { Button } from '../../../../components/button/index.js';
4
+ import { ClearIcon, SearchIcon } from '../../../../components/icon/index.js';
5
+ import { InputGroup } from '../../../../components/input-group/index.js';
6
+ import { Input } from '../../../input/index.js';
7
+ import { MultiSelectContext } from '../../multi-select.component.js';
8
+
9
+ import { styles as searchbarStyles } from './multi-select-searchbar.styles.js';
10
+
11
+ import type { MultiSelectSearchbarProps } from './multi-select-searchbar.types.js';
12
+
13
+ export function MultiSelectSearchbar({
14
+ filterText,
15
+ setFilterText,
16
+ closeBtnRef,
17
+ }: Pick<MultiSelectSearchbarProps, 'filterText' | 'setFilterText' | 'closeBtnRef'>) {
18
+ const { size, inputRef, selectAllRef, listBoxRef } = useContext(MultiSelectContext);
19
+ const styles = searchbarStyles();
20
+ const handleInputKeyDown = useCallback(
21
+ (e: KeyboardEvent<HTMLInputElement>) => {
22
+ if (e.key === 'ArrowDown') {
23
+ e.preventDefault();
24
+ if (selectAllRef.current) {
25
+ selectAllRef.current.focus();
26
+ } else {
27
+ const firstItem = listBoxRef.current?.querySelector('[data-key]') as HTMLElement;
28
+ firstItem?.focus();
29
+ }
30
+ }
31
+ if (e.key === 'Escape' && filterText.length > 0) {
32
+ e.stopPropagation();
33
+ setFilterText('');
34
+ }
35
+ if (e.key === 'Tab' && filterText.length > 0) {
36
+ e.preventDefault();
37
+ e.stopPropagation();
38
+ closeBtnRef.current?.focus();
39
+ }
40
+ },
41
+ [filterText.length, setFilterText, selectAllRef, listBoxRef, closeBtnRef],
42
+ );
43
+ return (
44
+ <div className={styles.searchInputWrapper()}>
45
+ <InputGroup
46
+ before={{
47
+ icon: props => <SearchIcon {...props} color="muted" />,
48
+ }}
49
+ after={
50
+ filterText.length > 0 && {
51
+ inset: true,
52
+ element: (
53
+ <Button
54
+ onClick={() => {
55
+ setFilterText('');
56
+ inputRef.current?.focus();
57
+ }}
58
+ look="unstyled"
59
+ className={styles.clearButton()}
60
+ ref={closeBtnRef}
61
+ aria-label="Clear filter text"
62
+ >
63
+ <ClearIcon color="muted" size="small" />
64
+ </Button>
65
+ ),
66
+ }
67
+ }
68
+ aria-label="Filter options"
69
+ >
70
+ <Input
71
+ ref={inputRef}
72
+ size={size}
73
+ value={filterText}
74
+ onChange={e => setFilterText(e.target.value)}
75
+ onKeyDown={handleInputKeyDown}
76
+ tabIndex={-1}
77
+ />
78
+ </InputGroup>
79
+ </div>
80
+ );
81
+ }
@@ -0,0 +1,8 @@
1
+ import { tv } from 'tailwind-variants';
2
+
3
+ export const styles = tv({
4
+ slots: {
5
+ searchInputWrapper: 'border-b border-b-border p-2',
6
+ clearButton: 'mb-0.5 px-2',
7
+ },
8
+ });
@@ -0,0 +1,7 @@
1
+ import { ButtonRef } from '../../../../components/button/button.types.js';
2
+
3
+ export type MultiSelectSearchbarProps = {
4
+ filterText: string;
5
+ setFilterText: (text: string) => void;
6
+ closeBtnRef: React.RefObject<ButtonRef>;
7
+ };
@@ -0,0 +1,2 @@
1
+ export { MultiSelect, MultiSelectItem, MultiSelectSection } from './multi-select.component.js';
2
+ export { type MultiSelectValue } from './multi-select.types.js';
@@ -0,0 +1,116 @@
1
+ 'use client';
2
+
3
+ import { Node } from '@react-types/shared';
4
+ import React, { useRef, useState, memo, createContext } from 'react';
5
+ import { useFilter, useOverlayTrigger } from 'react-aria';
6
+ import { Item, useListState, useOverlayTriggerState } from 'react-stately';
7
+
8
+ import { MultiSelectDropdown } from './components/multi-select-dropdown/multi-select-dropdown.component.js';
9
+ import { MultiSelectListBoxTrigger } from './components/multi-select-list-box-trigger/multi-select-list-box-trigger.component.js';
10
+ import { styles as multiSelectStyles } from './multi-select.styles.js';
11
+ import { filterNodes } from './utils/filter-nodes.js';
12
+
13
+ import type {
14
+ MultiSelectContextProps,
15
+ MultiSelectItemProps,
16
+ MultiSelectProps,
17
+ MultiSelectValue,
18
+ } from './multi-select.types.js';
19
+
20
+ export const MultiSelectContext = createContext<MultiSelectContextProps>({
21
+ overlayState: {} as MultiSelectContextProps['overlayState'],
22
+ listState: {} as MultiSelectContextProps['listState'],
23
+ listBoxRef: { current: null },
24
+ buttonRef: { current: null },
25
+ popoverRef: { current: null },
26
+ selectAllRef: { current: null },
27
+ inputRef: { current: null },
28
+ filterText: '',
29
+ overlayProps: {},
30
+ });
31
+
32
+ export function BaseMultiSelect<T extends MultiSelectValue = MultiSelectValue>({
33
+ size = 'medium',
34
+ listBoxProps,
35
+ selectionMode = 'multiple',
36
+ selectedKeys,
37
+ onSelectionChange,
38
+ placeholder = 'Select',
39
+ showSingleSectionTitle = false,
40
+ placement,
41
+ portalContainer,
42
+ id,
43
+ ...props
44
+ }: MultiSelectProps<T>) {
45
+ const [filterText, setFilterText] = useState('');
46
+ const filter = useFilter({ sensitivity: 'base' });
47
+
48
+ const listState = useListState<T>({
49
+ ...props,
50
+ selectedKeys,
51
+ selectionMode,
52
+ onSelectionChange,
53
+ // Need to provide a custom filter as the default filtering in react-stately does not work with sections
54
+ // https://github.com/adobe/react-spectrum/issues/4930
55
+ filter: (nodes: Iterable<Node<T>>) =>
56
+ filterNodes(nodes, filterText, (value, string) => filter.contains(value, string)),
57
+ });
58
+
59
+ // refs
60
+ const inputRef = useRef<HTMLInputElement>(null);
61
+ const buttonRef = useRef<HTMLButtonElement>(null);
62
+ const popoverRef = useRef<HTMLDivElement>(null);
63
+ const selectAllRef = useRef<HTMLInputElement>(null);
64
+ const listBoxRef = useRef<HTMLUListElement>(null);
65
+
66
+ const overlayState = useOverlayTriggerState({
67
+ onOpenChange: isOpen => {
68
+ if (isOpen) {
69
+ requestAnimationFrame(() => {
70
+ inputRef.current?.focus();
71
+ });
72
+ }
73
+ if (!isOpen) {
74
+ buttonRef.current?.focus();
75
+ }
76
+ },
77
+ });
78
+ const { triggerProps, overlayProps } = useOverlayTrigger({ type: 'dialog' }, overlayState, buttonRef);
79
+
80
+ const styles = multiSelectStyles({});
81
+
82
+ return (
83
+ <MultiSelectContext.Provider
84
+ value={{
85
+ filterText,
86
+ size,
87
+ overlayState,
88
+ listState,
89
+ buttonRef,
90
+ popoverRef,
91
+ placement,
92
+ selectAllRef,
93
+ listBoxRef,
94
+ inputRef,
95
+ overlayProps,
96
+ portalContainer,
97
+ }}
98
+ >
99
+ <div className={styles.root()}>
100
+ <MultiSelectListBoxTrigger
101
+ placeholder={placeholder}
102
+ selectedKeys={selectedKeys}
103
+ showSingleSectionTitle={showSingleSectionTitle}
104
+ triggerProps={triggerProps}
105
+ id={id}
106
+ />
107
+ {overlayState.isOpen && <MultiSelectDropdown setFilterText={setFilterText} {...listBoxProps} />}
108
+ </div>
109
+ </MultiSelectContext.Provider>
110
+ );
111
+ }
112
+ export const MultiSelect = memo(BaseMultiSelect);
113
+
114
+ // Exporting react-stately's Item with custom props/naming and Section with custom naming to align with other components
115
+ export const MultiSelectItem = Item as (props: MultiSelectItemProps) => JSX.Element;
116
+ export { Section as MultiSelectSection } from 'react-stately';
@@ -0,0 +1,7 @@
1
+ import { tv } from 'tailwind-variants';
2
+
3
+ export const styles = tv({
4
+ slots: {
5
+ root: 'relative flex flex-col gap-1',
6
+ },
7
+ });
@@ -0,0 +1,60 @@
1
+ import { DOMProps } from '@react-types/shared';
2
+ import { Key, ReactNode, RefObject } from 'react';
3
+ import { AriaListBoxOptions, AriaPopoverProps } from 'react-aria';
4
+ import { ItemProps, ListProps, ListState, OverlayTriggerState } from 'react-stately';
5
+
6
+ import { MultiSelectSize } from './components/multi-select-list-box-trigger/multi-select-list-box-trigger.types.js';
7
+
8
+ export type MultiSelectContextProps<T extends object = object> = {
9
+ size?: MultiSelectSize;
10
+ overlayState: OverlayTriggerState;
11
+ listState: ListState<T>;
12
+ buttonRef: RefObject<HTMLButtonElement>;
13
+ listBoxRef: RefObject<HTMLUListElement>;
14
+ popoverRef: RefObject<HTMLDivElement>;
15
+ selectAllRef: RefObject<HTMLInputElement>;
16
+ inputRef: RefObject<HTMLInputElement>;
17
+ filterText: string;
18
+ overlayProps: DOMProps;
19
+ placement?: AriaPopoverProps['placement'];
20
+ portalContainer?: Element;
21
+ };
22
+
23
+ export type MultiSelectItemProps<T extends object = object> = { description?: string } & ItemProps<T>;
24
+
25
+ // Props for the items that can be passed to the MultiSelect component
26
+ export type MultiSelectValue = { textValue?: string; content?: ReactNode; key: Key; description?: string };
27
+
28
+ export type MultiSelectProps<T> = {
29
+ /**
30
+ * Props for the list box within the multi-select
31
+ */
32
+ listBoxProps?: Omit<AriaListBoxOptions<T>, 'state' | 'selectionMode'>;
33
+ /**
34
+ * id for the base multi-select container for accessibility/other uses
35
+ */
36
+ id?: string;
37
+ /**
38
+ * Placeholder text for the input
39
+ */
40
+ placeholder?: string;
41
+ /**
42
+ * Manual placement of the dropdown, will flip automatically if there is not enough space
43
+ * @default bottom
44
+ */
45
+ placement?: AriaPopoverProps['placement'];
46
+ /**
47
+ * Element where the popover will be rendered, by default it will be into the body
48
+ */
49
+ portalContainer?: Element;
50
+ /**
51
+ * Whether to show the section for the selected option in the field i.e. "Transaction: Savings" rather than "Savings"
52
+ * NOTE: Only works with single selectionMode multi-selects
53
+ */
54
+ showSingleSectionTitle?: boolean;
55
+ /**
56
+ * Size of input
57
+ * @default medium
58
+ */
59
+ size?: MultiSelectSize;
60
+ } & ListProps<T>;
@@ -0,0 +1,29 @@
1
+ import { Node } from '@react-types/shared';
2
+
3
+ export function filterNodes<T>(
4
+ nodes: Iterable<Node<T>>,
5
+ filterText: string,
6
+ contains: (value: string, search: string) => boolean,
7
+ ): Iterable<Node<T>> {
8
+ if (!filterText) return nodes;
9
+
10
+ const arr = Array.from(nodes);
11
+
12
+ return arr.flatMap((node: Node<T>) => {
13
+ if (node.type !== 'section') {
14
+ return contains(node.textValue ?? '', filterText) ? [node] : [];
15
+ }
16
+
17
+ // See https://github.com/adobe/react-spectrum/discussions/4348 for why this deprecation is ignored
18
+ // eslint-disable-next-line sonarjs/deprecation
19
+ const childNodesArr = Array.from(node.childNodes || []);
20
+ const matchedChildren: Node<T>[] = childNodesArr.filter((child: Node<T>) =>
21
+ contains(child.textValue ?? '', filterText),
22
+ );
23
+
24
+ if (matchedChildren.length === 0) return [];
25
+
26
+ const sectionWithMatches = { ...node, childNodes: matchedChildren } as Node<T>;
27
+ return [sectionWithMatches];
28
+ });
29
+ }
@@ -3,9 +3,9 @@ import React from 'react';
3
3
  import { styles } from './tooltip-content.styles.js';
4
4
  import { TooltipContentProps } from './tooltip-content.types.js';
5
5
 
6
- export function TooltipContent({ children, id }: TooltipContentProps) {
6
+ export function TooltipContent({ children, id, position }: TooltipContentProps) {
7
7
  return children ? (
8
- <span className={styles()} role="tooltip" id={id}>
8
+ <span className={styles({ position })} role="tooltip" id={id}>
9
9
  {children}
10
10
  </span>
11
11
  ) : null;
@@ -2,4 +2,10 @@ import { tv } from 'tailwind-variants';
2
2
 
3
3
  export const styles = tv({
4
4
  base: 'absolute left-1 top-full z-10 mt-2 whitespace-nowrap rounded-sm border border-border bg-background p-0.5 text-text',
5
+ variants: {
6
+ position: {
7
+ top: 'top-auto bottom-full',
8
+ bottom: 'top-full mt-2 mb-0',
9
+ },
10
+ },
5
11
  });
@@ -3,4 +3,5 @@ import { ReactNode } from 'react';
3
3
  export type TooltipContentProps = {
4
4
  children?: ReactNode;
5
5
  id: string;
6
+ position?: 'top' | 'bottom';
6
7
  };
@@ -8,7 +8,7 @@ import { styles } from './tooltip.styles.js';
8
8
  import { TooltipProps } from './tooltip.types.js';
9
9
 
10
10
  // TODO: Complete component/replace with a library that works (react-tooltip if can find a way to remove aria-described by for select)
11
- export function Tooltip({ children, tooltip, id, className }: TooltipProps) {
11
+ export function Tooltip({ children, disabled, tooltip, id, className, position = 'bottom' }: TooltipProps) {
12
12
  const localId = useId();
13
13
  const [isOpen, setIsOpen] = useState(false);
14
14
  const tooltipWaitTime = useRef<NodeJS.Timeout | null>(null);
@@ -34,7 +34,7 @@ export function Tooltip({ children, tooltip, id, className }: TooltipProps) {
34
34
  }, []);
35
35
 
36
36
  useEffect(() => {
37
- setIsOpen(isFocusVisible);
37
+ setIsOpen(isFocusVisible && !disabled);
38
38
  }, [isFocusVisible]);
39
39
 
40
40
  useEffect(() => {
@@ -55,7 +55,11 @@ export function Tooltip({ children, tooltip, id, className }: TooltipProps) {
55
55
  return (
56
56
  <span {...mergeProps(hoverProps, focusProps)} className={styles({ className })}>
57
57
  {children}
58
- {isOpen && <TooltipContent id={id ?? localId}>{tooltip}</TooltipContent>}
58
+ {isOpen && (
59
+ <TooltipContent id={id ?? localId} position={position}>
60
+ {tooltip}
61
+ </TooltipContent>
62
+ )}
59
63
  </span>
60
64
  );
61
65
  }
@@ -1,8 +1,12 @@
1
1
  import { ReactNode } from 'react';
2
2
 
3
+ import { TooltipContentProps } from './components/tooltip-content/tooltip-content.types.js';
4
+
3
5
  export type TooltipProps = {
4
6
  children: ReactNode;
7
+ disabled?: boolean;
5
8
  tooltip: string;
6
9
  id?: string;
7
10
  className?: string;
11
+ position?: TooltipContentProps['position'];
8
12
  };