@basic-ui/core 0.0.50 → 0.0.52
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/README.md +3 -3
- package/build/cjs/index.js +106 -92
- package/build/cjs/index.js.map +1 -1
- package/build/esm/Accordion/Accordion.d.ts +9 -9
- package/build/esm/Accordion/Accordion.js.map +1 -1
- package/build/esm/Accordion/AccordionBody.d.ts +6 -6
- package/build/esm/Accordion/AccordionBody.js.map +1 -1
- package/build/esm/Accordion/AccordionHeader.d.ts +7 -7
- package/build/esm/Accordion/AccordionHeader.js.map +1 -1
- package/build/esm/Accordion/AccordionItem.d.ts +9 -9
- package/build/esm/Accordion/AccordionItem.js.map +1 -1
- package/build/esm/Accordion/context.d.ts +19 -19
- package/build/esm/Accordion/context.js.map +1 -1
- package/build/esm/Accordion/index.d.ts +4 -4
- package/build/esm/Accordion/index.js.map +1 -1
- package/build/esm/Accordion/scopeQuery.d.ts +2 -2
- package/build/esm/Accordion/scopeQuery.js.map +1 -1
- package/build/esm/CheckBox/CheckBox.d.ts +7 -7
- package/build/esm/CheckBox/CheckBox.js.map +1 -1
- package/build/esm/CheckBox/index.d.ts +1 -1
- package/build/esm/CheckBox/index.js.map +1 -1
- package/build/esm/ComboBox/Combobox.d.ts +18 -18
- package/build/esm/ComboBox/Combobox.js.map +1 -1
- package/build/esm/ComboBox/ComboboxButton.d.ts +9 -9
- package/build/esm/ComboBox/ComboboxButton.js.map +1 -1
- package/build/esm/ComboBox/ComboboxInput.d.ts +17 -17
- package/build/esm/ComboBox/ComboboxInput.js.map +1 -1
- package/build/esm/ComboBox/ComboboxLabel.d.ts +7 -7
- package/build/esm/ComboBox/ComboboxLabel.js.map +1 -1
- package/build/esm/ComboBox/ComboboxList.d.ts +8 -8
- package/build/esm/ComboBox/ComboboxList.js.map +1 -1
- package/build/esm/ComboBox/ComboboxOption.d.ts +11 -11
- package/build/esm/ComboBox/ComboboxOption.js.map +1 -1
- package/build/esm/ComboBox/ComboboxPopover.d.ts +9 -9
- package/build/esm/ComboBox/ComboboxPopover.js.map +1 -1
- package/build/esm/ComboBox/cities.d.ts +5 -5
- package/build/esm/ComboBox/cities.js.map +1 -1
- package/build/esm/ComboBox/context.d.ts +30 -30
- package/build/esm/ComboBox/context.js.map +1 -1
- package/build/esm/ComboBox/hooks.d.ts +37 -37
- package/build/esm/ComboBox/hooks.js.map +1 -1
- package/build/esm/ComboBox/index.d.ts +8 -8
- package/build/esm/ComboBox/index.js.map +1 -1
- package/build/esm/ComboBox/makeHash.d.ts +1 -1
- package/build/esm/ComboBox/makeHash.js.map +1 -1
- package/build/esm/ComboBox/scopeQuery.d.ts +1 -1
- package/build/esm/ComboBox/scopeQuery.js.map +1 -1
- package/build/esm/FocusLock/FocusLock.d.ts +9 -9
- package/build/esm/FocusLock/FocusLock.js.map +1 -1
- package/build/esm/FocusLock/index.d.ts +1 -1
- package/build/esm/FocusLock/index.js.map +1 -1
- package/build/esm/FocusLock/tabUtils.d.ts +3 -3
- package/build/esm/FocusLock/tabUtils.js.map +1 -1
- package/build/esm/FocusLock/useFocusLock.d.ts +7 -7
- package/build/esm/FocusLock/useFocusLock.js.map +1 -1
- package/build/esm/List/List.d.ts +7 -7
- package/build/esm/List/List.js.map +1 -1
- package/build/esm/List/ListItem.d.ts +7 -7
- package/build/esm/List/ListItem.js.map +1 -1
- package/build/esm/List/context.d.ts +4 -4
- package/build/esm/List/context.js.map +1 -1
- package/build/esm/List/index.d.ts +2 -2
- package/build/esm/List/index.js.map +1 -1
- package/build/esm/Menu/ContextMenuTrigger.d.ts +11 -11
- package/build/esm/Menu/ContextMenuTrigger.js.map +1 -1
- package/build/esm/Menu/Menu.d.ts +10 -10
- package/build/esm/Menu/Menu.js.map +1 -1
- package/build/esm/Menu/MenuButton.d.ts +11 -11
- package/build/esm/Menu/MenuButton.js.map +1 -1
- package/build/esm/Menu/MenuItem.d.ts +8 -8
- package/build/esm/Menu/MenuItem.js +1 -0
- package/build/esm/Menu/MenuItem.js.map +1 -1
- package/build/esm/Menu/MenuList.d.ts +7 -7
- package/build/esm/Menu/MenuList.js +17 -4
- package/build/esm/Menu/MenuList.js.map +1 -1
- package/build/esm/Menu/MenuPopover.d.ts +8 -8
- package/build/esm/Menu/MenuPopover.js.map +1 -1
- package/build/esm/Menu/context.d.ts +25 -25
- package/build/esm/Menu/context.js.map +1 -1
- package/build/esm/Menu/fixtures/countryList.d.ts +1 -1
- package/build/esm/Menu/fixtures/countryList.js.map +1 -1
- package/build/esm/Menu/index.d.ts +6 -6
- package/build/esm/Menu/index.js.map +1 -1
- package/build/esm/Menu/scope.d.ts +1 -1
- package/build/esm/Menu/scope.js.map +1 -1
- package/build/esm/Modal/Modal.d.ts +9 -9
- package/build/esm/Modal/Modal.js.map +1 -1
- package/build/esm/Modal/ModalBackdrop.d.ts +10 -10
- package/build/esm/Modal/ModalBackdrop.js.map +1 -1
- package/build/esm/Modal/index.d.ts +2 -2
- package/build/esm/Modal/index.js.map +1 -1
- package/build/esm/Popper/Popper.d.ts +35 -35
- package/build/esm/Popper/Popper.js.map +1 -1
- package/build/esm/Popper/PopperArrow.d.ts +6 -6
- package/build/esm/Popper/PopperArrow.js.map +1 -1
- package/build/esm/Popper/context.d.ts +6 -6
- package/build/esm/Popper/context.js.map +1 -1
- package/build/esm/Popper/index.d.ts +3 -3
- package/build/esm/Popper/index.js.map +1 -1
- package/build/esm/Portal/Portal.d.ts +6 -6
- package/build/esm/Portal/Portal.js.map +1 -1
- package/build/esm/Portal/index.d.ts +1 -1
- package/build/esm/Portal/index.js.map +1 -1
- package/build/esm/RadioButton/RadioButton.d.ts +10 -10
- package/build/esm/RadioButton/RadioButton.js.map +1 -1
- package/build/esm/RadioButton/RadioGroup.d.ts +12 -12
- package/build/esm/RadioButton/RadioGroup.js.map +1 -1
- package/build/esm/RadioButton/context.d.ts +9 -9
- package/build/esm/RadioButton/context.js.map +1 -1
- package/build/esm/RadioButton/index.d.ts +2 -2
- package/build/esm/RadioButton/index.js.map +1 -1
- package/build/esm/SkipNav/SkipNav.d.ts +7 -7
- package/build/esm/SkipNav/SkipNav.js.map +1 -1
- package/build/esm/SkipNav/index.d.ts +1 -1
- package/build/esm/SkipNav/index.js.map +1 -1
- package/build/esm/Slider/Slider.d.ts +197 -197
- package/build/esm/Slider/Slider.js +82 -82
- package/build/esm/Slider/Slider.js.map +1 -1
- package/build/esm/Slider/index.d.ts +1 -1
- package/build/esm/Slider/index.js.map +1 -1
- package/build/esm/Spinner/Spinner.d.ts +12 -12
- package/build/esm/Spinner/Spinner.js.map +1 -1
- package/build/esm/Spinner/SpinnerButton.d.ts +8 -8
- package/build/esm/Spinner/SpinnerButton.js.map +1 -1
- package/build/esm/Spinner/context.d.ts +12 -12
- package/build/esm/Spinner/context.js.map +1 -1
- package/build/esm/Spinner/index.d.ts +2 -2
- package/build/esm/Spinner/index.js.map +1 -1
- package/build/esm/Tabs/Tab.d.ts +7 -7
- package/build/esm/Tabs/Tab.js.map +1 -1
- package/build/esm/Tabs/TabList.d.ts +9 -9
- package/build/esm/Tabs/TabList.js.map +1 -1
- package/build/esm/Tabs/TabPanel.d.ts +8 -8
- package/build/esm/Tabs/TabPanel.js.map +1 -1
- package/build/esm/Tabs/TabPanels.d.ts +8 -8
- package/build/esm/Tabs/TabPanels.js.map +1 -1
- package/build/esm/Tabs/Tabs.d.ts +10 -10
- package/build/esm/Tabs/Tabs.js.map +1 -1
- package/build/esm/Tabs/context.d.ts +17 -17
- package/build/esm/Tabs/context.js.map +1 -1
- package/build/esm/Tabs/index.d.ts +5 -5
- package/build/esm/Tabs/index.js.map +1 -1
- package/build/esm/Tabs/scopeQuery.d.ts +1 -1
- package/build/esm/Tabs/scopeQuery.js.map +1 -1
- package/build/esm/Tooltip/Tooltip.d.ts +10 -10
- package/build/esm/Tooltip/Tooltip.js.map +1 -1
- package/build/esm/Tooltip/index.d.ts +1 -1
- package/build/esm/Tooltip/index.js.map +1 -1
- package/build/esm/Tooltip/stateMachine.d.ts +28 -28
- package/build/esm/Tooltip/stateMachine.js.map +1 -1
- package/build/esm/Tooltip/useTooltip.d.ts +10 -10
- package/build/esm/Tooltip/useTooltip.js.map +1 -1
- package/build/esm/hooks/index.d.ts +13 -13
- package/build/esm/hooks/index.js.map +1 -1
- package/build/esm/hooks/useAutoFocus.d.ts +2 -2
- package/build/esm/hooks/useAutoFocus.js.map +1 -1
- package/build/esm/hooks/useChildrenCounter.d.ts +7 -7
- package/build/esm/hooks/useChildrenCounter.js.map +1 -1
- package/build/esm/hooks/useControlledState.d.ts +3 -3
- package/build/esm/hooks/useControlledState.js +1 -1
- package/build/esm/hooks/useControlledState.js.map +1 -1
- package/build/esm/hooks/useFocusReturn.d.ts +2 -2
- package/build/esm/hooks/useFocusReturn.js.map +1 -1
- package/build/esm/hooks/useFocusState.d.ts +11 -11
- package/build/esm/hooks/useFocusState.js.map +1 -1
- package/build/esm/hooks/useGestureHandlers.d.ts +52 -52
- package/build/esm/hooks/useGestureHandlers.js.map +1 -1
- package/build/esm/hooks/useMeasure.d.ts +7 -7
- package/build/esm/hooks/useMeasure.js.map +1 -1
- package/build/esm/hooks/useOnClickOutside.d.ts +2 -2
- package/build/esm/hooks/useOnClickOutside.js.map +1 -1
- package/build/esm/hooks/useOnKeyDown.d.ts +1 -1
- package/build/esm/hooks/useOnKeyDown.js.map +1 -1
- package/build/esm/hooks/useReducerMachine.d.ts +24 -24
- package/build/esm/hooks/useReducerMachine.js.map +1 -1
- package/build/esm/hooks/useRemoveBodyScroll.d.ts +2 -2
- package/build/esm/hooks/useRemoveBodyScroll.js.map +1 -1
- package/build/esm/hooks/useScope.d.ts +11 -11
- package/build/esm/hooks/useScope.js.map +1 -1
- package/build/esm/hooks/useThrottle.d.ts +1 -1
- package/build/esm/hooks/useThrottle.js.map +1 -1
- package/build/esm/index.d.ts +15 -15
- package/build/esm/index.js.map +1 -1
- package/build/esm/utils/assign-ref.d.ts +3 -3
- package/build/esm/utils/assign-ref.js.map +1 -1
- package/build/esm/utils/can-use-dom.d.ts +1 -1
- package/build/esm/utils/can-use-dom.js.map +1 -1
- package/build/esm/utils/clamp.d.ts +1 -1
- package/build/esm/utils/clamp.js.map +1 -1
- package/build/esm/utils/context.d.ts +7 -7
- package/build/esm/utils/context.js.map +1 -1
- package/build/esm/utils/create-subscription.d.ts +4 -4
- package/build/esm/utils/create-subscription.js.map +1 -1
- package/build/esm/utils/get-circular-index.d.ts +1 -1
- package/build/esm/utils/get-circular-index.js.map +1 -1
- package/build/esm/utils/index.d.ts +10 -10
- package/build/esm/utils/index.js.map +1 -1
- package/build/esm/utils/is-right-click.d.ts +6 -6
- package/build/esm/utils/is-right-click.js +4 -4
- package/build/esm/utils/is-right-click.js.map +1 -1
- package/build/esm/utils/owner-document.d.ts +7 -7
- package/build/esm/utils/owner-document.js +5 -5
- package/build/esm/utils/owner-document.js.map +1 -1
- package/build/esm/utils/polymorphic.d.ts +39 -39
- package/build/esm/utils/polymorphic.js.map +1 -1
- package/build/esm/utils/rubber-band-clamp.d.ts +2 -2
- package/build/esm/utils/rubber-band-clamp.js.map +1 -1
- package/build/esm/utils/use-stable-callback.d.ts +16 -16
- package/build/esm/utils/use-stable-callback.js +16 -16
- package/build/esm/utils/use-stable-callback.js.map +1 -1
- package/build/esm/utils/wrap-event.d.ts +3 -3
- package/build/esm/utils/wrap-event.js.map +1 -1
- package/build/tsconfig-build.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/Accordion/Accordion.story.tsx +74 -74
- package/src/Accordion/Accordion.tsx +59 -59
- package/src/Accordion/AccordionBody.tsx +52 -52
- package/src/Accordion/AccordionHeader.tsx +167 -167
- package/src/Accordion/AccordionItem.tsx +50 -50
- package/src/Accordion/context.ts +37 -37
- package/src/Accordion/index.ts +4 -4
- package/src/Accordion/scopeQuery.ts +7 -7
- package/src/Accordion/styles.css +21 -21
- package/src/CheckBox/CheckBox.tsx +41 -41
- package/src/CheckBox/index.ts +1 -1
- package/src/ComboBox/ComboBox.story.tsx +120 -120
- package/src/ComboBox/Combobox.tsx +148 -148
- package/src/ComboBox/ComboboxButton.tsx +61 -61
- package/src/ComboBox/ComboboxInput.tsx +187 -187
- package/src/ComboBox/ComboboxLabel.tsx +33 -33
- package/src/ComboBox/ComboboxList.tsx +47 -47
- package/src/ComboBox/ComboboxOption.tsx +111 -111
- package/src/ComboBox/ComboboxPopover.tsx +64 -64
- package/src/ComboBox/cities.ts +23194 -23194
- package/src/ComboBox/context.ts +35 -35
- package/src/ComboBox/hooks.tsx +451 -451
- package/src/ComboBox/index.ts +8 -8
- package/src/ComboBox/makeHash.ts +19 -19
- package/src/ComboBox/scopeQuery.ts +6 -6
- package/src/ComboBox/styles.css +32 -32
- package/src/FocusLock/FocusLock.tsx +66 -66
- package/src/FocusLock/index.ts +1 -1
- package/src/FocusLock/tabUtils.ts +40 -40
- package/src/FocusLock/useFocusLock.ts +56 -56
- package/src/List/List.story.tsx +18 -18
- package/src/List/List.tsx +17 -17
- package/src/List/ListItem.tsx +23 -23
- package/src/List/context.ts +19 -19
- package/src/List/index.ts +2 -2
- package/src/Menu/ContextMenu.story.tsx +73 -73
- package/src/Menu/ContextMenuTrigger.tsx +76 -76
- package/src/Menu/Menu.story.tsx +160 -160
- package/src/Menu/Menu.tsx +83 -83
- package/src/Menu/MenuButton.tsx +83 -83
- package/src/Menu/MenuComplex.story.tsx +58 -58
- package/src/Menu/MenuItem.tsx +88 -87
- package/src/Menu/MenuList.tsx +254 -243
- package/src/Menu/MenuPopover.tsx +35 -35
- package/src/Menu/context.ts +44 -44
- package/src/Menu/fixtures/countryList.ts +198 -198
- package/src/Menu/index.ts +6 -6
- package/src/Menu/scope.ts +7 -7
- package/src/Menu/styles.css +42 -42
- package/src/Modal/Modal.story.tsx +258 -258
- package/src/Modal/Modal.tsx +48 -48
- package/src/Modal/ModalBackdrop.tsx +78 -78
- package/src/Modal/NavDrawer.story.tsx +158 -158
- package/src/Modal/index.ts +2 -2
- package/src/Modal/styles.css +46 -46
- package/src/Popper/Popper.story.tsx +263 -263
- package/src/Popper/Popper.tsx +154 -154
- package/src/Popper/PopperArrow.tsx +35 -35
- package/src/Popper/context.ts +10 -10
- package/src/Popper/index.ts +3 -3
- package/src/Popper/styles.css +60 -60
- package/src/Portal/Portal.tsx +20 -20
- package/src/Portal/index.ts +1 -1
- package/src/RadioButton/RadioButton.story.tsx +77 -77
- package/src/RadioButton/RadioButton.tsx +55 -55
- package/src/RadioButton/RadioGroup.tsx +60 -60
- package/src/RadioButton/context.ts +17 -17
- package/src/RadioButton/index.ts +2 -2
- package/src/SkipNav/SkipNav.tsx +16 -16
- package/src/SkipNav/index.tsx +1 -1
- package/src/Slider/Slider.story.tsx +45 -45
- package/src/Slider/Slider.tsx +1120 -1120
- package/src/Slider/index.ts +1 -1
- package/src/Slider/styles.css +131 -131
- package/src/Spinner/Spinner.story.tsx +31 -31
- package/src/Spinner/Spinner.tsx +117 -117
- package/src/Spinner/SpinnerButton.tsx +54 -54
- package/src/Spinner/context.ts +20 -20
- package/src/Spinner/index.ts +2 -2
- package/src/Spinner/styles.css +23 -23
- package/src/Tabs/Tab.story.tsx +80 -80
- package/src/Tabs/Tab.tsx +136 -136
- package/src/Tabs/TabList.tsx +71 -71
- package/src/Tabs/TabPanel.tsx +53 -53
- package/src/Tabs/TabPanels.tsx +30 -30
- package/src/Tabs/Tabs.tsx +46 -46
- package/src/Tabs/context.ts +30 -30
- package/src/Tabs/index.tsx +5 -5
- package/src/Tabs/scopeQuery.ts +6 -6
- package/src/Tooltip/Tooltip.story.tsx +61 -61
- package/src/Tooltip/Tooltip.tsx +50 -50
- package/src/Tooltip/index.ts +1 -1
- package/src/Tooltip/stateMachine.ts +192 -192
- package/src/Tooltip/styles.css +17 -17
- package/src/Tooltip/useTooltip.ts +136 -136
- package/src/hooks/index.ts +13 -13
- package/src/hooks/useAutoFocus.ts +22 -22
- package/src/hooks/useChildrenCounter.ts +51 -51
- package/src/hooks/useControlledState.ts +3 -3
- package/src/hooks/useFocusReturn.ts +43 -43
- package/src/hooks/useFocusState.ts +30 -30
- package/src/hooks/useGestureHandlers.ts +286 -286
- package/src/hooks/useMeasure.ts +33 -33
- package/src/hooks/useOnClickOutside.ts +32 -32
- package/src/hooks/useOnKeyDown.ts +19 -19
- package/src/hooks/useReducerMachine.ts +60 -60
- package/src/hooks/useRemoveBodyScroll.ts +39 -39
- package/src/hooks/useScope.ts +52 -52
- package/src/hooks/useThrottle.ts +19 -19
- package/src/index.ts +20 -20
- package/src/utils/assign-ref.ts +27 -27
- package/src/utils/can-use-dom.ts +7 -7
- package/src/utils/clamp.ts +3 -3
- package/src/utils/context.tsx +48 -48
- package/src/utils/create-subscription.ts +16 -16
- package/src/utils/get-circular-index.ts +7 -7
- package/src/utils/index.ts +10 -10
- package/src/utils/is-right-click.ts +14 -14
- package/src/utils/owner-document.ts +13 -13
- package/src/utils/polymorphic.ts +78 -78
- package/src/utils/rubber-band-clamp.ts +25 -25
- package/src/utils/use-stable-callback.ts +58 -58
- package/src/utils/wrap-event.ts +22 -22
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
import type { RefObject } from 'react';
|
|
2
|
-
import { useEffect, useCallback } from 'react';
|
|
3
|
-
|
|
4
|
-
export function useOnClickOutside(
|
|
5
|
-
ref: RefObject<any>,
|
|
6
|
-
handler: (e: PointerEvent) => void,
|
|
7
|
-
active = true
|
|
8
|
-
) {
|
|
9
|
-
const listener = useCallback(
|
|
10
|
-
(event: PointerEvent) => {
|
|
11
|
-
// Do nothing if clicking ref's element or descendent elements
|
|
12
|
-
if (!ref.current || ref.current.contains(event.target)) {
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
handler && handler(event);
|
|
17
|
-
},
|
|
18
|
-
[ref, handler]
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
if (active) {
|
|
23
|
-
document.addEventListener('pointerup', listener);
|
|
24
|
-
|
|
25
|
-
return () => {
|
|
26
|
-
document.removeEventListener('pointerup', listener);
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return;
|
|
31
|
-
}, [listener, active]);
|
|
32
|
-
}
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
import { useEffect, useCallback } from 'react';
|
|
3
|
+
|
|
4
|
+
export function useOnClickOutside(
|
|
5
|
+
ref: RefObject<any>,
|
|
6
|
+
handler: (e: PointerEvent) => void,
|
|
7
|
+
active = true
|
|
8
|
+
) {
|
|
9
|
+
const listener = useCallback(
|
|
10
|
+
(event: PointerEvent) => {
|
|
11
|
+
// Do nothing if clicking ref's element or descendent elements
|
|
12
|
+
if (!ref.current || ref.current.contains(event.target)) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
handler && handler(event);
|
|
17
|
+
},
|
|
18
|
+
[ref, handler]
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
if (active) {
|
|
23
|
+
document.addEventListener('pointerup', listener);
|
|
24
|
+
|
|
25
|
+
return () => {
|
|
26
|
+
document.removeEventListener('pointerup', listener);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return;
|
|
31
|
+
}, [listener, active]);
|
|
32
|
+
}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
2
|
-
|
|
3
|
-
export function useOnKeyDown(
|
|
4
|
-
ownerWindow: Window,
|
|
5
|
-
handler: (e: KeyboardEvent) => void,
|
|
6
|
-
active = true
|
|
7
|
-
) {
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
if (active) {
|
|
10
|
-
ownerWindow.addEventListener('keydown', handler);
|
|
11
|
-
|
|
12
|
-
return () => {
|
|
13
|
-
ownerWindow.removeEventListener('keydown', handler);
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return;
|
|
18
|
-
}, [ownerWindow, active, handler]);
|
|
19
|
-
}
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useOnKeyDown(
|
|
4
|
+
ownerWindow: Window,
|
|
5
|
+
handler: (e: KeyboardEvent) => void,
|
|
6
|
+
active = true
|
|
7
|
+
) {
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (active) {
|
|
10
|
+
ownerWindow.addEventListener('keydown', handler);
|
|
11
|
+
|
|
12
|
+
return () => {
|
|
13
|
+
ownerWindow.removeEventListener('keydown', handler);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return;
|
|
18
|
+
}, [ownerWindow, active, handler]);
|
|
19
|
+
}
|
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
import type { Reducer } from 'react';
|
|
2
|
-
import { useReducer } from 'react';
|
|
3
|
-
|
|
4
|
-
export interface StateChart<STypes extends string, ATypes extends string> {
|
|
5
|
-
initial: STypes;
|
|
6
|
-
states: {
|
|
7
|
-
[state in STypes]?: {
|
|
8
|
-
enter?: (prevState: STypes, payload: any) => void;
|
|
9
|
-
leave?: (nextState: STypes, payload: any) => void;
|
|
10
|
-
on: { [action in ATypes]?: STypes };
|
|
11
|
-
};
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface StateMachineState<STypes, ATypes> {
|
|
16
|
-
state: STypes;
|
|
17
|
-
lastActionType: ATypes;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface StateMachineAction<STypes, ATypes> {
|
|
21
|
-
type: ATypes;
|
|
22
|
-
nextState: STypes;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
type TransitionType<ATypes extends string> = (
|
|
26
|
-
action: ATypes,
|
|
27
|
-
payload: any
|
|
28
|
-
) => void;
|
|
29
|
-
|
|
30
|
-
// This manages transitions between states with a built in reducer to manage
|
|
31
|
-
// the data that goes with those transitions.
|
|
32
|
-
export function useReducerMachine<
|
|
33
|
-
S extends StateMachineState<STypes, ATypes>,
|
|
34
|
-
A extends StateMachineAction<STypes, ATypes>,
|
|
35
|
-
STypes extends string,
|
|
36
|
-
ATypes extends string
|
|
37
|
-
>(
|
|
38
|
-
chart: StateChart<STypes, ATypes>,
|
|
39
|
-
reducer: Reducer<S, A>,
|
|
40
|
-
initialData: S
|
|
41
|
-
): [STypes, Omit<S, 'state'>, TransitionType<ATypes>] {
|
|
42
|
-
const [reducerState, dispatch] = useReducer(reducer, initialData);
|
|
43
|
-
const { state, ...data } = reducerState;
|
|
44
|
-
|
|
45
|
-
const transition: TransitionType<ATypes> = (action, payload = {}) => {
|
|
46
|
-
const currentState = chart.states[state];
|
|
47
|
-
if (!currentState) {
|
|
48
|
-
throw new Error(`Unknown currentState "${state}"`);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const nextState: STypes | undefined = currentState.on[action];
|
|
52
|
-
if (!nextState) {
|
|
53
|
-
throw new Error(`Unknown action "${action}" for state "${state}"`);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
dispatch({ type: action, nextState, ...payload } as any);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
return [state, data, transition];
|
|
60
|
-
}
|
|
1
|
+
import type { Reducer } from 'react';
|
|
2
|
+
import { useReducer } from 'react';
|
|
3
|
+
|
|
4
|
+
export interface StateChart<STypes extends string, ATypes extends string> {
|
|
5
|
+
initial: STypes;
|
|
6
|
+
states: {
|
|
7
|
+
[state in STypes]?: {
|
|
8
|
+
enter?: (prevState: STypes, payload: any) => void;
|
|
9
|
+
leave?: (nextState: STypes, payload: any) => void;
|
|
10
|
+
on: { [action in ATypes]?: STypes };
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface StateMachineState<STypes, ATypes> {
|
|
16
|
+
state: STypes;
|
|
17
|
+
lastActionType: ATypes;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface StateMachineAction<STypes, ATypes> {
|
|
21
|
+
type: ATypes;
|
|
22
|
+
nextState: STypes;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type TransitionType<ATypes extends string> = (
|
|
26
|
+
action: ATypes,
|
|
27
|
+
payload: any
|
|
28
|
+
) => void;
|
|
29
|
+
|
|
30
|
+
// This manages transitions between states with a built in reducer to manage
|
|
31
|
+
// the data that goes with those transitions.
|
|
32
|
+
export function useReducerMachine<
|
|
33
|
+
S extends StateMachineState<STypes, ATypes>,
|
|
34
|
+
A extends StateMachineAction<STypes, ATypes>,
|
|
35
|
+
STypes extends string,
|
|
36
|
+
ATypes extends string
|
|
37
|
+
>(
|
|
38
|
+
chart: StateChart<STypes, ATypes>,
|
|
39
|
+
reducer: Reducer<S, A>,
|
|
40
|
+
initialData: S
|
|
41
|
+
): [STypes, Omit<S, 'state'>, TransitionType<ATypes>] {
|
|
42
|
+
const [reducerState, dispatch] = useReducer(reducer, initialData);
|
|
43
|
+
const { state, ...data } = reducerState;
|
|
44
|
+
|
|
45
|
+
const transition: TransitionType<ATypes> = (action, payload = {}) => {
|
|
46
|
+
const currentState = chart.states[state];
|
|
47
|
+
if (!currentState) {
|
|
48
|
+
throw new Error(`Unknown currentState "${state}"`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const nextState: STypes | undefined = currentState.on[action];
|
|
52
|
+
if (!nextState) {
|
|
53
|
+
throw new Error(`Unknown action "${action}" for state "${state}"`);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
dispatch({ type: action, nextState, ...payload } as any);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
return [state, data, transition];
|
|
60
|
+
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import type { RefObject } from 'react';
|
|
2
|
-
import { useEffect } from 'react';
|
|
3
|
-
|
|
4
|
-
import { getOwnerDocument } from '../utils';
|
|
5
|
-
|
|
6
|
-
let scrollBodyCount = 0;
|
|
7
|
-
export function useRemoveBodyScroll(
|
|
8
|
-
open: boolean,
|
|
9
|
-
elementRef: RefObject<HTMLElement | null>
|
|
10
|
-
) {
|
|
11
|
-
useEffect(() => {
|
|
12
|
-
if (open && elementRef.current) {
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
14
|
-
const ownerDocument = getOwnerDocument(elementRef.current)!;
|
|
15
|
-
const ownerWindow = ownerDocument.defaultView || window;
|
|
16
|
-
scrollBodyCount += 1;
|
|
17
|
-
|
|
18
|
-
// calculate scrollbar width if mounting the first scroll lock
|
|
19
|
-
let scrollBarWidth = 0;
|
|
20
|
-
if (scrollBodyCount === 1) {
|
|
21
|
-
scrollBarWidth =
|
|
22
|
-
ownerWindow.innerWidth - ownerDocument.body.clientWidth;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
ownerDocument.body.style.overflow = 'hidden';
|
|
26
|
-
if (scrollBarWidth > 0) {
|
|
27
|
-
ownerDocument.body.style.marginRight = `${scrollBarWidth}px`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return () => {
|
|
31
|
-
scrollBodyCount -= 1;
|
|
32
|
-
if (scrollBodyCount === 0) {
|
|
33
|
-
ownerDocument.body.style.overflow = '';
|
|
34
|
-
ownerDocument.body.style.marginRight = '';
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
}, [elementRef, open]);
|
|
39
|
-
}
|
|
1
|
+
import type { RefObject } from 'react';
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
import { getOwnerDocument } from '../utils';
|
|
5
|
+
|
|
6
|
+
let scrollBodyCount = 0;
|
|
7
|
+
export function useRemoveBodyScroll(
|
|
8
|
+
open: boolean,
|
|
9
|
+
elementRef: RefObject<HTMLElement | null>
|
|
10
|
+
) {
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (open && elementRef.current) {
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
14
|
+
const ownerDocument = getOwnerDocument(elementRef.current)!;
|
|
15
|
+
const ownerWindow = ownerDocument.defaultView || window;
|
|
16
|
+
scrollBodyCount += 1;
|
|
17
|
+
|
|
18
|
+
// calculate scrollbar width if mounting the first scroll lock
|
|
19
|
+
let scrollBarWidth = 0;
|
|
20
|
+
if (scrollBodyCount === 1) {
|
|
21
|
+
scrollBarWidth =
|
|
22
|
+
ownerWindow.innerWidth - ownerDocument.body.clientWidth;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ownerDocument.body.style.overflow = 'hidden';
|
|
26
|
+
if (scrollBarWidth > 0) {
|
|
27
|
+
ownerDocument.body.style.marginRight = `${scrollBarWidth}px`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return () => {
|
|
31
|
+
scrollBodyCount -= 1;
|
|
32
|
+
if (scrollBodyCount === 0) {
|
|
33
|
+
ownerDocument.body.style.overflow = '';
|
|
34
|
+
ownerDocument.body.style.marginRight = '';
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
}, [elementRef, open]);
|
|
39
|
+
}
|
package/src/hooks/useScope.ts
CHANGED
|
@@ -1,52 +1,52 @@
|
|
|
1
|
-
import type { MutableRefObject } from 'react';
|
|
2
|
-
import { useRef } from 'react';
|
|
3
|
-
|
|
4
|
-
export type ScopeMatcherFn = (
|
|
5
|
-
nodeType: string,
|
|
6
|
-
props: {
|
|
7
|
-
[key: string]: string;
|
|
8
|
-
},
|
|
9
|
-
instance: Element
|
|
10
|
-
) => boolean;
|
|
11
|
-
|
|
12
|
-
export type Scope<T extends HTMLElement> = MutableRefObject<{
|
|
13
|
-
queryAllNodes: (matcherFn: ScopeMatcherFn) => T[];
|
|
14
|
-
}>;
|
|
15
|
-
|
|
16
|
-
export function getScope<T extends HTMLElement, R extends HTMLElement>(
|
|
17
|
-
rootRef: MutableRefObject<R | undefined | null>
|
|
18
|
-
) {
|
|
19
|
-
const queryAllNodes = (matcherFn: ScopeMatcherFn) => {
|
|
20
|
-
if (!rootRef.current) {
|
|
21
|
-
return [];
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const allNodes = rootRef.current.querySelectorAll('*');
|
|
25
|
-
|
|
26
|
-
const filtered: T[] = [];
|
|
27
|
-
allNodes.forEach((node) => {
|
|
28
|
-
const props = {};
|
|
29
|
-
const { attributes } = node;
|
|
30
|
-
for (let i = 0; i < attributes.length; i++) {
|
|
31
|
-
const attr = attributes[i];
|
|
32
|
-
props[attr.name] = attr.value;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
if (matcherFn(node.tagName.toLowerCase(), props, node)) {
|
|
36
|
-
filtered.push(node as T);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
return filtered;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
return { queryAllNodes };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function useScope<T extends HTMLElement, R extends HTMLElement>(
|
|
47
|
-
rootRef: MutableRefObject<R | undefined | null>
|
|
48
|
-
): Scope<T> {
|
|
49
|
-
const scope: Scope<T> = useRef(getScope(rootRef));
|
|
50
|
-
|
|
51
|
-
return scope;
|
|
52
|
-
}
|
|
1
|
+
import type { MutableRefObject } from 'react';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
export type ScopeMatcherFn = (
|
|
5
|
+
nodeType: string,
|
|
6
|
+
props: {
|
|
7
|
+
[key: string]: string;
|
|
8
|
+
},
|
|
9
|
+
instance: Element
|
|
10
|
+
) => boolean;
|
|
11
|
+
|
|
12
|
+
export type Scope<T extends HTMLElement> = MutableRefObject<{
|
|
13
|
+
queryAllNodes: (matcherFn: ScopeMatcherFn) => T[];
|
|
14
|
+
}>;
|
|
15
|
+
|
|
16
|
+
export function getScope<T extends HTMLElement, R extends HTMLElement>(
|
|
17
|
+
rootRef: MutableRefObject<R | undefined | null>
|
|
18
|
+
) {
|
|
19
|
+
const queryAllNodes = (matcherFn: ScopeMatcherFn) => {
|
|
20
|
+
if (!rootRef.current) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const allNodes = rootRef.current.querySelectorAll('*');
|
|
25
|
+
|
|
26
|
+
const filtered: T[] = [];
|
|
27
|
+
allNodes.forEach((node) => {
|
|
28
|
+
const props = {};
|
|
29
|
+
const { attributes } = node;
|
|
30
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
31
|
+
const attr = attributes[i];
|
|
32
|
+
props[attr.name] = attr.value;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (matcherFn(node.tagName.toLowerCase(), props, node)) {
|
|
36
|
+
filtered.push(node as T);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return filtered;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return { queryAllNodes };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function useScope<T extends HTMLElement, R extends HTMLElement>(
|
|
47
|
+
rootRef: MutableRefObject<R | undefined | null>
|
|
48
|
+
): Scope<T> {
|
|
49
|
+
const scope: Scope<T> = useRef(getScope(rootRef));
|
|
50
|
+
|
|
51
|
+
return scope;
|
|
52
|
+
}
|
package/src/hooks/useThrottle.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
import { useState, useEffect, useRef } from 'react';
|
|
2
|
-
|
|
3
|
-
export function useThrottle<T>(value: T, limit: number) {
|
|
4
|
-
const [throttledValue, setThrottledValue] = useState(value);
|
|
5
|
-
const lastRan = useRef(Date.now());
|
|
6
|
-
|
|
7
|
-
useEffect(() => {
|
|
8
|
-
const handler = setTimeout(() => {
|
|
9
|
-
setThrottledValue(value);
|
|
10
|
-
lastRan.current = Date.now();
|
|
11
|
-
}, limit - (Date.now() - lastRan.current));
|
|
12
|
-
|
|
13
|
-
return () => {
|
|
14
|
-
clearTimeout(handler);
|
|
15
|
-
};
|
|
16
|
-
}, [value, limit]);
|
|
17
|
-
|
|
18
|
-
return throttledValue;
|
|
19
|
-
}
|
|
1
|
+
import { useState, useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useThrottle<T>(value: T, limit: number) {
|
|
4
|
+
const [throttledValue, setThrottledValue] = useState(value);
|
|
5
|
+
const lastRan = useRef(Date.now());
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const handler = setTimeout(() => {
|
|
9
|
+
setThrottledValue(value);
|
|
10
|
+
lastRan.current = Date.now();
|
|
11
|
+
}, limit - (Date.now() - lastRan.current));
|
|
12
|
+
|
|
13
|
+
return () => {
|
|
14
|
+
clearTimeout(handler);
|
|
15
|
+
};
|
|
16
|
+
}, [value, limit]);
|
|
17
|
+
|
|
18
|
+
return throttledValue;
|
|
19
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
// Components
|
|
2
|
-
export * from './Accordion';
|
|
3
|
-
export * from './CheckBox';
|
|
4
|
-
export * from './ComboBox';
|
|
5
|
-
export * from './FocusLock';
|
|
6
|
-
export * from './Menu';
|
|
7
|
-
export * from './Modal';
|
|
8
|
-
export * from './Popper';
|
|
9
|
-
export * from './Portal';
|
|
10
|
-
export * from './RadioButton';
|
|
11
|
-
export * from './Slider';
|
|
12
|
-
export * from './Spinner';
|
|
13
|
-
export * from './Tabs';
|
|
14
|
-
export * from './Tooltip';
|
|
15
|
-
|
|
16
|
-
// General React utilities
|
|
17
|
-
export * from './utils';
|
|
18
|
-
|
|
19
|
-
// Hooks
|
|
20
|
-
export * from './hooks';
|
|
1
|
+
// Components
|
|
2
|
+
export * from './Accordion';
|
|
3
|
+
export * from './CheckBox';
|
|
4
|
+
export * from './ComboBox';
|
|
5
|
+
export * from './FocusLock';
|
|
6
|
+
export * from './Menu';
|
|
7
|
+
export * from './Modal';
|
|
8
|
+
export * from './Popper';
|
|
9
|
+
export * from './Portal';
|
|
10
|
+
export * from './RadioButton';
|
|
11
|
+
export * from './Slider';
|
|
12
|
+
export * from './Spinner';
|
|
13
|
+
export * from './Tabs';
|
|
14
|
+
export * from './Tooltip';
|
|
15
|
+
|
|
16
|
+
// General React utilities
|
|
17
|
+
export * from './utils';
|
|
18
|
+
|
|
19
|
+
// Hooks
|
|
20
|
+
export * from './hooks';
|
package/src/utils/assign-ref.ts
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
import type { MutableRefObject, RefCallback } from 'react';
|
|
2
|
-
|
|
3
|
-
export function assignRef<T>(
|
|
4
|
-
ref: MutableRefObject<T> | RefCallback<T> | null | undefined,
|
|
5
|
-
value: T
|
|
6
|
-
) {
|
|
7
|
-
if (ref == null) return;
|
|
8
|
-
if (typeof ref === 'function') {
|
|
9
|
-
ref(value);
|
|
10
|
-
} else {
|
|
11
|
-
try {
|
|
12
|
-
ref.current = value;
|
|
13
|
-
} catch (error) {
|
|
14
|
-
throw new Error(`Cannot assign value "${value}" to ref "${ref}"`);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function assignMultipleRefs<T>(
|
|
20
|
-
...refs: (MutableRefObject<T> | RefCallback<T> | null | undefined)[]
|
|
21
|
-
): RefCallback<T> {
|
|
22
|
-
return (node: T | null) => {
|
|
23
|
-
refs.forEach((ref) => {
|
|
24
|
-
assignRef(ref, node);
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
}
|
|
1
|
+
import type { MutableRefObject, RefCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
export function assignRef<T>(
|
|
4
|
+
ref: MutableRefObject<T> | RefCallback<T> | null | undefined,
|
|
5
|
+
value: T
|
|
6
|
+
) {
|
|
7
|
+
if (ref == null) return;
|
|
8
|
+
if (typeof ref === 'function') {
|
|
9
|
+
ref(value);
|
|
10
|
+
} else {
|
|
11
|
+
try {
|
|
12
|
+
ref.current = value;
|
|
13
|
+
} catch (error) {
|
|
14
|
+
throw new Error(`Cannot assign value "${value}" to ref "${ref}"`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function assignMultipleRefs<T>(
|
|
20
|
+
...refs: (MutableRefObject<T> | RefCallback<T> | null | undefined)[]
|
|
21
|
+
): RefCallback<T> {
|
|
22
|
+
return (node: T | null) => {
|
|
23
|
+
refs.forEach((ref) => {
|
|
24
|
+
assignRef(ref, node);
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
}
|
package/src/utils/can-use-dom.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export function canUseDOM() {
|
|
2
|
-
return !!(
|
|
3
|
-
typeof window !== 'undefined' &&
|
|
4
|
-
window.document &&
|
|
5
|
-
window.document.createElement
|
|
6
|
-
);
|
|
7
|
-
}
|
|
1
|
+
export function canUseDOM() {
|
|
2
|
+
return !!(
|
|
3
|
+
typeof window !== 'undefined' &&
|
|
4
|
+
window.document &&
|
|
5
|
+
window.document.createElement
|
|
6
|
+
);
|
|
7
|
+
}
|
package/src/utils/clamp.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function clamp(value: number, min: number, max: number) {
|
|
2
|
-
return Math.min(Math.max(value, min), max);
|
|
3
|
-
}
|
|
1
|
+
export function clamp(value: number, min: number, max: number) {
|
|
2
|
+
return Math.min(Math.max(value, min), max);
|
|
3
|
+
}
|
package/src/utils/context.tsx
CHANGED
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
import type { FC, PropsWithChildren } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
useMemo,
|
|
4
|
-
createContext as ReactCreateContext,
|
|
5
|
-
useContext as useReactContext,
|
|
6
|
-
} from 'react';
|
|
7
|
-
|
|
8
|
-
////////////////////////////////////////////////////////////////////////////////
|
|
9
|
-
|
|
10
|
-
type ContextProvider<T> = FC<PropsWithChildren<T>>;
|
|
11
|
-
|
|
12
|
-
export function createContext<ContextValueType extends object | null>(
|
|
13
|
-
rootName: string,
|
|
14
|
-
defaultContext?: ContextValueType
|
|
15
|
-
): [
|
|
16
|
-
ContextProvider<ContextValueType>,
|
|
17
|
-
(childName: string) => ContextValueType
|
|
18
|
-
] {
|
|
19
|
-
const Ctx = ReactCreateContext<ContextValueType | undefined>(defaultContext);
|
|
20
|
-
|
|
21
|
-
function Provider(props: PropsWithChildren<ContextValueType>) {
|
|
22
|
-
const { children, ...context } = props;
|
|
23
|
-
const value = useMemo(
|
|
24
|
-
() => context,
|
|
25
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
|
-
Object.values(context)
|
|
27
|
-
) as ContextValueType;
|
|
28
|
-
return <Ctx.Provider value={value}>{children}</Ctx.Provider>;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function useContext(childName: string) {
|
|
32
|
-
const context = useReactContext(Ctx);
|
|
33
|
-
if (context) {
|
|
34
|
-
return context;
|
|
35
|
-
}
|
|
36
|
-
if (defaultContext) {
|
|
37
|
-
return defaultContext;
|
|
38
|
-
}
|
|
39
|
-
throw Error(
|
|
40
|
-
`${childName} must be rendered inside of a ${rootName} component.`
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
Ctx.displayName = `${rootName}Context`;
|
|
45
|
-
Provider.displayName = `${rootName}Provider`;
|
|
46
|
-
|
|
47
|
-
return [Provider, useContext];
|
|
48
|
-
}
|
|
1
|
+
import type { FC, PropsWithChildren } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
useMemo,
|
|
4
|
+
createContext as ReactCreateContext,
|
|
5
|
+
useContext as useReactContext,
|
|
6
|
+
} from 'react';
|
|
7
|
+
|
|
8
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
9
|
+
|
|
10
|
+
type ContextProvider<T> = FC<PropsWithChildren<T>>;
|
|
11
|
+
|
|
12
|
+
export function createContext<ContextValueType extends object | null>(
|
|
13
|
+
rootName: string,
|
|
14
|
+
defaultContext?: ContextValueType
|
|
15
|
+
): [
|
|
16
|
+
ContextProvider<ContextValueType>,
|
|
17
|
+
(childName: string) => ContextValueType
|
|
18
|
+
] {
|
|
19
|
+
const Ctx = ReactCreateContext<ContextValueType | undefined>(defaultContext);
|
|
20
|
+
|
|
21
|
+
function Provider(props: PropsWithChildren<ContextValueType>) {
|
|
22
|
+
const { children, ...context } = props;
|
|
23
|
+
const value = useMemo(
|
|
24
|
+
() => context,
|
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
26
|
+
Object.values(context)
|
|
27
|
+
) as ContextValueType;
|
|
28
|
+
return <Ctx.Provider value={value}>{children}</Ctx.Provider>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function useContext(childName: string) {
|
|
32
|
+
const context = useReactContext(Ctx);
|
|
33
|
+
if (context) {
|
|
34
|
+
return context;
|
|
35
|
+
}
|
|
36
|
+
if (defaultContext) {
|
|
37
|
+
return defaultContext;
|
|
38
|
+
}
|
|
39
|
+
throw Error(
|
|
40
|
+
`${childName} must be rendered inside of a ${rootName} component.`
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
Ctx.displayName = `${rootName}Context`;
|
|
45
|
+
Provider.displayName = `${rootName}Provider`;
|
|
46
|
+
|
|
47
|
+
return [Provider, useContext];
|
|
48
|
+
}
|