@etsoo/materialui 1.6.27 → 1.6.29

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.
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
3
+ /**
4
+ * Number field component
5
+ */
6
+ export declare function NumberField({ id: idProp, label, error, size, ...other }: BaseNumberField.Root.Props & {
7
+ label?: React.ReactNode;
8
+ size?: "small" | "medium";
9
+ error?: boolean;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.NumberField = NumberField;
40
+ const jsx_runtime_1 = require("react/jsx-runtime");
41
+ const React = __importStar(require("react"));
42
+ const number_field_1 = require("@base-ui/react/number-field");
43
+ const IconButton_1 = __importDefault(require("@mui/material/IconButton"));
44
+ const FormControl_1 = __importDefault(require("@mui/material/FormControl"));
45
+ const FormHelperText_1 = __importDefault(require("@mui/material/FormHelperText"));
46
+ const OutlinedInput_1 = __importDefault(require("@mui/material/OutlinedInput"));
47
+ const InputAdornment_1 = __importDefault(require("@mui/material/InputAdornment"));
48
+ const InputLabel_1 = __importDefault(require("@mui/material/InputLabel"));
49
+ const KeyboardArrowUp_1 = __importDefault(require("@mui/icons-material/KeyboardArrowUp"));
50
+ const KeyboardArrowDown_1 = __importDefault(require("@mui/icons-material/KeyboardArrowDown"));
51
+ /**
52
+ * This component is a placeholder for FormControl to correctly set the shrink label state on SSR.
53
+ */
54
+ function SSRInitialFilled(_) {
55
+ return null;
56
+ }
57
+ SSRInitialFilled.muiName = "Input";
58
+ /**
59
+ * Number field component
60
+ */
61
+ function NumberField({ id: idProp, label, error, size = "medium", ...other }) {
62
+ let id = React.useId();
63
+ if (idProp) {
64
+ id = idProp;
65
+ }
66
+ return ((0, jsx_runtime_1.jsxs)(number_field_1.NumberField.Root, { ...other, render: (props, state) => ((0, jsx_runtime_1.jsx)(FormControl_1.default, { size: size, ref: props.ref, disabled: state.disabled, required: state.required, error: error, variant: "outlined", children: props.children })), children: [(0, jsx_runtime_1.jsx)(SSRInitialFilled, { ...other }), (0, jsx_runtime_1.jsx)(InputLabel_1.default, { htmlFor: id, children: label }), (0, jsx_runtime_1.jsx)(number_field_1.NumberField.Input, { id: id, render: (props, state) => ((0, jsx_runtime_1.jsx)(OutlinedInput_1.default, { label: label, inputRef: props.ref, value: state.inputValue, onBlur: props.onBlur, onChange: props.onChange, onKeyUp: props.onKeyUp, onKeyDown: props.onKeyDown, onFocus: props.onFocus, slotProps: {
67
+ input: props
68
+ }, endAdornment: (0, jsx_runtime_1.jsxs)(InputAdornment_1.default, { position: "end", sx: {
69
+ flexDirection: "column",
70
+ maxHeight: "unset",
71
+ alignSelf: "stretch",
72
+ borderLeft: "1px solid",
73
+ borderColor: "divider",
74
+ ml: 0,
75
+ "& button": {
76
+ py: 0,
77
+ flex: 1,
78
+ borderRadius: 0.5
79
+ }
80
+ }, children: [(0, jsx_runtime_1.jsx)(number_field_1.NumberField.Increment, { render: (0, jsx_runtime_1.jsx)(IconButton_1.default, { size: size, "aria-label": "Increase" }), children: (0, jsx_runtime_1.jsx)(KeyboardArrowUp_1.default, { fontSize: size, sx: { transform: "translateY(2px)" } }) }), (0, jsx_runtime_1.jsx)(number_field_1.NumberField.Decrement, { render: (0, jsx_runtime_1.jsx)(IconButton_1.default, { size: size, "aria-label": "Decrease" }), children: (0, jsx_runtime_1.jsx)(KeyboardArrowDown_1.default, { fontSize: size, sx: { transform: "translateY(-2px)" } }) })] }), sx: { pr: 0 } })) }), (0, jsx_runtime_1.jsx)(FormHelperText_1.default, { sx: { ml: 0, "&:empty": { mt: 0 } }, children: "Enter value between 10 and 40" })] }));
81
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
3
+ /**
4
+ * Number spinner component
5
+ */
6
+ export declare function NumberSpinner({ id: idProp, label, error, size, ...other }: BaseNumberField.Root.Props & {
7
+ label?: React.ReactNode;
8
+ size?: "small" | "medium";
9
+ error?: boolean;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.NumberSpinner = NumberSpinner;
40
+ const jsx_runtime_1 = require("react/jsx-runtime");
41
+ const React = __importStar(require("react"));
42
+ const number_field_1 = require("@base-ui/react/number-field");
43
+ const Box_1 = __importDefault(require("@mui/material/Box"));
44
+ const Button_1 = __importDefault(require("@mui/material/Button"));
45
+ const FormControl_1 = __importDefault(require("@mui/material/FormControl"));
46
+ const FormLabel_1 = __importDefault(require("@mui/material/FormLabel"));
47
+ const Add_1 = __importDefault(require("@mui/icons-material/Add"));
48
+ const Remove_1 = __importDefault(require("@mui/icons-material/Remove"));
49
+ const OutlinedInput_1 = __importDefault(require("@mui/material/OutlinedInput"));
50
+ const OpenInFull_1 = __importDefault(require("@mui/icons-material/OpenInFull"));
51
+ /**
52
+ * Number spinner component
53
+ */
54
+ function NumberSpinner({ id: idProp, label, error, size = "medium", ...other }) {
55
+ let id = React.useId();
56
+ if (idProp) {
57
+ id = idProp;
58
+ }
59
+ return ((0, jsx_runtime_1.jsxs)(number_field_1.NumberField.Root, { ...other, render: (props, state) => ((0, jsx_runtime_1.jsx)(FormControl_1.default, { size: size, ref: props.ref, disabled: state.disabled, required: state.required, error: error, variant: "outlined", sx: {
60
+ "& .MuiButton-root": {
61
+ borderColor: "divider",
62
+ minWidth: 0,
63
+ bgcolor: "action.hover",
64
+ "&:not(.Mui-disabled)": {
65
+ color: "text.primary"
66
+ }
67
+ }
68
+ }, children: props.children })), children: [(0, jsx_runtime_1.jsxs)(number_field_1.NumberField.ScrubArea, { render: (0, jsx_runtime_1.jsx)(Box_1.default, { component: "span", sx: { userSelect: "none", width: "max-content" } }), children: [(0, jsx_runtime_1.jsx)(FormLabel_1.default, { htmlFor: id, sx: {
69
+ display: "inline-block",
70
+ cursor: "ew-resize",
71
+ fontSize: "0.875rem",
72
+ color: "text.primary",
73
+ fontWeight: 500,
74
+ lineHeight: 1.5,
75
+ mb: 0.5
76
+ }, children: label }), (0, jsx_runtime_1.jsx)(number_field_1.NumberField.ScrubAreaCursor, { children: (0, jsx_runtime_1.jsx)(OpenInFull_1.default, { fontSize: "small", sx: { transform: "translateY(12.5%) rotate(45deg)" } }) })] }), (0, jsx_runtime_1.jsxs)(Box_1.default, { sx: { display: "flex" }, children: [(0, jsx_runtime_1.jsx)(number_field_1.NumberField.Decrement, { render: (0, jsx_runtime_1.jsx)(Button_1.default, { variant: "outlined", "aria-label": "Decrease", size: size, sx: {
77
+ borderTopRightRadius: 0,
78
+ borderBottomRightRadius: 0,
79
+ borderRight: "0px",
80
+ "&.Mui-disabled": {
81
+ borderRight: "0px"
82
+ }
83
+ } }), children: (0, jsx_runtime_1.jsx)(Remove_1.default, { fontSize: size }) }), (0, jsx_runtime_1.jsx)(number_field_1.NumberField.Input, { id: id, render: (props, state) => ((0, jsx_runtime_1.jsx)(OutlinedInput_1.default, { inputRef: props.ref, value: state.inputValue, onBlur: props.onBlur, onChange: props.onChange, onKeyUp: props.onKeyUp, onKeyDown: props.onKeyDown, onFocus: props.onFocus, slotProps: {
84
+ input: {
85
+ ...props,
86
+ size: Math.max((other.min?.toString() || "").length, state.inputValue.length || 1) + 1,
87
+ sx: {
88
+ textAlign: "center"
89
+ }
90
+ }
91
+ }, sx: { pr: 0, borderRadius: 0, flex: 1 } })) }), (0, jsx_runtime_1.jsx)(number_field_1.NumberField.Increment, { render: (0, jsx_runtime_1.jsx)(Button_1.default, { variant: "outlined", "aria-label": "Increase", size: size, sx: {
92
+ borderTopLeftRadius: 0,
93
+ borderBottomLeftRadius: 0,
94
+ borderLeft: "0px",
95
+ "&.Mui-disabled": {
96
+ borderLeft: "0px"
97
+ }
98
+ } }), children: (0, jsx_runtime_1.jsx)(Add_1.default, { fontSize: size }) })] })] }));
99
+ }
@@ -94,7 +94,9 @@ export * from "./MUGlobal";
94
94
  export * from "./MUUtils";
95
95
  export * from "./NotifierMU";
96
96
  export * from "./NotifierPopupProps";
97
+ export * from "./NumberField";
97
98
  export * from "./NumberInputField";
99
+ export * from "./NumberSpinner";
98
100
  export * from "./OptionBool";
99
101
  export * from "./OptionGroup";
100
102
  export * from "./OptionGroupFlag";
package/lib/cjs/index.js CHANGED
@@ -110,7 +110,9 @@ __exportStar(require("./MUGlobal"), exports);
110
110
  __exportStar(require("./MUUtils"), exports);
111
111
  __exportStar(require("./NotifierMU"), exports);
112
112
  __exportStar(require("./NotifierPopupProps"), exports);
113
+ __exportStar(require("./NumberField"), exports);
113
114
  __exportStar(require("./NumberInputField"), exports);
115
+ __exportStar(require("./NumberSpinner"), exports);
114
116
  __exportStar(require("./OptionBool"), exports);
115
117
  __exportStar(require("./OptionGroup"), exports);
116
118
  __exportStar(require("./OptionGroupFlag"), exports);
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
3
+ /**
4
+ * Number field component
5
+ */
6
+ export declare function NumberField({ id: idProp, label, error, size, ...other }: BaseNumberField.Root.Props & {
7
+ label?: React.ReactNode;
8
+ size?: "small" | "medium";
9
+ error?: boolean;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,42 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
4
+ import IconButton from "@mui/material/IconButton";
5
+ import FormControl from "@mui/material/FormControl";
6
+ import FormHelperText from "@mui/material/FormHelperText";
7
+ import OutlinedInput from "@mui/material/OutlinedInput";
8
+ import InputAdornment from "@mui/material/InputAdornment";
9
+ import InputLabel from "@mui/material/InputLabel";
10
+ import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
11
+ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
12
+ /**
13
+ * This component is a placeholder for FormControl to correctly set the shrink label state on SSR.
14
+ */
15
+ function SSRInitialFilled(_) {
16
+ return null;
17
+ }
18
+ SSRInitialFilled.muiName = "Input";
19
+ /**
20
+ * Number field component
21
+ */
22
+ export function NumberField({ id: idProp, label, error, size = "medium", ...other }) {
23
+ let id = React.useId();
24
+ if (idProp) {
25
+ id = idProp;
26
+ }
27
+ return (_jsxs(BaseNumberField.Root, { ...other, render: (props, state) => (_jsx(FormControl, { size: size, ref: props.ref, disabled: state.disabled, required: state.required, error: error, variant: "outlined", children: props.children })), children: [_jsx(SSRInitialFilled, { ...other }), _jsx(InputLabel, { htmlFor: id, children: label }), _jsx(BaseNumberField.Input, { id: id, render: (props, state) => (_jsx(OutlinedInput, { label: label, inputRef: props.ref, value: state.inputValue, onBlur: props.onBlur, onChange: props.onChange, onKeyUp: props.onKeyUp, onKeyDown: props.onKeyDown, onFocus: props.onFocus, slotProps: {
28
+ input: props
29
+ }, endAdornment: _jsxs(InputAdornment, { position: "end", sx: {
30
+ flexDirection: "column",
31
+ maxHeight: "unset",
32
+ alignSelf: "stretch",
33
+ borderLeft: "1px solid",
34
+ borderColor: "divider",
35
+ ml: 0,
36
+ "& button": {
37
+ py: 0,
38
+ flex: 1,
39
+ borderRadius: 0.5
40
+ }
41
+ }, children: [_jsx(BaseNumberField.Increment, { render: _jsx(IconButton, { size: size, "aria-label": "Increase" }), children: _jsx(KeyboardArrowUpIcon, { fontSize: size, sx: { transform: "translateY(2px)" } }) }), _jsx(BaseNumberField.Decrement, { render: _jsx(IconButton, { size: size, "aria-label": "Decrease" }), children: _jsx(KeyboardArrowDownIcon, { fontSize: size, sx: { transform: "translateY(-2px)" } }) })] }), sx: { pr: 0 } })) }), _jsx(FormHelperText, { sx: { ml: 0, "&:empty": { mt: 0 } }, children: "Enter value between 10 and 40" })] }));
42
+ }
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
3
+ /**
4
+ * Number spinner component
5
+ */
6
+ export declare function NumberSpinner({ id: idProp, label, error, size, ...other }: BaseNumberField.Root.Props & {
7
+ label?: React.ReactNode;
8
+ size?: "small" | "medium";
9
+ error?: boolean;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,60 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
4
+ import Box from "@mui/material/Box";
5
+ import Button from "@mui/material/Button";
6
+ import FormControl from "@mui/material/FormControl";
7
+ import FormLabel from "@mui/material/FormLabel";
8
+ import AddIcon from "@mui/icons-material/Add";
9
+ import RemoveIcon from "@mui/icons-material/Remove";
10
+ import OutlinedInput from "@mui/material/OutlinedInput";
11
+ import OpenInFullIcon from "@mui/icons-material/OpenInFull";
12
+ /**
13
+ * Number spinner component
14
+ */
15
+ export function NumberSpinner({ id: idProp, label, error, size = "medium", ...other }) {
16
+ let id = React.useId();
17
+ if (idProp) {
18
+ id = idProp;
19
+ }
20
+ return (_jsxs(BaseNumberField.Root, { ...other, render: (props, state) => (_jsx(FormControl, { size: size, ref: props.ref, disabled: state.disabled, required: state.required, error: error, variant: "outlined", sx: {
21
+ "& .MuiButton-root": {
22
+ borderColor: "divider",
23
+ minWidth: 0,
24
+ bgcolor: "action.hover",
25
+ "&:not(.Mui-disabled)": {
26
+ color: "text.primary"
27
+ }
28
+ }
29
+ }, children: props.children })), children: [_jsxs(BaseNumberField.ScrubArea, { render: _jsx(Box, { component: "span", sx: { userSelect: "none", width: "max-content" } }), children: [_jsx(FormLabel, { htmlFor: id, sx: {
30
+ display: "inline-block",
31
+ cursor: "ew-resize",
32
+ fontSize: "0.875rem",
33
+ color: "text.primary",
34
+ fontWeight: 500,
35
+ lineHeight: 1.5,
36
+ mb: 0.5
37
+ }, children: label }), _jsx(BaseNumberField.ScrubAreaCursor, { children: _jsx(OpenInFullIcon, { fontSize: "small", sx: { transform: "translateY(12.5%) rotate(45deg)" } }) })] }), _jsxs(Box, { sx: { display: "flex" }, children: [_jsx(BaseNumberField.Decrement, { render: _jsx(Button, { variant: "outlined", "aria-label": "Decrease", size: size, sx: {
38
+ borderTopRightRadius: 0,
39
+ borderBottomRightRadius: 0,
40
+ borderRight: "0px",
41
+ "&.Mui-disabled": {
42
+ borderRight: "0px"
43
+ }
44
+ } }), children: _jsx(RemoveIcon, { fontSize: size }) }), _jsx(BaseNumberField.Input, { id: id, render: (props, state) => (_jsx(OutlinedInput, { inputRef: props.ref, value: state.inputValue, onBlur: props.onBlur, onChange: props.onChange, onKeyUp: props.onKeyUp, onKeyDown: props.onKeyDown, onFocus: props.onFocus, slotProps: {
45
+ input: {
46
+ ...props,
47
+ size: Math.max((other.min?.toString() || "").length, state.inputValue.length || 1) + 1,
48
+ sx: {
49
+ textAlign: "center"
50
+ }
51
+ }
52
+ }, sx: { pr: 0, borderRadius: 0, flex: 1 } })) }), _jsx(BaseNumberField.Increment, { render: _jsx(Button, { variant: "outlined", "aria-label": "Increase", size: size, sx: {
53
+ borderTopLeftRadius: 0,
54
+ borderBottomLeftRadius: 0,
55
+ borderLeft: "0px",
56
+ "&.Mui-disabled": {
57
+ borderLeft: "0px"
58
+ }
59
+ } }), children: _jsx(AddIcon, { fontSize: size }) })] })] }));
60
+ }
@@ -94,7 +94,9 @@ export * from "./MUGlobal";
94
94
  export * from "./MUUtils";
95
95
  export * from "./NotifierMU";
96
96
  export * from "./NotifierPopupProps";
97
+ export * from "./NumberField";
97
98
  export * from "./NumberInputField";
99
+ export * from "./NumberSpinner";
98
100
  export * from "./OptionBool";
99
101
  export * from "./OptionGroup";
100
102
  export * from "./OptionGroupFlag";
package/lib/mjs/index.js CHANGED
@@ -94,7 +94,9 @@ export * from "./MUGlobal";
94
94
  export * from "./MUUtils";
95
95
  export * from "./NotifierMU";
96
96
  export * from "./NotifierPopupProps";
97
+ export * from "./NumberField";
97
98
  export * from "./NumberInputField";
99
+ export * from "./NumberSpinner";
98
100
  export * from "./OptionBool";
99
101
  export * from "./OptionGroup";
100
102
  export * from "./OptionGroupFlag";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@etsoo/materialui",
3
- "version": "1.6.27",
3
+ "version": "1.6.29",
4
4
  "description": "TypeScript Material-UI Implementation",
5
5
  "main": "lib/cjs/index.js",
6
6
  "module": "lib/mjs/index.js",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "homepage": "https://github.com/ETSOO/ReactMU#readme",
38
38
  "dependencies": {
39
+ "@base-ui/react": "^1.2.0",
39
40
  "@dnd-kit/react": "^0.3.2",
40
41
  "@emotion/react": "^11.14.0",
41
42
  "@emotion/styled": "^11.14.1",
@@ -0,0 +1,116 @@
1
+ import * as React from "react";
2
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
3
+ import IconButton from "@mui/material/IconButton";
4
+ import FormControl from "@mui/material/FormControl";
5
+ import FormHelperText from "@mui/material/FormHelperText";
6
+ import OutlinedInput from "@mui/material/OutlinedInput";
7
+ import InputAdornment from "@mui/material/InputAdornment";
8
+ import InputLabel from "@mui/material/InputLabel";
9
+ import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
10
+ import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
11
+
12
+ /**
13
+ * This component is a placeholder for FormControl to correctly set the shrink label state on SSR.
14
+ */
15
+ function SSRInitialFilled(_: BaseNumberField.Root.Props) {
16
+ return null;
17
+ }
18
+ SSRInitialFilled.muiName = "Input";
19
+
20
+ /**
21
+ * Number field component
22
+ */
23
+ export function NumberField({
24
+ id: idProp,
25
+ label,
26
+ error,
27
+ size = "medium",
28
+ ...other
29
+ }: BaseNumberField.Root.Props & {
30
+ label?: React.ReactNode;
31
+ size?: "small" | "medium";
32
+ error?: boolean;
33
+ }) {
34
+ let id = React.useId();
35
+ if (idProp) {
36
+ id = idProp;
37
+ }
38
+ return (
39
+ <BaseNumberField.Root
40
+ {...other}
41
+ render={(props, state) => (
42
+ <FormControl
43
+ size={size}
44
+ ref={props.ref}
45
+ disabled={state.disabled}
46
+ required={state.required}
47
+ error={error}
48
+ variant="outlined"
49
+ >
50
+ {props.children}
51
+ </FormControl>
52
+ )}
53
+ >
54
+ <SSRInitialFilled {...other} />
55
+ <InputLabel htmlFor={id}>{label}</InputLabel>
56
+ <BaseNumberField.Input
57
+ id={id}
58
+ render={(props, state) => (
59
+ <OutlinedInput
60
+ label={label}
61
+ inputRef={props.ref}
62
+ value={state.inputValue}
63
+ onBlur={props.onBlur}
64
+ onChange={props.onChange}
65
+ onKeyUp={props.onKeyUp}
66
+ onKeyDown={props.onKeyDown}
67
+ onFocus={props.onFocus}
68
+ slotProps={{
69
+ input: props
70
+ }}
71
+ endAdornment={
72
+ <InputAdornment
73
+ position="end"
74
+ sx={{
75
+ flexDirection: "column",
76
+ maxHeight: "unset",
77
+ alignSelf: "stretch",
78
+ borderLeft: "1px solid",
79
+ borderColor: "divider",
80
+ ml: 0,
81
+ "& button": {
82
+ py: 0,
83
+ flex: 1,
84
+ borderRadius: 0.5
85
+ }
86
+ }}
87
+ >
88
+ <BaseNumberField.Increment
89
+ render={<IconButton size={size} aria-label="Increase" />}
90
+ >
91
+ <KeyboardArrowUpIcon
92
+ fontSize={size}
93
+ sx={{ transform: "translateY(2px)" }}
94
+ />
95
+ </BaseNumberField.Increment>
96
+
97
+ <BaseNumberField.Decrement
98
+ render={<IconButton size={size} aria-label="Decrease" />}
99
+ >
100
+ <KeyboardArrowDownIcon
101
+ fontSize={size}
102
+ sx={{ transform: "translateY(-2px)" }}
103
+ />
104
+ </BaseNumberField.Decrement>
105
+ </InputAdornment>
106
+ }
107
+ sx={{ pr: 0 }}
108
+ />
109
+ )}
110
+ />
111
+ <FormHelperText sx={{ ml: 0, "&:empty": { mt: 0 } }}>
112
+ Enter value between 10 and 40
113
+ </FormHelperText>
114
+ </BaseNumberField.Root>
115
+ );
116
+ }
@@ -0,0 +1,157 @@
1
+ import * as React from "react";
2
+ import { NumberField as BaseNumberField } from "@base-ui/react/number-field";
3
+ import Box from "@mui/material/Box";
4
+ import Button from "@mui/material/Button";
5
+ import FormControl from "@mui/material/FormControl";
6
+ import FormLabel from "@mui/material/FormLabel";
7
+ import AddIcon from "@mui/icons-material/Add";
8
+ import RemoveIcon from "@mui/icons-material/Remove";
9
+ import OutlinedInput from "@mui/material/OutlinedInput";
10
+ import OpenInFullIcon from "@mui/icons-material/OpenInFull";
11
+
12
+ /**
13
+ * Number spinner component
14
+ */
15
+ export function NumberSpinner({
16
+ id: idProp,
17
+ label,
18
+ error,
19
+ size = "medium",
20
+ ...other
21
+ }: BaseNumberField.Root.Props & {
22
+ label?: React.ReactNode;
23
+ size?: "small" | "medium";
24
+ error?: boolean;
25
+ }) {
26
+ let id = React.useId();
27
+ if (idProp) {
28
+ id = idProp;
29
+ }
30
+ return (
31
+ <BaseNumberField.Root
32
+ {...other}
33
+ render={(props, state) => (
34
+ <FormControl
35
+ size={size}
36
+ ref={props.ref}
37
+ disabled={state.disabled}
38
+ required={state.required}
39
+ error={error}
40
+ variant="outlined"
41
+ sx={{
42
+ "& .MuiButton-root": {
43
+ borderColor: "divider",
44
+ minWidth: 0,
45
+ bgcolor: "action.hover",
46
+ "&:not(.Mui-disabled)": {
47
+ color: "text.primary"
48
+ }
49
+ }
50
+ }}
51
+ >
52
+ {props.children}
53
+ </FormControl>
54
+ )}
55
+ >
56
+ <BaseNumberField.ScrubArea
57
+ render={
58
+ <Box
59
+ component="span"
60
+ sx={{ userSelect: "none", width: "max-content" }}
61
+ />
62
+ }
63
+ >
64
+ <FormLabel
65
+ htmlFor={id}
66
+ sx={{
67
+ display: "inline-block",
68
+ cursor: "ew-resize",
69
+ fontSize: "0.875rem",
70
+ color: "text.primary",
71
+ fontWeight: 500,
72
+ lineHeight: 1.5,
73
+ mb: 0.5
74
+ }}
75
+ >
76
+ {label}
77
+ </FormLabel>
78
+ <BaseNumberField.ScrubAreaCursor>
79
+ <OpenInFullIcon
80
+ fontSize="small"
81
+ sx={{ transform: "translateY(12.5%) rotate(45deg)" }}
82
+ />
83
+ </BaseNumberField.ScrubAreaCursor>
84
+ </BaseNumberField.ScrubArea>
85
+ <Box sx={{ display: "flex" }}>
86
+ <BaseNumberField.Decrement
87
+ render={
88
+ <Button
89
+ variant="outlined"
90
+ aria-label="Decrease"
91
+ size={size}
92
+ sx={{
93
+ borderTopRightRadius: 0,
94
+ borderBottomRightRadius: 0,
95
+ borderRight: "0px",
96
+ "&.Mui-disabled": {
97
+ borderRight: "0px"
98
+ }
99
+ }}
100
+ />
101
+ }
102
+ >
103
+ <RemoveIcon fontSize={size} />
104
+ </BaseNumberField.Decrement>
105
+
106
+ <BaseNumberField.Input
107
+ id={id}
108
+ render={(props, state) => (
109
+ <OutlinedInput
110
+ inputRef={props.ref}
111
+ value={state.inputValue}
112
+ onBlur={props.onBlur}
113
+ onChange={props.onChange}
114
+ onKeyUp={props.onKeyUp}
115
+ onKeyDown={props.onKeyDown}
116
+ onFocus={props.onFocus}
117
+ slotProps={{
118
+ input: {
119
+ ...props,
120
+ size:
121
+ Math.max(
122
+ (other.min?.toString() || "").length,
123
+ state.inputValue.length || 1
124
+ ) + 1,
125
+ sx: {
126
+ textAlign: "center"
127
+ }
128
+ }
129
+ }}
130
+ sx={{ pr: 0, borderRadius: 0, flex: 1 }}
131
+ />
132
+ )}
133
+ />
134
+
135
+ <BaseNumberField.Increment
136
+ render={
137
+ <Button
138
+ variant="outlined"
139
+ aria-label="Increase"
140
+ size={size}
141
+ sx={{
142
+ borderTopLeftRadius: 0,
143
+ borderBottomLeftRadius: 0,
144
+ borderLeft: "0px",
145
+ "&.Mui-disabled": {
146
+ borderLeft: "0px"
147
+ }
148
+ }}
149
+ />
150
+ }
151
+ >
152
+ <AddIcon fontSize={size} />
153
+ </BaseNumberField.Increment>
154
+ </Box>
155
+ </BaseNumberField.Root>
156
+ );
157
+ }
package/src/index.ts CHANGED
@@ -100,7 +100,9 @@ export * from "./MUGlobal";
100
100
  export * from "./MUUtils";
101
101
  export * from "./NotifierMU";
102
102
  export * from "./NotifierPopupProps";
103
+ export * from "./NumberField";
103
104
  export * from "./NumberInputField";
105
+ export * from "./NumberSpinner";
104
106
  export * from "./OptionBool";
105
107
  export * from "./OptionGroup";
106
108
  export * from "./OptionGroupFlag";