@nomos-ui/form 0.0.1

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/README.md ADDED
@@ -0,0 +1,277 @@
1
+ # @nomos-ui/react
2
+
3
+ > **νόμος** (nomos) - Greek: law, order, principle
4
+
5
+ Beautiful, validated form components that integrate seamlessly with React Hook Form. Built on the principle that forms should enforce order and validation effortlessly.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @nomos-ui/react react-hook-form
11
+ # or
12
+ yarn add @nomos-ui/react react-hook-form
13
+ # or
14
+ pnpm add @nomos-ui/react react-hook-form
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```jsx
20
+ import { useForm } from "react-hook-form";
21
+ import { Input, Button, Form } from "@nomos-ui/react";
22
+
23
+ function LoginForm() {
24
+ const form = useForm();
25
+
26
+ const onSubmit = (data) => {
27
+ console.log(data);
28
+ };
29
+
30
+ return (
31
+ <Form form={form} onSubmit={onSubmit}>
32
+ <Input
33
+ name="email"
34
+ label="Email"
35
+ type="email"
36
+ rules={{ required: "Email is required" }}
37
+ />
38
+ <Input
39
+ name="password"
40
+ label="Password"
41
+ type="password"
42
+ rules={{ required: "Password is required", minLength: 8 }}
43
+ />
44
+ <Button type="submit">Sign In</Button>
45
+ </Form>
46
+ );
47
+ }
48
+ ```
49
+
50
+ ## Why Nomos UI?
51
+
52
+ - **Zero Boilerplate** - Components auto-register with React Hook Form
53
+ - **Built-in Validation** - Error states handled automatically
54
+ - **Accessible** - WCAG 2.1 AA compliant
55
+ - **Customizable** - Style with Tailwind or your own CSS
56
+ - **Type Safe** - Full TypeScript support
57
+ - **Lightweight** - Tree-shakeable, minimal bundle size
58
+
59
+ ## Components
60
+
61
+ ### Form Components
62
+
63
+ - `<Input />` - Text, email, password, number inputs
64
+ - `<Textarea />` - Multi-line text input
65
+ - `<Select />` - Dropdown selection
66
+ - `<Checkbox />` - Single checkbox
67
+ - `<CheckboxGroup />` - Multiple checkboxes
68
+ - `<Radio />` - Radio button
69
+ - `<RadioGroup />` - Radio button group
70
+ - `<Switch />` - Toggle switch
71
+ - `<DatePicker />` - Date selection
72
+ - `<FileUpload />` - File input with drag & drop
73
+
74
+ ### Layout & UI
75
+
76
+ - `<Form />` - Form wrapper with context
77
+ - `<Button />` - Submit and action buttons
78
+ - `<FieldGroup />` - Group related fields
79
+ - `<FormSection />` - Organize form into sections
80
+
81
+ ## Examples
82
+
83
+ ### Basic Input with Validation
84
+
85
+ ```jsx
86
+ <Input
87
+ name="username"
88
+ label="Username"
89
+ placeholder="Enter username"
90
+ rules={{
91
+ required: "Username is required",
92
+ minLength: { value: 3, message: "Minimum 3 characters" },
93
+ pattern: { value: /^[a-zA-Z0-9_]+$/, message: "Alphanumeric only" },
94
+ }}
95
+ helperText="Choose a unique username"
96
+ />
97
+ ```
98
+
99
+ ### Select with Options
100
+
101
+ ```jsx
102
+ <Select
103
+ name="country"
104
+ label="Country"
105
+ rules={{ required: "Please select a country" }}
106
+ options={[
107
+ { value: "us", label: "United States" },
108
+ { value: "uk", label: "United Kingdom" },
109
+ { value: "ca", label: "Canada" },
110
+ ]}
111
+ />
112
+ ```
113
+
114
+ ### Checkbox Group
115
+
116
+ ```jsx
117
+ <CheckboxGroup
118
+ name="interests"
119
+ label="Interests"
120
+ options={[
121
+ { value: "sports", label: "Sports" },
122
+ { value: "music", label: "Music" },
123
+ { value: "reading", label: "Reading" },
124
+ ]}
125
+ rules={{ required: "Select at least one interest" }}
126
+ />
127
+ ```
128
+
129
+ ### Custom Styling
130
+
131
+ ```jsx
132
+ <Input
133
+ name="email"
134
+ label="Email"
135
+ className="custom-input"
136
+ labelClassName="custom-label"
137
+ errorClassName="custom-error"
138
+ />
139
+ ```
140
+
141
+ ### Controlled Components
142
+
143
+ ```jsx
144
+ const { watch, setValue } = useForm();
145
+ const emailValue = watch("email");
146
+
147
+ <Input
148
+ name="email"
149
+ label="Email"
150
+ onChange={(e) => {
151
+ // Custom logic
152
+ setValue("email", e.target.value.toLowerCase());
153
+ }}
154
+ />;
155
+ ```
156
+
157
+ ## API Reference
158
+
159
+ ### Common Props
160
+
161
+ All form components share these props:
162
+
163
+ | Prop | Type | Description |
164
+ | ------------ | --------- | -------------------------------- |
165
+ | `name` | `string` | Field name (required) |
166
+ | `label` | `string` | Field label |
167
+ | `rules` | `object` | React Hook Form validation rules |
168
+ | `helperText` | `string` | Help text shown below field |
169
+ | `disabled` | `boolean` | Disable the field |
170
+ | `className` | `string` | Custom CSS class |
171
+ | `...rest` | `any` | Native HTML attributes |
172
+
173
+ ### Input Props
174
+
175
+ | Prop | Type | Default | Description |
176
+ | -------------- | -------- | -------- | ---------------------------------------- |
177
+ | `type` | `string` | `'text'` | Input type (text, email, password, etc.) |
178
+ | `placeholder` | `string` | - | Placeholder text |
179
+ | `autoComplete` | `string` | - | Browser autocomplete hint |
180
+
181
+ ### Button Props
182
+
183
+ | Prop | Type | Default | Description |
184
+ | ----------- | --------------------------------------------------- | ----------- | -------------------- |
185
+ | `variant` | `'primary' \| 'secondary' \| 'outline' \| 'danger'` | `'primary'` | Button style variant |
186
+ | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | Button size |
187
+ | `loading` | `boolean` | `false` | Show loading spinner |
188
+ | `fullWidth` | `boolean` | `false` | Take full width |
189
+
190
+ ## Customization
191
+
192
+ ### Theming
193
+
194
+ Override default styles with CSS variables:
195
+
196
+ ```css
197
+ :root {
198
+ --nomos-primary: #3b82f6;
199
+ --nomos-error: #ef4444;
200
+ --nomos-border: #d1d5db;
201
+ --nomos-radius: 0.5rem;
202
+ }
203
+ ```
204
+
205
+ ### Tailwind Integration
206
+
207
+ Components use Tailwind classes by default. Extend with your own:
208
+
209
+ ```jsx
210
+ <Input
211
+ name="email"
212
+ className="shadow-xl border-purple-500 focus:ring-purple-500"
213
+ />
214
+ ```
215
+
216
+ ## TypeScript
217
+
218
+ Full type safety with TypeScript:
219
+
220
+ ```tsx
221
+ import { useForm } from "react-hook-form";
222
+ import { Input, Button } from "@nomos-ui/react";
223
+
224
+ interface FormData {
225
+ email: string;
226
+ password: string;
227
+ }
228
+
229
+ function LoginForm() {
230
+ const form = useForm<FormData>();
231
+
232
+ const onSubmit = (data: FormData) => {
233
+ console.log(data);
234
+ };
235
+
236
+ return (
237
+ <Form form={form} onSubmit={onSubmit}>
238
+ <Input<FormData> name="email" label="Email" />
239
+ <Input<FormData> name="password" label="Password" type="password" />
240
+ <Button type="submit">Sign In</Button>
241
+ </Form>
242
+ );
243
+ }
244
+ ```
245
+
246
+ ## Roadmap
247
+
248
+ - [ ] `@nomos-ui/vue` - Vue 3 components
249
+ - [ ] `@nomos-ui/svelte` - Svelte components
250
+ - [ ] Advanced components (Autocomplete, MultiSelect, RichText)
251
+ - [ ] Form builder/generator
252
+ - [ ] Headless components
253
+ - [ ] Theme presets
254
+
255
+ ## Philosophy
256
+
257
+ **νόμος** (nomos) means "law" or "order" in Greek. In the New Testament, it often refers to divine law and principles. Just as law brings order to society, Nomos UI brings order to your forms - enforcing validation rules, maintaining structure, and ensuring data integrity.
258
+
259
+ > "For the law was given through Moses; grace and truth came through Jesus Christ." - John 1:17
260
+
261
+ We believe forms should be both functional and graceful, enforcing rules while remaining pleasant to use.
262
+
263
+ ## Contributing
264
+
265
+ Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) first.
266
+
267
+ ## License
268
+
269
+ MIT ©
270
+
271
+ ## Credits
272
+
273
+ Built on top of [React Hook Form](https://react-hook-form.com/) - the most performant, flexible form library for React.
274
+
275
+ ---
276
+
277
+ **Made with ♥︎ for developers who value order in chaos**
@@ -0,0 +1,20 @@
1
+ import * as React from "react";
2
+ import { type VariantProps } from "class-variance-authority";
3
+ declare const buttonVariants: (props?: ({
4
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
5
+ size?: "default" | "sm" | "lg" | "icon" | "icon-sm" | "icon-lg" | null | undefined;
6
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
7
+ type ButtonProps = React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
8
+ /** Render as a child component (Radix Slot pattern) */
9
+ asChild?: boolean;
10
+ /** Show loading spinner and disable button */
11
+ isLoading?: boolean;
12
+ /** Render as Next.js Link with href */
13
+ href?: string;
14
+ /** Mark button as selected (adds data-selected attribute) */
15
+ selected?: boolean;
16
+ };
17
+ export default function Button({ className, variant, size, asChild, isLoading, href, type, selected, disabled, children, ...props }: ButtonProps): import("react/jsx-runtime").JSX.Element;
18
+ export { buttonVariants };
19
+ export type { ButtonProps };
20
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/components/button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIlE,QAAA,MAAM,cAAc;;;8EA8BnB,CAAC;AAEF,KAAK,WAAW,GAAG,KAAK,CAAC,cAAc,CAAC,QAAQ,CAAC,GAC/C,YAAY,CAAC,OAAO,cAAc,CAAC,GAAG;IACpC,uDAAuD;IACvD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEJ,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAe,EACf,SAAiB,EACjB,IAAI,EACJ,IAAe,EACf,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,WAAW,2CA4Cb;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,94 @@
1
+ "use client";
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.buttonVariants = void 0;
38
+ exports.default = Button;
39
+ const jsx_runtime_1 = require("react/jsx-runtime");
40
+ const React = __importStar(require("react"));
41
+ const react_slot_1 = require("@radix-ui/react-slot");
42
+ const class_variance_authority_1 = require("class-variance-authority");
43
+ const lucide_react_1 = require("lucide-react");
44
+ const utils_1 = require("../utils/shadcn-ui/utils");
45
+ const buttonVariants = (0, class_variance_authority_1.cva)("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive active:opacity-80 relative", {
46
+ variants: {
47
+ variant: {
48
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
49
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
50
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
51
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
52
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 data-[selected=true]:bg-accent dark:data-[selected=true]:bg-accent/50",
53
+ link: "text-primary underline-offset-4 hover:underline p-0",
54
+ },
55
+ size: {
56
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
57
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
58
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
59
+ icon: "size-9",
60
+ "icon-sm": "size-8",
61
+ "icon-lg": "size-10",
62
+ },
63
+ },
64
+ defaultVariants: {
65
+ variant: "default",
66
+ size: "default",
67
+ },
68
+ });
69
+ exports.buttonVariants = buttonVariants;
70
+ function Button({ className, variant, size, asChild = false, isLoading = false, href, type = "button", selected, disabled, children, ...props }) {
71
+ const [buttonWidth, setButtonWidth] = React.useState();
72
+ const buttonRef = React.useRef(null);
73
+ React.useEffect(() => {
74
+ if (isLoading && buttonRef.current && !buttonWidth) {
75
+ setButtonWidth(buttonRef.current.offsetWidth);
76
+ }
77
+ else if (!isLoading && buttonWidth) {
78
+ setButtonWidth(undefined);
79
+ }
80
+ }, [isLoading, buttonWidth]);
81
+ const commonProps = {
82
+ "data-slot": "button",
83
+ "data-selected": selected,
84
+ className: (0, utils_1.cn)(buttonVariants({ variant, size, className })),
85
+ style: buttonWidth ? { width: buttonWidth } : undefined,
86
+ ref: buttonRef,
87
+ };
88
+ const content = isLoading ? ((0, jsx_runtime_1.jsx)(lucide_react_1.LoaderIcon, { className: "size-4 animate-spin" })) : (children);
89
+ if (asChild) {
90
+ return ((0, jsx_runtime_1.jsx)(react_slot_1.Slot, { ...commonProps, ...props, children: content }));
91
+ }
92
+ return ((0, jsx_runtime_1.jsx)("button", { type: type, disabled: isLoading || disabled, ...commonProps, ...props, children: content }));
93
+ }
94
+ //# sourceMappingURL=button.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/components/button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoDb,yBAwDC;;AA1GD,6CAA+B;AAC/B,qDAA4C;AAC5C,uEAAkE;AAClE,+CAA0C;AAC1C,oDAA8C;AAE9C,MAAM,cAAc,GAAG,IAAA,8BAAG,EACxB,wdAAwd,EACxd;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,wDAAwD;YACjE,WAAW,EACT,mJAAmJ;YACrJ,OAAO,EACL,uIAAuI;YACzI,SAAS,EACP,8DAA8D;YAChE,KAAK,EACH,4IAA4I;YAC9I,IAAI,EAAE,qDAAqD;SAC5D;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,+BAA+B;YACxC,EAAE,EAAE,+CAA+C;YACnD,EAAE,EAAE,sCAAsC;YAC1C,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,SAAS;SACrB;KACF;IACD,eAAe,EAAE;QACf,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,SAAS;KAChB;CACF,CACF,CAAC;AAwEO,wCAAc;AA1DvB,SAAwB,MAAM,CAAC,EAC7B,SAAS,EACT,OAAO,EACP,IAAI,EACJ,OAAO,GAAG,KAAK,EACf,SAAS,GAAG,KAAK,EACjB,IAAI,EACJ,IAAI,GAAG,QAAQ,EACf,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,GAAG,KAAK,EACI;IACZ,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,KAAK,CAAC,QAAQ,EAAsB,CAAC;IAC3E,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAoB,IAAI,CAAC,CAAC;IAExD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,SAAS,IAAI,SAAS,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YACnD,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAChD,CAAC;aAAM,IAAI,CAAC,SAAS,IAAI,WAAW,EAAE,CAAC;YACrC,cAAc,CAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAC;IAE7B,MAAM,WAAW,GAAG;QAClB,WAAW,EAAE,QAAQ;QACrB,eAAe,EAAE,QAAQ;QACzB,SAAS,EAAE,IAAA,UAAE,EAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QAC3D,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QACvD,GAAG,EAAE,SAAS;KACf,CAAC;IAEF,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,CAC1B,uBAAC,yBAAU,IAAC,SAAS,EAAC,qBAAqB,GAAG,CAC/C,CAAC,CAAC,CAAC,CACF,QAAQ,CACT,CAAC;IAEF,IAAI,OAAO,EAAE,CAAC;QACZ,OAAO,CACL,uBAAC,iBAAI,OAAK,WAAW,KAAM,KAAK,YAC7B,OAAO,GACH,CACR,CAAC;IACJ,CAAC;IAED,OAAO,CACL,mCACE,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,SAAS,IAAI,QAAQ,KAC3B,WAAW,KACX,KAAK,YAER,OAAO,GACD,CACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { Control, FieldValues, Path, PathValue } from "react-hook-form";
2
+ import Input from "./input";
3
+ import React from "react";
4
+ /**
5
+ * Props for the `FormInput` component with type-safe form integration
6
+ */
7
+ export type FormInputProps<TFieldValues extends FieldValues> = {
8
+ /** React Hook Form control instance */
9
+ control: Control<TFieldValues>;
10
+ /** The name of the field (type-safe, must match form schema) */
11
+ name: Path<TFieldValues>;
12
+ /** Default value of the input (type-safe based on field) */
13
+ defaultValue?: PathValue<TFieldValues, Path<TFieldValues>>;
14
+ } & Omit<React.ComponentProps<typeof Input>, "value" | "onChange" | "error" | "control">;
15
+ /**
16
+ * A form input component that adds type-safe form functionality to the base Input component.
17
+ * Designed to integrate with React Hook Form with full TypeScript support.
18
+ *
19
+ * @component
20
+ * @example
21
+ * ```tsx
22
+ * type FormData = {
23
+ * email: string;
24
+ * age: number;
25
+ * };
26
+ *
27
+ * const { control } = useForm<FormData>();
28
+ *
29
+ * <FormInput
30
+ * control={control}
31
+ * name="email" // ✅ Type-safe: only "email" or "age" allowed
32
+ * defaultValue="test@example.com" // ✅ Type-safe: must be string
33
+ * label="Email"
34
+ * placeholder="Enter your email"
35
+ * required
36
+ * tip="Enter a valid email address"
37
+ * />
38
+ * ```
39
+ */
40
+ export default function FormInput<TFieldValues extends FieldValues>({ control, name, defaultValue, required, ...props }: FormInputProps<TFieldValues>): import("react/jsx-runtime").JSX.Element;
41
+ //# sourceMappingURL=form-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-input.d.ts","sourceRoot":"","sources":["../../src/components/form-input.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,OAAO,EACP,WAAW,EACX,IAAI,EACJ,SAAS,EACV,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,MAAM,SAAS,CAAC;AAC5B,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,MAAM,cAAc,CAAC,YAAY,SAAS,WAAW,IAAI;IAC7D,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,gEAAgE;IAChE,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IACzB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;CAC5D,GAAG,IAAI,CACN,KAAK,CAAC,cAAc,CAAC,OAAO,KAAK,CAAC,EAClC,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,SAAS,CAC3C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,YAAY,SAAS,WAAW,EAAE,EAClE,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,QAAe,EACf,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,YAAY,CAAC,2CAmB9B"}
@@ -0,0 +1,38 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.default = FormInput;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_hook_form_1 = require("react-hook-form");
9
+ const input_1 = __importDefault(require("./input"));
10
+ /**
11
+ * A form input component that adds type-safe form functionality to the base Input component.
12
+ * Designed to integrate with React Hook Form with full TypeScript support.
13
+ *
14
+ * @component
15
+ * @example
16
+ * ```tsx
17
+ * type FormData = {
18
+ * email: string;
19
+ * age: number;
20
+ * };
21
+ *
22
+ * const { control } = useForm<FormData>();
23
+ *
24
+ * <FormInput
25
+ * control={control}
26
+ * name="email" // ✅ Type-safe: only "email" or "age" allowed
27
+ * defaultValue="test@example.com" // ✅ Type-safe: must be string
28
+ * label="Email"
29
+ * placeholder="Enter your email"
30
+ * required
31
+ * tip="Enter a valid email address"
32
+ * />
33
+ * ```
34
+ */
35
+ function FormInput({ control, name, defaultValue, required = true, ...props }) {
36
+ return ((0, jsx_runtime_1.jsx)(react_hook_form_1.Controller, { control: control, name: name, defaultValue: defaultValue, rules: { required: required ? "Required" : false }, render: ({ field: { onChange, value }, fieldState: { error } }) => ((0, jsx_runtime_1.jsx)(input_1.default, { id: `form-input-${name}`, value: value ?? "", onChange: onChange, required: required, error: error?.message, ...props })) }));
37
+ }
38
+ //# sourceMappingURL=form-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-input.js","sourceRoot":"","sources":["../../src/components/form-input.tsx"],"names":[],"mappings":";;;;;AAkDA,4BAyBC;;AA3ED,qDAMyB;AACzB,oDAA4B;AAkB5B;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAwB,SAAS,CAAmC,EAClE,OAAO,EACP,IAAI,EACJ,YAAY,EACZ,QAAQ,GAAG,IAAI,EACf,GAAG,KAAK,EACqB;IAC7B,OAAO,CACL,uBAAC,4BAAU,IACT,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,EAAE,EAClD,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CACjE,uBAAC,eAAK,IACJ,EAAE,EAAE,cAAc,IAAI,EAAE,EACxB,KAAK,EAAE,KAAK,IAAI,EAAE,EAClB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,KAAK,EAAE,OAAO,KACjB,KAAK,GACT,CACH,GACD,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,69 @@
1
+ import * as React from "react";
2
+ /**
3
+ * Props for the enhanced Input component
4
+ */
5
+ export type InputProps = {
6
+ /** Additional class name for the input element */
7
+ inputClassName?: string;
8
+ /** Additional class name for the container */
9
+ className?: string;
10
+ /** Placeholder text for the input */
11
+ placeholder?: string;
12
+ /** Label text for the input */
13
+ label?: string;
14
+ /** Additional class name for the label */
15
+ labelClassName?: string;
16
+ /** Additional class name for the input container/wrapper */
17
+ inputContainerClassName?: string;
18
+ /** Input type (e.g., text, number, password) */
19
+ type?: string;
20
+ /** Whether the input is disabled */
21
+ disabled?: boolean;
22
+ /** Whether to trim input value before calling onChange */
23
+ trim?: boolean;
24
+ /** Current value of the input */
25
+ value?: string | number;
26
+ /** Callback fired when input value changes */
27
+ onChange?: (value: string | number | null, e?: React.ChangeEvent<HTMLInputElement>) => void;
28
+ /** Whether the field is required */
29
+ required?: boolean;
30
+ /** Whether to show an asterisk for required fields */
31
+ showRequiredSign?: boolean;
32
+ /** Tooltip text providing additional information */
33
+ tip?: string;
34
+ /** Error message to display */
35
+ error?: string;
36
+ /** Ref for the container div */
37
+ ref?: any;
38
+ /** Ref for the input element */
39
+ inputRef?: any;
40
+ /** Whether to show search icon (overrides type="search" icon display) */
41
+ showSearchIcon?: boolean;
42
+ };
43
+ /**
44
+ * An enhanced input component combining the best of both worlds:
45
+ * - Semantic color tokens from design system (foreground, muted-foreground, etc.)
46
+ * - Label support with required indicators
47
+ * - Password visibility toggle
48
+ * - Search icon support
49
+ * - Focus state management
50
+ * - Error state with validation
51
+ * - Value trimming and type coercion
52
+ * - Datetime/date value formatting
53
+ *
54
+ * @component
55
+ * @example
56
+ * ```tsx
57
+ * <Input
58
+ * label="Username"
59
+ * placeholder="Enter username"
60
+ * type="text"
61
+ * required
62
+ * showRequiredSign
63
+ * error="Username is required"
64
+ * onChange={(value) => console.log(value)}
65
+ * />
66
+ * ```
67
+ */
68
+ export default function Input({ inputClassName, className, placeholder, label, labelClassName, type, disabled, trim, value, onChange, required, showRequiredSign, tip, error, inputContainerClassName, ref, inputRef, showSearchIcon, ...props }: InputProps & Omit<React.InputHTMLAttributes<HTMLInputElement>, keyof InputProps>): import("react/jsx-runtime").JSX.Element;
69
+ //# sourceMappingURL=input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../src/components/input.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,kDAAkD;IAClD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,8CAA8C;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,gDAAgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,iCAAiC;IACjC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,EAC7B,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,KACpC,IAAI,CAAC;IACV,oCAAoC;IACpC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oDAAoD;IACpD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gCAAgC;IAChC,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,gCAAgC;IAChC,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,yEAAyE;IACzE,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,OAAO,UAAU,KAAK,CAAC,EAC5B,cAAc,EACd,SAAS,EACT,WAAW,EACX,KAAK,EACL,cAAc,EACd,IAAa,EACb,QAAgB,EAChB,IAAY,EACZ,KAAU,EACV,QAAQ,EACR,QAAgB,EAChB,gBAAwB,EACxB,GAAG,EACH,KAAK,EACL,uBAAuB,EACvB,GAAG,EACH,QAAQ,EACR,cAAc,EACd,GAAG,KAAK,EACT,EAAE,UAAU,GACX,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAAE,MAAM,UAAU,CAAC,2CA6IpE"}
@@ -0,0 +1,85 @@
1
+ "use client";
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.default = Input;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const lucide_react_1 = require("lucide-react");
8
+ const utils_1 = require("../utils/shadcn-ui/utils");
9
+ /**
10
+ * An enhanced input component combining the best of both worlds:
11
+ * - Semantic color tokens from design system (foreground, muted-foreground, etc.)
12
+ * - Label support with required indicators
13
+ * - Password visibility toggle
14
+ * - Search icon support
15
+ * - Focus state management
16
+ * - Error state with validation
17
+ * - Value trimming and type coercion
18
+ * - Datetime/date value formatting
19
+ *
20
+ * @component
21
+ * @example
22
+ * ```tsx
23
+ * <Input
24
+ * label="Username"
25
+ * placeholder="Enter username"
26
+ * type="text"
27
+ * required
28
+ * showRequiredSign
29
+ * error="Username is required"
30
+ * onChange={(value) => console.log(value)}
31
+ * />
32
+ * ```
33
+ */
34
+ function Input({ inputClassName, className, placeholder, label, labelClassName, type = "text", disabled = false, trim = false, value = "", onChange, required = false, showRequiredSign = false, tip, error, inputContainerClassName, ref, inputRef, showSearchIcon, ...props }) {
35
+ const isPassword = type.includes("password");
36
+ const [showPassword, setShowPassword] = (0, react_1.useState)(!isPassword);
37
+ const [isFocused, setIsFocused] = (0, react_1.useState)(false);
38
+ function handleOnChange(text) {
39
+ if (disabled || !onChange)
40
+ return;
41
+ const processedValue = trim ? text.trim() : text;
42
+ onChange(type === "number" && processedValue
43
+ ? Number(processedValue)
44
+ : processedValue);
45
+ }
46
+ const currentValue = (0, react_1.useMemo)(() => {
47
+ if (type === "datetime-local") {
48
+ let newValue = value.toString().split(".");
49
+ if (newValue.length === 2)
50
+ return newValue[0]?.slice?.(0, -3);
51
+ else
52
+ return value;
53
+ }
54
+ if (type === "date")
55
+ return value.toString().split("T")[0];
56
+ return value;
57
+ }, [value, type]);
58
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, className: (0, utils_1.cn)("gap-1 grid", className), children: [label && ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-row items-center gap-1", children: [(0, jsx_runtime_1.jsx)("label", { htmlFor: props.id, className: (0, utils_1.cn)("text-sm font-bold text-foreground", labelClassName), children: label }), required && showRequiredSign && ((0, jsx_runtime_1.jsx)(lucide_react_1.AsteriskIcon, { size: 12, className: "text-destructive" }))] })), (0, jsx_runtime_1.jsxs)("div", { "data-focus": isFocused, className: (0, utils_1.cn)(
59
+ // Base styles with semantic colors
60
+ "flex w-full min-w-0 rounded-md border bg-transparent shadow-xs transition-[color,box-shadow,border-color]", "border-input file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground", "placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground",
61
+ // Focus styles
62
+ "focus-within:border-ring focus-within:ring-ring/50 focus-within:ring-[3px]", "data-[focus=true]:border-ring data-[focus=true]:ring-ring/50 data-[focus=true]:ring-[3px]",
63
+ // Error/Invalid styles
64
+ error &&
65
+ "border-destructive ring-destructive/20 dark:ring-destructive/40", "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
66
+ // Disabled styles
67
+ "disabled:cursor-not-allowed disabled:opacity-50",
68
+ // Dark mode
69
+ "dark:bg-input/30",
70
+ // Layout
71
+ "flex-row items-center", inputContainerClassName), children: [(type === "search" || showSearchIcon) && ((0, jsx_runtime_1.jsx)(lucide_react_1.SearchIcon, { size: 18, className: "text-muted-foreground ml-3 flex-shrink-0" })), (0, jsx_runtime_1.jsx)("input", { type: isPassword && showPassword ? "text" : type, disabled: disabled, required: required, "aria-invalid": error ? "true" : "false", onBlur: (e) => {
72
+ props?.onBlur?.(e);
73
+ setIsFocused(false);
74
+ }, onFocus: (e) => {
75
+ props?.onFocus?.(e);
76
+ setIsFocused(true);
77
+ }, onChange: (e) => {
78
+ const value = e.currentTarget.value;
79
+ if (onChange) {
80
+ handleOnChange(value);
81
+ onChange(value, e);
82
+ }
83
+ }, value: currentValue, placeholder: placeholder, className: (0, utils_1.cn)("h-9 w-full flex-1 bg-transparent px-3 py-1 text-base outline-none", "file:inline-flex file:h-7", "disabled:cursor-not-allowed disabled:bg-transparent", "md:text-sm", inputClassName), step: "any", ref: inputRef, ...props }), isPassword && ((0, jsx_runtime_1.jsx)("button", { type: "button", onClick: () => !disabled && setShowPassword((prev) => !prev), disabled: disabled, className: "mr-3 flex-shrink-0 cursor-pointer text-muted-foreground hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50", tabIndex: -1, children: showPassword ? (0, jsx_runtime_1.jsx)(lucide_react_1.EyeIcon, { size: 16 }) : (0, jsx_runtime_1.jsx)(lucide_react_1.EyeOffIcon, { size: 16 }) }))] }), tip && !error && ((0, jsx_runtime_1.jsx)("p", { className: "text-xs text-muted-foreground tip-message", children: tip })), error && ((0, jsx_runtime_1.jsxs)("p", { className: "text-xs text-destructive error-message", children: ["*", error] }))] }));
84
+ }
85
+ //# sourceMappingURL=input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"input.js","sourceRoot":"","sources":["../../src/components/input.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import Button from "../components/button";
2
+ import FormInput from "../components/form-input";
3
+ import Input from "../components/input";
4
+ export { Button, FormInput, Input };
5
+ export * from "../components/input";
6
+ export * from "../components/form-input";
7
+ export * from "../components/button";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,sBAAsB,CAAC;AAC1C,OAAO,SAAS,MAAM,0BAA0B,CAAC;AACjD,OAAO,KAAK,MAAM,qBAAqB,CAAC;AAExC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.Input = exports.FormInput = exports.Button = void 0;
21
+ const button_1 = __importDefault(require("../components/button"));
22
+ exports.Button = button_1.default;
23
+ const form_input_1 = __importDefault(require("../components/form-input"));
24
+ exports.FormInput = form_input_1.default;
25
+ const input_1 = __importDefault(require("../components/input"));
26
+ exports.Input = input_1.default;
27
+ __exportStar(require("../components/input"), exports);
28
+ __exportStar(require("../components/form-input"), exports);
29
+ __exportStar(require("../components/button"), exports);
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exports/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,kEAA0C;AAIjC,iBAJF,gBAAM,CAIE;AAHf,0EAAiD;AAGhC,oBAHV,oBAAS,CAGU;AAF1B,gEAAwC;AAEZ,gBAFrB,eAAK,CAEqB;AACjC,sDAAoC;AACpC,2DAAyC;AACzC,uDAAqC"}
@@ -0,0 +1,3 @@
1
+ import { type ClassValue } from "clsx";
2
+ export declare function cn(...inputs: ClassValue[]): string;
3
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/shadcn-ui/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAAQ,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cn = cn;
4
+ const clsx_1 = require("clsx");
5
+ const tailwind_merge_1 = require("tailwind-merge");
6
+ function cn(...inputs) {
7
+ return (0, tailwind_merge_1.twMerge)((0, clsx_1.clsx)(...inputs));
8
+ }
9
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils/shadcn-ui/utils.ts"],"names":[],"mappings":";;AAGA,gBAEC;AALD,+BAA6C;AAC7C,mDAAyC;AAEzC,SAAgB,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,IAAA,wBAAO,EAAC,IAAA,WAAI,EAAC,GAAG,MAAM,CAAC,CAAC,CAAC;AAClC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,123 @@
1
+ {
2
+ "name": "@nomos-ui/form",
3
+ "version": "0.0.1",
4
+ "description": "The Shadcn library for building robust React forms",
5
+ "main": "dist/index.js",
6
+ "module": "dist/exports/index.js",
7
+ "types": "dist/exports/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/exports/index.d.ts",
11
+ "import": "./dist/exports/index.js"
12
+ },
13
+ "./hooks": {
14
+ "types": "./dist/hooks/index.d.ts",
15
+ "import": "./dist/hooks/index.js"
16
+ },
17
+ "./utils": {
18
+ "types": "./dist/utils/index.d.ts",
19
+ "import": "./dist/utils/index.js"
20
+ },
21
+ "./types": {
22
+ "types": "./dist/types/index.d.ts",
23
+ "import": "./dist/types/index.js"
24
+ }
25
+ },
26
+ "typesVersions": {
27
+ "*": {
28
+ "components": ["./dist/components/index.d.ts"],
29
+ "hooks": ["./dist/hooks/index.d.ts"],
30
+ "utils": ["./dist/utils/index.d.ts"],
31
+ "types": ["./dist/types/index.d.ts"]
32
+ }
33
+ },
34
+ "scripts": {
35
+ "build": "trash dist && tsc",
36
+ "dev": "tsc --watch",
37
+ "clean": "rm -rf dist",
38
+ "lint": "eslint src --ext .ts,.tsx",
39
+ "type-check": "tsc --noEmit",
40
+ "test": "vitest",
41
+ "test:watch": "vitest --watch",
42
+ "test:ui": "vitest --ui",
43
+ "test:coverage": "vitest --coverage",
44
+ "prepublishOnly": "pnpm run build"
45
+ },
46
+ "keywords": [
47
+ "react",
48
+ "react-hook-form",
49
+ "form",
50
+ "forms",
51
+ "validation",
52
+ "components",
53
+ "ui",
54
+ "input",
55
+ "select",
56
+ "checkbox",
57
+ "accessible",
58
+ "a11y",
59
+ "tailwind",
60
+ "typescript",
61
+ "nomos"
62
+ ],
63
+ "author": "Uanela Como",
64
+ "license": "MIT",
65
+ "repository": {
66
+ "type": "git",
67
+ "url": "git+https://github.com/uanela/nomos-ui.git",
68
+ "directory": "packages/react"
69
+ },
70
+ "bugs": {
71
+ "url": "https://github.com/uanela/nomos-ui/issues"
72
+ },
73
+ "homepage": "https://github.com/uanela/nomos-ui/tree/main/packages/react#readme",
74
+ "files": ["dist", "README.md", "LICENSE"],
75
+ "sideEffects": false,
76
+ "packageManager": "pnpm@10.13.1",
77
+ "dependencies": {
78
+ "@radix-ui/react-slot": "^1.2.3",
79
+ "@tailwindcss/postcss": "^4.1.16",
80
+ "@tailwindcss/vite": "^4.1.16",
81
+ "class-variance-authority": "^0.7.1",
82
+ "clsx": "^2.1.1",
83
+ "lucide-react": "^0.548.0",
84
+ "tailwind-merge": "^3.3.1"
85
+ },
86
+ "devDependencies": {
87
+ "@types/node": "^24.9.1",
88
+ "@types/react": "^19.2.2",
89
+ "@types/react-dom": "^19.2.0",
90
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
91
+ "@typescript-eslint/parser": "^6.0.0",
92
+ "eslint": "^8.56.0",
93
+ "eslint-plugin-react": "^7.33.2",
94
+ "eslint-plugin-react-hooks": "^4.6.0",
95
+ "tailwindcss": "^4.1.16",
96
+ "trash-cli": "^7.0.0",
97
+ "tsx": "^4.20.3",
98
+ "typescript": "^5.9.3",
99
+ "vitest": "^4.0.3"
100
+ },
101
+ "peerDependencies": {
102
+ "react": "^18.0.0 || ^19.0.0",
103
+ "react-dom": "^18.0.0 || ^19.0.0",
104
+ "react-hook-form": "^7.0.0"
105
+ },
106
+ "peerDependenciesMeta": {
107
+ "react": {
108
+ "optional": false
109
+ },
110
+ "react-dom": {
111
+ "optional": false
112
+ },
113
+ "react-hook-form": {
114
+ "optional": false
115
+ }
116
+ },
117
+ "engines": {
118
+ "node": ">=18.0.0"
119
+ },
120
+ "publishConfig": {
121
+ "access": "public"
122
+ }
123
+ }