mui-fast-start 0.1.4 → 0.2.0

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.
Files changed (120) hide show
  1. package/README.md +356 -356
  2. package/README_KR.md +355 -0
  3. package/dist/components/Obj/Checkbox/ObjCheckIcon.d.ts +3 -0
  4. package/dist/components/Obj/Checkbox/ObjCheckIcon.d.ts.map +1 -0
  5. package/dist/components/Obj/Checkbox/ObjCheckbox.d.ts +3 -0
  6. package/dist/components/Obj/Checkbox/ObjCheckbox.d.ts.map +1 -0
  7. package/dist/components/Obj/Textfield/ObjFloat.d.ts +3 -0
  8. package/dist/components/Obj/Textfield/ObjFloat.d.ts.map +1 -0
  9. package/dist/components/Obj/Textfield/ObjInteger.d.ts +3 -0
  10. package/dist/components/Obj/Textfield/ObjInteger.d.ts.map +1 -0
  11. package/dist/components/Obj/Textfield/ObjText.d.ts +3 -0
  12. package/dist/components/Obj/Textfield/ObjText.d.ts.map +1 -0
  13. package/dist/components/Single/Checkbox/SingleCheckIcon.d.ts +3 -0
  14. package/dist/components/Single/Checkbox/SingleCheckIcon.d.ts.map +1 -0
  15. package/dist/components/Single/Checkbox/SingleCheckbox.d.ts +3 -0
  16. package/dist/components/Single/Checkbox/SingleCheckbox.d.ts.map +1 -0
  17. package/dist/components/Single/TextField/SingleFloat.d.ts +3 -0
  18. package/dist/components/Single/TextField/SingleFloat.d.ts.map +1 -0
  19. package/dist/components/Single/TextField/SingleInteger.d.ts +3 -0
  20. package/dist/components/Single/TextField/SingleInteger.d.ts.map +1 -0
  21. package/dist/components/Single/TextField/SingleText.d.ts +3 -0
  22. package/dist/components/Single/TextField/SingleText.d.ts.map +1 -0
  23. package/dist/components/index.d.ts +11 -0
  24. package/dist/components/index.d.ts.map +1 -0
  25. package/dist/hooks/index.d.ts +4 -0
  26. package/dist/hooks/index.d.ts.map +1 -0
  27. package/dist/{types/hooks → hooks}/splits/useSplitSingleNumberProps.d.ts +2 -1
  28. package/dist/hooks/splits/useSplitSingleNumberProps.d.ts.map +1 -0
  29. package/dist/{types/hooks → hooks}/splits/useSplitSingleTextProps.d.ts +2 -1
  30. package/dist/hooks/splits/useSplitSingleTextProps.d.ts.map +1 -0
  31. package/dist/{types/hooks → hooks}/state/useObjToSingle.d.ts +2 -1
  32. package/dist/hooks/state/useObjToSingle.d.ts.map +1 -0
  33. package/dist/index.d.ts +5 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +278 -0
  36. package/dist/styles/FastStartProvider.d.ts +21 -0
  37. package/dist/styles/FastStartProvider.d.ts.map +1 -0
  38. package/dist/styles/createDefaultProps.d.ts +3 -0
  39. package/dist/styles/createDefaultProps.d.ts.map +1 -0
  40. package/dist/types/index.d.ts +4 -0
  41. package/dist/types/index.d.ts.map +1 -0
  42. package/dist/types/{types/props.d.ts → props.d.ts} +8 -1
  43. package/dist/types/props.d.ts.map +1 -0
  44. package/dist/types/{types/provider.d.ts → provider.d.ts} +2 -1
  45. package/dist/types/provider.d.ts.map +1 -0
  46. package/dist/types/{types/types.d.ts → types.d.ts} +1 -0
  47. package/dist/types/types.d.ts.map +1 -0
  48. package/dist/utils/index.d.ts +3 -0
  49. package/dist/utils/index.d.ts.map +1 -0
  50. package/dist/utils/number/calculate.d.ts +7 -0
  51. package/dist/utils/number/calculate.d.ts.map +1 -0
  52. package/dist/utils/object/error.d.ts +4 -0
  53. package/dist/utils/object/error.d.ts.map +1 -0
  54. package/dist/utils/object/merge.d.ts +4 -0
  55. package/dist/utils/object/merge.d.ts.map +1 -0
  56. package/eslint.config.js +23 -0
  57. package/examples/basic/README.md +73 -0
  58. package/examples/basic/eslint.config.js +23 -0
  59. package/examples/basic/index.html +13 -0
  60. package/examples/basic/package.json +37 -0
  61. package/examples/basic/src/App.css +5 -0
  62. package/examples/basic/src/App.tsx +28 -0
  63. package/examples/basic/src/index.css +30 -0
  64. package/examples/basic/src/main.tsx +57 -0
  65. package/examples/basic/src/pages/ObjPage.tsx +93 -0
  66. package/examples/basic/src/pages/SinglePage.tsx +70 -0
  67. package/examples/basic/tsconfig.app.json +38 -0
  68. package/examples/basic/tsconfig.json +7 -0
  69. package/examples/basic/tsconfig.node.json +35 -0
  70. package/examples/basic/vite.config.ts +28 -0
  71. package/mui-fast-start-0.1.5.tgz +0 -0
  72. package/package.json +67 -85
  73. package/src/components/Obj/Checkbox/ObjCheckIcon.tsx +19 -0
  74. package/src/components/Obj/Checkbox/ObjCheckbox.tsx +19 -0
  75. package/src/components/Obj/Textfield/ObjFloat.tsx +22 -0
  76. package/src/components/Obj/Textfield/ObjInteger.tsx +22 -0
  77. package/src/components/Obj/Textfield/ObjText.tsx +22 -0
  78. package/src/components/Single/Checkbox/SingleCheckIcon.tsx +25 -0
  79. package/src/components/Single/Checkbox/SingleCheckbox.tsx +31 -0
  80. package/src/components/Single/TextField/SingleFloat.tsx +12 -0
  81. package/src/components/Single/TextField/SingleInteger.tsx +12 -0
  82. package/src/components/Single/TextField/SingleText.tsx +12 -0
  83. package/src/components/index.ts +13 -0
  84. package/src/hooks/splits/useSplitSingleNumberProps.ts +159 -0
  85. package/src/hooks/splits/useSplitSingleTextProps.ts +36 -0
  86. package/src/hooks/state/useObjToSingle.ts +23 -0
  87. package/src/index.ts +8 -0
  88. package/src/styles/FastStartProvider.tsx +26 -0
  89. package/src/styles/createDefaultProps.ts +45 -0
  90. package/src/types/props.ts +67 -0
  91. package/src/types/provider.ts +47 -0
  92. package/src/types/types.ts +9 -0
  93. package/src/utils/number/calculate.ts +102 -0
  94. package/src/utils/object/error.ts +14 -0
  95. package/src/utils/object/merge.ts +47 -0
  96. package/src.zip +0 -0
  97. package/tsconfig.json +34 -0
  98. package/tsconfig.lib.json +9 -0
  99. package/vite.config.ts +35 -0
  100. package/dist/index.cjs.js +0 -1
  101. package/dist/index.esm.js +0 -266
  102. package/dist/types/components/Obj/Checkbox/ObjCheckIcon.d.ts +0 -3
  103. package/dist/types/components/Obj/Checkbox/ObjCheckbox.d.ts +0 -3
  104. package/dist/types/components/Obj/Textfield/ObjFloat.d.ts +0 -3
  105. package/dist/types/components/Obj/Textfield/ObjInteger.d.ts +0 -3
  106. package/dist/types/components/Obj/Textfield/ObjText.d.ts +0 -3
  107. package/dist/types/components/Single/Checkbox/SingleCheckIcon.d.ts +0 -3
  108. package/dist/types/components/Single/Checkbox/SingleCheckbox.d.ts +0 -3
  109. package/dist/types/components/Single/TextField/SingleFloat.d.ts +0 -3
  110. package/dist/types/components/Single/TextField/SingleInteger.d.ts +0 -3
  111. package/dist/types/components/Single/TextField/SingleText.d.ts +0 -3
  112. package/dist/types/components/index.d.ts +0 -12
  113. package/dist/types/styles/FastStartProvider.d.ts +0 -20
  114. package/dist/types/styles/createDefaultProps.d.ts +0 -3
  115. package/dist/types/styles/index.d.ts +0 -2
  116. package/dist/types/utils/number/calculate.d.ts +0 -5
  117. package/dist/types/utils/object/merge.d.ts +0 -3
  118. /package/{dist/types/hooks/index.d.ts → src/hooks/index.ts} +0 -0
  119. /package/{dist/types/types/index.d.ts → src/types/index.ts} +0 -0
  120. /package/{dist/types/utils/index.d.ts → src/utils/index.ts} +0 -0
@@ -0,0 +1,12 @@
1
+ import {useContext} from "react";
2
+ import {TextField} from "@mui/material";
3
+ import {FastStartContext} from "../../../styles/FastStartProvider.tsx";
4
+ import {SingleNumberProps} from "../../../types";
5
+ import {useSplitSingleFloatProps} from "../../../hooks";
6
+
7
+
8
+ export const SingleFloat = (customProps: SingleNumberProps) => {
9
+ const defaultProps = useContext(FastStartContext)?.Single?.Float as SingleNumberProps;
10
+ const props = useSplitSingleFloatProps(defaultProps, customProps);
11
+ return <TextField {...props}/>;
12
+ }
@@ -0,0 +1,12 @@
1
+ import {useContext} from "react";
2
+ import {TextField} from "@mui/material";
3
+ import {FastStartContext} from "../../../styles/FastStartProvider.tsx";
4
+ import {SingleNumberProps} from "../../../types";
5
+ import {useSplitSingleIntegerProps} from "../../../hooks";
6
+
7
+
8
+ export const SingleInteger = (customProps: SingleNumberProps) => {
9
+ const defaultProps = useContext(FastStartContext)?.Single?.Integer as SingleNumberProps;
10
+ const props = useSplitSingleIntegerProps(defaultProps, customProps);
11
+ return <TextField {...props}/>;
12
+ }
@@ -0,0 +1,12 @@
1
+ import {useContext} from "react";
2
+ import useSplitSingleTextProps from '../../../hooks/splits/useSplitSingleTextProps';
3
+ import {TextField} from "@mui/material";
4
+ import {FastStartContext} from "../../../styles/FastStartProvider.tsx";
5
+ import {SingleTextProps} from "../../../types";
6
+
7
+
8
+ export const SingleText = (customProps: SingleTextProps) => {
9
+ const defaultProps = useContext(FastStartContext)?.Single?.Text as SingleTextProps;
10
+ const props = useSplitSingleTextProps(defaultProps, customProps);
11
+ return <TextField {...props}/>;
12
+ }
@@ -0,0 +1,13 @@
1
+ // Object components
2
+ export { ObjCheckbox } from './Obj/Checkbox/ObjCheckbox';
3
+ export { ObjCheckIcon } from './Obj/Checkbox/ObjCheckIcon';
4
+ export { ObjFloat } from './Obj/Textfield/ObjFloat';
5
+ export { ObjInteger } from './Obj/Textfield/ObjInteger';
6
+ export { ObjText } from './Obj/Textfield/ObjText';
7
+
8
+ // Single components
9
+ export { SingleCheckbox } from './Single/Checkbox/SingleCheckbox';
10
+ export { SingleCheckIcon } from './Single/Checkbox/SingleCheckIcon';
11
+ export { SingleFloat } from './Single/TextField/SingleFloat';
12
+ export { SingleInteger } from './Single/TextField/SingleInteger';
13
+ export { SingleText } from './Single/TextField/SingleText';
@@ -0,0 +1,159 @@
1
+ import type {TextFieldProps} from "@mui/material";
2
+ import {fastDeepMerge, floatCalculate, integerCalculate, processFloat, processInteger} from "../../utils";
3
+ import React, {useCallback, useMemo, useState} from "react";
4
+ import {InputLabelType, SingleNumberProps} from "../../types";
5
+
6
+ type CalculateNumber = number | null | undefined;
7
+ type CalculateFunction = (
8
+ value: string | null,
9
+ min: CalculateNumber,
10
+ max: CalculateNumber,
11
+ def: CalculateNumber
12
+ ) => CalculateNumber;
13
+
14
+ const useSplitSingleNumberProps = (
15
+ defaultProps: SingleNumberProps,
16
+ customProps: SingleNumberProps,
17
+ process: (value: string) => string,
18
+ calculate: CalculateFunction,
19
+ lockKeys: string[] = []
20
+ ): TextFieldProps => {
21
+ const [draft, setDraft] = useState<string | null>(null);
22
+ const {
23
+ get, set, errorData,
24
+ minLength, maxLength,
25
+ startAdornment, endAdornment,
26
+ disappear, def, min, max, step,
27
+ ...props
28
+ } = useMemo(() =>
29
+ fastDeepMerge<SingleNumberProps>({...defaultProps}, customProps),
30
+ [defaultProps, customProps]
31
+ );
32
+
33
+ const getCalculate = useCallback((value: string | null) => (
34
+ calculate(value, min, max, def)
35
+ ), [calculate, min, max, def]);
36
+
37
+ const getKeyboardValue = useCallback((event: React.KeyboardEvent<HTMLInputElement>) => {
38
+ const {value, valueAsNumber} = event.currentTarget;
39
+ return isNaN(valueAsNumber) ? getCalculate(value) : valueAsNumber;
40
+ }, [getCalculate]);
41
+
42
+ const getProcess = useCallback((event: React.ChangeEvent<HTMLInputElement>): string => {
43
+ const target = event.currentTarget;
44
+ const value: string = process(target.value);
45
+ if (value != target.value) {
46
+ target.value = value;
47
+ }
48
+ return value;
49
+ }, [process]);
50
+
51
+
52
+ const onSelect = useCallback(() => {
53
+ if (draft == null) setDraft(get.toString());
54
+ }, [draft, get]);
55
+
56
+ const onChange = useCallback(
57
+ (event: React.ChangeEvent<HTMLInputElement>) => {
58
+ const result: string = getProcess(event);
59
+ const num: CalculateNumber = getCalculate(result);
60
+ if (num != null && !isNaN(num) && get != num) {
61
+ set(num);
62
+ }
63
+
64
+ setDraft(event.currentTarget.value);
65
+ },
66
+ [getProcess, getCalculate, get, set]
67
+ );
68
+
69
+ const onBlur = useCallback((event: React.FocusEvent<HTMLInputElement>) => {
70
+ const {value} = event.currentTarget;
71
+
72
+ setDraft(null);
73
+ const num: CalculateNumber = getCalculate(value);
74
+ if (get != num) set(num as number);
75
+ }, [getCalculate, get, set]);
76
+
77
+ const onKeyDown = useCallback((event: React.KeyboardEvent<HTMLInputElement>) => {
78
+ if (lockKeys.includes(event.key) || step == null) {
79
+ event.preventDefault();
80
+ return;
81
+ }
82
+
83
+ const input = event.currentTarget;
84
+ if (event.key === "ArrowUp") {
85
+ event.preventDefault();
86
+ const calNum: CalculateNumber = getKeyboardValue(event);
87
+ if (calNum == null) return;
88
+
89
+ const num: number = calNum + step;
90
+ if (max != null && num > max) {
91
+ input.value = max.toString();
92
+ } else {
93
+ input.value = digitRound(num, step).toString();
94
+ }
95
+ } else if (event.key === "ArrowDown") {
96
+ event.preventDefault();
97
+ const calNum: CalculateNumber = getKeyboardValue(event);
98
+ if (calNum == null) return;
99
+
100
+ const num: number = calNum - step;
101
+ if (min != null && num < min) {
102
+ input.value = min.toString();
103
+ } else {
104
+ input.value = digitRound(num, step).toString();
105
+ }
106
+ }
107
+ }, [getKeyboardValue, lockKeys, max, min, step]);
108
+
109
+ const value = useMemo(() => (draft == null ? get : draft), [get, draft]);
110
+ const inputLabel: InputLabelType = useMemo(() => (
111
+ (draft == null && (!get || isNaN(get))) ? {} : { shrink: true }
112
+ ), [draft, get]);
113
+
114
+ return fastDeepMerge<TextFieldProps>({
115
+ error: !!errorData,
116
+ helperText: errorData,
117
+ value,
118
+ onChange,
119
+ onSelect,
120
+ onBlur,
121
+ slotProps: {
122
+ htmlInput: {step, min, max, minLength, maxLength, onKeyDown},
123
+ inputLabel: inputLabel,
124
+ input: {startAdornment, endAdornment}
125
+ }
126
+ }, (props as TextFieldProps));
127
+ }
128
+
129
+ const digitRound = (num: number, step: number) => {
130
+ step = Math.abs(step);
131
+ if (step === 0) return num;
132
+ const decimals: number = -Math.floor(Math.log10(step));
133
+ if (decimals > 0) {
134
+ return Number(Math.round(num * Math.pow(10, decimals)) / Math.pow(10, decimals));
135
+ }
136
+ return num;
137
+ }
138
+
139
+ const useSplitSingleFloatProps = (
140
+ defaultProps: SingleNumberProps,
141
+ customProps: SingleNumberProps,
142
+ ): TextFieldProps => useSplitSingleNumberProps(
143
+ defaultProps, customProps,
144
+ processFloat, floatCalculate
145
+ );
146
+
147
+ const useSplitSingleIntegerProps = (
148
+ defaultProps: SingleNumberProps,
149
+ customProps: SingleNumberProps,
150
+ ): TextFieldProps => useSplitSingleNumberProps(
151
+ defaultProps, customProps,
152
+ processInteger, integerCalculate,
153
+ [".", "e", "E"]
154
+ )
155
+
156
+ export {
157
+ useSplitSingleFloatProps,
158
+ useSplitSingleIntegerProps
159
+ };
@@ -0,0 +1,36 @@
1
+ import type {TextFieldProps} from "@mui/material";
2
+ import React, {useCallback} from "react";
3
+ import {SingleTextProps} from "../../types";
4
+ import {fastDeepMerge} from "../../utils";
5
+
6
+ const useSplitSingleTextProps = (
7
+ defaultProps: SingleTextProps,
8
+ customProps: SingleTextProps
9
+ ): TextFieldProps => {
10
+ const {
11
+ get, set, errorData,
12
+ minLength, maxLength,
13
+ startAdornment, endAdornment,
14
+ ...props
15
+ } = fastDeepMerge({...defaultProps}, customProps);
16
+
17
+ const onChange = useCallback(
18
+ (event: React.ChangeEvent<HTMLInputElement>) => {
19
+ set(event.currentTarget.value);
20
+ },
21
+ [set]
22
+ );
23
+
24
+ return fastDeepMerge<TextFieldProps>({
25
+ error: !!errorData,
26
+ helperText: errorData,
27
+ value: get,
28
+ onChange,
29
+ slotProps: {
30
+ htmlInput: {minLength, maxLength},
31
+ input: {startAdornment, endAdornment}
32
+ }
33
+ }, (props as TextFieldProps));
34
+ }
35
+
36
+ export default useSplitSingleTextProps;
@@ -0,0 +1,23 @@
1
+ import type {Dispatch, SetStateAction} from "react";
2
+ import {useCallback} from "react";
3
+ import {KeysWithValue} from "../../types";
4
+
5
+ const useObjToSingle = <Type extends object, Target>(
6
+ name: KeysWithValue<Type, Target> | string,
7
+ get: Type,
8
+ set: Dispatch<SetStateAction<Type>>
9
+ ): [Target, Dispatch<SetStateAction<Target>>] => {
10
+ const value: Target = (get as Record<string, Target>)?.[name as string];
11
+
12
+ const setValue: Dispatch<SetStateAction<Target>> = useCallback((action: SetStateAction<Target>) => {
13
+ set((state) => {
14
+ const newValue = typeof action === "function"
15
+ ? (action as (prev: Target) => Target)((state as Record<string, Target>)?.[name as string])
16
+ : action;
17
+ return ({ ...state, [name]: newValue });
18
+ });
19
+ }, [name, set]);
20
+ return [value, setValue];
21
+ }
22
+
23
+ export default useObjToSingle;
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export {createDefaultProps} from "./styles/createDefaultProps.ts";
2
+ export {
3
+ FastStartProvider,
4
+ FastStartContext
5
+ } from "./styles/FastStartProvider.tsx";
6
+
7
+ export * from "./components";
8
+ export * from "./types";
@@ -0,0 +1,26 @@
1
+ import {createContext} from "react";
2
+ import {ThemeProvider} from "@mui/material";
3
+ import type {DefaultTheme} from "@mui/system";
4
+ import {createDefaultProps} from "./createDefaultProps";
5
+ import {FastStartDefaultProps, FastStartProviderProps} from "../types";
6
+
7
+
8
+ const FastStartContext = createContext<FastStartDefaultProps>(createDefaultProps());
9
+
10
+ const FastStartProvider = <T = DefaultTheme>(props: FastStartProviderProps<T>) => {
11
+ const {
12
+ defaultProps,
13
+ ...themeProps
14
+ } = props;
15
+
16
+ return (
17
+ <FastStartContext value={defaultProps}>
18
+ <ThemeProvider<T> {...themeProps}/>
19
+ </FastStartContext>
20
+ )
21
+ }
22
+
23
+ export {
24
+ FastStartContext,
25
+ FastStartProvider
26
+ }
@@ -0,0 +1,45 @@
1
+ import type {TextFieldProps} from "@mui/material";
2
+ import {BaseNumberProps, FastStartDefaultProps} from "../types";
3
+ import {fastDeepMerge} from "../utils";
4
+
5
+
6
+ export const createDefaultProps = (
7
+ props?: FastStartDefaultProps | undefined
8
+ ): FastStartDefaultProps => {
9
+ const textFieldProps: TextFieldProps & BaseNumberProps = {
10
+ fullWidth: true,
11
+ autoComplete: 'off',
12
+ variant: 'outlined',
13
+ size: 'small'
14
+ }
15
+ const floatProps: TextFieldProps & BaseNumberProps = Object.assign({
16
+ inputMode: 'decimal',
17
+ type: 'text',
18
+ step: 0.01,
19
+ def: 0
20
+ }, textFieldProps);
21
+
22
+ const integerProps: TextFieldProps & BaseNumberProps = Object.assign({
23
+ inputMode: 'numeric',
24
+ type: 'text',
25
+ step: 1,
26
+ def: 0
27
+ }, textFieldProps);
28
+
29
+ return fastDeepMerge({
30
+ Single: {
31
+ Float: {...floatProps},
32
+ Integer: {...integerProps},
33
+ Text: {...textFieldProps},
34
+ Checkbox: {size: 'small'},
35
+ CheckIcon: {size: 'small'},
36
+ },
37
+ Obj: {
38
+ Float: {...floatProps},
39
+ Integer: {...integerProps},
40
+ Text: {...textFieldProps},
41
+ Checkbox: {size: 'small'},
42
+ CheckIcon: {size: 'small'},
43
+ }
44
+ } as FastStartDefaultProps, props as FastStartDefaultProps);
45
+ }
@@ -0,0 +1,67 @@
1
+ import type {SlotProps, TextFieldOwnerState} from "@mui/material";
2
+ import type {Dispatch, SetStateAction} from "react";
3
+ import * as React from "react";
4
+ import type {InputBaseProps} from "@mui/material/InputBase";
5
+ import type {InputLabelProps} from "@mui/material/InputLabel";
6
+
7
+ type HtmlInputType = SlotProps<React.ElementType<InputBaseProps['inputProps']>, {}, TextFieldOwnerState>;
8
+ type InputLabelType = SlotProps<React.ElementType<InputLabelProps>, {}, TextFieldOwnerState>;
9
+ type KeysWithValue<Type extends object, Target> = {
10
+ [K in keyof Type]: Type[K] extends Target ? K : never
11
+ }[keyof Type];
12
+
13
+ interface BaseProps<Type, Error> {
14
+ get: Type;
15
+ set: Dispatch<SetStateAction<Type>>;
16
+ label?: React.ReactNode;
17
+ errorData?: Error;
18
+ }
19
+
20
+ type BasePropertyProps<TYPE> = BaseProps<TYPE, string>;
21
+
22
+ interface BaseObjectProps<Type extends object, Target>
23
+ extends BaseProps<Type, Partial<Type> | object> {
24
+ name: KeysWithValue<Type, Target> | string;
25
+ }
26
+
27
+
28
+ interface BaseTextProps {
29
+ minLength?: number;
30
+ maxLength?: number;
31
+ startAdornment?: React.ReactNode;
32
+ endAdornment?: React.ReactNode;
33
+ }
34
+
35
+ interface BaseCheckIconProps {
36
+ on: React.ReactNode;
37
+ off: React.ReactNode;
38
+ }
39
+
40
+ interface BaseNumberProps extends BaseTextProps {
41
+ disappear?: boolean;
42
+ def?: number;
43
+ min?: number;
44
+ max?: number;
45
+ step?: number;
46
+ }
47
+
48
+
49
+ interface BaseSelectProps<I> {
50
+ renderMenuItem?: (item: I) => React.ReactNode;
51
+ }
52
+
53
+ interface BaseSelectItemProps<I> extends BaseSelectProps<I> {
54
+ items: I[];
55
+ }
56
+
57
+ export type {
58
+ KeysWithValue,
59
+ HtmlInputType,
60
+ InputLabelType,
61
+ BasePropertyProps,
62
+ BaseObjectProps,
63
+ BaseTextProps,
64
+ BaseCheckIconProps,
65
+ BaseNumberProps,
66
+ BaseSelectItemProps
67
+ }
@@ -0,0 +1,47 @@
1
+ import type {CheckboxProps, IconButtonProps, SelectProps, TextFieldProps, ThemeProviderProps} from "@mui/material";
2
+ import {
3
+ BaseCheckIconProps,
4
+ BaseNumberProps,
5
+ BaseObjectProps,
6
+ BasePropertyProps,
7
+ BaseSelectItemProps,
8
+ BaseTextProps
9
+ } from './props';
10
+ import type {DeepPartial} from './types';
11
+
12
+ export type SingleNumberProps = TextFieldProps & BaseNumberProps & BasePropertyProps<number>;
13
+ export type SingleTextProps = TextFieldProps & BaseTextProps & BasePropertyProps<string>;
14
+ export type SingleCheckboxProps = CheckboxProps & Omit<BasePropertyProps<boolean>, 'errorData'>;
15
+ export type SingleCheckIconProps = IconButtonProps & BaseCheckIconProps & Omit<BasePropertyProps<boolean>, 'errorData' | 'label'>;
16
+
17
+ export type ObjNumberProps<T extends object> = Omit<TextFieldProps, 'name'> & BaseNumberProps & BaseObjectProps<T, number>;
18
+ export type ObjTextProps<T extends object> = Omit<TextFieldProps, 'name'> & BaseTextProps & BaseObjectProps<T, string>;
19
+ export type ObjCheckboxProps<T extends object> = Omit<CheckboxProps, 'name'> & Omit<BaseObjectProps<T, boolean>, 'errorData'>;
20
+ export type ObjCheckIconProps<T extends object> = Omit<IconButtonProps, 'name'> & BaseCheckIconProps & Omit<BaseObjectProps<T, boolean>, 'errorData' | 'label'>;
21
+
22
+
23
+ type FastStartDefaultProps = DeepPartial<{
24
+ Single: {
25
+ Float: SingleNumberProps;
26
+ Integer: SingleNumberProps;
27
+ Text: SingleTextProps;
28
+ Checkbox: SingleCheckboxProps;
29
+ CheckIcon: SingleCheckIconProps;
30
+ },
31
+ Obj: {
32
+ Float: ObjNumberProps<object>;
33
+ Integer: ObjNumberProps<object>;
34
+ Text: ObjTextProps<object>;
35
+ Checkbox: ObjCheckboxProps<object>;
36
+ CheckIcon: ObjCheckIconProps<object>;
37
+ }
38
+ }>;
39
+
40
+ interface FastStartProviderProps<Theme> extends ThemeProviderProps<Theme> {
41
+ defaultProps: FastStartDefaultProps;
42
+ }
43
+
44
+ export type {
45
+ FastStartDefaultProps,
46
+ FastStartProviderProps,
47
+ }
@@ -0,0 +1,9 @@
1
+ type DeepPartial<T> = {
2
+ [K in keyof T]?: T[K] extends object
3
+ ? DeepPartial<T[K]>
4
+ : T[K];
5
+ };
6
+
7
+ export type {
8
+ DeepPartial
9
+ }
@@ -0,0 +1,102 @@
1
+ type CalculateNumber = number | null | undefined;
2
+
3
+ const floatCalculate = (
4
+ value: string | null,
5
+ min: CalculateNumber,
6
+ max: CalculateNumber,
7
+ def: CalculateNumber
8
+ ): CalculateNumber => {
9
+ let calc: CalculateNumber = 0;
10
+ if (value == null || isEmpty(value)) {
11
+ calc = def;
12
+ } else {
13
+ for (const token of value.split(/(?=[+-])/g)) {
14
+ if (/^[+-]?\d+\.\d+$/.test(token)) {
15
+ calc += parseFloat(token);
16
+ } else if (/^[+-]?\d+$/.test(token)) {
17
+ calc += parseInt(token, 10);
18
+ }
19
+ }
20
+ }
21
+
22
+ if (calc != null) {
23
+ if (max != null) calc = Math.min(max, calc);
24
+ if (min != null) calc = Math.min(min, calc);
25
+ }
26
+ return calc;
27
+ }
28
+
29
+ const integerCalculate = (
30
+ value: string | null,
31
+ min: CalculateNumber,
32
+ max: CalculateNumber,
33
+ def: CalculateNumber
34
+ ): CalculateNumber => {
35
+ let calc: CalculateNumber = 0;
36
+ if (value == null || isEmpty(value)) {
37
+ calc = def;
38
+ } else {
39
+ for (const token of value.split(/(?=[+-])/g)) {
40
+ if (/^[+-]?\d+$/.test(token)) {
41
+ calc += parseInt(token, 10);
42
+ }
43
+ }
44
+ }
45
+
46
+ if (calc != null) {
47
+ if (max != null) calc = Math.min(max, calc);
48
+ if (min != null) calc = Math.min(min, calc);
49
+ }
50
+ return calc;
51
+ }
52
+
53
+ const processFloat = (text: string): string => {
54
+ const value: string = text
55
+ .replace(/[^0-9+.-]/g, '')
56
+ .replace(/([+-]){2,}/g, (match, op) => op);
57
+
58
+ let result: string = '';
59
+ let token: string = '';
60
+ let decimalUsed: boolean = false;
61
+
62
+ for (let i = 0; i < value.length; i++) {
63
+ const char = value[i];
64
+
65
+ if (char >= '0' && char <= '9') {
66
+ token += char;
67
+ } else if (char === '.') {
68
+ if (!decimalUsed) {
69
+ if (token === '') {
70
+ token = '0';
71
+ }
72
+ token += '.';
73
+ decimalUsed = true;
74
+ }
75
+ } else if (char === '+' || char === '-') {
76
+ if (token !== '') {
77
+ result += token;
78
+ }
79
+ result += char;
80
+ token = '';
81
+ decimalUsed = false;
82
+ }
83
+ }
84
+ return result + token;
85
+ }
86
+
87
+ const processInteger = (text: string): string => text
88
+ .replace(/[^0-9+-]/g, '')
89
+ .replace(/\./g, '')
90
+ .replace(/([+-]){2,}/g, (match, op) => op.charAt(0))
91
+ .replace(/^([+-]{2,})/, match => match.charAt(0));
92
+
93
+ function isEmpty(str: string): boolean {
94
+ return str.length === 0 || !str.trim();
95
+ }
96
+
97
+ export {
98
+ floatCalculate,
99
+ integerCalculate,
100
+ processFloat,
101
+ processInteger
102
+ }
@@ -0,0 +1,14 @@
1
+ import {BaseObjectProps, KeysWithValue} from "../../types";
2
+
3
+ function errorObjectToString<Type extends object, Target>(
4
+ name: KeysWithValue<Type, Target> | string | undefined,
5
+ data: BaseObjectProps<Type, Target>['errorData']
6
+ ): string | undefined {
7
+ return (name != null && typeof data === 'object')
8
+ ? (data as Record<string, string>)[name as string]
9
+ : undefined;
10
+ }
11
+
12
+ export {
13
+ errorObjectToString
14
+ }
@@ -0,0 +1,47 @@
1
+ import {DeepPartial} from "../../types";
2
+
3
+ type AnyObj = Record<string, any>;
4
+
5
+ function isPlainObject(v: any): v is AnyObj {
6
+ return v !== null && typeof v === "object" && v.constructor === Object;
7
+ }
8
+
9
+ function isEmpty(v: object): boolean {
10
+ return Object.keys(v).length === 0;
11
+ }
12
+
13
+ function fastDeepMerge<T extends object>(target: DeepPartial<T> | undefined, source: T): T {
14
+ if (target === source || !isPlainObject(source) || isEmpty(source)) {
15
+ return target as T;
16
+ } else if (!isPlainObject(target) || isEmpty(target)) {
17
+ return source;
18
+ }
19
+
20
+ const result: AnyObj = {...target};
21
+ const stack: [AnyObj, AnyObj][] = [[result, source as AnyObj]];
22
+
23
+ while (stack.length) {
24
+ const [tNode, sNode] = stack.pop()!;
25
+
26
+ for (const key in sNode) {
27
+ if (!Object.prototype.hasOwnProperty.call(sNode, key)) continue;
28
+
29
+ const sVal = sNode[key];
30
+ const tVal = tNode[key];
31
+
32
+ if (isPlainObject(tVal) && isPlainObject(sVal)) {
33
+ const copy = {...tVal};
34
+ tNode[key] = copy;
35
+ stack.push([copy, sVal]);
36
+ } else {
37
+ tNode[key] = sVal;
38
+ }
39
+ }
40
+ }
41
+ return result as T;
42
+ }
43
+
44
+
45
+ export {
46
+ fastDeepMerge
47
+ }
package/src.zip ADDED
Binary file
package/tsconfig.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "useDefineForClassFields": true,
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+
6
+ "allowImportingTsExtensions": true,
7
+ "moduleDetection": "force",
8
+
9
+ /* Build options */
10
+ "declaration": true,
11
+ "declarationMap": true,
12
+ "emitDeclarationOnly": true,
13
+ "noEmit": false,
14
+ "rootDir": "src",
15
+ "outDir": "dist",
16
+ "declarationDir": "dist",
17
+
18
+ /* Bundler mode */
19
+ "strict": true,
20
+ "jsx": "react-jsx",
21
+ "moduleResolution": "bundler",
22
+ "module": "ESNext",
23
+ "target": "ES2022",
24
+
25
+ /* Interop */
26
+ "allowSyntheticDefaultImports": true,
27
+ "esModuleInterop": true,
28
+
29
+ /* Library options */
30
+ "skipLibCheck": true,
31
+ "skipDefaultLibCheck": true,
32
+ },
33
+ "include": ["src"],
34
+ }