@etsoo/materialui 1.0.60 → 1.0.62

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/lib/NotifierMU.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { NotificationAlign, NotificationMessageType, NotificationType } from '@etsoo/notificationbase';
2
+ import { DomUtils } from '@etsoo/shared';
2
3
  import { Alert, AlertTitle, Backdrop, Box, Button, CircularProgress, Dialog, DialogActions, DialogContent, DialogContentText, DialogTitle, Fade, Slider, Snackbar, styled, Switch, TextField, Typography } from '@mui/material';
3
4
  import { Error, Info, Help, Warning, Done } from '@mui/icons-material';
4
5
  import React from 'react';
@@ -134,33 +135,18 @@ export class NotificationMU extends NotificationReact {
134
135
  if (inputs && value == null)
135
136
  value = event.currentTarget.form;
136
137
  if (input) {
137
- if (type === 'date') {
138
- const dateValue = input.valueAsDate;
139
- if (dateValue == null && input.required) {
140
- input.focus();
141
- return false;
142
- }
143
- result = this.onReturn(dateValue);
144
- }
145
- else if (type === 'number') {
146
- const numberValue = input.valueAsNumber;
147
- if (isNaN(numberValue) && input.required) {
148
- input.focus();
149
- return false;
150
- }
151
- result = this.onReturn(numberValue);
152
- }
153
- else if (type === 'switch') {
138
+ if (type === 'switch') {
154
139
  const boolValue = input.value === 'true';
155
140
  result = this.onReturn(boolValue);
156
141
  }
157
142
  else {
158
- const textValue = input.value.trim();
159
- if (textValue === '' && input.required) {
143
+ const inputValue = DomUtils.getInputValue(input);
144
+ if ((inputValue == null || inputValue === '') &&
145
+ input.required) {
160
146
  input.focus();
161
147
  return false;
162
148
  }
163
- result = this.onReturn(textValue);
149
+ result = this.onReturn(inputValue);
164
150
  }
165
151
  }
166
152
  else if (value != null) {
@@ -0,0 +1,23 @@
1
+ /// <reference types="react" />
2
+ import { InputFieldProps } from './InputField';
3
+ declare type ValueType = string | number | Date | null | undefined;
4
+ /**
5
+ * TwoField Input props
6
+ */
7
+ export declare type TwoFieldInputProps = Omit<InputFieldProps, 'InputProps' | 'value'> & {
8
+ /**
9
+ * Values
10
+ */
11
+ values?: unknown | [ValueType, ValueType];
12
+ /**
13
+ * On values change, return false to prevent further onChange handler
14
+ */
15
+ onValuesChange?: (values: [ValueType, ValueType]) => boolean | void | Promise<boolean | void>;
16
+ };
17
+ /**
18
+ * TwoField Input
19
+ * @param props Props
20
+ * @returns Component
21
+ */
22
+ export declare function TwoFieldInput(props: TwoFieldInputProps): JSX.Element;
23
+ export {};
@@ -0,0 +1,53 @@
1
+ import { Input, InputAdornment } from '@mui/material';
2
+ import ArrowRightAltIcon from '@mui/icons-material/ArrowRightAlt';
3
+ import { useDimensions } from '@etsoo/react';
4
+ import React from 'react';
5
+ import { DomUtils } from '@etsoo/shared';
6
+ import { InputField } from './InputField';
7
+ /**
8
+ * TwoField Input
9
+ * @param props Props
10
+ * @returns Component
11
+ */
12
+ export function TwoFieldInput(props) {
13
+ var _a, _b;
14
+ // Destruct
15
+ const { name, inputProps, type = inputProps === null || inputProps === void 0 ? void 0 : inputProps.inputMode, values, onValuesChange, onChange, onInput, ...rest } = props;
16
+ // Local values
17
+ const localValues = values == null
18
+ ? [null, null]
19
+ : Array.isArray(values)
20
+ ? values
21
+ : [values, null];
22
+ // Ref
23
+ const valueRef = React.useRef(localValues);
24
+ // Watch container
25
+ const { dimensions } = useDimensions(1, (target, rect) => {
26
+ const width = (rect.width - 64) / 2;
27
+ const inputs = target.querySelectorAll('input');
28
+ inputs[0].style.width = `${width}px`;
29
+ inputs[1].parentElement.style.width = `${width}px`;
30
+ }, 0);
31
+ // Handle change
32
+ const handleChange = (event) => {
33
+ const value = DomUtils.getInputValue(event.target);
34
+ const index = event.target.name.endsWith('-start') ? 0 : 1;
35
+ valueRef.current[index] = value;
36
+ if (onValuesChange) {
37
+ if (onValuesChange(valueRef.current) === false)
38
+ return;
39
+ }
40
+ if (onChange)
41
+ onChange(event);
42
+ };
43
+ // Layout
44
+ return (React.createElement(InputField, { name: `${name}-start`, type: type, defaultValue: (_a = localValues[0]) !== null && _a !== void 0 ? _a : '', ref: dimensions[0][0], inputProps: inputProps, InputProps: {
45
+ endAdornment: (React.createElement(InputAdornment, { position: "end", sx: {
46
+ display: 'flex',
47
+ alignItems: 'center',
48
+ gap: 1
49
+ } },
50
+ React.createElement(ArrowRightAltIcon, null),
51
+ React.createElement(Input, { type: type, name: `${name}-end`, defaultValue: (_b = localValues[1]) !== null && _b !== void 0 ? _b : '', disableUnderline: true, onInput: onInput, onChange: handleChange, inputProps: inputProps })))
52
+ }, onInput: onInput, onChange: handleChange, ...rest }));
53
+ }
@@ -143,7 +143,7 @@ export declare class ReactApp<S extends IAppSettings, D extends IUser, P extends
143
143
  * @param result Action result
144
144
  * @param callback Callback
145
145
  */
146
- alertResult(result: IActionResult, callback?: NotificationReturn<void>): void;
146
+ alertResult(result: IActionResult | string, callback?: NotificationReturn<void>): void;
147
147
  /**
148
148
  * Change culture
149
149
  * @param culture New culture definition
@@ -88,7 +88,7 @@ export class ReactApp extends CoreApp {
88
88
  * @param callback Callback
89
89
  */
90
90
  alertResult(result, callback) {
91
- const message = this.formatResult(result);
91
+ const message = typeof result === 'string' ? result : this.formatResult(result);
92
92
  if (message.endsWith(')')) {
93
93
  const startPos = message.lastIndexOf('(');
94
94
  if (startPos > 0) {
@@ -99,7 +99,7 @@ export class ReactApp extends CoreApp {
99
99
  return;
100
100
  }
101
101
  }
102
- this.notifier.alert(message, callback);
102
+ super.alertResult(message, callback);
103
103
  }
104
104
  /**
105
105
  * Change culture
package/lib/index.d.ts CHANGED
@@ -72,6 +72,7 @@ export * from './TabBox';
72
72
  export * from './TableEx';
73
73
  export * from './TextFieldEx';
74
74
  export * from './Tiplist';
75
+ export * from './TwoFieldInput';
75
76
  export * from './TooltipClick';
76
77
  export * from './UserAvatar';
77
78
  export * from './UserAvatarEditor';
package/lib/index.js CHANGED
@@ -72,6 +72,7 @@ export * from './TabBox';
72
72
  export * from './TableEx';
73
73
  export * from './TextFieldEx';
74
74
  export * from './Tiplist';
75
+ export * from './TwoFieldInput';
75
76
  export * from './TooltipClick';
76
77
  export * from './UserAvatar';
77
78
  export * from './UserAvatarEditor';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.0.60",
3
+ "version": "1.0.62",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -51,12 +51,12 @@
51
51
  "@emotion/css": "^11.10.5",
52
52
  "@emotion/react": "^11.10.5",
53
53
  "@emotion/styled": "^11.10.5",
54
- "@etsoo/appscript": "^1.3.28",
55
- "@etsoo/notificationbase": "^1.1.13",
56
- "@etsoo/react": "^1.6.23",
57
- "@etsoo/shared": "^1.1.71",
54
+ "@etsoo/appscript": "^1.3.29",
55
+ "@etsoo/notificationbase": "^1.1.14",
56
+ "@etsoo/react": "^1.6.24",
57
+ "@etsoo/shared": "^1.1.73",
58
58
  "@mui/icons-material": "^5.10.9",
59
- "@mui/material": "^5.10.12",
59
+ "@mui/material": "^5.10.13",
60
60
  "@types/pica": "^9.0.1",
61
61
  "@types/pulltorefreshjs": "^0.1.5",
62
62
  "@types/react": "^18.0.25",
@@ -83,14 +83,14 @@
83
83
  "@testing-library/jest-dom": "^5.16.5",
84
84
  "@testing-library/react": "^13.4.0",
85
85
  "@types/jest": "^29.2.2",
86
- "@typescript-eslint/eslint-plugin": "^5.42.0",
87
- "@typescript-eslint/parser": "^5.42.0",
88
- "eslint": "^8.26.0",
86
+ "@typescript-eslint/eslint-plugin": "^5.42.1",
87
+ "@typescript-eslint/parser": "^5.42.1",
88
+ "eslint": "^8.27.0",
89
89
  "eslint-config-airbnb-base": "^15.0.0",
90
90
  "eslint-plugin-import": "^2.26.0",
91
91
  "eslint-plugin-react": "^7.31.10",
92
- "jest": "^29.2.2",
93
- "jest-environment-jsdom": "^29.2.2",
92
+ "jest": "^29.3.0",
93
+ "jest-environment-jsdom": "^29.3.0",
94
94
  "ts-jest": "^29.0.3",
95
95
  "typescript": "^4.8.4"
96
96
  }
@@ -4,7 +4,7 @@ import {
4
4
  NotificationRenderProps,
5
5
  NotificationType
6
6
  } from '@etsoo/notificationbase';
7
- import { DataTypes } from '@etsoo/shared';
7
+ import { DataTypes, DomUtils } from '@etsoo/shared';
8
8
  import {
9
9
  Alert,
10
10
  AlertColor,
@@ -291,30 +291,19 @@ export class NotificationMU extends NotificationReact {
291
291
  if (inputs && value == null) value = event.currentTarget.form;
292
292
 
293
293
  if (input) {
294
- if (type === 'date') {
295
- const dateValue = input.valueAsDate;
296
- if (dateValue == null && input.required) {
297
- input.focus();
298
- return false;
299
- }
300
- result = this.onReturn(dateValue);
301
- } else if (type === 'number') {
302
- const numberValue = input.valueAsNumber;
303
- if (isNaN(numberValue) && input.required) {
304
- input.focus();
305
- return false;
306
- }
307
- result = this.onReturn(numberValue);
308
- } else if (type === 'switch') {
294
+ if (type === 'switch') {
309
295
  const boolValue = input.value === 'true';
310
296
  result = this.onReturn(boolValue);
311
297
  } else {
312
- const textValue = input.value.trim();
313
- if (textValue === '' && input.required) {
298
+ const inputValue = DomUtils.getInputValue(input);
299
+ if (
300
+ (inputValue == null || inputValue === '') &&
301
+ input.required
302
+ ) {
314
303
  input.focus();
315
304
  return false;
316
305
  }
317
- result = this.onReturn(textValue);
306
+ result = this.onReturn(inputValue);
318
307
  }
319
308
  } else if (value != null) {
320
309
  result = this.onReturn(value);
@@ -0,0 +1,119 @@
1
+ import { Input, InputAdornment } from '@mui/material';
2
+ import ArrowRightAltIcon from '@mui/icons-material/ArrowRightAlt';
3
+ import { useDimensions } from '@etsoo/react';
4
+ import React from 'react';
5
+ import { DomUtils } from '@etsoo/shared';
6
+ import { InputField, InputFieldProps } from './InputField';
7
+
8
+ type ValueType = string | number | Date | null | undefined;
9
+
10
+ /**
11
+ * TwoField Input props
12
+ */
13
+ export type TwoFieldInputProps = Omit<
14
+ InputFieldProps,
15
+ 'InputProps' | 'value'
16
+ > & {
17
+ /**
18
+ * Values
19
+ */
20
+ values?: unknown | [ValueType, ValueType];
21
+
22
+ /**
23
+ * On values change, return false to prevent further onChange handler
24
+ */
25
+ onValuesChange?: (
26
+ values: [ValueType, ValueType]
27
+ ) => boolean | void | Promise<boolean | void>;
28
+ };
29
+
30
+ /**
31
+ * TwoField Input
32
+ * @param props Props
33
+ * @returns Component
34
+ */
35
+ export function TwoFieldInput(props: TwoFieldInputProps) {
36
+ // Destruct
37
+ const {
38
+ name,
39
+ inputProps,
40
+ type = inputProps?.inputMode,
41
+ values,
42
+ onValuesChange,
43
+ onChange,
44
+ onInput,
45
+ ...rest
46
+ } = props;
47
+
48
+ // Local values
49
+ const localValues: [ValueType, ValueType] =
50
+ values == null
51
+ ? [null, null]
52
+ : Array.isArray(values)
53
+ ? (values as [ValueType, ValueType])
54
+ : [values as ValueType, null];
55
+
56
+ // Ref
57
+ const valueRef = React.useRef<[ValueType, ValueType]>(localValues);
58
+
59
+ // Watch container
60
+ const { dimensions } = useDimensions(
61
+ 1,
62
+ (target, rect) => {
63
+ const width = (rect.width - 64) / 2;
64
+ const inputs = target.querySelectorAll('input');
65
+ inputs[0].style.width = `${width}px`;
66
+ inputs[1].parentElement!.style.width = `${width}px`;
67
+ },
68
+ 0
69
+ );
70
+
71
+ // Handle change
72
+ const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
73
+ const value = DomUtils.getInputValue(event.target);
74
+ const index = event.target.name.endsWith('-start') ? 0 : 1;
75
+ valueRef.current[index] = value;
76
+
77
+ if (onValuesChange) {
78
+ if (onValuesChange(valueRef.current) === false) return;
79
+ }
80
+ if (onChange) onChange(event);
81
+ };
82
+
83
+ // Layout
84
+ return (
85
+ <InputField
86
+ name={`${name}-start`}
87
+ type={type}
88
+ defaultValue={localValues[0] ?? ''}
89
+ ref={dimensions[0][0]}
90
+ inputProps={inputProps}
91
+ InputProps={{
92
+ endAdornment: (
93
+ <InputAdornment
94
+ position="end"
95
+ sx={{
96
+ display: 'flex',
97
+ alignItems: 'center',
98
+ gap: 1
99
+ }}
100
+ >
101
+ <ArrowRightAltIcon />
102
+ <Input
103
+ type={type}
104
+ name={`${name}-end`}
105
+ defaultValue={localValues[1] ?? ''}
106
+ disableUnderline
107
+ onInput={onInput}
108
+ onChange={handleChange}
109
+ inputProps={inputProps}
110
+ />
111
+ </InputAdornment>
112
+ )
113
+ }}
114
+ onInput={onInput}
115
+ onChange={handleChange}
116
+ {...rest}
117
+ />
118
+ );
119
+ }
@@ -280,10 +280,11 @@ export class ReactApp<
280
280
  * @param callback Callback
281
281
  */
282
282
  override alertResult(
283
- result: IActionResult,
283
+ result: IActionResult | string,
284
284
  callback?: NotificationReturn<void>
285
285
  ) {
286
- const message = this.formatResult(result);
286
+ const message =
287
+ typeof result === 'string' ? result : this.formatResult(result);
287
288
  if (message.endsWith(')')) {
288
289
  const startPos = message.lastIndexOf('(');
289
290
  if (startPos > 0) {
@@ -305,7 +306,7 @@ export class ReactApp<
305
306
  return;
306
307
  }
307
308
  }
308
- this.notifier.alert(message, callback);
309
+ super.alertResult(message, callback);
309
310
  }
310
311
 
311
312
  /**
package/src/index.ts CHANGED
@@ -75,6 +75,7 @@ export * from './TabBox';
75
75
  export * from './TableEx';
76
76
  export * from './TextFieldEx';
77
77
  export * from './Tiplist';
78
+ export * from './TwoFieldInput';
78
79
  export * from './TooltipClick';
79
80
  export * from './UserAvatar';
80
81
  export * from './UserAvatarEditor';