@etsoo/materialui 1.5.84 → 1.5.85

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 (46) hide show
  1. package/lib/cjs/CountdownButton.d.ts +1 -2
  2. package/lib/cjs/CountdownButton.js +4 -4
  3. package/lib/cjs/EmailInput.d.ts +2 -2
  4. package/lib/cjs/EmailInput.js +2 -5
  5. package/lib/cjs/InputField.d.ts +1 -52
  6. package/lib/cjs/InputField.js +5 -5
  7. package/lib/cjs/InputTipField.d.ts +22 -3
  8. package/lib/cjs/InputTipField.js +13 -2
  9. package/lib/cjs/IntInputField.d.ts +1 -1
  10. package/lib/cjs/IntInputField.js +9 -12
  11. package/lib/cjs/MobileInput.d.ts +2 -2
  12. package/lib/cjs/MobileInput.js +2 -5
  13. package/lib/cjs/MoneyInputField.d.ts +1 -2
  14. package/lib/cjs/MoneyInputField.js +4 -8
  15. package/lib/cjs/PhoneInput.d.ts +2 -2
  16. package/lib/cjs/PhoneInput.js +2 -5
  17. package/lib/cjs/TextFieldEx.d.ts +5 -106
  18. package/lib/cjs/TextFieldEx.js +27 -18
  19. package/lib/mjs/CountdownButton.d.ts +1 -2
  20. package/lib/mjs/CountdownButton.js +3 -3
  21. package/lib/mjs/EmailInput.d.ts +2 -2
  22. package/lib/mjs/EmailInput.js +2 -2
  23. package/lib/mjs/InputField.d.ts +1 -52
  24. package/lib/mjs/InputField.js +4 -4
  25. package/lib/mjs/InputTipField.d.ts +22 -3
  26. package/lib/mjs/InputTipField.js +13 -2
  27. package/lib/mjs/IntInputField.d.ts +1 -1
  28. package/lib/mjs/IntInputField.js +8 -11
  29. package/lib/mjs/MobileInput.d.ts +2 -2
  30. package/lib/mjs/MobileInput.js +2 -2
  31. package/lib/mjs/MoneyInputField.d.ts +1 -2
  32. package/lib/mjs/MoneyInputField.js +3 -4
  33. package/lib/mjs/PhoneInput.d.ts +2 -2
  34. package/lib/mjs/PhoneInput.js +2 -2
  35. package/lib/mjs/TextFieldEx.d.ts +5 -106
  36. package/lib/mjs/TextFieldEx.js +26 -17
  37. package/package.json +7 -7
  38. package/src/CountdownButton.tsx +2 -6
  39. package/src/EmailInput.tsx +3 -3
  40. package/src/InputField.tsx +69 -74
  41. package/src/InputTipField.tsx +63 -35
  42. package/src/IntInputField.tsx +14 -22
  43. package/src/MobileInput.tsx +3 -3
  44. package/src/MoneyInputField.tsx +3 -7
  45. package/src/PhoneInput.tsx +3 -3
  46. package/src/TextFieldEx.tsx +33 -20
@@ -35,83 +35,78 @@ export type InputFieldProps = TextFieldProps & {
35
35
  * @param props Props
36
36
  * @returns Component
37
37
  */
38
- export const InputField = React.forwardRef<HTMLDivElement, InputFieldProps>(
39
- (props, ref) => {
40
- // Destruct
41
- const {
42
- InputProps = {},
43
- inputProps = {},
44
- changeDelay,
45
- slotProps,
46
- onChange,
47
- onChangeDelay,
48
- readOnly,
49
- size = MUGlobal.inputFieldSize,
50
- variant = MUGlobal.inputFieldVariant,
51
- minChars = 0,
52
- ...rest
53
- } = props;
38
+ export function InputField(props: InputFieldProps) {
39
+ // Destruct
40
+ const {
41
+ InputProps = {},
42
+ inputProps = {},
43
+ slotProps,
44
+ changeDelay,
45
+ onChange,
46
+ onChangeDelay,
47
+ readOnly,
48
+ size = MUGlobal.inputFieldSize,
49
+ variant = MUGlobal.inputFieldVariant,
50
+ minChars = 0,
51
+ ...rest
52
+ } = props;
54
53
 
55
- // Slot props
56
- const { htmlInput, input, inputLabel, ...restSlotProps } = slotProps ?? {};
54
+ // Slot props
55
+ const { htmlInput, input, inputLabel, ...restSlotProps } = slotProps ?? {};
57
56
 
58
- const isMounted = React.useRef(true);
59
- const createDelayed = () => {
60
- if (changeDelay != null && changeDelay >= 1) {
61
- const changeHandler = onChangeDelay ?? onChange;
62
- if (changeHandler)
63
- return useDelayedExecutor(changeHandler, changeDelay);
64
- }
65
- return undefined;
66
- };
67
- const delayed = createDelayed();
57
+ const isMounted = React.useRef(true);
58
+ const createDelayed = () => {
59
+ if (changeDelay != null && changeDelay >= 1) {
60
+ const changeHandler = onChangeDelay ?? onChange;
61
+ if (changeHandler) return useDelayedExecutor(changeHandler, changeDelay);
62
+ }
63
+ return undefined;
64
+ };
65
+ const delayed = createDelayed();
68
66
 
69
- const onChangeEx = (
70
- event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
71
- ) => {
72
- // Min characters check
73
- const len = event.target.value.length;
74
- if (len > 0 && len < minChars) {
75
- // Avoid to trigger the form change event
76
- event.stopPropagation();
77
- event.preventDefault();
78
- return;
79
- }
67
+ const onChangeEx = (
68
+ event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
69
+ ) => {
70
+ // Min characters check
71
+ const len = event.target.value.length;
72
+ if (len > 0 && len < minChars) {
73
+ // Avoid to trigger the form change event
74
+ event.stopPropagation();
75
+ event.preventDefault();
76
+ return;
77
+ }
80
78
 
81
- if (onChange && (delayed == null || onChangeDelay != null))
82
- onChange(event);
83
- delayed?.call(undefined, event);
84
- };
79
+ if (onChange && (delayed == null || onChangeDelay != null)) onChange(event);
80
+ delayed?.call(undefined, event);
81
+ };
85
82
 
86
- React.useEffect(() => {
87
- return () => {
88
- isMounted.current = false;
89
- delayed?.clear();
90
- };
91
- }, []);
83
+ React.useEffect(() => {
84
+ return () => {
85
+ isMounted.current = false;
86
+ delayed?.clear();
87
+ };
88
+ }, []);
92
89
 
93
- // Layout
94
- return (
95
- <TextField
96
- ref={ref}
97
- slotProps={{
98
- htmlInput: {
99
- ["data-min-chars"]: minChars,
100
- ...htmlInput,
101
- ...inputProps
102
- },
103
- input: { readOnly, ...input, ...InputProps },
104
- inputLabel: {
105
- shrink: MUGlobal.inputFieldShrink,
106
- ...inputLabel
107
- },
108
- ...restSlotProps
109
- }}
110
- onChange={onChangeEx}
111
- size={size}
112
- variant={variant}
113
- {...rest}
114
- />
115
- );
116
- }
117
- );
90
+ // Layout
91
+ return (
92
+ <TextField
93
+ slotProps={{
94
+ htmlInput: {
95
+ ["data-min-chars"]: minChars,
96
+ ...htmlInput,
97
+ ...inputProps
98
+ },
99
+ input: { readOnly, ...input, ...InputProps },
100
+ inputLabel: {
101
+ shrink: MUGlobal.inputFieldShrink,
102
+ ...inputLabel
103
+ },
104
+ ...restSlotProps
105
+ }}
106
+ onChange={onChangeEx}
107
+ size={size}
108
+ variant={variant}
109
+ {...rest}
110
+ />
111
+ );
112
+ }
@@ -1,54 +1,80 @@
1
1
  import { DataTypes } from "@etsoo/shared";
2
2
  import Typography, { TypographyProps } from "@mui/material/Typography";
3
3
  import React from "react";
4
- import { InputField, InputFieldProps } from "./InputField";
4
+ import { InputField } from "./InputField";
5
5
  import { useAppContext } from "./app/ReactApp";
6
6
  import ListItem from "@mui/material/ListItem";
7
7
  import Popover from "@mui/material/Popover";
8
8
  import List from "@mui/material/List";
9
9
  import InputAdornment from "@mui/material/InputAdornment";
10
+ import { EmailInput } from "./EmailInput";
11
+ import { MobileInput } from "./MobileInput";
12
+ import { PhoneInput } from "./PhoneInput";
10
13
 
11
14
  type ItemType = DataTypes.IdLabelItem<string | number>;
12
15
 
16
+ const componentMap = {
17
+ input: InputField,
18
+ email: EmailInput,
19
+ phone: PhoneInput,
20
+ mobile: MobileInput
21
+ };
22
+
23
+ type ComponentMap = typeof componentMap;
24
+ type ComponentKey = keyof ComponentMap;
25
+
13
26
  /**
14
27
  * InputField with tips properties
15
28
  */
16
- export type InputTipFieldProps<T extends ItemType = ItemType> =
17
- InputFieldProps & {
18
- /**
19
- * Load data
20
- * @param value Duplicate test value
21
- */
22
- loadData(value: string): Promise<[T[]?, string?]>;
23
-
24
- /**
25
- * Label props
26
- */
27
- labelProps?: Omit<TypographyProps, "onClick">;
28
-
29
- /**
30
- * Custom item label
31
- * @param item List item data
32
- * @returns Result
33
- */
34
- itemLabel?: (item: T) => React.ReactNode;
35
-
36
- /**
37
- * Custom render item
38
- * @param item List item data
39
- * @returns Result
40
- */
41
- renderItem?: (item: T) => React.ReactNode;
42
- };
29
+ export type InputTipFieldProps<
30
+ T extends ItemType = ItemType,
31
+ K extends ComponentKey = "input"
32
+ > = {
33
+ /**
34
+ * Component key
35
+ */
36
+ component?: K;
37
+
38
+ /**
39
+ * Component props
40
+ */
41
+ componentProps?: React.ComponentProps<ComponentMap[K]>;
42
+
43
+ /**
44
+ * Load data
45
+ * @param value Duplicate test value
46
+ */
47
+ loadData(value: string): Promise<[T[]?, string?]>;
48
+
49
+ /**
50
+ * Label props
51
+ */
52
+ labelProps?: Omit<TypographyProps, "onClick">;
53
+
54
+ /**
55
+ * Custom item label
56
+ * @param item List item data
57
+ * @returns Result
58
+ */
59
+ itemLabel?: (item: T) => React.ReactNode;
60
+
61
+ /**
62
+ * Custom render item
63
+ * @param item List item data
64
+ * @returns Result
65
+ */
66
+ renderItem?: (item: T) => React.ReactNode;
67
+ };
43
68
 
44
69
  /**
45
70
  * InputField with tips
46
71
  * @param props Props
47
72
  * @returns Component
48
73
  */
49
- export function InputTipField<T extends ItemType = ItemType>(
50
- props: InputTipFieldProps<T>
51
- ) {
74
+ export function InputTipField<
75
+ T extends ItemType = ItemType,
76
+ K extends ComponentKey = "input"
77
+ >(props: InputTipFieldProps<T, K>) {
52
78
  // Global app
53
79
  const app = useAppContext();
54
80
 
@@ -63,17 +89,19 @@ export function InputTipField<T extends ItemType = ItemType>(
63
89
  title: app?.get("clickForDetails"),
64
90
  sx: { color: (theme) => theme.palette.error.main, cursor: "pointer" }
65
91
  },
66
- changeDelay = 480,
67
- onChangeDelay,
68
92
  loadData,
69
93
  itemLabel = (item) => item.label,
70
94
  renderItem = (item) => <ListItem key={item.id}>{itemLabel(item)}</ListItem>,
71
- slotProps = {},
95
+ component = "input",
96
+ componentProps = {} as React.ComponentProps<ComponentMap[K]>,
72
97
  ...rest
73
98
  } = props;
74
99
 
100
+ const { changeDelay = 480, onChangeDelay, slotProps = {} } = componentProps;
75
101
  const { input, ...slotRests } = slotProps;
76
102
 
103
+ const Component: typeof InputField = componentMap[component];
104
+
77
105
  const load = (value: string) => {
78
106
  if (value.length < 2) {
79
107
  setTitle(undefined);
@@ -99,7 +127,7 @@ export function InputTipField<T extends ItemType = ItemType>(
99
127
  >
100
128
  {data && <List>{data.map((item) => renderItem(item))}</List>}
101
129
  </Popover>
102
- <InputField
130
+ <Component
103
131
  changeDelay={changeDelay}
104
132
  onChangeDelay={(event) => {
105
133
  load(event.target.value);
@@ -75,10 +75,7 @@ export type IntInputFieldProps = Omit<
75
75
  /**
76
76
  * Integer input field (controlled)
77
77
  */
78
- export const IntInputField = React.forwardRef<
79
- HTMLDivElement,
80
- IntInputFieldProps
81
- >((props, ref) => {
78
+ export function IntInputField(props: IntInputFieldProps) {
82
79
  // Destruct
83
80
  const {
84
81
  min = 0,
@@ -130,25 +127,20 @@ export const IntInputField = React.forwardRef<
130
127
  // Layout
131
128
  const layout = (
132
129
  <InputField
133
- ref={ref}
134
130
  type="number"
135
131
  value={localValue == null ? (required ? min : "") : localValue}
136
- inputProps={{
137
- min,
138
- step,
139
- max,
140
- style: inputStyle,
141
- inputMode: "numeric"
142
- }}
143
- InputProps={{
144
- startAdornment: symbol ? (
145
- <React.Fragment>
146
- <InputAdornment position="start">{symbol}</InputAdornment>
147
- </React.Fragment>
148
- ) : undefined,
149
- endAdornment: endSymbol ? (
150
- <InputAdornment position="end">{endSymbol}</InputAdornment>
151
- ) : undefined
132
+ slotProps={{
133
+ input: {
134
+ startAdornment: symbol ? (
135
+ <React.Fragment>
136
+ <InputAdornment position="start">{symbol}</InputAdornment>
137
+ </React.Fragment>
138
+ ) : undefined,
139
+ endAdornment: endSymbol ? (
140
+ <InputAdornment position="end">{endSymbol}</InputAdornment>
141
+ ) : undefined
142
+ },
143
+ htmlInput: { min, step, max, style: inputStyle, inputMode: "numeric" }
152
144
  }}
153
145
  sx={
154
146
  buttons
@@ -234,4 +226,4 @@ export const IntInputField = React.forwardRef<
234
226
  </Box>
235
227
  );
236
228
  else return layout;
237
- });
229
+ }
@@ -1,11 +1,11 @@
1
- import TextField, { TextFieldProps } from "@mui/material/TextField";
2
1
  import { useAppContext } from "./app/ReactApp";
3
2
  import { MUGlobal } from "./MUGlobal";
3
+ import { InputField, InputFieldProps } from "./InputField";
4
4
 
5
5
  /**
6
6
  * Mobile input props
7
7
  */
8
- export type MobileInputProps = Omit<TextFieldProps, "type"> & {};
8
+ export type MobileInputProps = Omit<InputFieldProps, "type"> & {};
9
9
 
10
10
  /**
11
11
  * Mobile input
@@ -32,7 +32,7 @@ export function MobileInput(props: MobileInputProps) {
32
32
 
33
33
  // Layout
34
34
  return (
35
- <TextField
35
+ <InputField
36
36
  type="tel"
37
37
  autoCapitalize={autoCapitalize}
38
38
  autoCorrect={autoCorrect}
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import { IntInputField, IntInputFieldProps } from "./IntInputField";
3
2
 
4
3
  /**
@@ -9,13 +8,10 @@ export type MoneyInputFieldProps = IntInputFieldProps & {};
9
8
  /**
10
9
  * Money input field (controlled)
11
10
  */
12
- export const MoneyInputField = React.forwardRef<
13
- HTMLDivElement,
14
- MoneyInputFieldProps
15
- >((props, ref) => {
11
+ export function MoneyInputField(props: MoneyInputFieldProps) {
16
12
  // Destruct
17
13
  const { step = 0.01, ...rest } = props;
18
14
 
19
15
  // Layout
20
- return <IntInputField ref={ref} step={step} {...rest} />;
21
- });
16
+ return <IntInputField step={step} {...rest} />;
17
+ }
@@ -1,11 +1,11 @@
1
- import TextField, { TextFieldProps } from "@mui/material/TextField";
2
1
  import { useAppContext } from "./app/ReactApp";
3
2
  import { MUGlobal } from "./MUGlobal";
3
+ import { InputField, InputFieldProps } from "./InputField";
4
4
 
5
5
  /**
6
6
  * Phone input props
7
7
  */
8
- export type PhoneInputProps = Omit<TextFieldProps, "type"> & {};
8
+ export type PhoneInputProps = Omit<InputFieldProps, "type"> & {};
9
9
 
10
10
  /**
11
11
  * Phone input
@@ -32,7 +32,7 @@ export function PhoneInput(props: PhoneInputProps) {
32
32
 
33
33
  // Layout
34
34
  return (
35
- <TextField
35
+ <InputField
36
36
  type="tel"
37
37
  autoCapitalize={autoCapitalize}
38
38
  autoCorrect={autoCorrect}
@@ -54,6 +54,11 @@ export type TextFieldExProps = TextFieldProps & {
54
54
  * Show password button
55
55
  */
56
56
  showPassword?: boolean;
57
+
58
+ /**
59
+ * Methods
60
+ */
61
+ mRef?: React.Ref<TextFieldExMethods>;
57
62
  };
58
63
 
59
64
  /**
@@ -67,10 +72,7 @@ export interface TextFieldExMethods {
67
72
  setError(error: React.ReactNode): void;
68
73
  }
69
74
 
70
- export const TextFieldEx = React.forwardRef<
71
- TextFieldExMethods,
72
- TextFieldExProps
73
- >((props, ref) => {
75
+ export function TextFieldEx(props: TextFieldExProps) {
74
76
  // Global app
75
77
  const app = useAppContext();
76
78
 
@@ -86,6 +88,7 @@ export const TextFieldEx = React.forwardRef<
86
88
  helperText,
87
89
  InputLabelProps = {},
88
90
  InputProps = {},
91
+ slotProps,
89
92
  onChange,
90
93
  onClear,
91
94
  onKeyDown,
@@ -97,9 +100,13 @@ export const TextFieldEx = React.forwardRef<
97
100
  showPassword,
98
101
  type,
99
102
  variant = MUGlobal.textFieldVariant,
103
+ mRef,
100
104
  ...rest
101
105
  } = props;
102
106
 
107
+ // Slot props
108
+ const { input, inputLabel, ...restSlotProps } = slotProps ?? {};
109
+
103
110
  // Shrink
104
111
  InputLabelProps.shrink ??= MUGlobal.searchFieldShrink;
105
112
 
@@ -120,19 +127,19 @@ export const TextFieldEx = React.forwardRef<
120
127
 
121
128
  let typeEx = showPassword ? "password" : type;
122
129
 
123
- let input: HTMLInputElement | undefined;
130
+ let inputEle: HTMLInputElement | undefined;
124
131
  const localRef = (ref: HTMLInputElement) => {
125
- input = ref;
132
+ inputEle = ref;
126
133
 
127
- if (input.value !== "") {
134
+ if (inputEle.value !== "") {
128
135
  updateEmpty(false);
129
136
  }
130
137
  };
131
138
 
132
139
  const doClear = () => {
133
- if (input == null) return;
134
- ReactUtils.triggerChange(input, "", false);
135
- input.focus();
140
+ if (inputEle == null) return;
141
+ ReactUtils.triggerChange(inputEle, "", false);
142
+ inputEle.focus();
136
143
  };
137
144
 
138
145
  const clearClick = () => {
@@ -152,24 +159,24 @@ export const TextFieldEx = React.forwardRef<
152
159
 
153
160
  const touchStart = async (e: React.TouchEvent | React.MouseEvent) => {
154
161
  // Show the password
155
- if (input) {
162
+ if (inputEle) {
156
163
  if (onVisibility) {
157
- const result = await onVisibility(input);
164
+ const result = await onVisibility(inputEle);
158
165
  if (result === false) return;
159
166
  }
160
167
 
161
- input.blur();
162
- input.type = "text";
168
+ inputEle.blur();
169
+ inputEle.type = "text";
163
170
  }
164
171
  preventDefault(e);
165
172
  };
166
173
 
167
174
  const touchEnd = (e: React.TouchEvent | React.MouseEvent) => {
168
175
  // Show the password
169
- if (input) {
176
+ if (inputEle) {
170
177
  if (onVisibility) return;
171
178
 
172
- input.type = "password";
179
+ inputEle.type = "password";
173
180
  }
174
181
  preventDefault(e);
175
182
  };
@@ -218,7 +225,7 @@ export const TextFieldEx = React.forwardRef<
218
225
  };
219
226
 
220
227
  React.useImperativeHandle(
221
- ref,
228
+ mRef,
222
229
  () => ({
223
230
  /**
224
231
  * Set error
@@ -277,13 +284,19 @@ export const TextFieldEx = React.forwardRef<
277
284
  fullWidth={fullWidth}
278
285
  helperText={helperTextEx}
279
286
  inputRef={useCombinedRefs(inputRef, localRef)}
280
- InputProps={InputProps}
281
- InputLabelProps={InputLabelProps}
282
287
  onChange={onChangeEx}
283
288
  onKeyDown={onKeyPressEx}
289
+ slotProps={{
290
+ input: { readOnly, ...input, ...InputProps },
291
+ inputLabel: {
292
+ shrink: MUGlobal.inputFieldShrink,
293
+ ...inputLabel
294
+ },
295
+ ...restSlotProps
296
+ }}
284
297
  type={typeEx}
285
298
  variant={variant}
286
299
  {...rest}
287
300
  />
288
301
  );
289
- });
302
+ }