sonance-brand-mcp 1.1.4 → 1.2.2

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 (73) hide show
  1. package/dist/assets/BRAND_GUIDELINES.md +0 -8
  2. package/dist/assets/components/accordion.stories.tsx +310 -0
  3. package/dist/assets/components/accordion.tsx +56 -30
  4. package/dist/assets/components/alert.stories.tsx +199 -0
  5. package/dist/assets/components/autocomplete.stories.tsx +307 -0
  6. package/dist/assets/components/autocomplete.tsx +28 -4
  7. package/dist/assets/components/avatar.stories.tsx +175 -0
  8. package/dist/assets/components/badge.stories.tsx +258 -0
  9. package/dist/assets/components/breadcrumbs.stories.tsx +175 -0
  10. package/dist/assets/components/button.stories.tsx +362 -0
  11. package/dist/assets/components/button.tsx +48 -3
  12. package/dist/assets/components/calendar.stories.tsx +247 -0
  13. package/dist/assets/components/card.stories.tsx +275 -0
  14. package/dist/assets/components/card.tsx +26 -1
  15. package/dist/assets/components/checkbox-group.stories.tsx +281 -0
  16. package/dist/assets/components/checkbox.stories.tsx +160 -0
  17. package/dist/assets/components/checkbox.tsx +32 -4
  18. package/dist/assets/components/code.stories.tsx +265 -0
  19. package/dist/assets/components/date-input.stories.tsx +278 -0
  20. package/dist/assets/components/date-input.tsx +24 -2
  21. package/dist/assets/components/date-picker.stories.tsx +337 -0
  22. package/dist/assets/components/date-picker.tsx +28 -4
  23. package/dist/assets/components/date-range-picker.stories.tsx +340 -0
  24. package/dist/assets/components/dialog.stories.tsx +285 -0
  25. package/dist/assets/components/divider.stories.tsx +176 -0
  26. package/dist/assets/components/drawer.stories.tsx +216 -0
  27. package/dist/assets/components/dropdown.stories.tsx +342 -0
  28. package/dist/assets/components/dropdown.tsx +55 -10
  29. package/dist/assets/components/form.stories.tsx +372 -0
  30. package/dist/assets/components/image.stories.tsx +348 -0
  31. package/dist/assets/components/input-otp.stories.tsx +336 -0
  32. package/dist/assets/components/input-otp.tsx +24 -2
  33. package/dist/assets/components/input.stories.tsx +223 -0
  34. package/dist/assets/components/input.tsx +27 -2
  35. package/dist/assets/components/kbd.stories.tsx +272 -0
  36. package/dist/assets/components/link.stories.tsx +199 -0
  37. package/dist/assets/components/link.tsx +50 -1
  38. package/dist/assets/components/listbox.stories.tsx +287 -0
  39. package/dist/assets/components/listbox.tsx +30 -7
  40. package/dist/assets/components/navbar.stories.tsx +218 -0
  41. package/dist/assets/components/number-input.stories.tsx +295 -0
  42. package/dist/assets/components/number-input.tsx +30 -8
  43. package/dist/assets/components/pagination.stories.tsx +280 -0
  44. package/dist/assets/components/pagination.tsx +45 -21
  45. package/dist/assets/components/popover.stories.tsx +219 -0
  46. package/dist/assets/components/progress.stories.tsx +153 -0
  47. package/dist/assets/components/radio-group.stories.tsx +187 -0
  48. package/dist/assets/components/radio-group.tsx +30 -6
  49. package/dist/assets/components/range-calendar.stories.tsx +334 -0
  50. package/dist/assets/components/scroll-shadow.stories.tsx +335 -0
  51. package/dist/assets/components/select.stories.tsx +192 -0
  52. package/dist/assets/components/select.tsx +54 -7
  53. package/dist/assets/components/skeleton.stories.tsx +166 -0
  54. package/dist/assets/components/slider.stories.tsx +145 -0
  55. package/dist/assets/components/slider.tsx +43 -8
  56. package/dist/assets/components/spacer.stories.tsx +216 -0
  57. package/dist/assets/components/spinner.stories.tsx +149 -0
  58. package/dist/assets/components/switch.stories.tsx +170 -0
  59. package/dist/assets/components/switch.tsx +29 -4
  60. package/dist/assets/components/table.stories.tsx +322 -0
  61. package/dist/assets/components/tabs.stories.tsx +306 -0
  62. package/dist/assets/components/tabs.tsx +25 -4
  63. package/dist/assets/components/textarea.stories.tsx +103 -0
  64. package/dist/assets/components/textarea.tsx +27 -3
  65. package/dist/assets/components/theme-toggle.stories.tsx +248 -0
  66. package/dist/assets/components/time-input.stories.tsx +365 -0
  67. package/dist/assets/components/time-input.tsx +25 -3
  68. package/dist/assets/components/toast.stories.tsx +195 -0
  69. package/dist/assets/components/tooltip.stories.tsx +226 -0
  70. package/dist/assets/components/user.stories.tsx +274 -0
  71. package/dist/assets/logo-manifest.json +0 -18
  72. package/dist/index.js +2142 -85
  73. package/package.json +1 -1
@@ -0,0 +1,218 @@
1
+ import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
+ import {
3
+ Navbar,
4
+ NavbarContent,
5
+ NavbarBrand,
6
+ NavbarItems,
7
+ NavbarItem,
8
+ ResponsiveNavbar,
9
+ } from './navbar';
10
+ import { Button } from './button';
11
+
12
+ const meta: Meta<typeof Navbar> = {
13
+ title: 'Components/Navigation/Navbar',
14
+ component: Navbar,
15
+ tags: ['autodocs'],
16
+ parameters: {
17
+ docs: {
18
+ description: {
19
+ component: 'A responsive navigation bar component with multiple variants and mobile support.',
20
+ },
21
+ },
22
+ layout: 'fullscreen',
23
+ },
24
+ argTypes: {
25
+ variant: {
26
+ control: 'select',
27
+ options: ['default', 'dark', 'transparent', 'blur'],
28
+ },
29
+ sticky: { control: 'boolean' },
30
+ bordered: { control: 'boolean' },
31
+ },
32
+ };
33
+
34
+ export default meta;
35
+ type Story = StoryObj<typeof meta>;
36
+
37
+ export const Default: Story = {
38
+ render: () => (
39
+ <Navbar>
40
+ <NavbarContent>
41
+ <NavbarBrand>
42
+ <span className="text-xl font-semibold">Sonance</span>
43
+ </NavbarBrand>
44
+ <NavbarItems>
45
+ <NavbarItem href="#" active>Home</NavbarItem>
46
+ <NavbarItem href="#">Products</NavbarItem>
47
+ <NavbarItem href="#">About</NavbarItem>
48
+ <NavbarItem href="#">Contact</NavbarItem>
49
+ </NavbarItems>
50
+ <Button size="sm">Sign In</Button>
51
+ </NavbarContent>
52
+ </Navbar>
53
+ ),
54
+ };
55
+
56
+ export const Dark: Story = {
57
+ render: () => (
58
+ <Navbar variant="dark">
59
+ <NavbarContent>
60
+ <NavbarBrand>
61
+ <span className="text-xl font-semibold">Sonance</span>
62
+ </NavbarBrand>
63
+ <NavbarItems>
64
+ <NavbarItem href="#" active>Home</NavbarItem>
65
+ <NavbarItem href="#">Products</NavbarItem>
66
+ <NavbarItem href="#">About</NavbarItem>
67
+ </NavbarItems>
68
+ <Button size="sm" variant="inverted">Sign In</Button>
69
+ </NavbarContent>
70
+ </Navbar>
71
+ ),
72
+ };
73
+
74
+ export const Transparent: Story = {
75
+ render: () => (
76
+ <div className="relative h-64 bg-gradient-to-br from-sonance-charcoal to-sonance-gray-700">
77
+ <Navbar variant="transparent" className="text-white">
78
+ <NavbarContent>
79
+ <NavbarBrand>
80
+ <span className="text-xl font-semibold">Sonance</span>
81
+ </NavbarBrand>
82
+ <NavbarItems>
83
+ <NavbarItem href="#" active>Home</NavbarItem>
84
+ <NavbarItem href="#">Products</NavbarItem>
85
+ <NavbarItem href="#">About</NavbarItem>
86
+ </NavbarItems>
87
+ <Button size="sm" variant="inverted">Sign In</Button>
88
+ </NavbarContent>
89
+ </Navbar>
90
+ </div>
91
+ ),
92
+ };
93
+
94
+ export const Blur: Story = {
95
+ render: () => (
96
+ <div className="relative h-64 bg-gradient-to-br from-sonance-blue to-foundation-green">
97
+ <Navbar variant="blur">
98
+ <NavbarContent>
99
+ <NavbarBrand>
100
+ <span className="text-xl font-semibold">Sonance</span>
101
+ </NavbarBrand>
102
+ <NavbarItems>
103
+ <NavbarItem href="#" active>Home</NavbarItem>
104
+ <NavbarItem href="#">Products</NavbarItem>
105
+ <NavbarItem href="#">About</NavbarItem>
106
+ </NavbarItems>
107
+ <Button size="sm">Sign In</Button>
108
+ </NavbarContent>
109
+ </Navbar>
110
+ <div className="p-8 text-white">
111
+ <p>Content behind the blurred navbar</p>
112
+ </div>
113
+ </div>
114
+ ),
115
+ };
116
+
117
+ export const Responsive: Story = {
118
+ render: () => (
119
+ <ResponsiveNavbar
120
+ brand={<span className="text-xl font-semibold">Sonance</span>}
121
+ items={[
122
+ { label: 'Home', href: '#', active: true },
123
+ { label: 'Products', href: '#' },
124
+ { label: 'About', href: '#' },
125
+ { label: 'Contact', href: '#' },
126
+ ]}
127
+ actions={<Button size="sm">Sign In</Button>}
128
+ />
129
+ ),
130
+ };
131
+
132
+ export const WithLogo: Story = {
133
+ render: () => (
134
+ <Navbar>
135
+ <NavbarContent>
136
+ <NavbarBrand>
137
+ <div className="w-8 h-8 bg-primary rounded" />
138
+ <span className="text-xl font-semibold">Sonance</span>
139
+ </NavbarBrand>
140
+ <NavbarItems>
141
+ <NavbarItem href="#" active>Home</NavbarItem>
142
+ <NavbarItem href="#">Products</NavbarItem>
143
+ <NavbarItem href="#">Support</NavbarItem>
144
+ </NavbarItems>
145
+ <div className="flex items-center gap-2">
146
+ <Button size="sm" variant="ghost">Log In</Button>
147
+ <Button size="sm">Sign Up</Button>
148
+ </div>
149
+ </NavbarContent>
150
+ </Navbar>
151
+ ),
152
+ };
153
+
154
+ // Responsive Matrix - Mobile, Tablet, Desktop
155
+ export const ResponsiveMatrix: Story = {
156
+ render: () => (
157
+ <div className="space-y-8">
158
+ {/* Mobile */}
159
+ <div>
160
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
161
+ <div className="w-[375px] border border-dashed border-border overflow-hidden">
162
+ <ResponsiveNavbar
163
+ brand={<span className="text-lg font-semibold">Sonance</span>}
164
+ items={[
165
+ { label: 'Home', href: '#', active: true },
166
+ { label: 'Products', href: '#' },
167
+ { label: 'About', href: '#' },
168
+ ]}
169
+ actions={<Button size="sm">Sign In</Button>}
170
+ />
171
+ </div>
172
+ </div>
173
+ {/* Tablet */}
174
+ <div>
175
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
176
+ <div className="w-[768px] border border-dashed border-border overflow-hidden">
177
+ <Navbar>
178
+ <NavbarContent>
179
+ <NavbarBrand>
180
+ <span className="text-xl font-semibold">Sonance</span>
181
+ </NavbarBrand>
182
+ <NavbarItems>
183
+ <NavbarItem href="#" active>Home</NavbarItem>
184
+ <NavbarItem href="#">Products</NavbarItem>
185
+ <NavbarItem href="#">About</NavbarItem>
186
+ </NavbarItems>
187
+ <Button size="sm">Sign In</Button>
188
+ </NavbarContent>
189
+ </Navbar>
190
+ </div>
191
+ </div>
192
+ {/* Desktop */}
193
+ <div>
194
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
195
+ <div className="w-[1280px] border border-dashed border-border overflow-hidden">
196
+ <Navbar>
197
+ <NavbarContent>
198
+ <NavbarBrand>
199
+ <span className="text-xl font-semibold">Sonance</span>
200
+ </NavbarBrand>
201
+ <NavbarItems>
202
+ <NavbarItem href="#" active>Home</NavbarItem>
203
+ <NavbarItem href="#">Products</NavbarItem>
204
+ <NavbarItem href="#">About</NavbarItem>
205
+ <NavbarItem href="#">Support</NavbarItem>
206
+ <NavbarItem href="#">Contact</NavbarItem>
207
+ </NavbarItems>
208
+ <div className="flex items-center gap-2">
209
+ <Button size="sm" variant="ghost">Log In</Button>
210
+ <Button size="sm">Sign Up</Button>
211
+ </div>
212
+ </NavbarContent>
213
+ </Navbar>
214
+ </div>
215
+ </div>
216
+ </div>
217
+ ),
218
+ };
@@ -0,0 +1,295 @@
1
+ import type { Meta, StoryObj } from '@storybook/nextjs-vite';
2
+ import { useState } from 'react';
3
+ import { NumberInput, Stepper, type NumberInputState } from './number-input';
4
+
5
+ const meta: Meta<typeof NumberInput> = {
6
+ title: 'Components/Forms/NumberInput',
7
+ component: NumberInput,
8
+ tags: ['autodocs'],
9
+ parameters: {
10
+ docs: {
11
+ description: {
12
+ component: 'A number input component with increment/decrement controls.',
13
+ },
14
+ },
15
+ },
16
+ argTypes: {
17
+ state: {
18
+ control: 'select',
19
+ options: ['default', 'hover', 'focus', 'error', 'disabled'],
20
+ description: 'Visual state for documentation',
21
+ table: {
22
+ defaultValue: { summary: 'default' },
23
+ },
24
+ },
25
+ },
26
+ };
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof meta>;
30
+
31
+ export const Default: Story = {
32
+ render: () => (
33
+ <div className="w-48">
34
+ <NumberInput defaultValue={5} />
35
+ </div>
36
+ ),
37
+ };
38
+
39
+ export const WithLabel: Story = {
40
+ render: () => (
41
+ <div className="w-48">
42
+ <NumberInput label="Quantity" defaultValue={1} />
43
+ </div>
44
+ ),
45
+ };
46
+
47
+ export const WithMinMax: Story = {
48
+ render: () => (
49
+ <div className="w-48">
50
+ <NumberInput
51
+ label="Volume Level"
52
+ defaultValue={50}
53
+ min={0}
54
+ max={100}
55
+ />
56
+ </div>
57
+ ),
58
+ };
59
+
60
+ export const CustomStep: Story = {
61
+ render: () => (
62
+ <div className="w-48">
63
+ <NumberInput
64
+ label="Price (in cents)"
65
+ defaultValue={500}
66
+ step={25}
67
+ min={0}
68
+ />
69
+ </div>
70
+ ),
71
+ };
72
+
73
+ export const DecimalStep: Story = {
74
+ render: () => (
75
+ <div className="w-48">
76
+ <NumberInput
77
+ label="Temperature"
78
+ defaultValue={72.5}
79
+ step={0.5}
80
+ min={60}
81
+ max={85}
82
+ />
83
+ </div>
84
+ ),
85
+ };
86
+
87
+ export const WithError: Story = {
88
+ render: () => (
89
+ <div className="w-48">
90
+ <NumberInput
91
+ label="Quantity"
92
+ defaultValue={0}
93
+ min={1}
94
+ error="Minimum quantity is 1"
95
+ />
96
+ </div>
97
+ ),
98
+ };
99
+
100
+ export const Disabled: Story = {
101
+ render: () => (
102
+ <div className="w-48">
103
+ <NumberInput
104
+ label="Locked Value"
105
+ defaultValue={42}
106
+ disabled
107
+ />
108
+ </div>
109
+ ),
110
+ };
111
+
112
+ export const HiddenControls: Story = {
113
+ render: () => (
114
+ <div className="w-48">
115
+ <NumberInput
116
+ label="Direct Entry"
117
+ defaultValue={100}
118
+ hideControls
119
+ />
120
+ </div>
121
+ ),
122
+ };
123
+
124
+ export const CurrencyFormat: Story = {
125
+ render: () => (
126
+ <div className="w-48">
127
+ <NumberInput
128
+ label="Price"
129
+ defaultValue={1299}
130
+ formatOptions={{
131
+ style: 'currency',
132
+ currency: 'USD',
133
+ }}
134
+ />
135
+ </div>
136
+ ),
137
+ };
138
+
139
+ export const PercentageFormat: Story = {
140
+ render: () => (
141
+ <div className="w-48">
142
+ <NumberInput
143
+ label="Discount"
144
+ defaultValue={15}
145
+ min={0}
146
+ max={100}
147
+ formatOptions={{
148
+ style: 'percent',
149
+ maximumFractionDigits: 0,
150
+ }}
151
+ />
152
+ </div>
153
+ ),
154
+ };
155
+
156
+ export const Controlled: Story = {
157
+ render: () => {
158
+ const [value, setValue] = useState(10);
159
+ return (
160
+ <div className="w-48 space-y-4">
161
+ <NumberInput
162
+ label="Controlled Input"
163
+ value={value}
164
+ onValueChange={setValue}
165
+ min={0}
166
+ max={20}
167
+ />
168
+ <p className="text-sm text-foreground-muted">
169
+ Current value: {value}
170
+ </p>
171
+ <div className="flex gap-2">
172
+ <button
173
+ onClick={() => setValue(0)}
174
+ className="text-sm text-primary hover:text-primary-hover"
175
+ >
176
+ Reset to 0
177
+ </button>
178
+ <button
179
+ onClick={() => setValue(20)}
180
+ className="text-sm text-primary hover:text-primary-hover"
181
+ >
182
+ Set to Max
183
+ </button>
184
+ </div>
185
+ </div>
186
+ );
187
+ },
188
+ };
189
+
190
+ export const StepperVariant: Story = {
191
+ render: () => (
192
+ <div className="space-y-4">
193
+ <div className="w-48">
194
+ <Stepper label="Small" size="sm" defaultValue={1} />
195
+ </div>
196
+ <div className="w-48">
197
+ <Stepper label="Medium" size="md" defaultValue={1} />
198
+ </div>
199
+ <div className="w-48">
200
+ <Stepper label="Large" size="lg" defaultValue={1} />
201
+ </div>
202
+ </div>
203
+ ),
204
+ };
205
+
206
+ export const QuantitySelector: Story = {
207
+ render: () => {
208
+ const [quantity, setQuantity] = useState(1);
209
+ const pricePerUnit = 1299;
210
+ const total = quantity * pricePerUnit;
211
+
212
+ return (
213
+ <div className="p-4 border border-border w-80">
214
+ <h3 className="font-medium text-foreground">VP66 TL In-Wall Speaker</h3>
215
+ <p className="text-sm text-foreground-muted mt-1">${pricePerUnit.toFixed(2)} each</p>
216
+ <div className="mt-4">
217
+ <NumberInput
218
+ label="Quantity"
219
+ value={quantity}
220
+ onValueChange={setQuantity}
221
+ min={1}
222
+ max={10}
223
+ />
224
+ </div>
225
+ <div className="mt-4 pt-4 border-t border-border flex justify-between items-center">
226
+ <span className="text-sm text-foreground-muted">Total:</span>
227
+ <span className="text-lg font-medium text-foreground">
228
+ ${total.toFixed(2)}
229
+ </span>
230
+ </div>
231
+ </div>
232
+ );
233
+ },
234
+ };
235
+
236
+ // State Matrix - Visual documentation of all states
237
+ export const StateMatrix: Story = {
238
+ render: () => {
239
+ const states: NumberInputState[] = ['default', 'hover', 'focus', 'error', 'disabled'];
240
+ return (
241
+ <div className="space-y-6 w-48">
242
+ <h3 className="text-sm font-medium text-foreground-muted">NumberInput States</h3>
243
+ <div className="space-y-4">
244
+ {states.map((state) => (
245
+ <div key={state}>
246
+ <span className="text-xs font-medium text-foreground-muted uppercase">{state}</span>
247
+ <NumberInput
248
+ state={state}
249
+ defaultValue={5}
250
+ error={state === 'error' ? 'Error message' : undefined}
251
+ />
252
+ </div>
253
+ ))}
254
+ </div>
255
+ </div>
256
+ );
257
+ },
258
+ };
259
+
260
+ // Responsive Matrix - Mobile, Tablet, Desktop
261
+ export const ResponsiveMatrix: Story = {
262
+ render: () => (
263
+ <div className="space-y-8">
264
+ {/* Mobile */}
265
+ <div>
266
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Mobile (375px)</h4>
267
+ <div className="w-[375px] border border-dashed border-border p-4">
268
+ <NumberInput label="Quantity" defaultValue={1} min={1} max={10} />
269
+ </div>
270
+ </div>
271
+ {/* Tablet */}
272
+ <div>
273
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Tablet (768px)</h4>
274
+ <div className="w-[768px] border border-dashed border-border p-4">
275
+ <div className="grid grid-cols-2 gap-4">
276
+ <NumberInput label="Quantity" defaultValue={5} />
277
+ <NumberInput label="Volume" defaultValue={50} min={0} max={100} />
278
+ </div>
279
+ </div>
280
+ </div>
281
+ {/* Desktop */}
282
+ <div>
283
+ <h4 className="text-xs uppercase text-foreground-muted mb-2">Desktop (1280px)</h4>
284
+ <div className="w-[1280px] border border-dashed border-border p-4">
285
+ <div className="grid grid-cols-4 gap-4">
286
+ <NumberInput label="Default" defaultValue={5} />
287
+ <NumberInput label="With Min/Max" defaultValue={50} min={0} max={100} />
288
+ <NumberInput label="With Error" defaultValue={0} min={1} error="Min 1" />
289
+ <NumberInput label="Disabled" defaultValue={42} disabled />
290
+ </div>
291
+ </div>
292
+ </div>
293
+ </div>
294
+ ),
295
+ };
@@ -4,6 +4,22 @@ import { forwardRef, useState, useCallback } from "react";
4
4
  import { Plus, Minus } from "lucide-react";
5
5
  import { cn } from "@/lib/utils";
6
6
 
7
+ export type NumberInputState = "default" | "hover" | "focus" | "error" | "disabled";
8
+
9
+ // State styles for Storybook/Figma visualization
10
+ const getStateStyles = (state?: NumberInputState) => {
11
+ if (!state || state === "default") return "";
12
+
13
+ const stateMap: Record<string, string> = {
14
+ hover: "border-border-hover",
15
+ focus: "border-input-focus",
16
+ error: "border-error",
17
+ disabled: "opacity-50 cursor-not-allowed",
18
+ };
19
+
20
+ return stateMap[state] || "";
21
+ };
22
+
7
23
  interface NumberInputProps {
8
24
  value?: number;
9
25
  defaultValue?: number;
@@ -17,6 +33,8 @@ interface NumberInputProps {
17
33
  hideControls?: boolean;
18
34
  formatOptions?: Intl.NumberFormatOptions;
19
35
  className?: string;
36
+ /** Visual state for Storybook/Figma documentation */
37
+ state?: NumberInputState;
20
38
  }
21
39
 
22
40
  export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
@@ -34,9 +52,12 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
34
52
  hideControls = false,
35
53
  formatOptions,
36
54
  className,
55
+ state,
37
56
  },
38
57
  ref
39
58
  ) => {
59
+ const isDisabled = disabled || state === "disabled";
60
+ const hasError = error || state === "error";
40
61
  const [internalValue, setInternalValue] = useState(defaultValue);
41
62
  const [inputValue, setInputValue] = useState(String(defaultValue));
42
63
 
@@ -58,13 +79,13 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
58
79
  );
59
80
 
60
81
  const increment = () => {
61
- if (!disabled) {
82
+ if (!isDisabled) {
62
83
  updateValue(value + step);
63
84
  }
64
85
  };
65
86
 
66
87
  const decrement = () => {
67
- if (!disabled) {
88
+ if (!isDisabled) {
68
89
  updateValue(value - step);
69
90
  }
70
91
  };
@@ -90,7 +111,7 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
90
111
  };
91
112
 
92
113
  const handleKeyDown = (e: React.KeyboardEvent) => {
93
- if (disabled) return;
114
+ if (isDisabled) return;
94
115
 
95
116
  switch (e.key) {
96
117
  case "ArrowUp":
@@ -124,7 +145,7 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
124
145
  <button
125
146
  type="button"
126
147
  onClick={decrement}
127
- disabled={disabled || !canDecrement}
148
+ disabled={isDisabled || !canDecrement}
128
149
  className={cn(
129
150
  "flex items-center justify-center w-10",
130
151
  "border border-r-0 border-input-border bg-background-secondary",
@@ -145,22 +166,23 @@ export const NumberInput = forwardRef<HTMLInputElement, NumberInputProps>(
145
166
  onChange={handleInputChange}
146
167
  onBlur={handleBlur}
147
168
  onKeyDown={handleKeyDown}
148
- disabled={disabled}
169
+ disabled={isDisabled}
149
170
  className={cn(
150
171
  "flex-1 min-w-0 border border-input-border bg-input px-4 py-3",
151
172
  "text-center text-foreground",
152
173
  "transition-colors duration-200",
153
174
  "focus:border-input-focus focus:outline-none focus:z-10",
154
175
  "disabled:cursor-not-allowed disabled:opacity-50",
155
- error && "border-error",
156
- hideControls ? "" : "border-x-0"
176
+ hasError && "border-error",
177
+ hideControls ? "" : "border-x-0",
178
+ getStateStyles(state)
157
179
  )}
158
180
  />
159
181
  {!hideControls && (
160
182
  <button
161
183
  type="button"
162
184
  onClick={increment}
163
- disabled={disabled || !canIncrement}
185
+ disabled={isDisabled || !canIncrement}
164
186
  className={cn(
165
187
  "flex items-center justify-center w-10",
166
188
  "border border-l-0 border-input-border bg-background-secondary",