@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,139 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useCallback, useRef, useState, MouseEvent } from 'react';
|
|
3
|
+
import { Color, ColorChangeHandler, ColorResult, SketchPicker } from 'react-color';
|
|
4
|
+
import { OptionalListener, useListener } from '../../Hooks/useListener';
|
|
5
|
+
import { withMemo } from '../../../helper/withMemo';
|
|
6
|
+
|
|
7
|
+
import styles from './colorInput.scss';
|
|
8
|
+
import { useSharedSelectedColor } from './sharedSelectedColor';
|
|
9
|
+
|
|
10
|
+
export type ColorInputProps<OnChangeData> = {
|
|
11
|
+
defaultValue?: string;
|
|
12
|
+
value?: string;
|
|
13
|
+
label?: string;
|
|
14
|
+
onChangeColor?: (newColor: string) => void;
|
|
15
|
+
onOpen?: (currentColor: string) => void;
|
|
16
|
+
onChangeColorComplete?: (newColor: string) => void;
|
|
17
|
+
onClose?: (newColor: string) => void;
|
|
18
|
+
disableAlpha?: boolean;
|
|
19
|
+
presetColors?: string[];
|
|
20
|
+
sharedColorKey?: string;
|
|
21
|
+
} & OptionalListener<'onChange', OnChangeData>;
|
|
22
|
+
|
|
23
|
+
function convertToHex(color: { r: number; g: number; b: number; a?: number }, disableAlpha?: boolean) {
|
|
24
|
+
let newColor = `#${color.r.toString(16).padStart(2, '0')}${color.g.toString(16).padStart(2, '0')}${color.b
|
|
25
|
+
.toString(16)
|
|
26
|
+
.padStart(2, '0')}`;
|
|
27
|
+
if (color.a !== undefined && !disableAlpha) {
|
|
28
|
+
newColor += Math.round(color.a * 255)
|
|
29
|
+
.toString(16)
|
|
30
|
+
.padStart(2, '0');
|
|
31
|
+
}
|
|
32
|
+
return newColor;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function ColorInput<OnChangeData>({
|
|
36
|
+
defaultValue,
|
|
37
|
+
value,
|
|
38
|
+
label,
|
|
39
|
+
onChangeColor,
|
|
40
|
+
onChangeColorComplete,
|
|
41
|
+
onOpen,
|
|
42
|
+
onClose,
|
|
43
|
+
disableAlpha,
|
|
44
|
+
presetColors,
|
|
45
|
+
sharedColorKey,
|
|
46
|
+
...otherProps
|
|
47
|
+
}: ColorInputProps<OnChangeData>) {
|
|
48
|
+
// Variables
|
|
49
|
+
// useStyles(styles);
|
|
50
|
+
|
|
51
|
+
// Refs
|
|
52
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
53
|
+
|
|
54
|
+
// States
|
|
55
|
+
const [color, setColor] = useState<string>(value ?? defaultValue ?? '#000000FF');
|
|
56
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
57
|
+
const [position, setPosition] = useState({ x: 0, y: 0 });
|
|
58
|
+
|
|
59
|
+
const { colors, addColor } = useSharedSelectedColor(sharedColorKey);
|
|
60
|
+
|
|
61
|
+
const colVal: Color = value ?? color;
|
|
62
|
+
// Selectors
|
|
63
|
+
|
|
64
|
+
// Callbacks
|
|
65
|
+
const onChangeWithData = useListener<'onChange', OnChangeData>('onChange', otherProps);
|
|
66
|
+
const onChange = useCallback<ColorChangeHandler>(
|
|
67
|
+
(newColor: ColorResult, e) => {
|
|
68
|
+
const hexColor = convertToHex(newColor.rgb, disableAlpha);
|
|
69
|
+
setColor(hexColor);
|
|
70
|
+
if (onChangeColor) {
|
|
71
|
+
onChangeColor(hexColor);
|
|
72
|
+
}
|
|
73
|
+
onChangeWithData(e);
|
|
74
|
+
},
|
|
75
|
+
[disableAlpha, onChangeColor, onChangeWithData]
|
|
76
|
+
);
|
|
77
|
+
const onChangeComplete = useCallback(
|
|
78
|
+
(newColor: ColorResult) => {
|
|
79
|
+
const hexColor = convertToHex(newColor.rgb, disableAlpha);
|
|
80
|
+
setColor(hexColor);
|
|
81
|
+
if (onChangeColorComplete) {
|
|
82
|
+
onChangeColorComplete(hexColor);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
[disableAlpha, onChangeColorComplete]
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const onContainerClick = useCallback(
|
|
89
|
+
(e: MouseEvent) => {
|
|
90
|
+
if (e.target === containerRef?.current) {
|
|
91
|
+
setIsOpen(false);
|
|
92
|
+
console.log('onContainerClick', colVal);
|
|
93
|
+
addColor(colVal);
|
|
94
|
+
onClose?.(colVal);
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
[addColor, colVal, onClose]
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const openElement = useCallback(
|
|
101
|
+
(e: MouseEvent) => {
|
|
102
|
+
setIsOpen(true);
|
|
103
|
+
setPosition({ x: e.clientX, y: e.clientY });
|
|
104
|
+
onOpen?.(colVal);
|
|
105
|
+
},
|
|
106
|
+
[colVal, onOpen]
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
// Effects
|
|
110
|
+
|
|
111
|
+
// Other
|
|
112
|
+
|
|
113
|
+
// Render Functions
|
|
114
|
+
return (
|
|
115
|
+
<span className={styles.colorInput}>
|
|
116
|
+
{isOpen ? (
|
|
117
|
+
<div onClick={onContainerClick} className={styles.modalContainer} ref={containerRef}>
|
|
118
|
+
<div className={styles.modal} style={{ top: position.y, left: position.x }}>
|
|
119
|
+
<SketchPicker
|
|
120
|
+
color={colVal}
|
|
121
|
+
onChange={onChange}
|
|
122
|
+
onChangeComplete={onChangeComplete}
|
|
123
|
+
disableAlpha={disableAlpha}
|
|
124
|
+
presetColors={presetColors ?? colors}
|
|
125
|
+
/>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
) : null}
|
|
129
|
+
<span onClick={openElement} className={styles.label}>
|
|
130
|
+
{label}
|
|
131
|
+
</span>
|
|
132
|
+
<span onClick={openElement} style={{ backgroundColor: colVal }} className={styles.preview} />
|
|
133
|
+
</span>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Need ColorInputMemo for autocompletion of phpstorm
|
|
138
|
+
const ColorInputMemo = withMemo(ColorInput, styles);
|
|
139
|
+
export { ColorInputMemo as ColorInput };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
.colorInput {
|
|
2
|
+
margin-left: 0.5rem;
|
|
3
|
+
margin-right: 0.5rem;
|
|
4
|
+
display: flex;
|
|
5
|
+
|
|
6
|
+
.preview {
|
|
7
|
+
margin-left: 0.4rem;
|
|
8
|
+
width: 1rem;
|
|
9
|
+
height: 1rem;
|
|
10
|
+
display: inline-block;
|
|
11
|
+
border: 1px solid black;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.modalContainer {
|
|
15
|
+
z-index: 9999;
|
|
16
|
+
position: fixed;
|
|
17
|
+
top: 0;
|
|
18
|
+
left: 0;
|
|
19
|
+
right: 0;
|
|
20
|
+
bottom: 0;
|
|
21
|
+
width: 100vw;
|
|
22
|
+
height: 100vh;
|
|
23
|
+
overflow: auto;
|
|
24
|
+
|
|
25
|
+
.modal {
|
|
26
|
+
position: absolute;
|
|
27
|
+
background-color: white;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.label {
|
|
32
|
+
flex: 1;
|
|
33
|
+
margin-right: 0.2rem;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { Random } from '@ainias42/js-helper';
|
|
3
|
+
|
|
4
|
+
const sharedSelectedColor: Record<string, { colors: string[]; updateFunctions: (() => void)[] }> = {};
|
|
5
|
+
|
|
6
|
+
export function useSharedSelectedColor(key?: string, numberSavedColors = 15) {
|
|
7
|
+
const [, setVersion] = useState(1);
|
|
8
|
+
const innerKey = useRef(Random.getStringRandom(12));
|
|
9
|
+
const realKey = key ?? innerKey.current;
|
|
10
|
+
|
|
11
|
+
if (!sharedSelectedColor[realKey]) {
|
|
12
|
+
sharedSelectedColor[realKey] = {
|
|
13
|
+
colors: [],
|
|
14
|
+
updateFunctions: [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const update = useCallback(() => setVersion((old) => old + 1), []);
|
|
19
|
+
useMemo(() => {
|
|
20
|
+
sharedSelectedColor[realKey].updateFunctions.push(update);
|
|
21
|
+
}, [realKey, update]);
|
|
22
|
+
|
|
23
|
+
const addColor = useCallback(
|
|
24
|
+
(newColor: string) => {
|
|
25
|
+
sharedSelectedColor[realKey].colors = sharedSelectedColor[realKey].colors.filter(
|
|
26
|
+
(color) => color !== newColor
|
|
27
|
+
);
|
|
28
|
+
sharedSelectedColor[realKey].colors.unshift(newColor);
|
|
29
|
+
if (sharedSelectedColor[realKey].colors.length > numberSavedColors) {
|
|
30
|
+
sharedSelectedColor[realKey].colors.splice(numberSavedColors, 1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// triggers rerender
|
|
34
|
+
sharedSelectedColor[realKey].updateFunctions.forEach((u) => u());
|
|
35
|
+
},
|
|
36
|
+
[numberSavedColors, realKey]
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
return { colors: sharedSelectedColor[realKey]?.colors, addColor };
|
|
40
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { RbmComponentProps } from '../../RbmComponentProps';
|
|
3
|
+
import { Override } from '../../../TypeHelpers';
|
|
4
|
+
import { ChangeEventHandler, InputHTMLAttributes, useCallback, useState } from 'react';
|
|
5
|
+
import { OptionalListener, useListener } from '../../Hooks/useListener';
|
|
6
|
+
import { Button } from '../Button/Button';
|
|
7
|
+
|
|
8
|
+
import styles from './imageInput.scss';
|
|
9
|
+
import { withMemo } from '../../../helper/withMemo';
|
|
10
|
+
import classNames from 'classnames';
|
|
11
|
+
|
|
12
|
+
export type ImageType = { name: string; url: string };
|
|
13
|
+
|
|
14
|
+
export type ImageInputProps<OnChangeData> = RbmComponentProps<
|
|
15
|
+
Override<
|
|
16
|
+
InputHTMLAttributes<HTMLInputElement>,
|
|
17
|
+
{
|
|
18
|
+
defaultValue?: ImageType;
|
|
19
|
+
value?: ImageType;
|
|
20
|
+
label?: string;
|
|
21
|
+
onChangeImage?: (image: ImageType, imageData: File) => void;
|
|
22
|
+
} & OptionalListener<'onChange', OnChangeData>
|
|
23
|
+
>
|
|
24
|
+
>;
|
|
25
|
+
|
|
26
|
+
function ImageInput<OnChangeData>({
|
|
27
|
+
className,
|
|
28
|
+
style,
|
|
29
|
+
value,
|
|
30
|
+
defaultValue,
|
|
31
|
+
onChangeImage,
|
|
32
|
+
label,
|
|
33
|
+
...otherProps
|
|
34
|
+
}: ImageInputProps<OnChangeData>) {
|
|
35
|
+
// Variables
|
|
36
|
+
const [image, setImage] = useState(defaultValue);
|
|
37
|
+
|
|
38
|
+
// Refs
|
|
39
|
+
|
|
40
|
+
// States
|
|
41
|
+
|
|
42
|
+
// Selectors
|
|
43
|
+
|
|
44
|
+
// Callbacks
|
|
45
|
+
const onChangeWithData = useListener<'onChange', OnChangeData>('onChange', otherProps);
|
|
46
|
+
const getBase64 = useCallback((file: Blob) => {
|
|
47
|
+
return new Promise<string>((resolve, reject) => {
|
|
48
|
+
const reader = new FileReader();
|
|
49
|
+
reader.onload = () => {
|
|
50
|
+
resolve(reader.result as string);
|
|
51
|
+
};
|
|
52
|
+
reader.onerror = reject;
|
|
53
|
+
reader.readAsDataURL(file);
|
|
54
|
+
});
|
|
55
|
+
}, []);
|
|
56
|
+
const onChange = useCallback<ChangeEventHandler<HTMLInputElement>>(
|
|
57
|
+
async (e) => {
|
|
58
|
+
if (!e.target.files || e.target.files.length === 0) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
onChangeWithData(e);
|
|
63
|
+
const newUrl = await getBase64(e.target.files[0]);
|
|
64
|
+
const newValue = { name: e.target.files[0].name, url: newUrl };
|
|
65
|
+
setImage(newValue);
|
|
66
|
+
|
|
67
|
+
if (onChangeImage) {
|
|
68
|
+
onChangeImage(newValue, e.target.files[0]);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
[onChangeWithData, onChangeImage, getBase64]
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Effects
|
|
75
|
+
|
|
76
|
+
// Other
|
|
77
|
+
|
|
78
|
+
// Render Functions
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
|
82
|
+
<label className={classNames(styles.imageInput, className)} style={style}>
|
|
83
|
+
{label ? <span>{label}</span> : null}
|
|
84
|
+
<img
|
|
85
|
+
src={(value ?? image)?.url}
|
|
86
|
+
alt={(value ?? image)?.name}
|
|
87
|
+
className={classNames(styles.preview, (value ?? image)?.url ? undefined : styles.empty)}
|
|
88
|
+
/>
|
|
89
|
+
<Button __allowChildren="all">{(value ?? image)?.name ?? <i>Select Image</i>}</Button>
|
|
90
|
+
<input {...otherProps} className={styles.value} onChange={onChange} type="file" />
|
|
91
|
+
</label>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Need ImageInputMemo for autocompletion of phpstorm
|
|
96
|
+
const ImageInputMemo = withMemo(ImageInput, styles);
|
|
97
|
+
export { ImageInputMemo as ImageInput };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
.imageInput {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
position: relative;
|
|
5
|
+
cursor: pointer;
|
|
6
|
+
|
|
7
|
+
.preview {
|
|
8
|
+
flex: 1;
|
|
9
|
+
object-fit: contain;
|
|
10
|
+
|
|
11
|
+
&.empty {
|
|
12
|
+
background-color: #d3d3d3;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.value {
|
|
17
|
+
position: absolute;
|
|
18
|
+
top: 0;
|
|
19
|
+
left: 0;
|
|
20
|
+
right: 0;
|
|
21
|
+
bottom: 0;
|
|
22
|
+
opacity: 0;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Input, InputProps } from './Input';
|
|
3
|
+
import { withMemo } from '../../../helper/withMemo';
|
|
4
|
+
|
|
5
|
+
import styles from './input.scss';
|
|
6
|
+
import classNames from 'classnames';
|
|
7
|
+
|
|
8
|
+
export type HiddenInputProps<OnChangeType, OnBlurData, OnChangeEndData> = InputProps<
|
|
9
|
+
OnChangeType,
|
|
10
|
+
OnBlurData,
|
|
11
|
+
OnChangeEndData
|
|
12
|
+
> & {
|
|
13
|
+
noFocusHint?: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
function HiddenInput<OnChangeData, OnBlurData, OnChangeEndData>({
|
|
17
|
+
noFocusHint = false,
|
|
18
|
+
className,
|
|
19
|
+
...props
|
|
20
|
+
}: HiddenInputProps<OnChangeData, OnBlurData, OnChangeEndData>) {
|
|
21
|
+
// Variables
|
|
22
|
+
|
|
23
|
+
// States
|
|
24
|
+
|
|
25
|
+
// Refs
|
|
26
|
+
|
|
27
|
+
// Callbacks
|
|
28
|
+
|
|
29
|
+
// Effects
|
|
30
|
+
|
|
31
|
+
// Other
|
|
32
|
+
|
|
33
|
+
// Render Functions
|
|
34
|
+
return (
|
|
35
|
+
<Input
|
|
36
|
+
className={classNames(styles.hiddenInput, { [styles.noFocusHint]: noFocusHint }, className)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const tmp = withMemo(HiddenInput);
|
|
43
|
+
export { tmp as HiddenInput };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ChangeEventHandler, InputHTMLAttributes, KeyboardEvent, MutableRefObject, useCallback } from 'react';
|
|
3
|
+
import { RbmComponentProps } from '../../RbmComponentProps';
|
|
4
|
+
import { Override } from '../../../TypeHelpers';
|
|
5
|
+
import { OptionalListener, useListenerWithExtractedProps } from '../../Hooks/useListener';
|
|
6
|
+
import { withForwardRef } from '../../../helper/withForwardRef';
|
|
7
|
+
|
|
8
|
+
import styles from './input.scss';
|
|
9
|
+
import classNames from 'classnames';
|
|
10
|
+
import { useComposedRef } from '../../Hooks/useComposedRef';
|
|
11
|
+
import { useOnChangeDone } from '../hooks/useOnChangeDone';
|
|
12
|
+
|
|
13
|
+
export type InputProps<OnChangeData, OnBlurData, OnChangeDoneData> = RbmComponentProps<
|
|
14
|
+
Override<
|
|
15
|
+
Omit<InputHTMLAttributes<HTMLInputElement>, 'onInput'>,
|
|
16
|
+
{
|
|
17
|
+
label?: string;
|
|
18
|
+
onChangeText?: (newText: string) => void;
|
|
19
|
+
onEnter?: (newText: string) => void;
|
|
20
|
+
} & OptionalListener<'onChange', OnChangeData> &
|
|
21
|
+
OptionalListener<'onBlur', OnBlurData> &
|
|
22
|
+
OptionalListener<'onChangeDone', OnChangeDoneData>
|
|
23
|
+
>
|
|
24
|
+
>;
|
|
25
|
+
|
|
26
|
+
export const Input = withForwardRef(function Input<OnChangeData, OnBlurData, OnChangeDoneData>(
|
|
27
|
+
{
|
|
28
|
+
label,
|
|
29
|
+
className,
|
|
30
|
+
style,
|
|
31
|
+
onEnter,
|
|
32
|
+
onKeyDown,
|
|
33
|
+
onChangeText,
|
|
34
|
+
...otherProps
|
|
35
|
+
}: InputProps<OnChangeData, OnBlurData, OnChangeDoneData>,
|
|
36
|
+
ref: MutableRefObject<HTMLInputElement> | null
|
|
37
|
+
) {
|
|
38
|
+
// Variables
|
|
39
|
+
|
|
40
|
+
// States
|
|
41
|
+
|
|
42
|
+
// Refs
|
|
43
|
+
const innerRef = useComposedRef(ref);
|
|
44
|
+
|
|
45
|
+
// Callbacks
|
|
46
|
+
const [onChangeWithData, otherPropsWithoutOnchange] = useListenerWithExtractedProps<'onChange', OnChangeData>(
|
|
47
|
+
'onChange',
|
|
48
|
+
otherProps
|
|
49
|
+
);
|
|
50
|
+
const onChange = useCallback<ChangeEventHandler<HTMLInputElement>>(
|
|
51
|
+
(e) => {
|
|
52
|
+
if (onChangeText) {
|
|
53
|
+
onChangeText(e.target.value);
|
|
54
|
+
}
|
|
55
|
+
onChangeWithData(e);
|
|
56
|
+
},
|
|
57
|
+
[onChangeWithData, onChangeText]
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
const [onBlur, otherPropsWithoutBlur] = useListenerWithExtractedProps<'onBlur', OnBlurData>(
|
|
61
|
+
'onBlur',
|
|
62
|
+
otherPropsWithoutOnchange
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
const [onChangeDone, otherPropsWithoutData] = useListenerWithExtractedProps<'onChangeDone', OnChangeDoneData>(
|
|
66
|
+
'onChangeDone',
|
|
67
|
+
otherPropsWithoutBlur
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const realOnKeyDown = useCallback(
|
|
71
|
+
(e: KeyboardEvent<HTMLInputElement>) => {
|
|
72
|
+
onKeyDown?.(e);
|
|
73
|
+
if (onEnter && e.key === 'Enter' && !e.defaultPrevented) {
|
|
74
|
+
onEnter((e.target as HTMLInputElement).value);
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
[onEnter, onKeyDown]
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
// Effects
|
|
81
|
+
useOnChangeDone(onChangeDone, innerRef);
|
|
82
|
+
|
|
83
|
+
// Other
|
|
84
|
+
|
|
85
|
+
// Render Functions
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
// eslint-disable-next-line jsx-a11y/label-has-associated-control
|
|
89
|
+
<label className={classNames(styles.input, className)} style={style}>
|
|
90
|
+
{label ? <span className={styles.label}>{label}</span> : null}
|
|
91
|
+
<input
|
|
92
|
+
{...otherPropsWithoutData}
|
|
93
|
+
ref={innerRef}
|
|
94
|
+
className={styles.text}
|
|
95
|
+
onBlur={onBlur}
|
|
96
|
+
onChange={onChange}
|
|
97
|
+
onKeyDown={realOnKeyDown}
|
|
98
|
+
/>
|
|
99
|
+
</label>
|
|
100
|
+
);
|
|
101
|
+
},
|
|
102
|
+
styles);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React, { ForwardedRef, useCallback, useState } from 'react';
|
|
2
|
+
import { Input, InputProps } from '../Input';
|
|
3
|
+
import { DistributiveOmit } from '../../../../helper/DistributiveOmit';
|
|
4
|
+
import { withForwardRef } from '../../../../helper/withForwardRef';
|
|
5
|
+
import { Flex } from '../../../Layout/Flex';
|
|
6
|
+
import { Grow } from '../../../Layout/Grow';
|
|
7
|
+
import { Icon } from '../../../Icon/Icon';
|
|
8
|
+
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
|
|
9
|
+
import { Clickable } from '../../../Clickable/Clickable';
|
|
10
|
+
|
|
11
|
+
import styles from './passwordInput.scss';
|
|
12
|
+
import classNames from 'classnames';
|
|
13
|
+
|
|
14
|
+
export type PasswordInputProps<OnChangeData, OnBlurData, OnChangeEndData> = DistributiveOmit<
|
|
15
|
+
InputProps<OnChangeData, OnBlurData, OnChangeEndData>,
|
|
16
|
+
'type'
|
|
17
|
+
>;
|
|
18
|
+
|
|
19
|
+
export const PasswordInput = withForwardRef(function PasswordInput<OnChangeData, OnBlurData, OnChangeEndData>(
|
|
20
|
+
{ className, style, ...props }: PasswordInputProps<OnChangeData, OnBlurData, OnChangeEndData>,
|
|
21
|
+
ref: ForwardedRef<HTMLInputElement>
|
|
22
|
+
) {
|
|
23
|
+
// Variables
|
|
24
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
25
|
+
|
|
26
|
+
// Refs
|
|
27
|
+
|
|
28
|
+
// States
|
|
29
|
+
|
|
30
|
+
// Selectors
|
|
31
|
+
|
|
32
|
+
// Callbacks
|
|
33
|
+
const toggleVisible = useCallback(() => setIsVisible((old) => !old), []);
|
|
34
|
+
|
|
35
|
+
// Effects
|
|
36
|
+
|
|
37
|
+
// Other
|
|
38
|
+
|
|
39
|
+
// Render Functions
|
|
40
|
+
return (
|
|
41
|
+
<Flex horizontal={true} className={classNames(styles.passwordInput, className)} style={style}>
|
|
42
|
+
<Grow>
|
|
43
|
+
<Input {...props} type={isVisible ? 'text' : 'password'} ref={ref} />
|
|
44
|
+
</Grow>
|
|
45
|
+
<Clickable onClick={toggleVisible} className={styles.showButton}>
|
|
46
|
+
<Icon icon={isVisible ? faEye : faEyeSlash} />
|
|
47
|
+
</Clickable>
|
|
48
|
+
</Flex>
|
|
49
|
+
);
|
|
50
|
+
},
|
|
51
|
+
styles);
|
|
52
|
+
|
|
53
|
+
// // Need PasswordInputMemo for autocompletion of phpstorm
|
|
54
|
+
// const PasswordInputMemo = withMemo(PasswordInput);
|
|
55
|
+
// export { PasswordInputMemo as PasswordInput };
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
@import "../../../scss/variables";
|
|
2
|
+
@import "../../../scss/designMixin";
|
|
3
|
+
|
|
4
|
+
.input {
|
|
5
|
+
width: 100%;
|
|
6
|
+
|
|
7
|
+
.label {
|
|
8
|
+
display: block;
|
|
9
|
+
font-weight: bold;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.text {
|
|
13
|
+
width: 100%;
|
|
14
|
+
background-color: transparent;
|
|
15
|
+
border: 0;
|
|
16
|
+
outline: none;
|
|
17
|
+
padding: 0;
|
|
18
|
+
font-size: 1rem;
|
|
19
|
+
|
|
20
|
+
@include design($material) {
|
|
21
|
+
color: #212121;
|
|
22
|
+
background-image: linear-gradient(to top, transparent 1px, #afafaf 1px);
|
|
23
|
+
background-size: 100% 2px;
|
|
24
|
+
background-repeat: no-repeat;
|
|
25
|
+
background-position: center bottom;
|
|
26
|
+
padding-bottom: 2px;
|
|
27
|
+
|
|
28
|
+
&:focus {
|
|
29
|
+
background-image: linear-gradient(var(--flavor-focus), var(--flavor-focus)),
|
|
30
|
+
linear-gradient(to top, transparent 1px, #afafaf 1px);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@include design($flat) {
|
|
35
|
+
color: #1f1f21;
|
|
36
|
+
&, &:focus {
|
|
37
|
+
border-bottom: 1px solid var(--border-light);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
&.hiddenInput {
|
|
43
|
+
.text {
|
|
44
|
+
background-image: none;
|
|
45
|
+
border-bottom: 1px solid transparent;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&.noFocusHint {
|
|
49
|
+
.text {
|
|
50
|
+
&:focus {
|
|
51
|
+
background-image: none;
|
|
52
|
+
border-bottom: 1px solid transparent;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|