@rovula/ui 0.0.76 → 0.0.78
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/dist/cjs/bundle.css +40 -0
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +7 -0
- package/dist/cjs/types/components/InputFilter/InputFilter.stories.d.ts +7 -0
- package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.d.ts +75 -0
- package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +491 -0
- package/dist/cjs/types/components/MaskedTextInput/index.d.ts +3 -0
- package/dist/cjs/types/components/NumberInput/NumberInput.d.ts +39 -0
- package/dist/cjs/types/components/NumberInput/NumberInput.stories.d.ts +18 -0
- package/dist/cjs/types/components/NumberInput/index.d.ts +2 -0
- package/dist/cjs/types/components/RadioGroup/RadioGroup.stories.d.ts +1 -1
- package/dist/cjs/types/components/Search/Search.stories.d.ts +7 -0
- package/dist/cjs/types/components/Slider/Slider.stories.d.ts +1 -1
- package/dist/cjs/types/components/TextInput/TextInput.d.ts +14 -0
- package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +14 -0
- package/dist/cjs/types/index.d.ts +4 -0
- package/dist/components/MaskedTextInput/MaskedTextInput.js +267 -0
- package/dist/components/MaskedTextInput/MaskedTextInput.stories.js +167 -0
- package/dist/components/MaskedTextInput/index.js +2 -0
- package/dist/components/NumberInput/NumberInput.js +254 -0
- package/dist/components/NumberInput/NumberInput.stories.js +212 -0
- package/dist/components/NumberInput/index.js +1 -0
- package/dist/components/TextInput/TextInput.js +13 -11
- package/dist/components/Toast/Toast.styles.js +1 -1
- package/dist/esm/bundle.css +40 -0
- package/dist/esm/bundle.js +3 -3
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +7 -0
- package/dist/esm/types/components/InputFilter/InputFilter.stories.d.ts +7 -0
- package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.d.ts +75 -0
- package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +491 -0
- package/dist/esm/types/components/MaskedTextInput/index.d.ts +3 -0
- package/dist/esm/types/components/NumberInput/NumberInput.d.ts +39 -0
- package/dist/esm/types/components/NumberInput/NumberInput.stories.d.ts +18 -0
- package/dist/esm/types/components/NumberInput/index.d.ts +2 -0
- package/dist/esm/types/components/RadioGroup/RadioGroup.stories.d.ts +1 -1
- package/dist/esm/types/components/Search/Search.stories.d.ts +7 -0
- package/dist/esm/types/components/Slider/Slider.stories.d.ts +1 -1
- package/dist/esm/types/components/TextInput/TextInput.d.ts +14 -0
- package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +14 -0
- package/dist/esm/types/index.d.ts +4 -0
- package/dist/index.d.ts +110 -1
- package/dist/index.js +2 -0
- package/dist/src/theme/global.css +51 -0
- package/package.json +1 -1
- package/src/components/MaskedTextInput/MaskedTextInput.stories.tsx +414 -0
- package/src/components/MaskedTextInput/MaskedTextInput.tsx +391 -0
- package/src/components/MaskedTextInput/README.md +202 -0
- package/src/components/MaskedTextInput/index.ts +3 -0
- package/src/components/NumberInput/NumberInput.stories.tsx +350 -0
- package/src/components/NumberInput/NumberInput.tsx +428 -0
- package/src/components/NumberInput/index.ts +2 -0
- package/src/components/TextInput/TextInput.tsx +54 -12
- package/src/components/Toast/Toast.styles.tsx +1 -1
- package/src/index.ts +7 -0
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
|
+
var t = {};
|
|
3
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
4
|
+
t[p] = s[p];
|
|
5
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
6
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
7
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
8
|
+
t[p[i]] = s[p[i]];
|
|
9
|
+
}
|
|
10
|
+
return t;
|
|
11
|
+
};
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
import React, { forwardRef, useCallback, useImperativeHandle, useRef, useState, } from "react";
|
|
14
|
+
import { TextInput, } from "../TextInput/TextInput";
|
|
15
|
+
import { ChevronUpIcon, ChevronDownIcon } from "@heroicons/react/16/solid";
|
|
16
|
+
import { cn } from "@/utils/cn";
|
|
17
|
+
export const NumberInput = forwardRef((_a, ref) => {
|
|
18
|
+
var _b;
|
|
19
|
+
var { value, defaultValue, min, max, step = 1, precision, hideControls = false, allowDecimal = true, allowNegative = true, formatDisplay = false, thousandSeparator = ",", decimalSeparator = ".", prefix = "", suffix = "", disabled = false, onChange, onValueChange, className, size = "md" } = _a, props = __rest(_a, ["value", "defaultValue", "min", "max", "step", "precision", "hideControls", "allowDecimal", "allowNegative", "formatDisplay", "thousandSeparator", "decimalSeparator", "prefix", "suffix", "disabled", "onChange", "onValueChange", "className", "size"]);
|
|
20
|
+
const inputRef = useRef(null);
|
|
21
|
+
const [internalValue, setInternalValue] = useState(((_b = value !== null && value !== void 0 ? value : defaultValue) !== null && _b !== void 0 ? _b : "").toString());
|
|
22
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
23
|
+
useImperativeHandle(ref, () => inputRef === null || inputRef === void 0 ? void 0 : inputRef.current);
|
|
24
|
+
// Helper function to remove formatting
|
|
25
|
+
const unformatNumber = useCallback((formattedValue) => {
|
|
26
|
+
let cleaned = formattedValue;
|
|
27
|
+
// Remove prefix and suffix
|
|
28
|
+
if (prefix)
|
|
29
|
+
cleaned = cleaned.replace(prefix, "");
|
|
30
|
+
if (suffix)
|
|
31
|
+
cleaned = cleaned.replace(suffix, "");
|
|
32
|
+
// Remove thousand separators
|
|
33
|
+
if (thousandSeparator) {
|
|
34
|
+
cleaned = cleaned.split(thousandSeparator).join("");
|
|
35
|
+
}
|
|
36
|
+
// Replace decimal separator with standard dot
|
|
37
|
+
if (decimalSeparator !== ".") {
|
|
38
|
+
cleaned = cleaned.replace(decimalSeparator, ".");
|
|
39
|
+
}
|
|
40
|
+
return cleaned.trim();
|
|
41
|
+
}, [prefix, suffix, thousandSeparator, decimalSeparator]);
|
|
42
|
+
// Helper function to format number for display
|
|
43
|
+
const formatNumber = useCallback((numValue) => {
|
|
44
|
+
if (!formatDisplay || numValue === "" || numValue === "-")
|
|
45
|
+
return numValue;
|
|
46
|
+
const num = parseFloat(numValue);
|
|
47
|
+
if (isNaN(num))
|
|
48
|
+
return numValue;
|
|
49
|
+
let formatted = num.toString();
|
|
50
|
+
// Apply precision formatting
|
|
51
|
+
if (precision !== undefined) {
|
|
52
|
+
formatted = num.toFixed(precision);
|
|
53
|
+
}
|
|
54
|
+
// Split into integer and decimal parts
|
|
55
|
+
const parts = formatted.split(".");
|
|
56
|
+
let integerPart = parts[0];
|
|
57
|
+
const decimalPart = parts[1];
|
|
58
|
+
// Add thousand separators
|
|
59
|
+
if (thousandSeparator) {
|
|
60
|
+
integerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
|
|
61
|
+
}
|
|
62
|
+
// Combine with decimal separator
|
|
63
|
+
formatted = decimalPart
|
|
64
|
+
? `${integerPart}${decimalSeparator}${decimalPart}`
|
|
65
|
+
: integerPart;
|
|
66
|
+
// Add prefix and suffix
|
|
67
|
+
if (prefix)
|
|
68
|
+
formatted = `${prefix}${formatted}`;
|
|
69
|
+
if (suffix)
|
|
70
|
+
formatted = `${formatted}${suffix}`;
|
|
71
|
+
return formatted;
|
|
72
|
+
}, [
|
|
73
|
+
formatDisplay,
|
|
74
|
+
precision,
|
|
75
|
+
thousandSeparator,
|
|
76
|
+
decimalSeparator,
|
|
77
|
+
prefix,
|
|
78
|
+
suffix,
|
|
79
|
+
]);
|
|
80
|
+
const validateAndFormat = useCallback((val) => {
|
|
81
|
+
if (val === "" || val === "-")
|
|
82
|
+
return val;
|
|
83
|
+
let numValue = parseFloat(val);
|
|
84
|
+
if (isNaN(numValue))
|
|
85
|
+
return internalValue;
|
|
86
|
+
// Apply min/max constraints
|
|
87
|
+
if (min !== undefined && numValue < min)
|
|
88
|
+
numValue = min;
|
|
89
|
+
if (max !== undefined && numValue > max)
|
|
90
|
+
numValue = max;
|
|
91
|
+
// Apply precision
|
|
92
|
+
if (precision !== undefined) {
|
|
93
|
+
numValue = parseFloat(numValue.toFixed(precision));
|
|
94
|
+
}
|
|
95
|
+
return numValue.toString();
|
|
96
|
+
}, [min, max, precision, internalValue]);
|
|
97
|
+
const handleInputChange = useCallback((e) => {
|
|
98
|
+
let inputValue = e.target.value;
|
|
99
|
+
// Unformat the input if formatting is enabled
|
|
100
|
+
if (formatDisplay) {
|
|
101
|
+
inputValue = unformatNumber(inputValue);
|
|
102
|
+
}
|
|
103
|
+
// Allow empty input
|
|
104
|
+
if (inputValue === "") {
|
|
105
|
+
setInternalValue("");
|
|
106
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(undefined);
|
|
107
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange("");
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Allow negative sign at the start
|
|
111
|
+
if (allowNegative && inputValue === "-") {
|
|
112
|
+
setInternalValue("-");
|
|
113
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange("-");
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Filter non-numeric characters based on settings
|
|
117
|
+
const regex = allowDecimal
|
|
118
|
+
? allowNegative
|
|
119
|
+
? /^-?\d*\.?\d*$/
|
|
120
|
+
: /^\d*\.?\d*$/
|
|
121
|
+
: allowNegative
|
|
122
|
+
? /^-?\d*$/
|
|
123
|
+
: /^\d*$/;
|
|
124
|
+
if (!regex.test(inputValue)) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
setInternalValue(inputValue);
|
|
128
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(inputValue);
|
|
129
|
+
// Only call onChange with a valid number
|
|
130
|
+
const numValue = parseFloat(inputValue);
|
|
131
|
+
if (!isNaN(numValue)) {
|
|
132
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(numValue);
|
|
133
|
+
}
|
|
134
|
+
}, [
|
|
135
|
+
allowDecimal,
|
|
136
|
+
allowNegative,
|
|
137
|
+
formatDisplay,
|
|
138
|
+
unformatNumber,
|
|
139
|
+
onChange,
|
|
140
|
+
onValueChange,
|
|
141
|
+
]);
|
|
142
|
+
const handleFocus = useCallback((e) => {
|
|
143
|
+
var _a;
|
|
144
|
+
setIsFocused(true);
|
|
145
|
+
(_a = props.onFocus) === null || _a === void 0 ? void 0 : _a.call(props, e);
|
|
146
|
+
}, [props]);
|
|
147
|
+
const handleBlur = useCallback((e) => {
|
|
148
|
+
var _a;
|
|
149
|
+
setIsFocused(false);
|
|
150
|
+
const formatted = validateAndFormat(internalValue);
|
|
151
|
+
setInternalValue(formatted);
|
|
152
|
+
const numValue = parseFloat(formatted);
|
|
153
|
+
if (!isNaN(numValue)) {
|
|
154
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(numValue);
|
|
155
|
+
}
|
|
156
|
+
(_a = props.onBlur) === null || _a === void 0 ? void 0 : _a.call(props, e);
|
|
157
|
+
}, [internalValue, validateAndFormat, onChange, props]);
|
|
158
|
+
const increment = useCallback((e) => {
|
|
159
|
+
if (disabled)
|
|
160
|
+
return;
|
|
161
|
+
e.stopPropagation();
|
|
162
|
+
e.preventDefault();
|
|
163
|
+
const currentValue = parseFloat(internalValue) || 0;
|
|
164
|
+
let newValue = currentValue + step;
|
|
165
|
+
if (max !== undefined && newValue > max) {
|
|
166
|
+
newValue = max;
|
|
167
|
+
}
|
|
168
|
+
const formatted = validateAndFormat(newValue.toString());
|
|
169
|
+
setInternalValue(formatted);
|
|
170
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(parseFloat(formatted));
|
|
171
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(formatted);
|
|
172
|
+
}, [
|
|
173
|
+
internalValue,
|
|
174
|
+
step,
|
|
175
|
+
max,
|
|
176
|
+
disabled,
|
|
177
|
+
validateAndFormat,
|
|
178
|
+
onChange,
|
|
179
|
+
onValueChange,
|
|
180
|
+
]);
|
|
181
|
+
const decrement = useCallback((e) => {
|
|
182
|
+
if (disabled)
|
|
183
|
+
return;
|
|
184
|
+
e.stopPropagation();
|
|
185
|
+
e.preventDefault();
|
|
186
|
+
const currentValue = parseFloat(internalValue) || 0;
|
|
187
|
+
let newValue = currentValue - step;
|
|
188
|
+
if (min !== undefined && newValue < min) {
|
|
189
|
+
newValue = min;
|
|
190
|
+
}
|
|
191
|
+
const formatted = validateAndFormat(newValue.toString());
|
|
192
|
+
setInternalValue(formatted);
|
|
193
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(parseFloat(formatted));
|
|
194
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(formatted);
|
|
195
|
+
}, [
|
|
196
|
+
internalValue,
|
|
197
|
+
step,
|
|
198
|
+
min,
|
|
199
|
+
disabled,
|
|
200
|
+
validateAndFormat,
|
|
201
|
+
onChange,
|
|
202
|
+
onValueChange,
|
|
203
|
+
]);
|
|
204
|
+
const handleKeyDown = useCallback((e) => {
|
|
205
|
+
var _a;
|
|
206
|
+
switch (e.key) {
|
|
207
|
+
case "ArrowUp":
|
|
208
|
+
increment(e);
|
|
209
|
+
break;
|
|
210
|
+
case "ArrowDown":
|
|
211
|
+
decrement(e);
|
|
212
|
+
break;
|
|
213
|
+
case "Enter":
|
|
214
|
+
e.currentTarget.blur();
|
|
215
|
+
break;
|
|
216
|
+
default:
|
|
217
|
+
break;
|
|
218
|
+
}
|
|
219
|
+
(_a = props.onKeyDown) === null || _a === void 0 ? void 0 : _a.call(props, e);
|
|
220
|
+
}, [increment, decrement, props]);
|
|
221
|
+
// Sync internal value with external value prop
|
|
222
|
+
React.useEffect(() => {
|
|
223
|
+
if (value !== undefined) {
|
|
224
|
+
setInternalValue(value.toString());
|
|
225
|
+
}
|
|
226
|
+
}, [value]);
|
|
227
|
+
// Get the display value (formatted when not focused)
|
|
228
|
+
const displayValue = React.useMemo(() => {
|
|
229
|
+
if (isFocused || !formatDisplay) {
|
|
230
|
+
return internalValue;
|
|
231
|
+
}
|
|
232
|
+
return formatNumber(internalValue);
|
|
233
|
+
}, [isFocused, formatDisplay, internalValue, formatNumber]);
|
|
234
|
+
const controlsSize = {
|
|
235
|
+
sm: "w-3 h-3",
|
|
236
|
+
md: "w-4 h-4",
|
|
237
|
+
lg: "w-6 h-6",
|
|
238
|
+
}[size];
|
|
239
|
+
const paddingSize = {
|
|
240
|
+
sm: "absolute top-0.5",
|
|
241
|
+
md: "absolute top-1",
|
|
242
|
+
lg: "absolute top-1",
|
|
243
|
+
}[size];
|
|
244
|
+
const renderControls = () => {
|
|
245
|
+
if (hideControls)
|
|
246
|
+
return null;
|
|
247
|
+
return (_jsxs("div", { className: cn("flex flex-col", props.iconMode === "flat" && paddingSize), children: [_jsx("button", { type: "button", onClick: increment, disabled: disabled ||
|
|
248
|
+
(max !== undefined && parseFloat(internalValue) >= max), className: cn(" hover:bg-input-active-stroke/10 disabled:opacity-30 disabled:cursor-not-allowed transition-colors rounded-full text-input-filled-text"), tabIndex: -1, children: _jsx(ChevronUpIcon, { className: controlsSize }) }), _jsx("button", { type: "button", onClick: decrement, disabled: disabled ||
|
|
249
|
+
(min !== undefined && parseFloat(internalValue) <= min), className: cn(" hover:bg-input-active-stroke/10 disabled:opacity-30 disabled:cursor-not-allowed transition-colors rounded-full text-input-filled-text"), tabIndex: -1, children: _jsx(ChevronDownIcon, { className: controlsSize }) })] }));
|
|
250
|
+
};
|
|
251
|
+
return (_jsx(TextInput, Object.assign({}, props, { ref: inputRef, type: "text", inputMode: "decimal", value: displayValue, onChange: handleInputChange, onFocus: handleFocus, onBlur: handleBlur, onKeyDown: handleKeyDown, disabled: disabled, size: size, hasClearIcon: false, endIcon: renderControls(), className: cn(className) })));
|
|
252
|
+
});
|
|
253
|
+
NumberInput.displayName = "NumberInput";
|
|
254
|
+
export default NumberInput;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { NumberInput } from "@/index";
|
|
3
|
+
const meta = {
|
|
4
|
+
title: "Components/NumberInput",
|
|
5
|
+
component: NumberInput,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: "fullscreen",
|
|
8
|
+
},
|
|
9
|
+
tags: ["autodocs"],
|
|
10
|
+
decorators: [
|
|
11
|
+
(Story) => (_jsx("div", { className: "p-5 flex h-screen w-full bg-base-bg2", children: _jsx(Story, {}) })),
|
|
12
|
+
],
|
|
13
|
+
argTypes: {
|
|
14
|
+
size: {
|
|
15
|
+
control: { type: "radio" },
|
|
16
|
+
options: ["sm", "md", "lg"],
|
|
17
|
+
},
|
|
18
|
+
rounded: {
|
|
19
|
+
control: { type: "radio" },
|
|
20
|
+
options: ["none", "normal", "full"],
|
|
21
|
+
},
|
|
22
|
+
variant: {
|
|
23
|
+
control: { type: "radio" },
|
|
24
|
+
options: ["flat", "outline", "underline"],
|
|
25
|
+
},
|
|
26
|
+
isFloatingLabel: { control: "boolean" },
|
|
27
|
+
fullwidth: { control: "boolean" },
|
|
28
|
+
disabled: { control: "boolean" },
|
|
29
|
+
error: { control: "boolean" },
|
|
30
|
+
required: { control: "boolean" },
|
|
31
|
+
hideControls: { control: "boolean" },
|
|
32
|
+
allowDecimal: { control: "boolean" },
|
|
33
|
+
allowNegative: { control: "boolean" },
|
|
34
|
+
},
|
|
35
|
+
args: {
|
|
36
|
+
label: "Number",
|
|
37
|
+
placeholder: "Enter a number",
|
|
38
|
+
size: "md",
|
|
39
|
+
rounded: "normal",
|
|
40
|
+
variant: "outline",
|
|
41
|
+
isFloatingLabel: true,
|
|
42
|
+
fullwidth: true,
|
|
43
|
+
disabled: false,
|
|
44
|
+
error: false,
|
|
45
|
+
required: true,
|
|
46
|
+
hideControls: false,
|
|
47
|
+
allowDecimal: true,
|
|
48
|
+
allowNegative: true,
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
export default meta;
|
|
52
|
+
export const Default = {
|
|
53
|
+
render: (args) => {
|
|
54
|
+
console.log("args ", args);
|
|
55
|
+
const props = Object.assign({}, args);
|
|
56
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
export const WithMinMax = {
|
|
60
|
+
args: {
|
|
61
|
+
label: "Age",
|
|
62
|
+
min: 0,
|
|
63
|
+
max: 120,
|
|
64
|
+
helperText: "Age must be between 0 and 120",
|
|
65
|
+
},
|
|
66
|
+
render: (args) => {
|
|
67
|
+
const props = Object.assign({}, args);
|
|
68
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
export const WithStep = {
|
|
72
|
+
args: {
|
|
73
|
+
label: "Rating",
|
|
74
|
+
min: 0,
|
|
75
|
+
max: 5,
|
|
76
|
+
step: 0.5,
|
|
77
|
+
defaultValue: 2.5,
|
|
78
|
+
helperText: "Use 0.5 increments",
|
|
79
|
+
},
|
|
80
|
+
render: (args) => {
|
|
81
|
+
const props = Object.assign({}, args);
|
|
82
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
export const IntegerOnly = {
|
|
86
|
+
args: {
|
|
87
|
+
label: "Quantity",
|
|
88
|
+
allowDecimal: false,
|
|
89
|
+
min: 1,
|
|
90
|
+
defaultValue: 1,
|
|
91
|
+
helperText: "Integer values only",
|
|
92
|
+
},
|
|
93
|
+
render: (args) => {
|
|
94
|
+
const props = Object.assign({}, args);
|
|
95
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
export const ControllWithOutLine = {
|
|
99
|
+
args: {
|
|
100
|
+
label: "Quantity",
|
|
101
|
+
allowDecimal: false,
|
|
102
|
+
iconMode: "flat",
|
|
103
|
+
min: 1,
|
|
104
|
+
defaultValue: 1,
|
|
105
|
+
helperText: "Integer values only",
|
|
106
|
+
},
|
|
107
|
+
render: (args) => {
|
|
108
|
+
const props = Object.assign({}, args);
|
|
109
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
export const WithoutControls = {
|
|
113
|
+
args: {
|
|
114
|
+
label: "Custom Number",
|
|
115
|
+
hideControls: true,
|
|
116
|
+
helperText: "No increment/decrement buttons",
|
|
117
|
+
},
|
|
118
|
+
render: (args) => {
|
|
119
|
+
const props = Object.assign({}, args);
|
|
120
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
export const ErrorState = {
|
|
124
|
+
args: {
|
|
125
|
+
error: true,
|
|
126
|
+
errorMessage: "Value exceeds maximum allowed",
|
|
127
|
+
defaultValue: 150,
|
|
128
|
+
},
|
|
129
|
+
render: (args) => {
|
|
130
|
+
const props = Object.assign({}, args);
|
|
131
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
export const HelperText = {
|
|
135
|
+
args: {
|
|
136
|
+
helperText: "Enter a number between 0 and 100",
|
|
137
|
+
min: 0,
|
|
138
|
+
max: 100,
|
|
139
|
+
},
|
|
140
|
+
render: (args) => {
|
|
141
|
+
const props = Object.assign({}, args);
|
|
142
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
export const Disabled = {
|
|
146
|
+
args: {
|
|
147
|
+
disabled: true,
|
|
148
|
+
defaultValue: 50,
|
|
149
|
+
},
|
|
150
|
+
render: (args) => {
|
|
151
|
+
const props = Object.assign({}, args);
|
|
152
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
export const FormattedNumber = {
|
|
156
|
+
args: {
|
|
157
|
+
label: "Amount",
|
|
158
|
+
formatDisplay: true,
|
|
159
|
+
precision: 2,
|
|
160
|
+
defaultValue: 1234567.89,
|
|
161
|
+
helperText: "Number with thousand separator",
|
|
162
|
+
},
|
|
163
|
+
render: (args) => {
|
|
164
|
+
const props = Object.assign({}, args);
|
|
165
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
export const CurrencyFormat = {
|
|
169
|
+
args: {
|
|
170
|
+
label: "Price",
|
|
171
|
+
formatDisplay: true,
|
|
172
|
+
precision: 2,
|
|
173
|
+
prefix: "$",
|
|
174
|
+
defaultValue: 1230.0,
|
|
175
|
+
min: 0,
|
|
176
|
+
helperText: "Currency format with $ prefix",
|
|
177
|
+
},
|
|
178
|
+
render: (args) => {
|
|
179
|
+
const props = Object.assign({}, args);
|
|
180
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
export const CurrencyThailand = {
|
|
184
|
+
args: {
|
|
185
|
+
label: "ราคา",
|
|
186
|
+
formatDisplay: true,
|
|
187
|
+
precision: 2,
|
|
188
|
+
suffix: " ฿",
|
|
189
|
+
defaultValue: 15000.5,
|
|
190
|
+
min: 0,
|
|
191
|
+
helperText: "Thai Baht format",
|
|
192
|
+
},
|
|
193
|
+
render: (args) => {
|
|
194
|
+
const props = Object.assign({}, args);
|
|
195
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
export const CustomSeparators = {
|
|
199
|
+
args: {
|
|
200
|
+
label: "European Format",
|
|
201
|
+
formatDisplay: true,
|
|
202
|
+
precision: 2,
|
|
203
|
+
thousandSeparator: ".",
|
|
204
|
+
decimalSeparator: ",",
|
|
205
|
+
defaultValue: 9999.99,
|
|
206
|
+
helperText: "European number format (9.999,99)",
|
|
207
|
+
},
|
|
208
|
+
render: (args) => {
|
|
209
|
+
const props = Object.assign({}, args);
|
|
210
|
+
return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(NumberInput, Object.assign({ id: "1" }, props, { size: "lg" })), _jsx(NumberInput, Object.assign({ id: "2" }, props, { size: "md" })), _jsx(NumberInput, Object.assign({ id: "3" }, props, { size: "sm" }))] }));
|
|
211
|
+
},
|
|
212
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { NumberInput, default } from "./NumberInput";
|
|
@@ -15,7 +15,7 @@ import { helperTextVariant, iconSearchWrapperVariant, iconVariant, iconWrapperVa
|
|
|
15
15
|
import { XCircleIcon, ExclamationCircleIcon, MagnifyingGlassIcon, } from "@heroicons/react/16/solid";
|
|
16
16
|
import { cn } from "@/utils/cn";
|
|
17
17
|
export const TextInput = forwardRef((_a, ref) => {
|
|
18
|
-
var { id, label, size = "md", rounded = "normal", variant = "outline", type = "text", iconMode = "solid", helperText, errorMessage, fullwidth = true, disabled = false, error = false, required = true, isFloatingLabel = true, keepCloseIconOnValue = false, hasClearIcon = true, hasSearchIcon = false, startIcon, endIcon, labelClassName, onClickStartIcon, onClickEndIcon, renderStartIcon, renderEndIcon } = _a, props = __rest(_a, ["id", "label", "size", "rounded", "variant", "type", "iconMode", "helperText", "errorMessage", "fullwidth", "disabled", "error", "required", "isFloatingLabel", "keepCloseIconOnValue", "hasClearIcon", "hasSearchIcon", "startIcon", "endIcon", "labelClassName", "onClickStartIcon", "onClickEndIcon", "renderStartIcon", "renderEndIcon"]);
|
|
18
|
+
var { id, label, size = "md", rounded = "normal", variant = "outline", type = "text", iconMode = "solid", helperText, errorMessage, fullwidth = true, disabled = false, error = false, required = true, isFloatingLabel = true, keepCloseIconOnValue = false, hasClearIcon = true, hasSearchIcon = false, startIcon, endIcon, labelClassName, onClickStartIcon, onClickEndIcon, renderStartIcon, renderEndIcon, classes } = _a, props = __rest(_a, ["id", "label", "size", "rounded", "variant", "type", "iconMode", "helperText", "errorMessage", "fullwidth", "disabled", "error", "required", "isFloatingLabel", "keepCloseIconOnValue", "hasClearIcon", "hasSearchIcon", "startIcon", "endIcon", "labelClassName", "onClickStartIcon", "onClickEndIcon", "renderStartIcon", "renderEndIcon", "classes"]);
|
|
19
19
|
const inputRef = useRef(null);
|
|
20
20
|
const _id = id || `${type}-${label}-input`;
|
|
21
21
|
const hasLeftSectionIcon = !!startIcon || !!renderStartIcon;
|
|
@@ -86,12 +86,13 @@ export const TextInput = forwardRef((_a, ref) => {
|
|
|
86
86
|
const startIconElement = useMemo(() => {
|
|
87
87
|
if (!hasLeftSectionIcon)
|
|
88
88
|
return;
|
|
89
|
-
if (renderStartIcon)
|
|
90
|
-
return renderStartIcon();
|
|
89
|
+
if (renderStartIcon) {
|
|
90
|
+
return (_jsx("div", { className: cn(iconSearchWrapperClassname, "flex", classes === null || classes === void 0 ? void 0 : classes.iconSearchWrapper), children: renderStartIcon() }));
|
|
91
|
+
}
|
|
91
92
|
if (iconMode === "flat") {
|
|
92
|
-
return (_jsx("div", { className: iconSearchWrapperClassname, children: _jsx("div", { className: iconClassname, onClick: handleOnClickLeftSectionIcon, children: startIcon }) }));
|
|
93
|
+
return (_jsx("div", { className: cn(iconSearchWrapperClassname, classes === null || classes === void 0 ? void 0 : classes.iconSearchWrapper), children: _jsx("div", { className: cn(iconClassname, classes === null || classes === void 0 ? void 0 : classes.icon), onClick: handleOnClickLeftSectionIcon, children: startIcon }) }));
|
|
93
94
|
}
|
|
94
|
-
return (_jsx("div", { className: startIconWrapperClassname, onClick: handleOnClickLeftSectionIcon, children: startIcon }));
|
|
95
|
+
return (_jsx("div", { className: cn(startIconWrapperClassname, classes === null || classes === void 0 ? void 0 : classes.startIconWrapper), onClick: handleOnClickLeftSectionIcon, children: startIcon }));
|
|
95
96
|
}, [
|
|
96
97
|
hasLeftSectionIcon,
|
|
97
98
|
startIcon,
|
|
@@ -105,12 +106,13 @@ export const TextInput = forwardRef((_a, ref) => {
|
|
|
105
106
|
const endIconElement = useMemo(() => {
|
|
106
107
|
if (!hasRightSectionIcon)
|
|
107
108
|
return;
|
|
108
|
-
if (renderEndIcon)
|
|
109
|
-
return renderEndIcon();
|
|
109
|
+
if (renderEndIcon) {
|
|
110
|
+
return (_jsx("div", { className: cn(iconWrapperClassname, "flex", classes === null || classes === void 0 ? void 0 : classes.iconWrapper), children: renderEndIcon() }));
|
|
111
|
+
}
|
|
110
112
|
if (iconMode === "flat") {
|
|
111
|
-
return (_jsx("div", { className: cn(iconWrapperClassname, "flex"), children: _jsx("div", { className: iconClassname, onClick: handleOnClickRightSectionIcon, children: endIcon }) }));
|
|
113
|
+
return (_jsx("div", { className: cn(iconWrapperClassname, "flex", classes === null || classes === void 0 ? void 0 : classes.iconWrapper), children: _jsx("div", { className: cn(iconClassname, classes === null || classes === void 0 ? void 0 : classes.icon), onClick: handleOnClickRightSectionIcon, children: endIcon }) }));
|
|
112
114
|
}
|
|
113
|
-
return (_jsx("div", { className: endIconWrapperClassname, onClick: handleOnClickRightSectionIcon, children: endIcon }));
|
|
115
|
+
return (_jsx("div", { className: cn(endIconWrapperClassname, classes === null || classes === void 0 ? void 0 : classes.endIconWrapper), onClick: handleOnClickRightSectionIcon, children: endIcon }));
|
|
114
116
|
}, [
|
|
115
117
|
hasRightSectionIcon,
|
|
116
118
|
endIcon,
|
|
@@ -121,9 +123,9 @@ export const TextInput = forwardRef((_a, ref) => {
|
|
|
121
123
|
renderEndIcon,
|
|
122
124
|
handleOnClickRightSectionIcon,
|
|
123
125
|
]);
|
|
124
|
-
return (_jsxs("div", { className: `inline-flex flex-col ${fullwidth ? "w-full" : ""}`, children: [_jsxs("div", { className: "relative", children: [hasSearchIcon && !hasLeftSectionIcon && (_jsx("div", { className: iconSearchWrapperClassname, children: _jsx(MagnifyingGlassIcon, { className: iconClassname }) })), _jsx("input", Object.assign({}, props, { placeholder: " ", ref: inputRef, type: type, id: _id, disabled: disabled, className: cn(inputClassname, props.className) })), startIconElement, hasClearIcon && !hasRightSectionIcon && (_jsx("div", { className: iconWrapperClassname, style: {
|
|
126
|
+
return (_jsxs("div", { className: `inline-flex flex-col ${fullwidth ? "w-full" : ""}`, children: [_jsxs("div", { className: "relative", children: [hasSearchIcon && !hasLeftSectionIcon && (_jsx("div", { className: cn(iconSearchWrapperClassname, classes === null || classes === void 0 ? void 0 : classes.iconSearchWrapper), children: _jsx(MagnifyingGlassIcon, { className: cn(iconClassname, classes === null || classes === void 0 ? void 0 : classes.icon) }) })), _jsx("input", Object.assign({}, props, { placeholder: " ", ref: inputRef, type: type, id: _id, disabled: disabled, className: cn(inputClassname, props.className) })), startIconElement, hasClearIcon && !hasRightSectionIcon && (_jsx("div", { className: cn(iconWrapperClassname, classes === null || classes === void 0 ? void 0 : classes.iconWrapper), style: {
|
|
125
127
|
display: keepCloseIconOnValue && props.value ? "flex" : undefined,
|
|
126
|
-
}, children: _jsx(XCircleIcon, { type: "button", className: iconClassname, onMouseDown: handleClearInput }) })), endIconElement, _jsxs("label", { htmlFor: _id, className: cn(labelClassname), children: [label, " ", required && (_jsx("span", { className: cn("text-error", {
|
|
128
|
+
}, children: _jsx(XCircleIcon, { type: "button", className: cn(iconClassname, classes === null || classes === void 0 ? void 0 : classes.icon), onMouseDown: handleClearInput }) })), endIconElement, _jsxs("label", { htmlFor: _id, className: cn(labelClassname), children: [label, " ", required && (_jsx("span", { className: cn("text-error", {
|
|
127
129
|
"text-input-disable-text": disabled,
|
|
128
130
|
}), children: "*" }))] })] }), (errorMessage || helperText) && (_jsxs("span", { className: helperTextClassname, children: [_jsx("span", { className: "h-full", children: _jsx(ExclamationCircleIcon, { width: 16, height: 16, className: error ? "fill-error" : "" }) }), errorMessage || helperText] }))] }));
|
|
129
131
|
});
|
|
@@ -18,7 +18,7 @@ export const toastVariants = cva([
|
|
|
18
18
|
variant: "success",
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
|
-
export const toastViewportVariants = cva(["fixed z-[
|
|
21
|
+
export const toastViewportVariants = cva(["fixed z-[1000] flex w-auto flex-col-reverse px-4"], {
|
|
22
22
|
variants: {
|
|
23
23
|
position: {
|
|
24
24
|
"top-center": "top-[40px] left-0 right-0 justify-self-center",
|
package/dist/esm/bundle.css
CHANGED
|
@@ -638,6 +638,12 @@ input[type=number] {
|
|
|
638
638
|
.top-0{
|
|
639
639
|
top: 0px;
|
|
640
640
|
}
|
|
641
|
+
.top-0\.5{
|
|
642
|
+
top: 0.125rem;
|
|
643
|
+
}
|
|
644
|
+
.top-1{
|
|
645
|
+
top: 0.25rem;
|
|
646
|
+
}
|
|
641
647
|
.top-4{
|
|
642
648
|
top: 1rem;
|
|
643
649
|
}
|
|
@@ -659,6 +665,9 @@ input[type=number] {
|
|
|
659
665
|
.z-50{
|
|
660
666
|
z-index: 50;
|
|
661
667
|
}
|
|
668
|
+
.z-\[1000\]{
|
|
669
|
+
z-index: 1000;
|
|
670
|
+
}
|
|
662
671
|
.z-\[100\]{
|
|
663
672
|
z-index: 100;
|
|
664
673
|
}
|
|
@@ -987,6 +996,9 @@ input[type=number] {
|
|
|
987
996
|
min-width: -moz-fit-content;
|
|
988
997
|
min-width: fit-content;
|
|
989
998
|
}
|
|
999
|
+
.max-w-2xl{
|
|
1000
|
+
max-width: 42rem;
|
|
1001
|
+
}
|
|
990
1002
|
.max-w-\[300px\]{
|
|
991
1003
|
max-width: 300px;
|
|
992
1004
|
}
|
|
@@ -996,6 +1008,9 @@ input[type=number] {
|
|
|
996
1008
|
.max-w-lg{
|
|
997
1009
|
max-width: 32rem;
|
|
998
1010
|
}
|
|
1011
|
+
.max-w-md{
|
|
1012
|
+
max-width: 28rem;
|
|
1013
|
+
}
|
|
999
1014
|
.flex-1{
|
|
1000
1015
|
flex: 1 1 0%;
|
|
1001
1016
|
}
|
|
@@ -1863,6 +1878,10 @@ input[type=number] {
|
|
|
1863
1878
|
--tw-bg-opacity: 1;
|
|
1864
1879
|
background-color: color-mix(in srgb, var(--function-default-stroke) calc(100% * var(--tw-bg-opacity, 1)), transparent);
|
|
1865
1880
|
}
|
|
1881
|
+
.bg-gray-100{
|
|
1882
|
+
--tw-bg-opacity: 1;
|
|
1883
|
+
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
|
|
1884
|
+
}
|
|
1866
1885
|
.bg-gray-200{
|
|
1867
1886
|
--tw-bg-opacity: 1;
|
|
1868
1887
|
background-color: rgb(229 231 235 / var(--tw-bg-opacity, 1));
|
|
@@ -3159,6 +3178,10 @@ input[type=number] {
|
|
|
3159
3178
|
line-height: var(--label-label2-line-height, 10px);
|
|
3160
3179
|
font-weight: var(--label-label2-weight, 400);
|
|
3161
3180
|
}
|
|
3181
|
+
.text-lg{
|
|
3182
|
+
font-size: 1.125rem;
|
|
3183
|
+
line-height: 1.75rem;
|
|
3184
|
+
}
|
|
3162
3185
|
.text-sm{
|
|
3163
3186
|
font-size: 0.875rem;
|
|
3164
3187
|
line-height: 1.25rem;
|
|
@@ -3252,6 +3275,9 @@ input[type=number] {
|
|
|
3252
3275
|
.font-medium{
|
|
3253
3276
|
font-weight: 500;
|
|
3254
3277
|
}
|
|
3278
|
+
.font-semibold{
|
|
3279
|
+
font-weight: 600;
|
|
3280
|
+
}
|
|
3255
3281
|
.uppercase{
|
|
3256
3282
|
text-transform: uppercase;
|
|
3257
3283
|
}
|
|
@@ -3452,6 +3478,10 @@ input[type=number] {
|
|
|
3452
3478
|
--tw-text-opacity: 1;
|
|
3453
3479
|
color: rgb(107 114 128 / var(--tw-text-opacity, 1));
|
|
3454
3480
|
}
|
|
3481
|
+
.text-gray-700{
|
|
3482
|
+
--tw-text-opacity: 1;
|
|
3483
|
+
color: rgb(55 65 81 / var(--tw-text-opacity, 1));
|
|
3484
|
+
}
|
|
3455
3485
|
.text-green-500{
|
|
3456
3486
|
--tw-text-opacity: 1;
|
|
3457
3487
|
color: rgb(34 197 94 / var(--tw-text-opacity, 1));
|
|
@@ -4086,6 +4116,9 @@ input[type=number] {
|
|
|
4086
4116
|
--tw-bg-opacity: 1;
|
|
4087
4117
|
background-color: rgb(243 244 246 / var(--tw-bg-opacity, 1));
|
|
4088
4118
|
}
|
|
4119
|
+
.hover\:bg-input-active-stroke\/10:hover{
|
|
4120
|
+
background-color: color-mix(in srgb, var(--input-color-active-stroke) calc(100% * 0.1), transparent);
|
|
4121
|
+
}
|
|
4089
4122
|
.hover\:bg-input-disable-bg:hover{
|
|
4090
4123
|
--tw-bg-opacity: 1;
|
|
4091
4124
|
background-color: color-mix(in srgb, var(--input-color-disable-bg) calc(100% * var(--tw-bg-opacity, 1)), transparent);
|
|
@@ -5165,6 +5198,9 @@ input[type=number] {
|
|
|
5165
5198
|
--tw-text-opacity: 1;
|
|
5166
5199
|
color: color-mix(in srgb, var(--state-color-disable-outline) calc(100% * var(--tw-text-opacity, 1)), transparent);
|
|
5167
5200
|
}
|
|
5201
|
+
.disabled\:opacity-30:disabled{
|
|
5202
|
+
opacity: 0.3;
|
|
5203
|
+
}
|
|
5168
5204
|
.disabled\:opacity-50:disabled{
|
|
5169
5205
|
opacity: 0.5;
|
|
5170
5206
|
}
|
|
@@ -5814,6 +5850,10 @@ input[type=number] {
|
|
|
5814
5850
|
.md\:right-\[40px\]{
|
|
5815
5851
|
right: 40px;
|
|
5816
5852
|
}
|
|
5853
|
+
|
|
5854
|
+
.md\:grid-cols-2{
|
|
5855
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
5856
|
+
}
|
|
5817
5857
|
}
|
|
5818
5858
|
.\[\&\:has\(\[role\=checkbox\]\)\]\:w-4:has([role=checkbox]){
|
|
5819
5859
|
width: 1rem;
|