@etsoo/materialui 1.6.57 → 1.6.59

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.
@@ -33,6 +33,11 @@ export type NumberInputFieldProps = Omit<InputFieldProps, "type" | "inputProps">
33
33
  * Step value
34
34
  */
35
35
  step?: number;
36
+ /**
37
+ * Number value change handler
38
+ * @param value New value
39
+ */
40
+ onNumberChange?: (value: number | undefined) => void;
36
41
  };
37
42
  /**
38
43
  * Number input field, for controlled only components, please see IntInputField and MoneyInputField
@@ -17,8 +17,21 @@ const InputAdornment_1 = __importDefault(require("@mui/material/InputAdornment")
17
17
  function NumberInputField(props) {
18
18
  const { currency, inputStyle, min = 0, step = 1, symbol = currency
19
19
  ? `${currency} ${shared_1.NumberUtils.getCurrencySymbol(currency)}`
20
- : undefined, endSymbol, max = 9999999, slotProps = {}, ...rest } = props;
21
- return ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { type: "number", slotProps: Object.assign(slotProps, {
20
+ : undefined, endSymbol, max = 9999999, onChange, onNumberChange, slotProps = {}, ...rest } = props;
21
+ return ((0, jsx_runtime_1.jsx)(InputField_1.InputField, { type: "number", onChange: (event) => {
22
+ onChange?.(event);
23
+ if (onNumberChange) {
24
+ const input = event.target;
25
+ if (input.checkValidity()) {
26
+ const qty = shared_1.NumberUtils.parse(input.value);
27
+ onNumberChange(qty);
28
+ }
29
+ else {
30
+ input.reportValidity();
31
+ onNumberChange(undefined);
32
+ }
33
+ }
34
+ }, slotProps: Object.assign(slotProps, {
22
35
  input: {
23
36
  startAdornment: symbol ? ((0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: (0, jsx_runtime_1.jsx)(InputAdornment_1.default, { position: "start", children: symbol }) })) : undefined,
24
37
  endAdornment: endSymbol ? ((0, jsx_runtime_1.jsx)(InputAdornment_1.default, { position: "end", children: endSymbol })) : undefined
@@ -130,6 +130,12 @@ function UserAvatarEditor(props) {
130
130
  const newState = { ...editorState, rotate };
131
131
  setEditorState(newState);
132
132
  };
133
+ let picaInstance;
134
+ // toBlob helper
135
+ // Convenience method, similar to canvas.toBlob(), but with promise interface & polyfill for old browsers.
136
+ const toBlob = (canvas, mimeType = type.current, quality = 1) => {
137
+ return picaInstance.toBlob(canvas, mimeType, quality);
138
+ };
133
139
  // Handle done
134
140
  const handleDone = async () => {
135
141
  // Data
@@ -139,13 +145,10 @@ function UserAvatarEditor(props) {
139
145
  if (data == null)
140
146
  return;
141
147
  // pica
142
- const pica = (await import("pica")).default;
143
- const picaInstance = pica();
144
- // toBlob helper
145
- // Convenience method, similar to canvas.toBlob(), but with promise interface & polyfill for old browsers.
146
- const toBlob = (canvas, mimeType = type.current, quality = 1) => {
147
- return picaInstance.toBlob(canvas, mimeType, quality);
148
- };
148
+ if (picaInstance == null) {
149
+ const pica = (await import("pica")).Pica;
150
+ picaInstance = new pica();
151
+ }
149
152
  if (data.width > maxWidthCalculated) {
150
153
  // Target height
151
154
  const heightCalculated = (localHeight * maxWidthCalculated) / width;
@@ -43,6 +43,14 @@ export type ResponsePageProps<T extends object, F> = Omit<DataGridPageProps<T, F
43
43
  * Row height
44
44
  */
45
45
  rowHeight?: ResponsibleContainerProps<T, F>["rowHeight"];
46
+ /**
47
+ * Header
48
+ */
49
+ header?: React.ReactNode;
50
+ /**
51
+ * Footer
52
+ */
53
+ footer?: React.ReactNode;
46
54
  };
47
55
  /**
48
56
  * Fixed height list page
@@ -17,14 +17,14 @@ const OperationMessageContainer_1 = require("../messages/OperationMessageContain
17
17
  */
18
18
  function ResponsivePage(props) {
19
19
  // Destruct
20
- const { pageProps = {}, operationMessageHandler, ...rest } = props;
20
+ const { pageProps = {}, operationMessageHandler, header, footer, ...rest } = props;
21
21
  pageProps.paddings ??= MUGlobal_1.MUGlobal.pagePaddings;
22
22
  const { paddings, fabColumnDirection, ...pageRest } = pageProps;
23
23
  // State
24
24
  const [scrollContainer, setScrollContainer] = react_1.default.useState();
25
25
  const [direction, setDirection] = react_1.default.useState(fabColumnDirection);
26
26
  // Layout
27
- return ((0, jsx_runtime_1.jsxs)(CommonPage_1.CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, fabColumnDirection: direction, children: [operationMessageHandler && ((0, jsx_runtime_1.jsx)(OperationMessageContainer_1.OperationMessageContainer, { handler: operationMessageHandler })), (0, jsx_runtime_1.jsx)(ResponsibleContainer_1.ResponsibleContainer, { paddings: paddings, containerBoxSx: (paddings, hasField, _dataGrid) => {
27
+ return ((0, jsx_runtime_1.jsxs)(CommonPage_1.CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, fabColumnDirection: direction, children: [operationMessageHandler && ((0, jsx_runtime_1.jsx)(OperationMessageContainer_1.OperationMessageContainer, { handler: operationMessageHandler })), header, (0, jsx_runtime_1.jsx)(ResponsibleContainer_1.ResponsibleContainer, { paddings: paddings, containerBoxSx: (paddings, hasField, _dataGrid) => {
28
28
  // Half
29
29
  const half = typeof paddings == "number"
30
30
  ? paddings / 2
@@ -49,5 +49,5 @@ function ResponsivePage(props) {
49
49
  }, elementReady: (element, isDataGrid) => {
50
50
  setDirection(!isDataGrid);
51
51
  setScrollContainer(element);
52
- }, ...rest })] }));
52
+ }, ...rest }), footer] }));
53
53
  }
@@ -33,6 +33,11 @@ export type NumberInputFieldProps = Omit<InputFieldProps, "type" | "inputProps">
33
33
  * Step value
34
34
  */
35
35
  step?: number;
36
+ /**
37
+ * Number value change handler
38
+ * @param value New value
39
+ */
40
+ onNumberChange?: (value: number | undefined) => void;
36
41
  };
37
42
  /**
38
43
  * Number input field, for controlled only components, please see IntInputField and MoneyInputField
@@ -11,8 +11,21 @@ import InputAdornment from "@mui/material/InputAdornment";
11
11
  export function NumberInputField(props) {
12
12
  const { currency, inputStyle, min = 0, step = 1, symbol = currency
13
13
  ? `${currency} ${NumberUtils.getCurrencySymbol(currency)}`
14
- : undefined, endSymbol, max = 9999999, slotProps = {}, ...rest } = props;
15
- return (_jsx(InputField, { type: "number", slotProps: Object.assign(slotProps, {
14
+ : undefined, endSymbol, max = 9999999, onChange, onNumberChange, slotProps = {}, ...rest } = props;
15
+ return (_jsx(InputField, { type: "number", onChange: (event) => {
16
+ onChange?.(event);
17
+ if (onNumberChange) {
18
+ const input = event.target;
19
+ if (input.checkValidity()) {
20
+ const qty = NumberUtils.parse(input.value);
21
+ onNumberChange(qty);
22
+ }
23
+ else {
24
+ input.reportValidity();
25
+ onNumberChange(undefined);
26
+ }
27
+ }
28
+ }, slotProps: Object.assign(slotProps, {
16
29
  input: {
17
30
  startAdornment: symbol ? (_jsx(React.Fragment, { children: _jsx(InputAdornment, { position: "start", children: symbol }) })) : undefined,
18
31
  endAdornment: endSymbol ? (_jsx(InputAdornment, { position: "end", children: endSymbol })) : undefined
@@ -124,6 +124,12 @@ export function UserAvatarEditor(props) {
124
124
  const newState = { ...editorState, rotate };
125
125
  setEditorState(newState);
126
126
  };
127
+ let picaInstance;
128
+ // toBlob helper
129
+ // Convenience method, similar to canvas.toBlob(), but with promise interface & polyfill for old browsers.
130
+ const toBlob = (canvas, mimeType = type.current, quality = 1) => {
131
+ return picaInstance.toBlob(canvas, mimeType, quality);
132
+ };
127
133
  // Handle done
128
134
  const handleDone = async () => {
129
135
  // Data
@@ -133,13 +139,10 @@ export function UserAvatarEditor(props) {
133
139
  if (data == null)
134
140
  return;
135
141
  // pica
136
- const pica = (await import("pica")).default;
137
- const picaInstance = pica();
138
- // toBlob helper
139
- // Convenience method, similar to canvas.toBlob(), but with promise interface & polyfill for old browsers.
140
- const toBlob = (canvas, mimeType = type.current, quality = 1) => {
141
- return picaInstance.toBlob(canvas, mimeType, quality);
142
- };
142
+ if (picaInstance == null) {
143
+ const pica = (await import("pica")).Pica;
144
+ picaInstance = new pica();
145
+ }
143
146
  if (data.width > maxWidthCalculated) {
144
147
  // Target height
145
148
  const heightCalculated = (localHeight * maxWidthCalculated) / width;
@@ -43,6 +43,14 @@ export type ResponsePageProps<T extends object, F> = Omit<DataGridPageProps<T, F
43
43
  * Row height
44
44
  */
45
45
  rowHeight?: ResponsibleContainerProps<T, F>["rowHeight"];
46
+ /**
47
+ * Header
48
+ */
49
+ header?: React.ReactNode;
50
+ /**
51
+ * Footer
52
+ */
53
+ footer?: React.ReactNode;
46
54
  };
47
55
  /**
48
56
  * Fixed height list page
@@ -11,14 +11,14 @@ import { OperationMessageContainer } from "../messages/OperationMessageContainer
11
11
  */
12
12
  export function ResponsivePage(props) {
13
13
  // Destruct
14
- const { pageProps = {}, operationMessageHandler, ...rest } = props;
14
+ const { pageProps = {}, operationMessageHandler, header, footer, ...rest } = props;
15
15
  pageProps.paddings ??= MUGlobal.pagePaddings;
16
16
  const { paddings, fabColumnDirection, ...pageRest } = pageProps;
17
17
  // State
18
18
  const [scrollContainer, setScrollContainer] = React.useState();
19
19
  const [direction, setDirection] = React.useState(fabColumnDirection);
20
20
  // Layout
21
- return (_jsxs(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, fabColumnDirection: direction, children: [operationMessageHandler && (_jsx(OperationMessageContainer, { handler: operationMessageHandler })), _jsx(ResponsibleContainer, { paddings: paddings, containerBoxSx: (paddings, hasField, _dataGrid) => {
21
+ return (_jsxs(CommonPage, { ...pageRest, paddings: {}, scrollContainer: scrollContainer, fabColumnDirection: direction, children: [operationMessageHandler && (_jsx(OperationMessageContainer, { handler: operationMessageHandler })), header, _jsx(ResponsibleContainer, { paddings: paddings, containerBoxSx: (paddings, hasField, _dataGrid) => {
22
22
  // Half
23
23
  const half = typeof paddings == "number"
24
24
  ? paddings / 2
@@ -43,5 +43,5 @@ export function ResponsivePage(props) {
43
43
  }, elementReady: (element, isDataGrid) => {
44
44
  setDirection(!isDataGrid);
45
45
  setScrollContainer(element);
46
- }, ...rest })] }));
46
+ }, ...rest }), footer] }));
47
47
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.6.57",
3
+ "version": "1.6.59",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -49,9 +49,9 @@
49
49
  "@mui/x-data-grid": "^9.1.0",
50
50
  "chart.js": "^4.5.1",
51
51
  "chartjs-plugin-datalabels": "^2.2.0",
52
- "dompurify": "^3.4.3",
52
+ "dompurify": "^3.4.5",
53
53
  "eventemitter3": "^5.0.4",
54
- "pica": "^9.0.1",
54
+ "pica": "^10.0.1",
55
55
  "pulltorefreshjs": "^0.1.22",
56
56
  "react": "^19.2.6",
57
57
  "react-avatar-editor": "^15.1.0",
@@ -46,6 +46,12 @@ export type NumberInputFieldProps = Omit<
46
46
  * Step value
47
47
  */
48
48
  step?: number;
49
+
50
+ /**
51
+ * Number value change handler
52
+ * @param value New value
53
+ */
54
+ onNumberChange?: (value: number | undefined) => void;
49
55
  };
50
56
 
51
57
  /**
@@ -64,6 +70,8 @@ export function NumberInputField(props: NumberInputFieldProps) {
64
70
  : undefined,
65
71
  endSymbol,
66
72
  max = 9999999,
73
+ onChange,
74
+ onNumberChange,
67
75
  slotProps = {},
68
76
  ...rest
69
77
  } = props;
@@ -71,6 +79,20 @@ export function NumberInputField(props: NumberInputFieldProps) {
71
79
  return (
72
80
  <InputField
73
81
  type="number"
82
+ onChange={(event) => {
83
+ onChange?.(event);
84
+
85
+ if (onNumberChange) {
86
+ const input = event.target;
87
+ if (input.checkValidity()) {
88
+ const qty = NumberUtils.parse(input.value);
89
+ onNumberChange(qty);
90
+ } else {
91
+ input.reportValidity();
92
+ onNumberChange(undefined);
93
+ }
94
+ }
95
+ }}
74
96
  slotProps={Object.assign(slotProps, {
75
97
  input: {
76
98
  startAdornment: symbol ? (
@@ -251,6 +251,18 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
251
251
  setEditorState(newState);
252
252
  };
253
253
 
254
+ let picaInstance: any;
255
+
256
+ // toBlob helper
257
+ // Convenience method, similar to canvas.toBlob(), but with promise interface & polyfill for old browsers.
258
+ const toBlob = (
259
+ canvas: HTMLCanvasElement,
260
+ mimeType: string = type.current,
261
+ quality: number = 1
262
+ ) => {
263
+ return picaInstance.toBlob(canvas, mimeType, quality);
264
+ };
265
+
254
266
  // Handle done
255
267
  const handleDone = async () => {
256
268
  // Data
@@ -260,18 +272,10 @@ export function UserAvatarEditor(props: UserAvatarEditorProps) {
260
272
  if (data == null) return;
261
273
 
262
274
  // pica
263
- const pica = (await import("pica")).default;
264
- const picaInstance = pica();
265
-
266
- // toBlob helper
267
- // Convenience method, similar to canvas.toBlob(), but with promise interface & polyfill for old browsers.
268
- const toBlob = (
269
- canvas: HTMLCanvasElement,
270
- mimeType: string = type.current,
271
- quality: number = 1
272
- ) => {
273
- return picaInstance.toBlob(canvas, mimeType, quality);
274
- };
275
+ if (picaInstance == null) {
276
+ const pica = (await import("pica")).Pica;
277
+ picaInstance = new pica();
278
+ }
275
279
 
276
280
  if (data.width > maxWidthCalculated) {
277
281
  // Target height
@@ -60,6 +60,16 @@ export type ResponsePageProps<T extends object, F> = Omit<
60
60
  * Row height
61
61
  */
62
62
  rowHeight?: ResponsibleContainerProps<T, F>["rowHeight"];
63
+
64
+ /**
65
+ * Header
66
+ */
67
+ header?: React.ReactNode;
68
+
69
+ /**
70
+ * Footer
71
+ */
72
+ footer?: React.ReactNode;
63
73
  };
64
74
 
65
75
  /**
@@ -71,7 +81,13 @@ export function ResponsivePage<T extends object, F>(
71
81
  props: ResponsePageProps<T, F>
72
82
  ) {
73
83
  // Destruct
74
- const { pageProps = {}, operationMessageHandler, ...rest } = props;
84
+ const {
85
+ pageProps = {},
86
+ operationMessageHandler,
87
+ header,
88
+ footer,
89
+ ...rest
90
+ } = props;
75
91
 
76
92
  pageProps.paddings ??= MUGlobal.pagePaddings;
77
93
  const { paddings, fabColumnDirection, ...pageRest } = pageProps;
@@ -91,6 +107,7 @@ export function ResponsivePage<T extends object, F>(
91
107
  {operationMessageHandler && (
92
108
  <OperationMessageContainer handler={operationMessageHandler} />
93
109
  )}
110
+ {header}
94
111
  <ResponsibleContainer<T, F>
95
112
  paddings={paddings}
96
113
  containerBoxSx={(paddings, hasField, _dataGrid) => {
@@ -124,6 +141,7 @@ export function ResponsivePage<T extends object, F>(
124
141
  }}
125
142
  {...rest}
126
143
  />
144
+ {footer}
127
145
  </CommonPage>
128
146
  );
129
147
  }