@ainias42/react-bootstrap-mobile 0.2.12 → 0.2.14
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/bin/release.sh +0 -1
- package/bin/updateCopies.js +1 -0
- package/bootstrapReactMobile.ts +1 -0
- package/dist/bootstrapReactMobile.d.ts +1 -0
- package/dist/bootstrapReactMobile.js +3295 -18691
- package/dist/bootstrapReactMobile.js.map +1 -1
- package/dist/src/Components/FormElements/Button/Button.d.ts +2 -1
- package/dist/src/Components/FormElements/ColorInput/ColorInput.d.ts +3 -3
- package/dist/src/Components/FormElements/ColorInput/sharedSelectedColor.d.ts +1 -1
- package/dist/src/Components/FormElements/Controller/useYupResolver.d.ts +11 -0
- package/dist/src/Components/FormElements/SearchSelectInput/SearchSelectInput.d.ts +8 -1
- package/dist/src/Components/FormElements/Slider/Slider.d.ts +2 -1
- package/dist/src/Components/FormElements/Switch/Switch.d.ts +4 -1
- package/dist/src/Components/SpoilerList/Spoiler/Spoiler.d.ts +2 -1
- package/package.json +4 -3
- package/src/Components/Clickable/Clickable.tsx +1 -1
- package/src/Components/Dialog/ButtonDialog.tsx +0 -2
- package/src/Components/Dialog/DialogBackground.tsx +1 -1
- package/src/Components/Dialog/DialogContext.ts +1 -1
- package/src/Components/Dialog/dialogBackground.scss +1 -0
- package/src/Components/FormElements/Button/Button.tsx +11 -3
- package/src/Components/FormElements/ColorInput/ColorInput.tsx +22 -37
- package/src/Components/FormElements/ColorInput/colorInput.scss +39 -0
- package/src/Components/FormElements/ColorInput/sharedSelectedColor.ts +33 -4
- package/src/Components/FormElements/Controller/FileInputController.tsx +2 -2
- package/src/Components/FormElements/Controller/HookForm.tsx +1 -1
- package/src/Components/FormElements/Controller/useYupResolver.ts +53 -0
- package/src/Components/FormElements/FormError.tsx +1 -1
- package/src/Components/FormElements/Input/FileInput/MultipleFileInput.tsx +0 -1
- package/src/Components/FormElements/SearchSelectInput/SearchSelectInput.tsx +161 -129
- package/src/Components/FormElements/SearchSelectInput/seachSelectInput.scss +6 -1
- package/src/Components/FormElements/Select/Select.tsx +1 -1
- package/src/Components/FormElements/Slider/Slider.tsx +9 -1
- package/src/Components/FormElements/Switch/Switch.tsx +26 -14
- package/src/Components/FormElements/Switch/switch.scss +18 -16
- package/src/Components/FullScreen/FullScreen.tsx +5 -7
- package/src/Components/Hooks/useComposedRef.ts +1 -1
- package/src/Components/Hooks/useDelayedEffect.ts +4 -3
- package/src/Components/Hooks/useRerender.ts +1 -1
- package/src/Components/Icon/Icon.tsx +0 -1
- package/src/Components/List/InfiniteList.tsx +3 -4
- package/src/Components/List/List.tsx +0 -2
- package/src/Components/SpoilerList/Spoiler/Spoiler.tsx +24 -18
- package/src/scss/_default.scss +14 -12
|
@@ -11,6 +11,7 @@ export type ButtonProps<ClickData> = RbmComponentProps<Override<HTMLAttributes<H
|
|
|
11
11
|
disabled?: boolean;
|
|
12
12
|
flavor?: Flavor;
|
|
13
13
|
fullWidth?: boolean;
|
|
14
|
+
stopPropagation?: boolean;
|
|
14
15
|
size?: Omit<Size, "xxLarge" | "xLarge" | "large" | "xSmall">;
|
|
15
16
|
} & OptionalListener<'onClick', ClickData>>>;
|
|
16
|
-
export declare const Button: <ClickData>({ children, className, disabled, size, fullWidth, flavor, type, ...props }: ButtonProps<ClickData>) => React.JSX.Element;
|
|
17
|
+
export declare const Button: <ClickData>({ children, className, disabled, size, fullWidth, flavor, type, stopPropagation, ...props }: ButtonProps<ClickData>) => React.JSX.Element;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { ColorResult } from '@uiw/react-color';
|
|
2
3
|
import { OptionalListener } from '../../Hooks/useListener';
|
|
3
4
|
export type ColorInputProps<OnChangeData> = {
|
|
4
5
|
defaultValue?: string;
|
|
@@ -6,7 +7,6 @@ export type ColorInputProps<OnChangeData> = {
|
|
|
6
7
|
label?: string;
|
|
7
8
|
onChangeColor?: (newColor: string) => void;
|
|
8
9
|
onOpen?: (currentColor: string) => void;
|
|
9
|
-
onChangeColorComplete?: (newColor: string) => void;
|
|
10
10
|
onClose?: (newColor: string) => void;
|
|
11
11
|
disableAlpha?: boolean;
|
|
12
12
|
presetColors?: string[];
|
|
@@ -14,7 +14,7 @@ export type ColorInputProps<OnChangeData> = {
|
|
|
14
14
|
disabled?: boolean;
|
|
15
15
|
error?: string;
|
|
16
16
|
className?: string;
|
|
17
|
-
} & OptionalListener<'onChange', OnChangeData>;
|
|
18
|
-
declare function ColorInput<OnChangeData>({ defaultValue, value, label, onChangeColor,
|
|
17
|
+
} & OptionalListener<'onChange', OnChangeData, ColorResult>;
|
|
18
|
+
declare function ColorInput<OnChangeData>({ defaultValue, value, label, onChangeColor, onOpen, onClose, disableAlpha, presetColors, error, sharedColorKey, disabled, className, ...otherProps }: ColorInputProps<OnChangeData>): React.JSX.Element;
|
|
19
19
|
declare const ColorInputMemo: typeof ColorInput;
|
|
20
20
|
export { ColorInputMemo as ColorInput };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare function useSharedSelectedColor(key?: string, numberSavedColors?: number): {
|
|
1
|
+
export declare function useSharedSelectedColor(key: string | undefined, predefinedColors?: string[], numberSavedColors?: number): {
|
|
2
2
|
colors: string[];
|
|
3
3
|
addColor: (newColor: string) => void;
|
|
4
4
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AnyObject, InferType, Maybe, ObjectSchema } from 'yup';
|
|
2
|
+
export declare function useYupResolver<ObjectType extends Maybe<AnyObject>>(validationSchema: ObjectSchema<ObjectType>, translate: (key: string, args?: Record<string, string | number>) => string): (data: InferType<ObjectSchema<ObjectType>>) => Promise<{
|
|
3
|
+
values: ObjectType extends AnyObject ? import("yup").MakePartial<ObjectType> extends infer T ? T extends import("yup").MakePartial<ObjectType> ? T extends {} ? { [k in keyof T]: T[k]; } : T : never : never : ObjectType;
|
|
4
|
+
errors: {};
|
|
5
|
+
} | {
|
|
6
|
+
values: {};
|
|
7
|
+
errors: Record<string, {
|
|
8
|
+
type: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}>;
|
|
11
|
+
}>;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { OptionalListener } from '../../Hooks/useListener';
|
|
3
3
|
import { SelectOption } from '../Select/Select';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
4
5
|
import { RbmComponentProps } from '../../RbmComponentProps';
|
|
5
6
|
export type SearchSelectInputProps<OnChangeData> = RbmComponentProps<{
|
|
6
7
|
label?: string;
|
|
7
8
|
options: SelectOption[];
|
|
8
9
|
onChangeValue?: (newValues: string[]) => void;
|
|
9
10
|
values: string[];
|
|
11
|
+
renderSelectableOptions?: (option: SelectOption, isActive: boolean, index: number, activeIndex: number) => ReactNode;
|
|
12
|
+
renderSelectedOption?: (option: SelectOption) => ReactNode;
|
|
13
|
+
showSelectedOptions?: boolean;
|
|
14
|
+
closeOnSelect?: boolean;
|
|
15
|
+
enableSearch?: boolean;
|
|
16
|
+
allowDeselect?: boolean;
|
|
10
17
|
} & OptionalListener<'onChange', OnChangeData>>;
|
|
11
|
-
export declare const SearchSelectInput: <OnChangeData>({ label, options, values, onChangeValue, className, style, }: SearchSelectInputProps<OnChangeData>) => React.JSX.Element;
|
|
18
|
+
export declare const SearchSelectInput: <OnChangeData>({ label, options, values, onChangeValue, className, renderSelectableOptions, renderSelectedOption, showSelectedOptions, closeOnSelect, enableSearch, allowDeselect, style, }: SearchSelectInputProps<OnChangeData>) => React.JSX.Element;
|
|
@@ -5,5 +5,6 @@ import { Override } from '../../../TypeHelpers';
|
|
|
5
5
|
import { OptionalListener } from '../../Hooks/useListener';
|
|
6
6
|
export type SliderProps<OnChangeData, OnChangeValueData, OnChangeDoneData> = RbmComponentProps<Override<Omit<InputHTMLAttributes<HTMLInputElement>, 'type'>, {
|
|
7
7
|
value?: number;
|
|
8
|
+
stopPropagation?: boolean;
|
|
8
9
|
} & OptionalListener<'onChange', OnChangeData> & OptionalListener<'onChangeValue', OnChangeValueData, number> & OptionalListener<'onChangeDone', OnChangeDoneData>>>;
|
|
9
|
-
export declare const Slider: <OnChangeData, OnChangeValueData, OnChangeDoneData>({ className, style, ...props }: SliderProps<OnChangeData, OnChangeValueData, OnChangeDoneData>) => React.JSX.Element;
|
|
10
|
+
export declare const Slider: <OnChangeData, OnChangeValueData, OnChangeDoneData>({ className, style, stopPropagation, ...props }: SliderProps<OnChangeData, OnChangeValueData, OnChangeDoneData>) => React.JSX.Element;
|
|
@@ -10,5 +10,8 @@ export type SwitchProps<OnChangeCheckedData> = RbmComponentProps<Override<InputH
|
|
|
10
10
|
isLabelBeforeSwitch?: boolean;
|
|
11
11
|
isDual?: boolean;
|
|
12
12
|
error?: string;
|
|
13
|
+
classNameLabel?: string;
|
|
14
|
+
classNamePreLabel?: string;
|
|
15
|
+
stopPropagation?: boolean;
|
|
13
16
|
} & OptionalListener<"onChangeChecked", OnChangeCheckedData, boolean>>>;
|
|
14
|
-
export declare const Switch: <OnChangeCheckedData>({ children, label, preLabel, isLabelBeforeSwitch, isDual, id, className, style, error, onChange, ...props }: SwitchProps<OnChangeCheckedData>) => React.JSX.Element;
|
|
17
|
+
export declare const Switch: <OnChangeCheckedData>({ children, label, preLabel, isLabelBeforeSwitch, isDual, stopPropagation, id, className, classNamePreLabel, classNameLabel, style, error, onChange, ...props }: SwitchProps<OnChangeCheckedData>) => React.JSX.Element;
|
|
@@ -7,10 +7,11 @@ export type SpoilerProps<OnClickData> = RbmComponentProps<{
|
|
|
7
7
|
title: ReactChild;
|
|
8
8
|
initialOpen?: boolean;
|
|
9
9
|
open?: boolean;
|
|
10
|
+
onlyTitleToggles?: boolean;
|
|
10
11
|
noClosingAnimation?: boolean;
|
|
11
12
|
openIcon?: IconSource | null;
|
|
12
13
|
closeIcon?: IconSource | null;
|
|
13
14
|
} & OptionalListener<'onClick', OnClickData>>;
|
|
14
|
-
declare function Spoiler<OnClickData>({ title, children, initialOpen, noClosingAnimation, openIcon, closeIcon, className, style, open, ...listenerProps }: SpoilerProps<OnClickData>): React.JSX.Element;
|
|
15
|
+
declare function Spoiler<OnClickData>({ title, children, initialOpen, noClosingAnimation, openIcon, closeIcon, className, onlyTitleToggles, style, open, ...listenerProps }: SpoilerProps<OnClickData>): React.JSX.Element;
|
|
15
16
|
declare const SpoilerMemo: typeof Spoiler;
|
|
16
17
|
export { SpoilerMemo as Spoiler };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ainias42/react-bootstrap-mobile",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"description": "Mobile React Components using Bootstrap",
|
|
5
5
|
"main": "dist/bootstrapReactMobile",
|
|
6
6
|
"scripts": {
|
|
@@ -54,7 +54,6 @@
|
|
|
54
54
|
"@fortawesome/react-fontawesome": "^0.2.2",
|
|
55
55
|
"@types/react": ">=18.0.0",
|
|
56
56
|
"@types/react-beautiful-dnd": "^13.1.8",
|
|
57
|
-
"@types/react-color": "^3.0.12",
|
|
58
57
|
"@types/react-dom": ">=18.0.0",
|
|
59
58
|
"@types/react-table": "^7.7.20",
|
|
60
59
|
"@types/react-window": "^1.8.8",
|
|
@@ -95,12 +94,14 @@
|
|
|
95
94
|
"dependencies": {
|
|
96
95
|
"@ainias42/js-helper": ">=0.8.16",
|
|
97
96
|
"@types/react-virtualized-auto-sizer": "^1.0.4",
|
|
97
|
+
"@uiw/react-color": "^2.5.5",
|
|
98
98
|
"classnames": "^2.5.1",
|
|
99
99
|
"isomorphic-style-loader": "^5.3.2",
|
|
100
100
|
"react-color": "^2.19.3",
|
|
101
101
|
"react-table": "^7.8.0",
|
|
102
102
|
"react-virtualized-auto-sizer": "^1.0.24",
|
|
103
103
|
"react-window": "^1.8.10",
|
|
104
|
-
"react-window-infinite-loader": "^1.0.9"
|
|
104
|
+
"react-window-infinite-loader": "^1.0.9",
|
|
105
|
+
"yup": "^1.6.1"
|
|
105
106
|
}
|
|
106
107
|
}
|
|
@@ -4,12 +4,10 @@ import { withMemo } from '../../helper/withMemo';
|
|
|
4
4
|
import { Block } from '../Layout/Block';
|
|
5
5
|
import { Text, TEXT_SIZE } from '../Text/Text';
|
|
6
6
|
import { Clickable } from '../Clickable/Clickable';
|
|
7
|
-
|
|
8
7
|
import styles from './buttonDialog.scss';
|
|
9
8
|
import { RbmComponentProps, WithNoChildren } from '../RbmComponentProps';
|
|
10
9
|
import classNames from 'classnames';
|
|
11
10
|
import { Flavor } from "../Flavor";
|
|
12
|
-
import { Size } from "../../Size";
|
|
13
11
|
|
|
14
12
|
export type ButtonDialogProps = RbmComponentProps<
|
|
15
13
|
{
|
|
@@ -40,7 +40,7 @@ export const DialogBackground = withMemo(function DialogBackground({
|
|
|
40
40
|
<Block __allowChildren="all" className={classNames(styles.dialogBackground, className)} style={style}>
|
|
41
41
|
{(!!title || !!onClose) && <Flex horizontal={true} className={styles.title}>{!!title &&
|
|
42
42
|
<Grow><Heading >{title}</Heading></Grow>}{!!onClose &&
|
|
43
|
-
<Clickable onClick={onClose}><Icon size=
|
|
43
|
+
<Clickable onClick={onClose}><Icon size="lg" icon={faCircleXmark}/></Clickable>}</Flex>}
|
|
44
44
|
{children}
|
|
45
45
|
</Block>
|
|
46
46
|
);
|
|
@@ -14,7 +14,7 @@ export type ShowDialog = <
|
|
|
14
14
|
|
|
15
15
|
const DialogContext = React.createContext<ShowDialog>(() => {
|
|
16
16
|
console.error("DialogContext not initialized");
|
|
17
|
-
return Promise.reject("DialogContext not initialized")
|
|
17
|
+
return Promise.reject(new Error("DialogContext not initialized"));
|
|
18
18
|
});
|
|
19
19
|
export const DialogProvider = DialogContext.Provider;
|
|
20
20
|
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { Override } from '@ainias42/js-helper';
|
|
3
3
|
import { OptionalListener, useListenerWithExtractedProps } from '../../Hooks/useListener';
|
|
4
|
-
|
|
5
4
|
import styles from './button.scss';
|
|
6
5
|
import classNames from 'classnames';
|
|
7
6
|
import { withMemo } from '../../../helper/withMemo';
|
|
8
|
-
import { HTMLAttributes } from 'react';
|
|
7
|
+
import { HTMLAttributes, MouseEvent, useCallback } from 'react';
|
|
9
8
|
import { RbmComponentProps } from '../../RbmComponentProps';
|
|
10
9
|
import { ButtonType } from "./ButtonType";
|
|
11
10
|
import { Flavor } from "../../Flavor";
|
|
@@ -17,6 +16,7 @@ export type ButtonProps<ClickData> = RbmComponentProps<
|
|
|
17
16
|
disabled?: boolean;
|
|
18
17
|
flavor?: Flavor
|
|
19
18
|
fullWidth?: boolean;
|
|
19
|
+
stopPropagation?: boolean;
|
|
20
20
|
size?: Omit<Size, "xxLarge" | "xLarge" | "large" | "xSmall">
|
|
21
21
|
} & OptionalListener<'onClick', ClickData>>
|
|
22
22
|
>;
|
|
@@ -29,10 +29,18 @@ export const Button = withMemo(function Button<ClickData>({
|
|
|
29
29
|
fullWidth = false,
|
|
30
30
|
flavor = Flavor.Accent,
|
|
31
31
|
type = ButtonType.Primary,
|
|
32
|
+
stopPropagation = true,
|
|
32
33
|
...props
|
|
33
34
|
}: ButtonProps<ClickData>) {
|
|
34
35
|
const [onClick, otherProps] = useListenerWithExtractedProps<'onClick', ClickData>('onClick', props);
|
|
35
36
|
|
|
37
|
+
const realOnClick = useCallback((ev: MouseEvent) => {
|
|
38
|
+
if (stopPropagation) {
|
|
39
|
+
ev.stopPropagation();
|
|
40
|
+
}
|
|
41
|
+
onClick?.(ev);
|
|
42
|
+
}, [onClick, stopPropagation]);
|
|
43
|
+
|
|
36
44
|
const classes = {
|
|
37
45
|
[styles.primary]: type === ButtonType.Primary,
|
|
38
46
|
[styles.secondary]: type === ButtonType.Secondary,
|
|
@@ -41,7 +49,7 @@ export const Button = withMemo(function Button<ClickData>({
|
|
|
41
49
|
};
|
|
42
50
|
|
|
43
51
|
return (
|
|
44
|
-
<button {...otherProps} disabled={disabled} type="button" onClick={
|
|
52
|
+
<button {...otherProps} disabled={disabled} type="button" onClick={realOnClick}
|
|
45
53
|
className={classNames(styles.button, {[styles.fullWidth]: fullWidth}, classes, flavor, className)}>
|
|
46
54
|
{children}
|
|
47
55
|
</button>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useCallback, useRef, useState, MouseEvent } from 'react';
|
|
3
|
-
import {
|
|
2
|
+
import { useCallback, useRef, useState, MouseEvent, useMemo } from 'react';
|
|
3
|
+
import { ColorResult, Sketch } from '@uiw/react-color';
|
|
4
4
|
import { OptionalListener, useListener } from '../../Hooks/useListener';
|
|
5
5
|
import { withMemo } from '../../../helper/withMemo';
|
|
6
6
|
import styles from './colorInput.scss';
|
|
@@ -16,7 +16,6 @@ export type ColorInputProps<OnChangeData> = {
|
|
|
16
16
|
label?: string;
|
|
17
17
|
onChangeColor?: (newColor: string) => void;
|
|
18
18
|
onOpen?: (currentColor: string) => void;
|
|
19
|
-
onChangeColorComplete?: (newColor: string) => void;
|
|
20
19
|
onClose?: (newColor: string) => void;
|
|
21
20
|
disableAlpha?: boolean;
|
|
22
21
|
presetColors?: string[];
|
|
@@ -24,26 +23,13 @@ export type ColorInputProps<OnChangeData> = {
|
|
|
24
23
|
disabled?: boolean
|
|
25
24
|
error?: string;
|
|
26
25
|
className?: string;
|
|
27
|
-
} & OptionalListener<'onChange', OnChangeData>;
|
|
28
|
-
|
|
29
|
-
function convertToHex(color: { r: number; g: number; b: number; a?: number }, disableAlpha?: boolean) {
|
|
30
|
-
let newColor = `#${color.r.toString(16).padStart(2, '0')}${color.g.toString(16).padStart(2, '0')}${color.b
|
|
31
|
-
.toString(16)
|
|
32
|
-
.padStart(2, '0')}`;
|
|
33
|
-
if (color.a !== undefined && !disableAlpha) {
|
|
34
|
-
newColor += Math.round(color.a * 255)
|
|
35
|
-
.toString(16)
|
|
36
|
-
.padStart(2, '0');
|
|
37
|
-
}
|
|
38
|
-
return newColor;
|
|
39
|
-
}
|
|
26
|
+
} & OptionalListener<'onChange', OnChangeData, ColorResult>;
|
|
40
27
|
|
|
41
28
|
function ColorInput<OnChangeData>({
|
|
42
29
|
defaultValue,
|
|
43
30
|
value,
|
|
44
31
|
label,
|
|
45
32
|
onChangeColor,
|
|
46
|
-
onChangeColorComplete,
|
|
47
33
|
onOpen,
|
|
48
34
|
onClose,
|
|
49
35
|
disableAlpha,
|
|
@@ -65,34 +51,34 @@ function ColorInput<OnChangeData>({
|
|
|
65
51
|
const [isOpen, setIsOpen] = useState(false);
|
|
66
52
|
const [position, setPosition] = useState({x: 0, y: 0});
|
|
67
53
|
|
|
68
|
-
const {colors, addColor} = useSharedSelectedColor(sharedColorKey);
|
|
54
|
+
const {colors, addColor} = useSharedSelectedColor(sharedColorKey, presetColors);
|
|
69
55
|
const realIsOpen = disabled !== true && isOpen;
|
|
70
56
|
|
|
71
|
-
const colVal
|
|
57
|
+
const colVal = useMemo(() => {
|
|
58
|
+
const newVal = value ?? color;
|
|
59
|
+
if (disableAlpha && newVal.length === 9) {
|
|
60
|
+
return newVal.substring(0, 7);
|
|
61
|
+
}
|
|
62
|
+
if (disableAlpha && newVal.length === 5) {
|
|
63
|
+
return newVal.substring(0,4);
|
|
64
|
+
}
|
|
65
|
+
return newVal;
|
|
66
|
+
}, [value, color, disableAlpha]);
|
|
67
|
+
|
|
72
68
|
// Selectors
|
|
73
69
|
|
|
74
70
|
// Callbacks
|
|
75
|
-
const onChangeWithData = useListener<'onChange', OnChangeData>('onChange', otherProps);
|
|
76
|
-
const onChange = useCallback
|
|
77
|
-
(newColor: ColorResult
|
|
78
|
-
const hexColor =
|
|
71
|
+
const onChangeWithData = useListener<'onChange', OnChangeData, ColorResult>('onChange', otherProps);
|
|
72
|
+
const onChange = useCallback(
|
|
73
|
+
(newColor: ColorResult) => {
|
|
74
|
+
const hexColor = newColor.hexa;
|
|
79
75
|
setColor(hexColor);
|
|
80
76
|
if (onChangeColor) {
|
|
81
77
|
onChangeColor(hexColor);
|
|
82
78
|
}
|
|
83
|
-
onChangeWithData(
|
|
84
|
-
},
|
|
85
|
-
[disableAlpha, onChangeColor, onChangeWithData]
|
|
86
|
-
);
|
|
87
|
-
const onChangeComplete = useCallback(
|
|
88
|
-
(newColor: ColorResult) => {
|
|
89
|
-
const hexColor = convertToHex(newColor.rgb, disableAlpha);
|
|
90
|
-
setColor(hexColor);
|
|
91
|
-
if (onChangeColorComplete) {
|
|
92
|
-
onChangeColorComplete(hexColor);
|
|
93
|
-
}
|
|
79
|
+
onChangeWithData(newColor);
|
|
94
80
|
},
|
|
95
|
-
[
|
|
81
|
+
[onChangeColor, onChangeWithData]
|
|
96
82
|
);
|
|
97
83
|
|
|
98
84
|
const onMenuClose = useCallback(
|
|
@@ -141,10 +127,9 @@ function ColorInput<OnChangeData>({
|
|
|
141
127
|
<>
|
|
142
128
|
<span className={classNames(styles.colorInput, className)}>
|
|
143
129
|
<Menu x={position.x} y={position.y} isOpen={realIsOpen} onClose={onMenuClose}>
|
|
144
|
-
<
|
|
130
|
+
<Sketch
|
|
145
131
|
color={colVal}
|
|
146
132
|
onChange={onChange}
|
|
147
|
-
onChangeComplete={onChangeComplete}
|
|
148
133
|
disableAlpha={disableAlpha}
|
|
149
134
|
presetColors={presetColors ?? colors}
|
|
150
135
|
/>
|
|
@@ -7,6 +7,22 @@
|
|
|
7
7
|
height: 1rem;
|
|
8
8
|
display: inline-block;
|
|
9
9
|
border: 1px solid black;
|
|
10
|
+
position: relative;
|
|
11
|
+
|
|
12
|
+
&:before {
|
|
13
|
+
content: '';
|
|
14
|
+
position: absolute;
|
|
15
|
+
top: 0;
|
|
16
|
+
left: 0;
|
|
17
|
+
right: 0;
|
|
18
|
+
bottom: 0;
|
|
19
|
+
display: block;
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
z-index: -1;
|
|
23
|
+
background: repeating-conic-gradient(#cccccc 0% 25%, #ffffff 0% 50%);
|
|
24
|
+
}
|
|
25
|
+
|
|
10
26
|
}
|
|
11
27
|
|
|
12
28
|
.modalContainer {
|
|
@@ -31,3 +47,26 @@
|
|
|
31
47
|
margin-right: 0.2rem;
|
|
32
48
|
}
|
|
33
49
|
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
:global(.w-color-swatch) {
|
|
53
|
+
z-index: 0;
|
|
54
|
+
|
|
55
|
+
> div {
|
|
56
|
+
position: relative;
|
|
57
|
+
|
|
58
|
+
&:before {
|
|
59
|
+
content: '';
|
|
60
|
+
position: absolute;
|
|
61
|
+
top: 0;
|
|
62
|
+
left: 0;
|
|
63
|
+
right: 0;
|
|
64
|
+
bottom: 0;
|
|
65
|
+
display: block;
|
|
66
|
+
width: 100%;
|
|
67
|
+
height: 100%;
|
|
68
|
+
z-index: -1;
|
|
69
|
+
background: repeating-conic-gradient(#cccccc 0% 25%, #ffffff 0% 50%);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
1
|
+
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
2
2
|
import { Random } from '@ainias42/js-helper';
|
|
3
3
|
|
|
4
4
|
const sharedSelectedColor: Record<string, { colors: string[]; updateFunctions: (() => void)[] }> = {};
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
function localStorageKey (key: string) {
|
|
7
|
+
return `sharedSelectedColor-${key}`;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function useSharedSelectedColor(key: string|undefined, predefinedColors: string[] = [], numberSavedColors = 16) {
|
|
11
|
+
const shouldSaveToLocalStorage = typeof window !== 'undefined' && window.localStorage !== undefined && !!key;
|
|
7
12
|
const [, setVersion] = useState(1);
|
|
8
13
|
const innerKey = useRef(Random.getStringRandom(12));
|
|
9
14
|
const realKey = key ?? innerKey.current;
|
|
@@ -22,6 +27,10 @@ export function useSharedSelectedColor(key?: string, numberSavedColors = 15) {
|
|
|
22
27
|
|
|
23
28
|
const addColor = useCallback(
|
|
24
29
|
(newColor: string) => {
|
|
30
|
+
if (predefinedColors.includes(newColor)) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
25
34
|
sharedSelectedColor[realKey].colors = sharedSelectedColor[realKey].colors.filter(
|
|
26
35
|
(color) => color !== newColor
|
|
27
36
|
);
|
|
@@ -29,12 +38,32 @@ export function useSharedSelectedColor(key?: string, numberSavedColors = 15) {
|
|
|
29
38
|
if (sharedSelectedColor[realKey].colors.length > numberSavedColors) {
|
|
30
39
|
sharedSelectedColor[realKey].colors.splice(numberSavedColors, 1);
|
|
31
40
|
}
|
|
41
|
+
if (shouldSaveToLocalStorage){
|
|
42
|
+
localStorage.setItem(localStorageKey(realKey), JSON.stringify(sharedSelectedColor[realKey].colors));
|
|
43
|
+
}
|
|
32
44
|
|
|
33
45
|
// triggers rerender
|
|
34
46
|
sharedSelectedColor[realKey].updateFunctions.forEach((u) => u());
|
|
35
47
|
},
|
|
36
|
-
[numberSavedColors, realKey]
|
|
48
|
+
[numberSavedColors, predefinedColors, realKey, shouldSaveToLocalStorage]
|
|
37
49
|
);
|
|
38
50
|
|
|
39
|
-
|
|
51
|
+
useLayoutEffect(() => {
|
|
52
|
+
if (shouldSaveToLocalStorage){
|
|
53
|
+
const savedColors = localStorage.getItem(localStorageKey(realKey));
|
|
54
|
+
if (savedColors) {
|
|
55
|
+
sharedSelectedColor[realKey].colors = JSON.parse(savedColors);
|
|
56
|
+
setVersion((old) => old + 1);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}, [realKey, shouldSaveToLocalStorage]);
|
|
60
|
+
|
|
61
|
+
const realColors = useMemo(() => {
|
|
62
|
+
if (predefinedColors.length > 0) {
|
|
63
|
+
return [...predefinedColors, ...sharedSelectedColor[realKey].colors.filter(color => !predefinedColors.includes(color))].slice(0, numberSavedColors);
|
|
64
|
+
}
|
|
65
|
+
return sharedSelectedColor[realKey].colors;
|
|
66
|
+
}, [numberSavedColors, predefinedColors, realKey]);
|
|
67
|
+
|
|
68
|
+
return { colors: realColors, addColor };
|
|
40
69
|
}
|
|
@@ -33,8 +33,8 @@ export const FileInputController = withMemo(function FileInputController<Values
|
|
|
33
33
|
const setErrorMessage = useCallback((error: string) => {
|
|
34
34
|
setError(name, {
|
|
35
35
|
message: error,
|
|
36
|
-
})
|
|
37
|
-
}, []);
|
|
36
|
+
});
|
|
37
|
+
}, [name, setError]);
|
|
38
38
|
|
|
39
39
|
return (
|
|
40
40
|
<FileInput
|
|
@@ -35,7 +35,7 @@ export const HookForm = withMemo(function HookForm<TFieldValues extends FieldVal
|
|
|
35
35
|
|
|
36
36
|
return <FormProvider {...methods}>
|
|
37
37
|
<SendFormContext.Provider value={innerOnSend}>
|
|
38
|
-
<LoadingArea loading={methods.formState.isSubmitting} __allowChildren=
|
|
38
|
+
<LoadingArea loading={methods.formState.isSubmitting} __allowChildren="all">
|
|
39
39
|
{children}
|
|
40
40
|
</LoadingArea>
|
|
41
41
|
</SendFormContext.Provider>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { AnyObject, InferType, Maybe, ObjectSchema, ValidationError } from 'yup';
|
|
3
|
+
|
|
4
|
+
// TODO set translate function from somewhere else
|
|
5
|
+
export function useYupResolver<ObjectType extends Maybe<AnyObject>>(validationSchema: ObjectSchema<ObjectType>, translate: (key: string, args?: Record<string, string | number>) => string) {
|
|
6
|
+
|
|
7
|
+
return useCallback(
|
|
8
|
+
async (data: InferType<ObjectSchema<ObjectType>>) => {
|
|
9
|
+
try {
|
|
10
|
+
const values = await validationSchema.validate(data, {
|
|
11
|
+
abortEarly: false,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
return {
|
|
15
|
+
values,
|
|
16
|
+
errors: {},
|
|
17
|
+
};
|
|
18
|
+
} catch (errors) {
|
|
19
|
+
const reducedErrors = (errors.inner as ValidationError[]).reduce(
|
|
20
|
+
(allErrors, currentError) => {
|
|
21
|
+
if (currentError.path === undefined) {
|
|
22
|
+
return allErrors;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let message = currentError.message as
|
|
26
|
+
| string
|
|
27
|
+
| {
|
|
28
|
+
key: string;
|
|
29
|
+
args?: Record<string, string | number>;
|
|
30
|
+
};
|
|
31
|
+
if (typeof message === 'object') {
|
|
32
|
+
message = translate(message.key, message.args);
|
|
33
|
+
} else {
|
|
34
|
+
message = translate(message);
|
|
35
|
+
}
|
|
36
|
+
allErrors[currentError.path] = {
|
|
37
|
+
type: currentError.type ?? 'validation',
|
|
38
|
+
message,
|
|
39
|
+
};
|
|
40
|
+
return allErrors;
|
|
41
|
+
},
|
|
42
|
+
{} as Record<string, { type: string; message: string }>,
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
values: {},
|
|
47
|
+
errors: reducedErrors,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
[translate, validationSchema],
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -16,7 +16,6 @@ import { Image } from '../../../Image/Image';
|
|
|
16
16
|
import { Clickable } from '../../../Clickable/Clickable';
|
|
17
17
|
import { Inline } from '../../../Layout/Inline';
|
|
18
18
|
import { FileType } from "./FileType";
|
|
19
|
-
import { InlineBlock } from "../../../Layout/InlineBlock";
|
|
20
19
|
import { FormError } from "../../FormError";
|
|
21
20
|
|
|
22
21
|
|