@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.
Files changed (56) hide show
  1. package/dist/cjs/bundle.css +40 -0
  2. package/dist/cjs/bundle.js +3 -3
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +7 -0
  5. package/dist/cjs/types/components/InputFilter/InputFilter.stories.d.ts +7 -0
  6. package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.d.ts +75 -0
  7. package/dist/cjs/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +491 -0
  8. package/dist/cjs/types/components/MaskedTextInput/index.d.ts +3 -0
  9. package/dist/cjs/types/components/NumberInput/NumberInput.d.ts +39 -0
  10. package/dist/cjs/types/components/NumberInput/NumberInput.stories.d.ts +18 -0
  11. package/dist/cjs/types/components/NumberInput/index.d.ts +2 -0
  12. package/dist/cjs/types/components/RadioGroup/RadioGroup.stories.d.ts +1 -1
  13. package/dist/cjs/types/components/Search/Search.stories.d.ts +7 -0
  14. package/dist/cjs/types/components/Slider/Slider.stories.d.ts +1 -1
  15. package/dist/cjs/types/components/TextInput/TextInput.d.ts +14 -0
  16. package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +14 -0
  17. package/dist/cjs/types/index.d.ts +4 -0
  18. package/dist/components/MaskedTextInput/MaskedTextInput.js +267 -0
  19. package/dist/components/MaskedTextInput/MaskedTextInput.stories.js +167 -0
  20. package/dist/components/MaskedTextInput/index.js +2 -0
  21. package/dist/components/NumberInput/NumberInput.js +254 -0
  22. package/dist/components/NumberInput/NumberInput.stories.js +212 -0
  23. package/dist/components/NumberInput/index.js +1 -0
  24. package/dist/components/TextInput/TextInput.js +13 -11
  25. package/dist/components/Toast/Toast.styles.js +1 -1
  26. package/dist/esm/bundle.css +40 -0
  27. package/dist/esm/bundle.js +3 -3
  28. package/dist/esm/bundle.js.map +1 -1
  29. package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +7 -0
  30. package/dist/esm/types/components/InputFilter/InputFilter.stories.d.ts +7 -0
  31. package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.d.ts +75 -0
  32. package/dist/esm/types/components/MaskedTextInput/MaskedTextInput.stories.d.ts +491 -0
  33. package/dist/esm/types/components/MaskedTextInput/index.d.ts +3 -0
  34. package/dist/esm/types/components/NumberInput/NumberInput.d.ts +39 -0
  35. package/dist/esm/types/components/NumberInput/NumberInput.stories.d.ts +18 -0
  36. package/dist/esm/types/components/NumberInput/index.d.ts +2 -0
  37. package/dist/esm/types/components/RadioGroup/RadioGroup.stories.d.ts +1 -1
  38. package/dist/esm/types/components/Search/Search.stories.d.ts +7 -0
  39. package/dist/esm/types/components/Slider/Slider.stories.d.ts +1 -1
  40. package/dist/esm/types/components/TextInput/TextInput.d.ts +14 -0
  41. package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +14 -0
  42. package/dist/esm/types/index.d.ts +4 -0
  43. package/dist/index.d.ts +110 -1
  44. package/dist/index.js +2 -0
  45. package/dist/src/theme/global.css +51 -0
  46. package/package.json +1 -1
  47. package/src/components/MaskedTextInput/MaskedTextInput.stories.tsx +414 -0
  48. package/src/components/MaskedTextInput/MaskedTextInput.tsx +391 -0
  49. package/src/components/MaskedTextInput/README.md +202 -0
  50. package/src/components/MaskedTextInput/index.ts +3 -0
  51. package/src/components/NumberInput/NumberInput.stories.tsx +350 -0
  52. package/src/components/NumberInput/NumberInput.tsx +428 -0
  53. package/src/components/NumberInput/index.ts +2 -0
  54. package/src/components/TextInput/TextInput.tsx +54 -12
  55. package/src/components/Toast/Toast.styles.tsx +1 -1
  56. 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-[100] flex w-auto flex-col-reverse px-4"], {
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",
@@ -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;