@ainias42/react-bootstrap-mobile 0.1.7
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/.eslintrc.json +189 -0
- package/.prettierrc +5 -0
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/babel.config.js +22 -0
- package/bin/build.js +60 -0
- package/bin/release.sh +35 -0
- package/bin/updateCopies.js +86 -0
- package/bootstrapReactMobile.ts +87 -0
- package/dist/bootstrapReactMobile.d.ts +87 -0
- package/dist/bootstrapReactMobile.js +6275 -0
- package/dist/src/Components/ActionSheet/ActionSheet.d.ts +21 -0
- package/dist/src/Components/Card/Card.d.ts +13 -0
- package/dist/src/Components/Clickable/Clickable.d.ts +14 -0
- package/dist/src/Components/Dialog/AlertDialog.d.ts +10 -0
- package/dist/src/Components/Dialog/ButtonDialog.d.ts +13 -0
- package/dist/src/Components/Dialog/ConfirmDialog.d.ts +11 -0
- package/dist/src/Components/Dialog/Dialog.d.ts +14 -0
- package/dist/src/Components/Dialog/DialogBackground.d.ts +7 -0
- package/dist/src/Components/Dialog/DialogContainer.d.ts +6 -0
- package/dist/src/Components/Dialog/DialogContext.d.ts +9 -0
- package/dist/src/Components/Dialog/useAlertDialog.d.ts +1 -0
- package/dist/src/Components/Dialog/useConfirmDialog.d.ts +1 -0
- package/dist/src/Components/DragAndDrop/DragItem.d.ts +7 -0
- package/dist/src/Components/DragAndDrop/DropArea.d.ts +7 -0
- package/dist/src/Components/DragAndDrop/useStrictEnabled.d.ts +1 -0
- package/dist/src/Components/FormElements/Button/Button.d.ts +8 -0
- package/dist/src/Components/FormElements/CheckBox/Checkbox.d.ts +10 -0
- package/dist/src/Components/FormElements/ColorInput/ColorInput.d.ts +17 -0
- package/dist/src/Components/FormElements/ColorInput/sharedSelectedColor.d.ts +4 -0
- package/dist/src/Components/FormElements/ImageInput/ImageInput.d.ts +17 -0
- package/dist/src/Components/FormElements/Input/HiddenInput.d.ts +8 -0
- package/dist/src/Components/FormElements/Input/Input.d.ts +10 -0
- package/dist/src/Components/FormElements/Input/PasswordInput/PasswordInput.d.ts +4 -0
- package/dist/src/Components/FormElements/SearchSelectInput/SearchSelectInput.d.ts +10 -0
- package/dist/src/Components/FormElements/Select/Select.d.ts +16 -0
- package/dist/src/Components/FormElements/Slider/Slider.d.ts +8 -0
- package/dist/src/Components/FormElements/Switch/Switch.d.ts +12 -0
- package/dist/src/Components/FormElements/Textarea/Textarea.d.ts +12 -0
- package/dist/src/Components/FormElements/hooks/useOnChangeDone.d.ts +2 -0
- package/dist/src/Components/FullScreen/FullScreen.d.ts +14 -0
- package/dist/src/Components/Hooks/useBreakpoint.d.ts +11 -0
- package/dist/src/Components/Hooks/useComposedRef.d.ts +2 -0
- package/dist/src/Components/Hooks/useDebounced.d.ts +1 -0
- package/dist/src/Components/Hooks/useDelayed.d.ts +1 -0
- package/dist/src/Components/Hooks/useInViewport.d.ts +2 -0
- package/dist/src/Components/Hooks/useKeyListener.d.ts +3 -0
- package/dist/src/Components/Hooks/useListener.d.ts +18 -0
- package/dist/src/Components/Hooks/useOnMount.d.ts +1 -0
- package/dist/src/Components/Hooks/useOnce.d.ts +1 -0
- package/dist/src/Components/Icon/Icon.d.ts +13 -0
- package/dist/src/Components/Image/Image.d.ts +12 -0
- package/dist/src/Components/InViewport/InViewport.d.ts +11 -0
- package/dist/src/Components/Layout/Block.d.ts +7 -0
- package/dist/src/Components/Layout/Container.d.ts +15 -0
- package/dist/src/Components/Layout/Flex.d.ts +10 -0
- package/dist/src/Components/Layout/Grid/Grid.d.ts +9 -0
- package/dist/src/Components/Layout/Grid/GridItem.d.ts +25 -0
- package/dist/src/Components/Layout/Grow.d.ts +9 -0
- package/dist/src/Components/Layout/Inline.d.ts +7 -0
- package/dist/src/Components/Layout/InlineBlock.d.ts +7 -0
- package/dist/src/Components/Layout/View.d.ts +9 -0
- package/dist/src/Components/Layout/ViewWithoutListeners.d.ts +8 -0
- package/dist/src/Components/List/BulletList/BulletList.d.ts +8 -0
- package/dist/src/Components/List/BulletList/ListItem.d.ts +7 -0
- package/dist/src/Components/List/List.d.ts +10 -0
- package/dist/src/Components/LoadingArea/LoadingArea.d.ts +12 -0
- package/dist/src/Components/LoadingCircle/LoadingCircle.d.ts +8 -0
- package/dist/src/Components/Menu/Menu.d.ts +16 -0
- package/dist/src/Components/Menu/useMenu.d.ts +3 -0
- package/dist/src/Components/RbmComponentProps.d.ts +31 -0
- package/dist/src/Components/SizeCalculator/SizeCalculator.d.ts +9 -0
- package/dist/src/Components/SpoilerList/Spoiler/Spoiler.d.ts +15 -0
- package/dist/src/Components/SpoilerList/SpoilerList.d.ts +15 -0
- package/dist/src/Components/SpoilerList/useSpoilerGroup.d.ts +12 -0
- package/dist/src/Components/TabBar/TabBar.d.ts +30 -0
- package/dist/src/Components/TabBar/TabBarButton.d.ts +9 -0
- package/dist/src/Components/Table/Table.d.ts +36 -0
- package/dist/src/Components/Text/Heading.d.ts +7 -0
- package/dist/src/Components/Text/Text.d.ts +26 -0
- package/dist/src/Components/Toast/Toast.d.ts +13 -0
- package/dist/src/Components/Toast/ToastContainer.d.ts +7 -0
- package/dist/src/Components/TopBar/MoreButton.d.ts +9 -0
- package/dist/src/Components/TopBar/TopBar.d.ts +25 -0
- package/dist/src/Components/TopBar/TopBarButton.d.ts +9 -0
- package/dist/src/StyleProvider.d.ts +2 -0
- package/dist/src/TypeHelpers.d.ts +4 -0
- package/dist/src/WindowContext/WindowContext.d.ts +3 -0
- package/dist/src/WrongChildError.d.ts +4 -0
- package/dist/src/helper/Characters.d.ts +5 -0
- package/dist/src/helper/DistributiveOmit.d.ts +1 -0
- package/dist/src/helper/EmptyProps.d.ts +1 -0
- package/dist/src/helper/memoComparator.d.ts +1 -0
- package/dist/src/helper/nonEmptyString.d.ts +1 -0
- package/dist/src/helper/withForwardRef.d.ts +7 -0
- package/dist/src/helper/withMemo.d.ts +3 -0
- package/dist/src/helper/withRenderBrowserOnly.d.ts +2 -0
- package/dist/src/helper/withRestrictedChildren.d.ts +6 -0
- package/package.json +92 -0
- package/react-bootstrap-mobile.scss +6 -0
- package/scripts/getPackageJson.js +25 -0
- package/src/Components/ActionSheet/ActionSheet.tsx +115 -0
- package/src/Components/ActionSheet/actionSheet.scss +153 -0
- package/src/Components/Card/Card.tsx +46 -0
- package/src/Components/Card/card.scss +76 -0
- package/src/Components/Clickable/Clickable.tsx +174 -0
- package/src/Components/Clickable/clickable.scss +3 -0
- package/src/Components/Dialog/AlertDialog.tsx +44 -0
- package/src/Components/Dialog/ButtonDialog.tsx +57 -0
- package/src/Components/Dialog/ConfirmDialog.tsx +46 -0
- package/src/Components/Dialog/Dialog.tsx +82 -0
- package/src/Components/Dialog/DialogBackground.tsx +38 -0
- package/src/Components/Dialog/DialogContainer.tsx +77 -0
- package/src/Components/Dialog/DialogContext.ts +21 -0
- package/src/Components/Dialog/buttonDialog.scss +114 -0
- package/src/Components/Dialog/dialog.scss +30 -0
- package/src/Components/Dialog/dialogBackground.scss +4 -0
- package/src/Components/Dialog/useAlertDialog.ts +13 -0
- package/src/Components/Dialog/useConfirmDialog.ts +13 -0
- package/src/Components/DragAndDrop/DragItem.tsx +38 -0
- package/src/Components/DragAndDrop/DropArea.tsx +43 -0
- package/src/Components/DragAndDrop/useStrictEnabled.ts +20 -0
- package/src/Components/FormElements/Button/Button.tsx +25 -0
- package/src/Components/FormElements/Button/button.scss +39 -0
- package/src/Components/FormElements/CheckBox/Checkbox.tsx +61 -0
- package/src/Components/FormElements/CheckBox/checkbox.scss +107 -0
- package/src/Components/FormElements/ColorInput/ColorInput.tsx +139 -0
- package/src/Components/FormElements/ColorInput/colorInput.scss +35 -0
- package/src/Components/FormElements/ColorInput/sharedSelectedColor.ts +40 -0
- package/src/Components/FormElements/ImageInput/ImageInput.tsx +97 -0
- package/src/Components/FormElements/ImageInput/imageInput.scss +24 -0
- package/src/Components/FormElements/Input/HiddenInput.tsx +43 -0
- package/src/Components/FormElements/Input/Input.tsx +102 -0
- package/src/Components/FormElements/Input/PasswordInput/PasswordInput.tsx +55 -0
- package/src/Components/FormElements/Input/PasswordInput/passwordInput.scss +7 -0
- package/src/Components/FormElements/Input/input.scss +57 -0
- package/src/Components/FormElements/SearchSelectInput/SearchSelectInput.tsx +162 -0
- package/src/Components/FormElements/SearchSelectInput/seachSelectInput.scss +90 -0
- package/src/Components/FormElements/Select/Select.tsx +77 -0
- package/src/Components/FormElements/Select/select.scss +51 -0
- package/src/Components/FormElements/Slider/Slider.tsx +80 -0
- package/src/Components/FormElements/Slider/slider.scss +92 -0
- package/src/Components/FormElements/Switch/Switch.tsx +82 -0
- package/src/Components/FormElements/Switch/switch.scss +149 -0
- package/src/Components/FormElements/Textarea/Textarea.tsx +77 -0
- package/src/Components/FormElements/Textarea/textarea.scss +22 -0
- package/src/Components/FormElements/hooks/useOnChangeDone.ts +16 -0
- package/src/Components/FullScreen/FullScreen.tsx +89 -0
- package/src/Components/Hooks/useBreakpoint.ts +66 -0
- package/src/Components/Hooks/useComposedRef.ts +17 -0
- package/src/Components/Hooks/useDebounced.ts +22 -0
- package/src/Components/Hooks/useDelayed.ts +46 -0
- package/src/Components/Hooks/useInViewport.ts +23 -0
- package/src/Components/Hooks/useKeyListener.ts +77 -0
- package/src/Components/Hooks/useListener.ts +73 -0
- package/src/Components/Hooks/useOnMount.ts +12 -0
- package/src/Components/Hooks/useOnce.ts +11 -0
- package/src/Components/Icon/Icon.tsx +45 -0
- package/src/Components/Image/Image.tsx +44 -0
- package/src/Components/Image/image.scss +3 -0
- package/src/Components/InViewport/InViewport.tsx +71 -0
- package/src/Components/InViewport/inViewport.scss +3 -0
- package/src/Components/Layout/Block.tsx +48 -0
- package/src/Components/Layout/Container.tsx +57 -0
- package/src/Components/Layout/Flex.tsx +51 -0
- package/src/Components/Layout/Grid/Grid.tsx +53 -0
- package/src/Components/Layout/Grid/GridItem.tsx +138 -0
- package/src/Components/Layout/Grid/grid.scss +43 -0
- package/src/Components/Layout/Grow.tsx +51 -0
- package/src/Components/Layout/Inline.tsx +48 -0
- package/src/Components/Layout/InlineBlock.tsx +48 -0
- package/src/Components/Layout/View.tsx +40 -0
- package/src/Components/Layout/ViewWithoutListeners.tsx +40 -0
- package/src/Components/Layout/container.scss +12 -0
- package/src/Components/Layout/layout.scss +56 -0
- package/src/Components/List/BulletList/BulletList.tsx +33 -0
- package/src/Components/List/BulletList/ListItem.tsx +34 -0
- package/src/Components/List/List.tsx +88 -0
- package/src/Components/List/list.scss +30 -0
- package/src/Components/LoadingArea/LoadingArea.tsx +64 -0
- package/src/Components/LoadingArea/loadingArea.scss +19 -0
- package/src/Components/LoadingCircle/LoadingCircle.tsx +41 -0
- package/src/Components/LoadingCircle/loadingCircle.scss +42 -0
- package/src/Components/Menu/Menu.tsx +113 -0
- package/src/Components/Menu/menu.scss +21 -0
- package/src/Components/Menu/useMenu.ts +20 -0
- package/src/Components/RbmComponentProps.ts +40 -0
- package/src/Components/SizeCalculator/SizeCalculator.tsx +45 -0
- package/src/Components/SpoilerList/Spoiler/Spoiler.tsx +106 -0
- package/src/Components/SpoilerList/Spoiler/spoiler.scss +120 -0
- package/src/Components/SpoilerList/SpoilerList.tsx +63 -0
- package/src/Components/SpoilerList/useSpoilerGroup.ts +39 -0
- package/src/Components/TabBar/TabBar.tsx +117 -0
- package/src/Components/TabBar/TabBarButton.tsx +44 -0
- package/src/Components/TabBar/tabBar.scss +108 -0
- package/src/Components/Table/Table.tsx +182 -0
- package/src/Components/Text/Heading.tsx +44 -0
- package/src/Components/Text/Text.tsx +79 -0
- package/src/Components/Text/heading.scss +3 -0
- package/src/Components/Text/text.scss +60 -0
- package/src/Components/Toast/Toast.tsx +107 -0
- package/src/Components/Toast/ToastContainer.tsx +35 -0
- package/src/Components/Toast/toast.scss +52 -0
- package/src/Components/TopBar/MoreButton.tsx +38 -0
- package/src/Components/TopBar/TopBar.tsx +176 -0
- package/src/Components/TopBar/TopBarButton.tsx +29 -0
- package/src/Components/TopBar/topBar.scss +124 -0
- package/src/StyleProvider.ts +4 -0
- package/src/TypeHelpers.ts +4 -0
- package/src/WindowContext/WindowContext.ts +8 -0
- package/src/WrongChildError.ts +19 -0
- package/src/env.d.ts +1 -0
- package/src/helper/Characters.ts +5 -0
- package/src/helper/DistributiveOmit.ts +1 -0
- package/src/helper/EmptyProps.ts +2 -0
- package/src/helper/memoComparator.ts +18 -0
- package/src/helper/nonEmptyString.ts +8 -0
- package/src/helper/withForwardRef.ts +28 -0
- package/src/helper/withMemo.ts +16 -0
- package/src/helper/withRenderBrowserOnly.tsx +30 -0
- package/src/helper/withRestrictedChildren.tsx +57 -0
- package/src/scss/_animations.scss +46 -0
- package/src/scss/_baseClasses.scss +27 -0
- package/src/scss/_colors.scss +13 -0
- package/src/scss/_default.scss +17 -0
- package/src/scss/_designMixin.scss +13 -0
- package/src/scss/_mobileMixin.scss +35 -0
- package/src/scss/_variables.scss +22 -0
- package/src/types/isomorphic-style-loader.d.ts +3 -0
- package/src/types/react-table-config.d.ts +120 -0
- package/src/types/scss-module.d.ts +7 -0
- package/tsconfig.json +57 -0
- package/webpack.config.js +85 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
@import "../../../scss/variables";
|
|
2
|
+
@import "../../../scss/designMixin";
|
|
3
|
+
|
|
4
|
+
.switch {
|
|
5
|
+
cursor: pointer;
|
|
6
|
+
position: relative;
|
|
7
|
+
display: inline-block;
|
|
8
|
+
|
|
9
|
+
> label {
|
|
10
|
+
display: flex;
|
|
11
|
+
cursor: pointer;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.label {
|
|
15
|
+
&:not(:empty) {
|
|
16
|
+
margin-left: 0.2rem;
|
|
17
|
+
margin-right: 0.2rem;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
input {
|
|
22
|
+
display: none;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.toggle {
|
|
26
|
+
width: 40px;
|
|
27
|
+
display: inline-block;
|
|
28
|
+
position: relative;
|
|
29
|
+
transition-property: all;
|
|
30
|
+
transition-duration: 0.35s;
|
|
31
|
+
transition-timing-function: ease-out;
|
|
32
|
+
border-radius: 30px;
|
|
33
|
+
|
|
34
|
+
.handle {
|
|
35
|
+
transition-property: all;
|
|
36
|
+
transition-duration: 0.35s;
|
|
37
|
+
transition-timing-function: cubic-bezier(.59, .01, .5, .99);
|
|
38
|
+
border-radius: 100%;
|
|
39
|
+
background-clip: padding-box;
|
|
40
|
+
position: absolute;
|
|
41
|
+
content: '';
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
%dual-handle-material {
|
|
46
|
+
background-color: var(--flavor-accent);
|
|
47
|
+
box-shadow: 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%), 0 3px 1px -2px rgb(0 0 0 / 20%);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
%dual-toggle-flat {
|
|
51
|
+
background-color: #44db5e;
|
|
52
|
+
box-shadow: inset 0 0 0 2px #44db5e;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
%dual-handle-flat {
|
|
56
|
+
background-color: #ffffff;
|
|
57
|
+
top: 2px;
|
|
58
|
+
box-shadow: 0 3px 2px rgb(0 0 0 / 25%);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@include design($material) {
|
|
62
|
+
input:checked + {
|
|
63
|
+
.toggle {
|
|
64
|
+
//box-shadow: none;
|
|
65
|
+
|
|
66
|
+
.handle {
|
|
67
|
+
@extend %dual-handle-material;
|
|
68
|
+
left: 18px;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.toggle {
|
|
74
|
+
background-color: rgba(55, 71, 79, 0.5);
|
|
75
|
+
|
|
76
|
+
margin-top: 4px;
|
|
77
|
+
height: 15px;
|
|
78
|
+
|
|
79
|
+
.handle {
|
|
80
|
+
margin-top: -4px;
|
|
81
|
+
width: 22px;
|
|
82
|
+
height: 22px;
|
|
83
|
+
background-color: #f1f1f1;
|
|
84
|
+
left: 0;
|
|
85
|
+
box-shadow: 0 4px 5px 0 rgb(0 0 0 / 14%), 0 1px 10px 0 rgb(0 0 0 / 12%), 0 2px 4px -1px rgb(0 0 0 / 40%);
|
|
86
|
+
|
|
87
|
+
&:before {
|
|
88
|
+
background: transparent;
|
|
89
|
+
content: '';
|
|
90
|
+
display: block;
|
|
91
|
+
width: 100%;
|
|
92
|
+
height: 100%;
|
|
93
|
+
border-radius: 50%;
|
|
94
|
+
z-index: 0;
|
|
95
|
+
box-shadow: 0 0 0 0 rgb(0 0 0 / 12%);
|
|
96
|
+
transition: box-shadow 0.1s linear;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
@include design($flat) {
|
|
103
|
+
input:checked + {
|
|
104
|
+
.toggle {
|
|
105
|
+
@extend %dual-toggle-flat;
|
|
106
|
+
|
|
107
|
+
.handle {
|
|
108
|
+
@extend %dual-handle-flat;
|
|
109
|
+
left: 19px
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.toggle {
|
|
115
|
+
height: 23px;
|
|
116
|
+
|
|
117
|
+
background-color: white;
|
|
118
|
+
box-shadow: inset 0 0 0 2px #e5e5e5;
|
|
119
|
+
|
|
120
|
+
.handle {
|
|
121
|
+
height: 19px;
|
|
122
|
+
width: 19px;
|
|
123
|
+
background-color: #ffffff;
|
|
124
|
+
left: 2px;
|
|
125
|
+
top: 2px;
|
|
126
|
+
box-shadow: 0 0 1px 0 rgb(0 0 0 / 25%), 0 3px 2px rgb(0 0 0 / 25%);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
&.dual {
|
|
132
|
+
@include design($material) {
|
|
133
|
+
.toggle {
|
|
134
|
+
.handle {
|
|
135
|
+
@extend %dual-handle-material;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
@include design($flat) {
|
|
140
|
+
.toggle {
|
|
141
|
+
@extend %dual-toggle-flat;
|
|
142
|
+
|
|
143
|
+
.handle {
|
|
144
|
+
@extend %dual-handle-flat;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { RbmComponentProps } from '../../RbmComponentProps';
|
|
3
|
+
import { Override } from '../../../TypeHelpers';
|
|
4
|
+
import { TextareaHTMLAttributes, useCallback, KeyboardEvent, ChangeEvent } from 'react';
|
|
5
|
+
import { OptionalListener, useListener } from '../../Hooks/useListener';
|
|
6
|
+
import { withMemo } from '../../../helper/withMemo';
|
|
7
|
+
|
|
8
|
+
import styles from './textarea.scss';
|
|
9
|
+
import classNames from 'classnames';
|
|
10
|
+
|
|
11
|
+
export type TextareaProps<OnChangeData> = RbmComponentProps<
|
|
12
|
+
Override<
|
|
13
|
+
TextareaHTMLAttributes<HTMLTextAreaElement>,
|
|
14
|
+
{
|
|
15
|
+
label?: string;
|
|
16
|
+
onChangeText?: (newText: string) => void;
|
|
17
|
+
onEnter?: (newText: string) => void;
|
|
18
|
+
} & OptionalListener<'onChange', OnChangeData>
|
|
19
|
+
>
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
function Textarea<OnChangeData>({
|
|
23
|
+
label,
|
|
24
|
+
className,
|
|
25
|
+
style,
|
|
26
|
+
onKeyPress,
|
|
27
|
+
onChangeText,
|
|
28
|
+
onEnter,
|
|
29
|
+
...otherProps
|
|
30
|
+
}: TextareaProps<OnChangeData>) {
|
|
31
|
+
// Variables
|
|
32
|
+
|
|
33
|
+
// States
|
|
34
|
+
|
|
35
|
+
// Refs
|
|
36
|
+
|
|
37
|
+
// Callbacks
|
|
38
|
+
const onChangeWithData = useListener<'onChange', OnChangeData>('onChange', otherProps);
|
|
39
|
+
const onChange = useCallback(
|
|
40
|
+
(e: ChangeEvent<HTMLTextAreaElement>) => {
|
|
41
|
+
if (onChangeText) {
|
|
42
|
+
onChangeText(e.target.value);
|
|
43
|
+
}
|
|
44
|
+
onChangeWithData(e);
|
|
45
|
+
},
|
|
46
|
+
[onChangeWithData, onChangeText]
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const realOnKeyPress = useCallback(
|
|
50
|
+
(e: KeyboardEvent<HTMLTextAreaElement>) => {
|
|
51
|
+
if (onKeyPress) {
|
|
52
|
+
onKeyPress(e);
|
|
53
|
+
}
|
|
54
|
+
if (onEnter && e.key === 'Enter' && !e.defaultPrevented) {
|
|
55
|
+
onEnter((e.target as HTMLTextAreaElement).value);
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
[onEnter, onKeyPress]
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// Effects
|
|
62
|
+
|
|
63
|
+
// Other
|
|
64
|
+
|
|
65
|
+
// Render Functions
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<label className={classNames(styles.container, className)} style={style}>
|
|
69
|
+
{label ? <span className={styles.label}>{label}</span> : null}
|
|
70
|
+
<textarea {...otherProps} onKeyPress={realOnKeyPress} className={styles.textarea} onChange={onChange} />
|
|
71
|
+
</label>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Need TextareaMemo for autocompletion of phpstorm
|
|
76
|
+
const TextareaMemo = withMemo(Textarea, styles);
|
|
77
|
+
export { TextareaMemo as Textarea };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
.container {
|
|
2
|
+
width: 100%;
|
|
3
|
+
height: 10rem;
|
|
4
|
+
|
|
5
|
+
.label {
|
|
6
|
+
display: block;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
textarea {
|
|
10
|
+
background-color: #efeff4;
|
|
11
|
+
color: #1f1f21;
|
|
12
|
+
box-shadow: none;
|
|
13
|
+
appearance: none;
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 100%;
|
|
16
|
+
resize: none;
|
|
17
|
+
outline: none;
|
|
18
|
+
padding: 5px;
|
|
19
|
+
border-radius: 4px;
|
|
20
|
+
border: 1px solid var(--border-light);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { MutableRefObject, useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useOnChangeDone(onChangeDone: (ev: any) => void, ref?: MutableRefObject<HTMLInputElement | null>) {
|
|
4
|
+
const innerRef = useRef<HTMLInputElement>(null);
|
|
5
|
+
const usedRef = ref ?? innerRef;
|
|
6
|
+
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const elem = usedRef.current;
|
|
9
|
+
elem?.addEventListener('change', onChangeDone);
|
|
10
|
+
return () => {
|
|
11
|
+
elem?.removeEventListener('change', onChangeDone);
|
|
12
|
+
};
|
|
13
|
+
}, [ref, onChangeDone, usedRef]);
|
|
14
|
+
|
|
15
|
+
return usedRef;
|
|
16
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
ComponentPropsWithoutRef,
|
|
4
|
+
ComponentRef,
|
|
5
|
+
PropsWithChildren,
|
|
6
|
+
useCallback,
|
|
7
|
+
useEffect,
|
|
8
|
+
useMemo,
|
|
9
|
+
useRef,
|
|
10
|
+
} from 'react';
|
|
11
|
+
import { Override } from '../../TypeHelpers';
|
|
12
|
+
import { withMemo } from '../../helper/withMemo';
|
|
13
|
+
import { useWindow } from '../../WindowContext/WindowContext';
|
|
14
|
+
|
|
15
|
+
export type FullScreenProps<AsType extends keyof JSX.IntrinsicElements> = PropsWithChildren<
|
|
16
|
+
Override<
|
|
17
|
+
ComponentPropsWithoutRef<AsType>,
|
|
18
|
+
{ as?: AsType; fullscreenKey?: string; onEnterFullscreen?: () => void; onLeaveFullscreen?: () => void }
|
|
19
|
+
>
|
|
20
|
+
>;
|
|
21
|
+
|
|
22
|
+
function FullScreen<AsTag extends keyof JSX.IntrinsicElements = 'span'>({
|
|
23
|
+
children,
|
|
24
|
+
as,
|
|
25
|
+
fullscreenKey,
|
|
26
|
+
onEnterFullscreen,
|
|
27
|
+
onLeaveFullscreen,
|
|
28
|
+
...otherProps
|
|
29
|
+
}: FullScreenProps<AsTag>) {
|
|
30
|
+
// Variables
|
|
31
|
+
|
|
32
|
+
// Refs
|
|
33
|
+
const containerRef = useRef<ComponentRef<AsTag>>(null);
|
|
34
|
+
const window = useWindow();
|
|
35
|
+
|
|
36
|
+
// States
|
|
37
|
+
|
|
38
|
+
// Selectors
|
|
39
|
+
|
|
40
|
+
// Callbacks
|
|
41
|
+
const toggleFullscreen = useCallback(() => {
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
43
|
+
// @ts-ignore
|
|
44
|
+
if (document.fullscreenElement || document.webkitFullscreenElement) {
|
|
45
|
+
if ('exitFullscreen' in document) {
|
|
46
|
+
document.exitFullscreen();
|
|
47
|
+
} else {
|
|
48
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
49
|
+
// @ts-ignore
|
|
50
|
+
document.webkitCancelFullScreen();
|
|
51
|
+
}
|
|
52
|
+
onLeaveFullscreen?.();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if ('webkitRequestFullscreen' in document.body) {
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
57
|
+
// @ts-ignore
|
|
58
|
+
containerRef.current?.webkitRequestFullscreen();
|
|
59
|
+
} else {
|
|
60
|
+
containerRef.current?.requestFullscreen();
|
|
61
|
+
}
|
|
62
|
+
onEnterFullscreen?.();
|
|
63
|
+
}, [onEnterFullscreen, onLeaveFullscreen]);
|
|
64
|
+
|
|
65
|
+
// Effects
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (!fullscreenKey) {
|
|
68
|
+
return undefined;
|
|
69
|
+
}
|
|
70
|
+
const listener = (e: KeyboardEvent) => {
|
|
71
|
+
if (e.key === fullscreenKey) {
|
|
72
|
+
toggleFullscreen();
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
window?.addEventListener('keyup', listener);
|
|
76
|
+
return () => window?.removeEventListener('keyup', listener);
|
|
77
|
+
}, [fullscreenKey, toggleFullscreen, window]);
|
|
78
|
+
|
|
79
|
+
// Other
|
|
80
|
+
|
|
81
|
+
// Render Functions
|
|
82
|
+
const element = as ?? 'span';
|
|
83
|
+
const props = useMemo(() => ({ ...otherProps, ref: containerRef }), [otherProps]);
|
|
84
|
+
return React.createElement(element, props, children);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Need FullScreenMemo for autocompletion of phpstorm
|
|
88
|
+
const FullScreenMemo = withMemo(FullScreen);
|
|
89
|
+
export { FullScreenMemo as FullScreen };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useWindow } from '../../WindowContext/WindowContext';
|
|
3
|
+
|
|
4
|
+
export const BreakpointNames = ['xs', 'sm', 'md', 'lg', 'xl', 'xxl'];
|
|
5
|
+
|
|
6
|
+
export enum Breakpoints {
|
|
7
|
+
XS = 0,
|
|
8
|
+
SM = 576,
|
|
9
|
+
MD = 768,
|
|
10
|
+
LG = 992,
|
|
11
|
+
XL = 1200,
|
|
12
|
+
XXL = 1400,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const resolveBreakpoint = (width: number) => {
|
|
16
|
+
if (width >= Breakpoints.XXL) {
|
|
17
|
+
return Breakpoints.XXL;
|
|
18
|
+
}
|
|
19
|
+
if (width >= Breakpoints.XL) {
|
|
20
|
+
return Breakpoints.XL;
|
|
21
|
+
}
|
|
22
|
+
if (width >= Breakpoints.LG) {
|
|
23
|
+
return Breakpoints.LG;
|
|
24
|
+
}
|
|
25
|
+
if (width >= Breakpoints.MD) {
|
|
26
|
+
return Breakpoints.MD;
|
|
27
|
+
}
|
|
28
|
+
if (width >= Breakpoints.SM) {
|
|
29
|
+
return Breakpoints.SM;
|
|
30
|
+
}
|
|
31
|
+
return Breakpoints.XS;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const useBreakpoint = () => {
|
|
35
|
+
const [size, setSize] = useState(Breakpoints.SM);
|
|
36
|
+
const window = useWindow();
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
setSize(resolveBreakpoint(window?.innerWidth ?? 1024));
|
|
40
|
+
const calcInnerWidth = () => setTimeout(() => setSize(resolveBreakpoint(window?.innerWidth ?? 1024)), 200);
|
|
41
|
+
|
|
42
|
+
window?.addEventListener('resize', calcInnerWidth);
|
|
43
|
+
return () => window?.removeEventListener('resize', calcInnerWidth);
|
|
44
|
+
}, [window]);
|
|
45
|
+
|
|
46
|
+
return size;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export function useBreakpointSelect<T1, T2, T3, T4, T5, T6>(breakpointValues: [T1, T2, T3, T4, T5, T6]) {
|
|
50
|
+
const size = useBreakpoint();
|
|
51
|
+
|
|
52
|
+
switch (size) {
|
|
53
|
+
case Breakpoints.XS:
|
|
54
|
+
return breakpointValues[0];
|
|
55
|
+
case Breakpoints.SM:
|
|
56
|
+
return breakpointValues[1];
|
|
57
|
+
case Breakpoints.MD:
|
|
58
|
+
return breakpointValues[2];
|
|
59
|
+
case Breakpoints.LG:
|
|
60
|
+
return breakpointValues[3];
|
|
61
|
+
case Breakpoints.XL:
|
|
62
|
+
return breakpointValues[4];
|
|
63
|
+
default:
|
|
64
|
+
return breakpointValues[5];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ForwardedRef, useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useComposedRef = <T>(ref: ForwardedRef<T>, initialValue: T | null = null) => {
|
|
4
|
+
const targetRef = useRef<T>(initialValue);
|
|
5
|
+
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (!ref) return;
|
|
8
|
+
|
|
9
|
+
if (typeof ref === 'function') {
|
|
10
|
+
ref(targetRef.current);
|
|
11
|
+
} else {
|
|
12
|
+
ref.current = targetRef.current;
|
|
13
|
+
}
|
|
14
|
+
}, [ref]);
|
|
15
|
+
|
|
16
|
+
return targetRef;
|
|
17
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { useCallback, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useDebounced<Args extends any[]>(
|
|
4
|
+
callback: (...args: Args) => void | Promise<void>,
|
|
5
|
+
dependencies: any[],
|
|
6
|
+
delay = 100
|
|
7
|
+
) {
|
|
8
|
+
const [shared] = useState({ timeout: undefined as undefined | any });
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11
|
+
const realCB = useCallback(callback, dependencies);
|
|
12
|
+
|
|
13
|
+
return useCallback(
|
|
14
|
+
(...newArgs: Args) => {
|
|
15
|
+
if (shared.timeout === undefined) {
|
|
16
|
+
realCB(...newArgs);
|
|
17
|
+
shared.timeout = setTimeout(() => (shared.timeout = undefined), delay);
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
[delay, realCB, shared]
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { useCallback, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useDelayed<Args extends any[]>(
|
|
4
|
+
callback: (...args: Args) => void | Promise<void>,
|
|
5
|
+
dependencies: any[],
|
|
6
|
+
delay = 100,
|
|
7
|
+
maxDelay?: number
|
|
8
|
+
) {
|
|
9
|
+
const argsRef = useRef<Args | undefined>(undefined);
|
|
10
|
+
const timeoutRef = useRef<any>(undefined);
|
|
11
|
+
const mayDelayTimeoutRef = useRef<any>(undefined);
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
14
|
+
const realCB = useCallback(callback, dependencies);
|
|
15
|
+
const func = useCallback(
|
|
16
|
+
(...newArgs: Args) => {
|
|
17
|
+
argsRef.current = newArgs;
|
|
18
|
+
|
|
19
|
+
const triggerFunc = () => {
|
|
20
|
+
clearTimeout(mayDelayTimeoutRef.current);
|
|
21
|
+
clearTimeout(timeoutRef.current);
|
|
22
|
+
timeoutRef.current = undefined;
|
|
23
|
+
maxDelayTimeout.current = undefined;
|
|
24
|
+
|
|
25
|
+
if (argsRef.current !== undefined) {
|
|
26
|
+
realCB(...argsRef.current);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
if (timeoutRef.current) {
|
|
31
|
+
clearTimeout(timeoutRef.current);
|
|
32
|
+
}
|
|
33
|
+
timeoutRef.current = setTimeout(triggerFunc, delay);
|
|
34
|
+
|
|
35
|
+
if (maxDelay && maxDelayTimeout.current === undefined) {
|
|
36
|
+
maxDelayTimeout.current = setTimeout(() => {
|
|
37
|
+
triggerFunc();
|
|
38
|
+
}, maxDelay);
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
[delay, maxDelay, realCB]
|
|
42
|
+
);
|
|
43
|
+
const maxDelayTimeout = useRef<any>();
|
|
44
|
+
|
|
45
|
+
return func;
|
|
46
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MutableRefObject, useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
export const useInViewport = (element: MutableRefObject<Element | null>, rootMargin = '0px') => {
|
|
4
|
+
const [isVisible, setState] = useState(false);
|
|
5
|
+
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const savedElement = element.current;
|
|
8
|
+
if (!savedElement) {
|
|
9
|
+
return undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const observer = new IntersectionObserver(
|
|
13
|
+
([entry]) => {
|
|
14
|
+
setState(entry.isIntersecting);
|
|
15
|
+
},
|
|
16
|
+
{ rootMargin }
|
|
17
|
+
);
|
|
18
|
+
observer.observe(savedElement);
|
|
19
|
+
return () => observer.unobserve(savedElement);
|
|
20
|
+
}, [element, rootMargin]);
|
|
21
|
+
|
|
22
|
+
return isVisible;
|
|
23
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
import { useWindow } from '../../WindowContext/WindowContext';
|
|
3
|
+
|
|
4
|
+
function isFormElement(element: EventTarget | null) {
|
|
5
|
+
return (
|
|
6
|
+
element instanceof HTMLInputElement ||
|
|
7
|
+
element instanceof HTMLSelectElement ||
|
|
8
|
+
element instanceof HTMLTextAreaElement
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function useKeyListener(
|
|
13
|
+
key: KeyboardEvent['key'],
|
|
14
|
+
listener: (e: KeyboardEvent) => void,
|
|
15
|
+
dependencies: any[] = [],
|
|
16
|
+
ignoreFormElements = true
|
|
17
|
+
) {
|
|
18
|
+
const window = useWindow();
|
|
19
|
+
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
const lowercaseKey = key.toLowerCase();
|
|
22
|
+
const keyListener = (e: KeyboardEvent) => {
|
|
23
|
+
if (e.key.toLowerCase() === lowercaseKey && (!ignoreFormElements || !isFormElement(e.target))) {
|
|
24
|
+
listener(e);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
window?.addEventListener('keydown', keyListener);
|
|
28
|
+
return () => window?.removeEventListener('keydown', keyListener);
|
|
29
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
30
|
+
}, [window, key, ...dependencies]);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function useKeyUpListener(
|
|
34
|
+
key: KeyboardEvent['key'],
|
|
35
|
+
listener: (e: KeyboardEvent) => void,
|
|
36
|
+
dependencies: any[] = [],
|
|
37
|
+
ignoreFormElements = true
|
|
38
|
+
) {
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
const lowercaseKey = key.toLowerCase();
|
|
41
|
+
const keyListener = (e: KeyboardEvent) => {
|
|
42
|
+
if (e.key.toLowerCase() === lowercaseKey && (!ignoreFormElements || !isFormElement(e.target))) {
|
|
43
|
+
listener(e);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
window.addEventListener('keyup', keyListener);
|
|
47
|
+
return () => window.removeEventListener('keyup', keyListener);
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
}, [key, ...dependencies]);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function useKeyPressed(key: KeyboardEvent['key'], ignoreFormElements = true, preventDefault = true) {
|
|
53
|
+
const [isPressed, setIsPressed] = useState(false);
|
|
54
|
+
useKeyListener(
|
|
55
|
+
key,
|
|
56
|
+
(e) => {
|
|
57
|
+
setIsPressed(true);
|
|
58
|
+
if (preventDefault) {
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
[isPressed],
|
|
63
|
+
ignoreFormElements
|
|
64
|
+
);
|
|
65
|
+
useKeyUpListener(
|
|
66
|
+
key,
|
|
67
|
+
(e) => {
|
|
68
|
+
setIsPressed(false);
|
|
69
|
+
if (preventDefault) {
|
|
70
|
+
e.preventDefault();
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
[],
|
|
74
|
+
false
|
|
75
|
+
);
|
|
76
|
+
return isPressed;
|
|
77
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
|
|
3
|
+
export type ListenerWithData<DataType, Event = void | any, ReturnType = void> = (
|
|
4
|
+
eventData: Event,
|
|
5
|
+
extraData: DataType
|
|
6
|
+
) => ReturnType;
|
|
7
|
+
export type ListenerWithoutData<Event = void | any, ReturnType = void> = (eventData: Event) => ReturnType;
|
|
8
|
+
|
|
9
|
+
export type Listener<ListenerProperty extends string, DataType, Event = any | void, ReturnType = void> =
|
|
10
|
+
| ({ [Property in ListenerProperty]: ListenerWithData<DataType, Event, ReturnType> } & {
|
|
11
|
+
[Property in `${ListenerProperty}Data`]: DataType;
|
|
12
|
+
})
|
|
13
|
+
| {
|
|
14
|
+
[Property in ListenerProperty]: ListenerWithoutData<Event, ReturnType>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type OptionalListener<ListenerProperty extends string, DataType, Event = any | void, ReturnType = void> =
|
|
18
|
+
| ({ [Property in ListenerProperty]: ListenerWithData<DataType, Event, ReturnType> } & {
|
|
19
|
+
[Property in `${ListenerProperty}Data`]: DataType;
|
|
20
|
+
})
|
|
21
|
+
| {
|
|
22
|
+
[Property in ListenerProperty]?: ListenerWithoutData<Event, ReturnType>;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export function useListener<ListenerName extends string, DataType, EventType = any, ReturnType = void>(
|
|
26
|
+
listener: ListenerName,
|
|
27
|
+
listenerProps: OptionalListener<ListenerName, DataType, EventType, ReturnType>
|
|
28
|
+
) {
|
|
29
|
+
const listenerDataName = `${listener}Data` as keyof typeof listenerProps;
|
|
30
|
+
const listenerName = listener as keyof typeof listenerProps;
|
|
31
|
+
|
|
32
|
+
const hasExtraData = listenerDataName in listenerProps;
|
|
33
|
+
|
|
34
|
+
const extraData = hasExtraData ? (listenerProps[listenerDataName] as DataType) : undefined;
|
|
35
|
+
const callback = listenerProps[listenerName] as
|
|
36
|
+
| ListenerWithoutData<EventType, ReturnType>
|
|
37
|
+
| ListenerWithData<DataType, EventType, ReturnType>
|
|
38
|
+
| undefined;
|
|
39
|
+
|
|
40
|
+
return useCallback(
|
|
41
|
+
(e: EventType) => {
|
|
42
|
+
let res: ReturnType | undefined;
|
|
43
|
+
if (extraData !== undefined) {
|
|
44
|
+
res = (callback as ListenerWithData<DataType, EventType, ReturnType>)(e, extraData);
|
|
45
|
+
} else if (callback) {
|
|
46
|
+
res = (callback as ListenerWithoutData<EventType, ReturnType>)(e);
|
|
47
|
+
}
|
|
48
|
+
return res as ReturnType;
|
|
49
|
+
},
|
|
50
|
+
[callback, extraData]
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function useListenerWithExtractedProps<
|
|
55
|
+
ListenerName extends string,
|
|
56
|
+
DataType,
|
|
57
|
+
EventType = any,
|
|
58
|
+
ReturnType = void,
|
|
59
|
+
PropTypes extends OptionalListener<ListenerName, DataType, EventType, ReturnType> = OptionalListener<
|
|
60
|
+
ListenerName,
|
|
61
|
+
DataType,
|
|
62
|
+
EventType,
|
|
63
|
+
ReturnType
|
|
64
|
+
>
|
|
65
|
+
>(listener: ListenerName, listenerProps: PropTypes) {
|
|
66
|
+
const {
|
|
67
|
+
[`${listener}Data` as keyof typeof listenerProps]: _,
|
|
68
|
+
[listener as keyof typeof listenerProps]: __,
|
|
69
|
+
...otherProps
|
|
70
|
+
} = listenerProps;
|
|
71
|
+
|
|
72
|
+
return [useListener<ListenerName, DataType, EventType, ReturnType>(listener, listenerProps), otherProps] as const;
|
|
73
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
|
+
|
|
3
|
+
export function useOnMount(cb: () => void | Promise<void>) {
|
|
4
|
+
const called = useRef(false);
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
if (!called.current) {
|
|
7
|
+
called.current = true;
|
|
8
|
+
cb();
|
|
9
|
+
}
|
|
10
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
11
|
+
}, []);
|
|
12
|
+
}
|