@lumx/react 2.2.2 → 2.2.3-alpha-export-hook1
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.
- package/esm/_internal/AlertDialog.js +1 -1
- package/esm/_internal/AutocompleteMultiple.js.map +1 -1
- package/esm/_internal/ButtonGroup.js +0 -4
- package/esm/_internal/ButtonGroup.js.map +1 -1
- package/esm/_internal/Checkbox2.js +6 -4
- package/esm/_internal/Checkbox2.js.map +1 -1
- package/esm/_internal/Chip2.js +2 -1
- package/esm/_internal/Chip2.js.map +1 -1
- package/esm/_internal/ChipGroup.js.map +1 -1
- package/esm/_internal/ClickAwayProvider.js +1 -1
- package/esm/_internal/ClickAwayProvider.js.map +1 -1
- package/esm/_internal/DatePickerField.js +0 -4
- package/esm/_internal/DatePickerField.js.map +1 -1
- package/esm/_internal/Dialog2.js.map +1 -1
- package/esm/_internal/Dropdown2.js +1 -1
- package/esm/_internal/Dropdown2.js.map +1 -1
- package/esm/_internal/IconButton.js +0 -4
- package/esm/_internal/IconButton.js.map +1 -1
- package/esm/_internal/Lightbox2.js.map +1 -1
- package/esm/_internal/List2.js +20 -4
- package/esm/_internal/List2.js.map +1 -1
- package/esm/_internal/Notification2.js.map +1 -1
- package/esm/_internal/Popover2.js.map +1 -1
- package/esm/_internal/ProgressTrackerStepPanel.js.map +1 -1
- package/esm/_internal/RadioGroup.js +1 -1
- package/esm/_internal/SelectMultiple.js +1 -1
- package/esm/_internal/SelectMultiple.js.map +1 -1
- package/esm/_internal/SideNavigationItem.js +2 -1
- package/esm/_internal/SideNavigationItem.js.map +1 -1
- package/esm/_internal/Slider2.js +1 -1
- package/esm/_internal/Slider2.js.map +1 -1
- package/esm/_internal/SlideshowControls.js +100 -2
- package/esm/_internal/SlideshowControls.js.map +1 -1
- package/esm/_internal/Switch2.js +6 -4
- package/esm/_internal/Switch2.js.map +1 -1
- package/esm/_internal/TabPanel.js.map +1 -1
- package/esm/_internal/TableRow.js +2 -1
- package/esm/_internal/TableRow.js.map +1 -1
- package/esm/_internal/TextField.js +1 -1
- package/esm/_internal/Tooltip2.js +12 -145
- package/esm/_internal/Tooltip2.js.map +1 -1
- package/esm/_internal/alert-dialog.js +3 -3
- package/esm/_internal/autocomplete.js +6 -5
- package/esm/_internal/autocomplete.js.map +1 -1
- package/esm/_internal/avatar.js +1 -2
- package/esm/_internal/avatar.js.map +1 -1
- package/esm/_internal/badge.js +1 -2
- package/esm/_internal/badge.js.map +1 -1
- package/esm/_internal/button.js +4 -4
- package/esm/_internal/checkbox.js +2 -3
- package/esm/_internal/checkbox.js.map +1 -1
- package/esm/_internal/chip.js +2 -2
- package/esm/_internal/comment-block.js +1 -2
- package/esm/_internal/comment-block.js.map +1 -1
- package/esm/_internal/constants.js.map +1 -1
- package/esm/_internal/date-picker.js +4 -4
- package/esm/_internal/dialog.js +2 -2
- package/esm/_internal/divider.js +1 -2
- package/esm/_internal/divider.js.map +1 -1
- package/esm/_internal/drag-handle.js +1 -2
- package/esm/_internal/drag-handle.js.map +1 -1
- package/esm/_internal/dropdown.js +4 -3
- package/esm/_internal/dropdown.js.map +1 -1
- package/esm/_internal/expansion-panel.js +4 -4
- package/esm/_internal/flag.js +1 -2
- package/esm/_internal/flag.js.map +1 -1
- package/esm/_internal/flex-box.js +1 -2
- package/esm/_internal/flex-box.js.map +1 -1
- package/esm/_internal/getRootClassName.js +40 -166
- package/esm/_internal/getRootClassName.js.map +1 -1
- package/esm/_internal/grid.js +1 -2
- package/esm/_internal/grid.js.map +1 -1
- package/esm/_internal/icon.js +1 -2
- package/esm/_internal/icon.js.map +1 -1
- package/esm/_internal/image-block.js +1 -2
- package/esm/_internal/image-block.js.map +1 -1
- package/esm/{index2.js → _internal/index.js} +1 -1
- package/esm/_internal/index.js.map +1 -0
- package/esm/_internal/input-helper.js +1 -2
- package/esm/_internal/input-helper.js.map +1 -1
- package/esm/_internal/input-label.js +1 -2
- package/esm/_internal/input-label.js.map +1 -1
- package/esm/_internal/lightbox.js +4 -4
- package/esm/_internal/link-preview.js +1 -2
- package/esm/_internal/link-preview.js.map +1 -1
- package/esm/_internal/link.js +1 -2
- package/esm/_internal/link.js.map +1 -1
- package/esm/_internal/list.js +3 -3
- package/esm/_internal/message.js +1 -2
- package/esm/_internal/message.js.map +1 -1
- package/esm/_internal/mosaic.js +1 -2
- package/esm/_internal/mosaic.js.map +1 -1
- package/esm/_internal/notification.js +1 -2
- package/esm/_internal/notification.js.map +1 -1
- package/esm/_internal/onEnterPressed.js +20 -0
- package/esm/_internal/onEnterPressed.js.map +1 -0
- package/esm/_internal/onEscapePressed.js +20 -0
- package/esm/_internal/onEscapePressed.js.map +1 -0
- package/esm/_internal/popover.js +2 -2
- package/esm/_internal/post-block.js +1 -2
- package/esm/_internal/post-block.js.map +1 -1
- package/esm/_internal/progress-tracker.js +2 -3
- package/esm/_internal/progress-tracker.js.map +1 -1
- package/esm/_internal/progress.js +1 -2
- package/esm/_internal/progress.js.map +1 -1
- package/esm/_internal/radio-button.js +2 -3
- package/esm/_internal/radio-button.js.map +1 -1
- package/esm/_internal/select.js +6 -5
- package/esm/_internal/select.js.map +1 -1
- package/esm/_internal/side-navigation.js +5 -4
- package/esm/_internal/side-navigation.js.map +1 -1
- package/esm/_internal/skeleton.js +1 -2
- package/esm/_internal/skeleton.js.map +1 -1
- package/esm/_internal/slider.js +2 -3
- package/esm/_internal/slider.js.map +1 -1
- package/esm/_internal/slideshow.js +6 -5
- package/esm/_internal/slideshow.js.map +1 -1
- package/esm/_internal/switch.js +2 -3
- package/esm/_internal/switch.js.map +1 -1
- package/esm/_internal/table.js +2 -2
- package/esm/_internal/tabs.js +2 -3
- package/esm/_internal/tabs.js.map +1 -1
- package/esm/_internal/text-field.js +4 -4
- package/esm/_internal/thumbnail.js +1 -2
- package/esm/_internal/thumbnail.js.map +1 -1
- package/esm/_internal/toolbar.js +1 -2
- package/esm/_internal/toolbar.js.map +1 -1
- package/esm/_internal/tooltip.js +4 -4
- package/esm/_internal/uploader.js +1 -2
- package/esm/_internal/uploader.js.map +1 -1
- package/esm/_internal/useDelayedVisibility.js.map +1 -1
- package/esm/_internal/useDisableBodyScroll.js.map +1 -1
- package/esm/_internal/useFocusTrap.js.map +1 -1
- package/esm/_internal/useRovingTabIndex.js +1 -1
- package/esm/_internal/useRovingTabIndex.js.map +1 -1
- package/esm/_internal/user-block.js +1 -2
- package/esm/_internal/user-block.js.map +1 -1
- package/esm/hooks/useOpenHoverOrLongPress.js +172 -0
- package/esm/hooks/useOpenHoverOrLongPress.js.map +1 -0
- package/esm/index.js +8 -6
- package/esm/index.js.map +1 -1
- package/package.json +4 -4
- package/src/{hooks → _internal/hooks}/useBooleanState.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useCallbackOnEscape.ts +0 -0
- package/src/{hooks → _internal/hooks}/useChipGroupNavigation.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useClickAway.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useDelayedVisibility.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useDisableBodyScroll.ts +0 -0
- package/src/{hooks → _internal/hooks}/useEventCallback.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useFocus.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useFocusTrap.ts +0 -0
- package/src/{hooks → _internal/hooks}/useInfiniteScroll.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useIntersectionObserver.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useInterval.tsx +1 -1
- package/src/{hooks → _internal/hooks}/useKeyboardListNavigation.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useListenFocus.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useOnResize.ts +0 -0
- package/src/{hooks → _internal/hooks}/useRovingTabIndex.tsx +0 -0
- package/src/{hooks → _internal/hooks}/useStopPropagation.ts +0 -0
- package/src/components/autocomplete/Autocomplete.tsx +1 -1
- package/src/components/button/__snapshots__/IconButton.test.tsx.snap +0 -5
- package/src/components/checkbox/Checkbox.test.tsx +14 -0
- package/src/components/checkbox/Checkbox.tsx +5 -1
- package/src/components/checkbox/__snapshots__/Checkbox.test.tsx.snap +51 -0
- package/src/components/chip/Chip.tsx +1 -1
- package/src/components/chip/ChipGroup.tsx +1 -1
- package/src/components/date-picker/DatePickerField.tsx +2 -2
- package/src/components/dialog/Dialog.test.tsx +1 -1
- package/src/components/dialog/Dialog.tsx +5 -5
- package/src/components/dropdown/Dropdown.tsx +1 -1
- package/src/components/lightbox/Lightbox.tsx +4 -4
- package/src/components/list/List.tsx +1 -1
- package/src/components/mosaic/Mosaic.test.tsx +1 -1
- package/src/components/notification/Notification.tsx +1 -1
- package/src/components/popover/Popover.tsx +2 -2
- package/src/components/progress-tracker/ProgressTracker.tsx +1 -1
- package/src/components/select/Select.stories.tsx +1 -1
- package/src/components/select/SelectMultiple.stories.tsx +1 -1
- package/src/components/select/WithSelectContext.tsx +1 -1
- package/src/components/slider/Slider.tsx +1 -1
- package/src/components/slideshow/Slideshow.tsx +1 -1
- package/src/components/slideshow/useSwipeNavigate.ts +1 -1
- package/src/components/switch/Switch.test.tsx +10 -0
- package/src/components/switch/Switch.tsx +5 -1
- package/src/components/switch/__snapshots__/Switch.test.tsx.snap +30 -0
- package/src/components/tabs/TabList.tsx +4 -4
- package/src/components/tooltip/Tooltip.tsx +7 -4
- package/src/constants.ts +7 -1
- package/src/hooks/useOpenHoverOrLongPress.ts +140 -0
- package/src/utils/ClickAwayProvider/ClickAwayProvider.tsx +1 -1
- package/src/utils/browserDoesNotSupportHover.test.js +24 -0
- package/src/utils/browserDoesNotSupportHover.ts +2 -0
- package/types.d.ts +6 -2
- package/esm/index2.js.map +0 -1
- package/src/components/tooltip/useTooltipOpen.tsx +0 -112
|
@@ -10,7 +10,7 @@ import { Placement } from '@lumx/react/components/popover/Popover';
|
|
|
10
10
|
|
|
11
11
|
import { getRootClassName, handleBasicClasses } from '@lumx/react/utils';
|
|
12
12
|
import { mergeRefs } from '@lumx/react/utils/mergeRefs';
|
|
13
|
-
import { useListenFocus } from '@lumx/react/hooks/useListenFocus';
|
|
13
|
+
import { useListenFocus } from '@lumx/react/_internal/hooks/useListenFocus';
|
|
14
14
|
import { CoreSelectProps, SelectVariant } from './constants';
|
|
15
15
|
|
|
16
16
|
/** The display name of the component. */
|
|
@@ -5,7 +5,7 @@ import classNames from 'classnames';
|
|
|
5
5
|
|
|
6
6
|
import { InputHelper, InputLabel, Theme } from '@lumx/react';
|
|
7
7
|
|
|
8
|
-
import useEventCallback from '@lumx/react/hooks/useEventCallback';
|
|
8
|
+
import useEventCallback from '@lumx/react/_internal/hooks/useEventCallback';
|
|
9
9
|
import { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';
|
|
10
10
|
|
|
11
11
|
import { uid } from 'uid';
|
|
@@ -5,7 +5,7 @@ import classNames from 'classnames';
|
|
|
5
5
|
import { SlideshowControls, SlideshowControlsProps, Theme } from '@lumx/react';
|
|
6
6
|
|
|
7
7
|
import { AUTOPLAY_DEFAULT_INTERVAL, FULL_WIDTH_PERCENT } from '@lumx/react/components/slideshow/constants';
|
|
8
|
-
import { useInterval } from '@lumx/react/hooks/useInterval';
|
|
8
|
+
import { useInterval } from '@lumx/react/_internal/hooks/useInterval';
|
|
9
9
|
import { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';
|
|
10
10
|
import { mergeRefs } from '@lumx/react/utils/mergeRefs';
|
|
11
11
|
|
|
@@ -142,6 +142,16 @@ describe(`<${Switch.displayName}>`, () => {
|
|
|
142
142
|
}
|
|
143
143
|
});
|
|
144
144
|
});
|
|
145
|
+
|
|
146
|
+
it('should use the given props while passing custom props to input', () => {
|
|
147
|
+
const { wrapper } = setup({
|
|
148
|
+
inputProps: {
|
|
149
|
+
'aria-labelledby': 'labelledby-id',
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
expect(wrapper).toMatchSnapshot();
|
|
154
|
+
});
|
|
145
155
|
});
|
|
146
156
|
|
|
147
157
|
// 3. Test events.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Children, forwardRef, SyntheticEvent, useMemo } from 'react';
|
|
1
|
+
import React, { Children, forwardRef, InputHTMLAttributes, SyntheticEvent, useMemo } from 'react';
|
|
2
2
|
|
|
3
3
|
import classNames from 'classnames';
|
|
4
4
|
import { uid } from 'uid';
|
|
@@ -29,6 +29,8 @@ export interface SwitchProps extends GenericProps {
|
|
|
29
29
|
value?: string;
|
|
30
30
|
/** On change callback. */
|
|
31
31
|
onChange?(isChecked: boolean, value?: string, name?: string, event?: SyntheticEvent): void;
|
|
32
|
+
/** optional props for input */
|
|
33
|
+
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
/**
|
|
@@ -71,6 +73,7 @@ export const Switch: Comp<SwitchProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
71
73
|
position,
|
|
72
74
|
theme,
|
|
73
75
|
value,
|
|
76
|
+
inputProps = {},
|
|
74
77
|
...forwardedProps
|
|
75
78
|
} = props;
|
|
76
79
|
const switchId = useMemo(() => id || `switch-${uid()}`, [id]);
|
|
@@ -109,6 +112,7 @@ export const Switch: Comp<SwitchProps, HTMLDivElement> = forwardRef((props, ref)
|
|
|
109
112
|
checked={isChecked}
|
|
110
113
|
aria-checked={Boolean(isChecked)}
|
|
111
114
|
onChange={handleChange}
|
|
115
|
+
{...inputProps}
|
|
112
116
|
/>
|
|
113
117
|
|
|
114
118
|
<div className={`${CLASSNAME}__input-placeholder`}>
|
|
@@ -29,6 +29,36 @@ exports[`<Switch> Conditions should not display the \`helper\` if no \`label\` i
|
|
|
29
29
|
</div>
|
|
30
30
|
`;
|
|
31
31
|
|
|
32
|
+
exports[`<Switch> Props should use the given props while passing custom props to input 1`] = `
|
|
33
|
+
<div
|
|
34
|
+
className="lumx-switch lumx-switch--position-left lumx-switch--theme-light lumx-switch--is-unchecked"
|
|
35
|
+
>
|
|
36
|
+
<div
|
|
37
|
+
className="lumx-switch__input-wrapper"
|
|
38
|
+
>
|
|
39
|
+
<input
|
|
40
|
+
aria-checked={false}
|
|
41
|
+
aria-labelledby="labelledby-id"
|
|
42
|
+
className="lumx-switch__input-native"
|
|
43
|
+
id="switch-uid"
|
|
44
|
+
onChange={[Function]}
|
|
45
|
+
role="switch"
|
|
46
|
+
type="checkbox"
|
|
47
|
+
/>
|
|
48
|
+
<div
|
|
49
|
+
className="lumx-switch__input-placeholder"
|
|
50
|
+
>
|
|
51
|
+
<div
|
|
52
|
+
className="lumx-switch__input-background"
|
|
53
|
+
/>
|
|
54
|
+
<div
|
|
55
|
+
className="lumx-switch__input-indicator"
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
`;
|
|
61
|
+
|
|
32
62
|
exports[`<Switch> Snapshots and structure should render correctly with a \`label\` and a \`helper\` 1`] = `
|
|
33
63
|
<div
|
|
34
64
|
className="lumx-switch lumx-switch--position-left lumx-switch--theme-light lumx-switch--is-unchecked"
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import classNames from 'classnames';
|
|
2
|
+
import React, { forwardRef, ReactNode } from 'react';
|
|
3
|
+
|
|
1
4
|
import { Alignment, Theme } from '@lumx/react';
|
|
2
5
|
import { CSS_PREFIX } from '@lumx/react/constants';
|
|
3
6
|
import { Comp, GenericProps, handleBasicClasses } from '@lumx/react/utils';
|
|
4
7
|
import { mergeRefs } from '@lumx/react/utils/mergeRefs';
|
|
5
|
-
|
|
6
|
-
import classNames from 'classnames';
|
|
7
|
-
import React, { forwardRef, ReactNode } from 'react';
|
|
8
|
-
import { useRovingTabIndex } from '../../hooks/useRovingTabIndex';
|
|
8
|
+
import { useRovingTabIndex } from '@lumx/react/_internal/hooks/useRovingTabIndex';
|
|
9
9
|
|
|
10
10
|
export enum TabListLayout {
|
|
11
11
|
clustered = 'clustered',
|
|
@@ -8,13 +8,13 @@ import classNames from 'classnames';
|
|
|
8
8
|
|
|
9
9
|
import { Placement } from '@lumx/react/components/popover/Popover';
|
|
10
10
|
|
|
11
|
-
import { DOCUMENT } from '@lumx/react/constants';
|
|
11
|
+
import { DOCUMENT, TOOLTIP_HOVER_DELAY, TOOLTIP_LONG_PRESS_DELAY } from '@lumx/react/constants';
|
|
12
12
|
|
|
13
13
|
import { Comp, GenericProps, getRootClassName, handleBasicClasses } from '@lumx/react/utils';
|
|
14
14
|
import { mergeRefs } from '@lumx/react/utils/mergeRefs';
|
|
15
15
|
|
|
16
|
+
import { useOpenHoverOrLongPress } from '@lumx/react/hooks/useOpenHoverOrLongPress';
|
|
16
17
|
import { useInjectTooltipRef } from './useInjectTooltipRef';
|
|
17
|
-
import { useTooltipOpen } from './useTooltipOpen';
|
|
18
18
|
|
|
19
19
|
/** Position of the tooltip relative to the anchor element. */
|
|
20
20
|
export type TooltipPlacement = Extract<Placement, 'top' | 'right' | 'bottom' | 'left'>;
|
|
@@ -49,7 +49,6 @@ const CLASSNAME = getRootClassName(COMPONENT_NAME);
|
|
|
49
49
|
* Component default props.
|
|
50
50
|
*/
|
|
51
51
|
const DEFAULT_PROPS: Partial<TooltipProps> = {
|
|
52
|
-
delay: 500,
|
|
53
52
|
placement: Placement.BOTTOM,
|
|
54
53
|
};
|
|
55
54
|
|
|
@@ -90,7 +89,11 @@ export const Tooltip: Comp<TooltipProps, HTMLDivElement> = forwardRef((props, re
|
|
|
90
89
|
});
|
|
91
90
|
|
|
92
91
|
const position = attributes?.popper?.['data-popper-placement'] ?? placement;
|
|
93
|
-
const isOpen =
|
|
92
|
+
const isOpen =
|
|
93
|
+
useOpenHoverOrLongPress(anchorElement, {
|
|
94
|
+
hover: { openDelay: delay ?? TOOLTIP_HOVER_DELAY.openDelay, closeDelay: TOOLTIP_HOVER_DELAY.closeDelay },
|
|
95
|
+
longPress: TOOLTIP_LONG_PRESS_DELAY,
|
|
96
|
+
}) || forceOpen;
|
|
94
97
|
const wrappedChildren = useInjectTooltipRef(children, setAnchorElement, isOpen as boolean, id);
|
|
95
98
|
|
|
96
99
|
return (
|
package/src/constants.ts
CHANGED
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {
|
|
2
|
+
CSS_PREFIX,
|
|
3
|
+
DIALOG_TRANSITION_DURATION,
|
|
4
|
+
NOTIFICATION_TRANSITION_DURATION,
|
|
5
|
+
TOOLTIP_HOVER_DELAY,
|
|
6
|
+
TOOLTIP_LONG_PRESS_DELAY,
|
|
7
|
+
} from '@lumx/core/js/constants';
|
|
2
8
|
|
|
3
9
|
/**
|
|
4
10
|
* Optional global `window` instance (not defined when running SSR).
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { onEscapePressed } from '@lumx/react/utils';
|
|
2
|
+
import { useEffect, useState } from 'react';
|
|
3
|
+
import { browserDoesNotSupportHover } from '@lumx/react/utils/browserDoesNotSupportHover';
|
|
4
|
+
|
|
5
|
+
interface OpenCloseConfig {
|
|
6
|
+
openDelay: number;
|
|
7
|
+
closeDelay: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Config {
|
|
11
|
+
hover: OpenCloseConfig;
|
|
12
|
+
longPress: OpenCloseConfig;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const DEFAULT_CONFIG: Config = {
|
|
16
|
+
hover: {
|
|
17
|
+
openDelay: 500,
|
|
18
|
+
closeDelay: 0,
|
|
19
|
+
},
|
|
20
|
+
longPress: {
|
|
21
|
+
openDelay: 250,
|
|
22
|
+
closeDelay: 3000,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Hook controlling an open/close action on hover on device supporting pointer hover
|
|
28
|
+
* and on long press on device not supporting pointer hover.
|
|
29
|
+
*
|
|
30
|
+
* @param anchorElement Anchor element on which the hover or longPress is watched.
|
|
31
|
+
* @param config Open/close delay configuration.
|
|
32
|
+
* @return true/false boolean.
|
|
33
|
+
*/
|
|
34
|
+
export function useOpenHoverOrLongPress(
|
|
35
|
+
anchorElement: HTMLElement | null,
|
|
36
|
+
config: { hover?: Partial<OpenCloseConfig>; longPress?: Partial<OpenCloseConfig> } = {},
|
|
37
|
+
): boolean {
|
|
38
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
39
|
+
const activation = browserDoesNotSupportHover() ? 'longPress' : 'hover';
|
|
40
|
+
const { openDelay: defaultOpenDelay, closeDelay: defaultCloseDelay } = DEFAULT_CONFIG[activation];
|
|
41
|
+
const { openDelay = defaultOpenDelay, closeDelay = defaultCloseDelay } = config?.[activation] || {};
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (!anchorElement) {
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
let timer: number | undefined;
|
|
48
|
+
let openStartTime: number | undefined;
|
|
49
|
+
let shouldOpen: boolean | undefined;
|
|
50
|
+
|
|
51
|
+
// Run timer to defer updating the isOpen state.
|
|
52
|
+
const deferUpdate = (duration: number) => {
|
|
53
|
+
if (timer) clearTimeout(timer);
|
|
54
|
+
timer = setTimeout(() => {
|
|
55
|
+
setIsOpen(!!shouldOpen);
|
|
56
|
+
}, duration) as any;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const hasTouch = 'ontouchstart' in window;
|
|
60
|
+
|
|
61
|
+
// Open (or/and cancel closing).
|
|
62
|
+
const open = () => {
|
|
63
|
+
if (shouldOpen && !timer) return;
|
|
64
|
+
shouldOpen = true;
|
|
65
|
+
openStartTime = Date.now();
|
|
66
|
+
deferUpdate(openDelay);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Close or cancel opening
|
|
70
|
+
const close = (overrideDelay = closeDelay) => {
|
|
71
|
+
if (!shouldOpen && !timer) return;
|
|
72
|
+
shouldOpen = false;
|
|
73
|
+
deferUpdate(overrideDelay);
|
|
74
|
+
};
|
|
75
|
+
const closeImmediately = () => close(0);
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Handle touchend event
|
|
79
|
+
* If `touchend` comes before the open delay => cancel open (close immediate).
|
|
80
|
+
* Else if `touchend` comes after the open delay => open takes priority, the anchor's default touch end event is prevented.
|
|
81
|
+
*/
|
|
82
|
+
const touchEnd = (evt: Event) => {
|
|
83
|
+
if (!openStartTime) return;
|
|
84
|
+
if (Date.now() - openStartTime >= openDelay) {
|
|
85
|
+
// Tooltip take priority, event prevented.
|
|
86
|
+
evt.stopPropagation();
|
|
87
|
+
evt.preventDefault();
|
|
88
|
+
anchorElement.focus();
|
|
89
|
+
// Close with delay.
|
|
90
|
+
close();
|
|
91
|
+
} else {
|
|
92
|
+
// Close immediately.
|
|
93
|
+
closeImmediately();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const events: Array<[Node, Event['type'], any]> = [];
|
|
98
|
+
|
|
99
|
+
// Long press activation.
|
|
100
|
+
if (activation === 'longPress') {
|
|
101
|
+
events.push(
|
|
102
|
+
[anchorElement, hasTouch ? 'touchstart' : 'mousedown', open],
|
|
103
|
+
[anchorElement, hasTouch ? 'touchend' : 'mouseup', touchEnd],
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Hover activation.
|
|
108
|
+
if (activation === 'hover') {
|
|
109
|
+
events.push(
|
|
110
|
+
[anchorElement, 'mouseenter', open],
|
|
111
|
+
[anchorElement, 'mouseleave', close],
|
|
112
|
+
[anchorElement, 'mouseup', closeImmediately],
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Events always applied no matter the browser:
|
|
117
|
+
events.push(
|
|
118
|
+
// Open on focus.
|
|
119
|
+
[anchorElement, 'focusin', open],
|
|
120
|
+
// Close on lost focus.
|
|
121
|
+
[anchorElement, 'focusout', closeImmediately],
|
|
122
|
+
// Close on ESC keydown
|
|
123
|
+
[anchorElement, 'keydown', onEscapePressed(closeImmediately)],
|
|
124
|
+
);
|
|
125
|
+
|
|
126
|
+
// Attach events
|
|
127
|
+
for (const [node, eventType, evenHandler] of events) {
|
|
128
|
+
node.addEventListener(eventType, evenHandler);
|
|
129
|
+
}
|
|
130
|
+
return () => {
|
|
131
|
+
// Detach events.
|
|
132
|
+
for (const [node, eventType, evenHandler] of events) {
|
|
133
|
+
node.removeEventListener(eventType, evenHandler);
|
|
134
|
+
}
|
|
135
|
+
closeImmediately();
|
|
136
|
+
};
|
|
137
|
+
}, [activation, anchorElement, closeDelay, openDelay]);
|
|
138
|
+
|
|
139
|
+
return isOpen;
|
|
140
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { createContext, useContext, useEffect } from 'react';
|
|
2
2
|
import pull from 'lodash/pull';
|
|
3
|
-
import { ClickAwayParameters, useClickAway } from '@lumx/react/hooks/useClickAway';
|
|
3
|
+
import { ClickAwayParameters, useClickAway } from '@lumx/react/_internal/hooks/useClickAway';
|
|
4
4
|
|
|
5
5
|
const ClickAwayAncestorContext = createContext<ClickAwayParameters['refs'] | null>(null);
|
|
6
6
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { browserDoesNotSupportHover } from '@lumx/react/utils/browserDoesNotSupportHover';
|
|
2
|
+
|
|
3
|
+
const originalMatchMedia = global.matchMedia;
|
|
4
|
+
|
|
5
|
+
describe('browserDoesNotSupportHover', () => {
|
|
6
|
+
afterAll(() => {
|
|
7
|
+
global.matchMedia = originalMatchMedia;
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it('should return `false` on browsers that do not support matchMedia', () => {
|
|
11
|
+
global.matchMedia = undefined;
|
|
12
|
+
expect(browserDoesNotSupportHover()).toBe(false);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should return `false` on browsers that support matchMedia and does support hover', () => {
|
|
16
|
+
global.matchMedia = () => ({ matches: false });
|
|
17
|
+
expect(browserDoesNotSupportHover()).toBe(false);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should return `true` on browsers that support matchMedia and does not support hover', () => {
|
|
21
|
+
global.matchMedia = () => ({ matches: true });
|
|
22
|
+
expect(browserDoesNotSupportHover()).toBe(true);
|
|
23
|
+
});
|
|
24
|
+
});
|
package/types.d.ts
CHANGED
|
@@ -599,6 +599,8 @@ export interface CheckboxProps extends GenericProps {
|
|
|
599
599
|
value?: string;
|
|
600
600
|
/** On change callback. */
|
|
601
601
|
onChange?(isChecked: boolean, value?: string, name?: string, event?: SyntheticEvent): void;
|
|
602
|
+
/** optional props for input */
|
|
603
|
+
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
602
604
|
}
|
|
603
605
|
/**
|
|
604
606
|
* Checkbox component.
|
|
@@ -666,7 +668,7 @@ export interface ChipGroupProps extends GenericProps {
|
|
|
666
668
|
children: ReactNode;
|
|
667
669
|
}
|
|
668
670
|
export declare const ChipGroup: Comp<ChipGroupProps, HTMLDivElement> & {
|
|
669
|
-
useChipGroupNavigation: import("../../hooks/useChipGroupNavigation").useChipGroupNavigationType<any>;
|
|
671
|
+
useChipGroupNavigation: import("../../_internal/hooks/useChipGroupNavigation").useChipGroupNavigationType<any>;
|
|
670
672
|
};
|
|
671
673
|
/**
|
|
672
674
|
* Comment block variants.
|
|
@@ -1480,7 +1482,7 @@ export interface ListProps extends GenericProps {
|
|
|
1480
1482
|
onListItemSelected?(key: Key, index: number, evt: SyntheticEvent): void;
|
|
1481
1483
|
}
|
|
1482
1484
|
export declare const List: Comp<ListProps, HTMLUListElement> & {
|
|
1483
|
-
useKeyboardListNavigation: import("../../hooks/useKeyboardListNavigation").useKeyboardListNavigationType;
|
|
1485
|
+
useKeyboardListNavigation: import("../../_internal/hooks/useKeyboardListNavigation").useKeyboardListNavigationType;
|
|
1484
1486
|
};
|
|
1485
1487
|
export declare type ListItemSize = Extract<Size, "tiny" | "regular" | "big" | "huge">;
|
|
1486
1488
|
/**
|
|
@@ -2167,6 +2169,8 @@ export interface SwitchProps extends GenericProps {
|
|
|
2167
2169
|
value?: string;
|
|
2168
2170
|
/** On change callback. */
|
|
2169
2171
|
onChange?(isChecked: boolean, value?: string, name?: string, event?: SyntheticEvent): void;
|
|
2172
|
+
/** optional props for input */
|
|
2173
|
+
inputProps?: InputHTMLAttributes<HTMLInputElement>;
|
|
2170
2174
|
}
|
|
2171
2175
|
/**
|
|
2172
2176
|
* Switch component.
|
package/esm/index2.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index2.js","sources":["../../../../node_modules/uid/dist/index.mjs"],"sourcesContent":["var IDX=256, HEX=[], SIZE=256, BUFFER;\nwhile (IDX--) HEX[IDX] = (IDX + 256).toString(16).substring(1);\n\nexport function uid(len) {\n\tvar i=0, tmp=(len || 11);\n\tif (!BUFFER || ((IDX + tmp) > SIZE*2)) {\n\t\tfor (BUFFER='',IDX=0; i < SIZE; i++) {\n\t\t\tBUFFER += HEX[Math.random() * 256 | 0];\n\t\t}\n\t}\n\n\treturn BUFFER.substring(IDX, IDX++ + tmp);\n}\n"],"names":[],"mappings":"AAAA,IAAI,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC;AACtC,OAAO,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC/D;AACO,SAAS,GAAG,CAAC,GAAG,EAAE;AACzB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC,CAAC;AAC1B,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE;AACxC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;AACvC,GAAG,MAAM,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC;AAC1C,GAAG;AACH,EAAE;AACF;AACA,CAAC,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,CAAC;AAC3C;;;;"}
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { Callback, onEscapePressed } from '@lumx/react/utils';
|
|
2
|
-
import { useEffect, useRef, useState } from 'react';
|
|
3
|
-
import pull from 'lodash/pull';
|
|
4
|
-
import debounce from 'lodash/debounce';
|
|
5
|
-
|
|
6
|
-
type Tooltip = { open: Callback; close: Callback; anchorElement: HTMLElement };
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* This singleton handle a global `mouseover` event listener on the `document` in order to toggle tooltips when
|
|
10
|
-
* entering and leaving their anchor element.
|
|
11
|
-
*/
|
|
12
|
-
const tooltipMouseToggle = (() => {
|
|
13
|
-
/** List of tooltips to toggle on anchor enter/leave. */
|
|
14
|
-
let tooltips: Array<Tooltip> | undefined;
|
|
15
|
-
|
|
16
|
-
/** Global listener added on the document. */
|
|
17
|
-
let globalListener: undefined | ((evt: MouseEvent) => void);
|
|
18
|
-
|
|
19
|
-
function addGlobalListener() {
|
|
20
|
-
if (globalListener) return;
|
|
21
|
-
globalListener = debounce((evt) => {
|
|
22
|
-
if (!tooltips || !evt.target) return;
|
|
23
|
-
for (const { open, close, anchorElement } of tooltips) {
|
|
24
|
-
if (anchorElement.contains(evt.target as any)) {
|
|
25
|
-
open();
|
|
26
|
-
} else {
|
|
27
|
-
close();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}, 10);
|
|
31
|
-
document.addEventListener('mouseover', globalListener);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function removeGlobalListener() {
|
|
35
|
-
if (!globalListener) return;
|
|
36
|
-
document.removeEventListener('mouseover', globalListener);
|
|
37
|
-
globalListener = undefined;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return {
|
|
41
|
-
addTooltip(tooltip: Tooltip) {
|
|
42
|
-
if (!tooltips) {
|
|
43
|
-
tooltips = [];
|
|
44
|
-
addGlobalListener();
|
|
45
|
-
}
|
|
46
|
-
tooltips.push(tooltip);
|
|
47
|
-
},
|
|
48
|
-
removeTooltip(actions: Tooltip) {
|
|
49
|
-
if (!tooltips) return;
|
|
50
|
-
pull(tooltips, actions);
|
|
51
|
-
if (tooltips.length === 0) {
|
|
52
|
-
removeGlobalListener();
|
|
53
|
-
tooltips = undefined;
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
};
|
|
57
|
-
})();
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Hook controlling tooltip visibility using mouse hover the anchor and delay.
|
|
61
|
-
*
|
|
62
|
-
* @param delay Delay in millisecond to display the tooltip.
|
|
63
|
-
* @param anchorElement Tooltip anchor element.
|
|
64
|
-
* @return whether or not to show the tooltip.
|
|
65
|
-
*/
|
|
66
|
-
export function useTooltipOpen(delay: number, anchorElement: HTMLElement | null): boolean {
|
|
67
|
-
const timer = useRef<number>();
|
|
68
|
-
const shouldOpen = useRef<boolean>(false);
|
|
69
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
70
|
-
|
|
71
|
-
useEffect(() => {
|
|
72
|
-
if (!anchorElement) {
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
const tooltip: Tooltip = {
|
|
76
|
-
anchorElement,
|
|
77
|
-
open() {
|
|
78
|
-
if (!shouldOpen.current) {
|
|
79
|
-
shouldOpen.current = true;
|
|
80
|
-
timer.current = setTimeout(() => {
|
|
81
|
-
setIsOpen(shouldOpen.current);
|
|
82
|
-
}, delay) as any;
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
close() {
|
|
86
|
-
if (timer.current) {
|
|
87
|
-
clearTimeout(timer.current);
|
|
88
|
-
timer.current = undefined;
|
|
89
|
-
}
|
|
90
|
-
if (shouldOpen.current) {
|
|
91
|
-
shouldOpen.current = false;
|
|
92
|
-
setIsOpen(shouldOpen.current);
|
|
93
|
-
}
|
|
94
|
-
},
|
|
95
|
-
};
|
|
96
|
-
const keydown = onEscapePressed(tooltip.close);
|
|
97
|
-
|
|
98
|
-
tooltipMouseToggle.addTooltip(tooltip);
|
|
99
|
-
anchorElement.addEventListener('focusin', tooltip.open);
|
|
100
|
-
anchorElement.addEventListener('focusout', tooltip.close);
|
|
101
|
-
anchorElement.addEventListener('keydown', keydown);
|
|
102
|
-
return () => {
|
|
103
|
-
tooltipMouseToggle.removeTooltip(tooltip);
|
|
104
|
-
anchorElement.removeEventListener('focusin', tooltip.open);
|
|
105
|
-
anchorElement.removeEventListener('focusout', tooltip.close);
|
|
106
|
-
anchorElement.removeEventListener('keydown', keydown);
|
|
107
|
-
tooltip.close();
|
|
108
|
-
};
|
|
109
|
-
}, [anchorElement, delay, timer, shouldOpen]);
|
|
110
|
-
|
|
111
|
-
return isOpen;
|
|
112
|
-
}
|