performa 1.0.0 → 1.0.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.
- package/README.md +47 -22
- package/dist/index.cjs +38 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +38 -38
- package/dist/index.js.map +1 -1
- package/dist/nextjs.cjs +20 -20
- package/dist/nextjs.cjs.map +1 -1
- package/dist/nextjs.js +20 -20
- package/dist/nextjs.js.map +1 -1
- package/dist/react-router.cjs +20 -20
- package/dist/react-router.cjs.map +1 -1
- package/dist/react-router.js +20 -20
- package/dist/react-router.js.map +1 -1
- package/dist/tanstack-start.cjs +20 -20
- package/dist/tanstack-start.cjs.map +1 -1
- package/dist/tanstack-start.js +20 -20
- package/dist/tanstack-start.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ A lightweight, framework-agnostic React form library with built-in server-side v
|
|
|
8
8
|
- **Server-Side Validation**: Secure form validation with comprehensive validation rules
|
|
9
9
|
- **TypeScript First**: Full type safety with excellent IDE autocomplete
|
|
10
10
|
- **Accessible**: Built-in ARIA attributes and keyboard navigation
|
|
11
|
-
- **Themeable**: Fully
|
|
11
|
+
- **Themeable**: Fully customisable with Tailwind CSS or custom styling
|
|
12
12
|
- **Lightweight**: Core library is only 7.69 KB (brotli compressed)
|
|
13
13
|
- **File Uploads**: Built-in support for file validation and previews
|
|
14
14
|
- **Dark Mode**: Native dark mode support out of the box
|
|
@@ -36,12 +36,37 @@ For TanStack Start:
|
|
|
36
36
|
npm install performa @tanstack/start
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
### Tailwind CSS Setup
|
|
40
|
+
|
|
41
|
+
performa uses Tailwind CSS for styling. To ensure the styles work correctly in your project, add the performa library path to your Tailwind configuration.
|
|
42
|
+
|
|
43
|
+
Add the following to your `tailwind.config.js` or `tailwind.config.ts`:
|
|
44
|
+
|
|
45
|
+
```javascript
|
|
46
|
+
/** @type {import('tailwindcss').Config} */
|
|
47
|
+
module.exports = {
|
|
48
|
+
content: [
|
|
49
|
+
'./app/**/*.{js,ts,jsx,tsx}', // Your app files
|
|
50
|
+
'./pages/**/*.{js,ts,jsx,tsx}',
|
|
51
|
+
'./components/**/*.{js,ts,jsx,tsx}',
|
|
52
|
+
// Add performa library path
|
|
53
|
+
'./node_modules/performa/dist/**/*.{js,mjs}',
|
|
54
|
+
],
|
|
55
|
+
theme: {
|
|
56
|
+
extend: {},
|
|
57
|
+
},
|
|
58
|
+
plugins: [],
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
That's it! performa uses standard Tailwind colors and works out of the box. If you want to customize the styling, use the [FormThemeProvider](#theming) to override the default theme.
|
|
63
|
+
|
|
39
64
|
## Quick Start
|
|
40
65
|
|
|
41
66
|
### 1. Define Your Form Configuration
|
|
42
67
|
|
|
43
68
|
```typescript
|
|
44
|
-
import { FormConfig } from 'performa';
|
|
69
|
+
import type { FormConfig } from 'performa';
|
|
45
70
|
|
|
46
71
|
const loginForm = {
|
|
47
72
|
key: 'login',
|
|
@@ -140,7 +165,7 @@ export default function LoginRoute() {
|
|
|
140
165
|
}
|
|
141
166
|
|
|
142
167
|
// Action handler
|
|
143
|
-
import { validateForm } from '
|
|
168
|
+
import { validateForm } from 'performa/server';
|
|
144
169
|
|
|
145
170
|
export async function action({ request }: ActionFunctionArgs) {
|
|
146
171
|
const result = await validateForm(request, loginForm);
|
|
@@ -159,7 +184,7 @@ export async function action({ request }: ActionFunctionArgs) {
|
|
|
159
184
|
```typescript
|
|
160
185
|
import { TanStackStartForm } from 'performa/tanstack-start';
|
|
161
186
|
import { createServerFn } from '@tanstack/start';
|
|
162
|
-
import { validateForm } from '
|
|
187
|
+
import { validateForm } from 'performa/server';
|
|
163
188
|
|
|
164
189
|
const submitLogin = createServerFn({ method: 'POST' }).handler(
|
|
165
190
|
async ({ data }: { data: FormData }) => {
|
|
@@ -185,7 +210,7 @@ export default function LoginPage() {
|
|
|
185
210
|
|
|
186
211
|
### Field Types
|
|
187
212
|
|
|
188
|
-
|
|
213
|
+
performa supports the following field types:
|
|
189
214
|
|
|
190
215
|
#### Text Inputs
|
|
191
216
|
- `text` - Standard text input
|
|
@@ -284,7 +309,7 @@ All validation rules are applied server-side for security:
|
|
|
284
309
|
The `validateForm` function performs server-side validation and returns typed results:
|
|
285
310
|
|
|
286
311
|
```typescript
|
|
287
|
-
import { validateForm } from '
|
|
312
|
+
import { validateForm } from 'performa/server';
|
|
288
313
|
|
|
289
314
|
const result = await validateForm(request, formConfig);
|
|
290
315
|
|
|
@@ -299,12 +324,12 @@ const { email, password } = result.values;
|
|
|
299
324
|
|
|
300
325
|
### Custom Error Messages
|
|
301
326
|
|
|
302
|
-
You can
|
|
327
|
+
You can customise validation error messages:
|
|
303
328
|
|
|
304
329
|
```typescript
|
|
305
330
|
import { defaultErrorMessages } from 'performa/server';
|
|
306
331
|
|
|
307
|
-
//
|
|
332
|
+
// customise individual messages
|
|
308
333
|
defaultErrorMessages.required = (label) => `${label} is mandatory`;
|
|
309
334
|
defaultErrorMessages.minLength = (label, min) =>
|
|
310
335
|
`${label} needs at least ${min} characters`;
|
|
@@ -394,7 +419,7 @@ export async function submitForm(prevState: any, formData: FormData) {
|
|
|
394
419
|
|
|
395
420
|
### Default Theme
|
|
396
421
|
|
|
397
|
-
|
|
422
|
+
performa comes with a default theme optimized for Tailwind CSS with dark mode support:
|
|
398
423
|
|
|
399
424
|
```typescript
|
|
400
425
|
import { FormThemeProvider } from 'performa';
|
|
@@ -413,7 +438,7 @@ function App() {
|
|
|
413
438
|
Override the default theme with your own styles:
|
|
414
439
|
|
|
415
440
|
```typescript
|
|
416
|
-
import { FormThemeProvider } from '
|
|
441
|
+
import { FormThemeProvider } from 'performa';
|
|
417
442
|
|
|
418
443
|
const customTheme = {
|
|
419
444
|
formGroup: 'mb-6',
|
|
@@ -521,10 +546,10 @@ The complete theme object structure:
|
|
|
521
546
|
|
|
522
547
|
### Custom Labels
|
|
523
548
|
|
|
524
|
-
|
|
549
|
+
customise form labels and messages:
|
|
525
550
|
|
|
526
551
|
```typescript
|
|
527
|
-
import { FormThemeProvider } from '
|
|
552
|
+
import { FormThemeProvider } from 'performa';
|
|
528
553
|
|
|
529
554
|
const customLabels = {
|
|
530
555
|
fileUpload: {
|
|
@@ -621,7 +646,7 @@ function CustomForm() {
|
|
|
621
646
|
### Conditional Fields
|
|
622
647
|
|
|
623
648
|
```typescript
|
|
624
|
-
const formConfig
|
|
649
|
+
const formConfig = {
|
|
625
650
|
key: 'signup',
|
|
626
651
|
fields: {
|
|
627
652
|
accountType: {
|
|
@@ -642,29 +667,29 @@ const formConfig: FormConfig = {
|
|
|
642
667
|
},
|
|
643
668
|
}),
|
|
644
669
|
},
|
|
645
|
-
}
|
|
670
|
+
} satisfies FormConfig
|
|
646
671
|
```
|
|
647
672
|
|
|
648
673
|
### Multi-Step Forms
|
|
649
674
|
|
|
650
675
|
```typescript
|
|
651
|
-
const step1Config
|
|
676
|
+
const step1Config = {
|
|
652
677
|
key: 'registration-step1',
|
|
653
678
|
fields: {
|
|
654
679
|
email: { type: 'email', label: 'Email', rules: { required: true } },
|
|
655
680
|
password: { type: 'password', label: 'Password', rules: { required: true } },
|
|
656
681
|
submit: { type: 'submit', label: 'Continue' },
|
|
657
682
|
},
|
|
658
|
-
};
|
|
683
|
+
} satisfies FormConfig;
|
|
659
684
|
|
|
660
|
-
const step2Config
|
|
685
|
+
const step2Config = {
|
|
661
686
|
key: 'registration-step2',
|
|
662
687
|
fields: {
|
|
663
688
|
firstName: { type: 'text', label: 'First Name', rules: { required: true } },
|
|
664
689
|
lastName: { type: 'text', label: 'Last Name', rules: { required: true } },
|
|
665
690
|
submit: { type: 'submit', label: 'Complete Registration' },
|
|
666
691
|
},
|
|
667
|
-
};
|
|
692
|
+
} satisfies FormConfig;
|
|
668
693
|
|
|
669
694
|
function MultiStepForm() {
|
|
670
695
|
const [step, setStep] = useState(1);
|
|
@@ -701,7 +726,7 @@ function DynamicForm() {
|
|
|
701
726
|
.then(data => setCategories(data));
|
|
702
727
|
}, []);
|
|
703
728
|
|
|
704
|
-
const formConfig
|
|
729
|
+
const formConfig = {
|
|
705
730
|
key: 'product',
|
|
706
731
|
fields: {
|
|
707
732
|
category: {
|
|
@@ -714,7 +739,7 @@ function DynamicForm() {
|
|
|
714
739
|
rules: { required: true },
|
|
715
740
|
},
|
|
716
741
|
},
|
|
717
|
-
}
|
|
742
|
+
} satisfies FormConfig
|
|
718
743
|
|
|
719
744
|
return <NextForm config={formConfig} action={submitProduct} />;
|
|
720
745
|
}
|
|
@@ -722,7 +747,7 @@ function DynamicForm() {
|
|
|
722
747
|
|
|
723
748
|
## TypeScript
|
|
724
749
|
|
|
725
|
-
|
|
750
|
+
performa is built with TypeScript and provides full type safety:
|
|
726
751
|
|
|
727
752
|
```typescript
|
|
728
753
|
import { FormConfig } from 'performa';
|
|
@@ -819,7 +844,7 @@ All components are memoized with `React.memo` for optimal performance. The libra
|
|
|
819
844
|
|
|
820
845
|
## Accessibility
|
|
821
846
|
|
|
822
|
-
|
|
847
|
+
performa is built with accessibility in mind:
|
|
823
848
|
|
|
824
849
|
- Proper ARIA attributes on all form elements
|
|
825
850
|
- Keyboard navigation support
|
package/dist/index.cjs
CHANGED
|
@@ -107,48 +107,48 @@ var defaultTheme = {
|
|
|
107
107
|
required: "text-red-500 ml-1"
|
|
108
108
|
},
|
|
109
109
|
input: {
|
|
110
|
-
base: "block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-
|
|
110
|
+
base: "block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500",
|
|
111
111
|
error: "border-red-500 dark:border-red-400",
|
|
112
112
|
disabled: "disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
|
|
113
|
-
focus: "focus:outline-none focus:ring focus:ring-
|
|
113
|
+
focus: "focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
|
|
114
114
|
},
|
|
115
115
|
select: {
|
|
116
|
-
base: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring focus:ring-
|
|
116
|
+
base: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
|
|
117
117
|
error: "border-red-500 dark:border-red-400",
|
|
118
118
|
disabled: "disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
|
|
119
119
|
option: "bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100"
|
|
120
120
|
},
|
|
121
121
|
textarea: {
|
|
122
|
-
base: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-
|
|
122
|
+
base: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed",
|
|
123
123
|
error: "border-red-500 dark:border-red-400",
|
|
124
124
|
disabled: "disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed"
|
|
125
125
|
},
|
|
126
126
|
checkbox: {
|
|
127
|
-
base: "h-4 w-4 text-
|
|
127
|
+
base: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 dark:border-gray-600 dark:bg-gray-800 rounded disabled:cursor-not-allowed",
|
|
128
128
|
error: "border-red-500 dark:border-red-400",
|
|
129
129
|
label: "ml-2 block text-sm font-medium text-gray-700 dark:text-gray-300"
|
|
130
130
|
},
|
|
131
131
|
toggle: {
|
|
132
|
-
track: "absolute inset-0 rounded-full transition-colors duration-200 bg-gray-300 dark:bg-gray-600 peer-focus:ring-2 peer-focus:ring-
|
|
133
|
-
trackActive: "peer-checked:bg-
|
|
132
|
+
track: "absolute inset-0 rounded-full transition-colors duration-200 bg-gray-300 dark:bg-gray-600 peer-focus:ring-2 peer-focus:ring-blue-500 peer-focus:ring-offset-2 dark:peer-focus:ring-offset-gray-800",
|
|
133
|
+
trackActive: "peer-checked:bg-blue-600 peer-checked:dark:bg-blue-500",
|
|
134
134
|
thumb: "absolute left-1 top-1 w-4 h-4 bg-white dark:bg-gray-200 rounded-full transition-transform duration-200 peer-checked:translate-x-5",
|
|
135
135
|
label: "block text-sm font-medium text-gray-700 dark:text-gray-300"
|
|
136
136
|
},
|
|
137
137
|
radio: {
|
|
138
|
-
base: "h-4 w-4 text-
|
|
138
|
+
base: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 dark:border-gray-600 dark:bg-gray-800 disabled:cursor-not-allowed",
|
|
139
139
|
label: "ml-2 text-sm text-gray-700 dark:text-gray-300",
|
|
140
140
|
group: "mt-1"
|
|
141
141
|
},
|
|
142
142
|
file: {
|
|
143
|
-
dropzone: "flex flex-col items-center justify-center w-full p-6 border-2 border-dashed rounded-md cursor-pointer border-gray-300 dark:border-gray-600 hover:border-
|
|
144
|
-
dropzoneActive: "border-
|
|
143
|
+
dropzone: "flex flex-col items-center justify-center w-full p-6 border-2 border-dashed rounded-md cursor-pointer border-gray-300 dark:border-gray-600 hover:border-blue-500 dark:hover:border-blue-500 transition-colors duration-200",
|
|
144
|
+
dropzoneActive: "border-blue-500 bg-blue-50 dark:bg-blue-900/20",
|
|
145
145
|
dropzoneError: "border-red-500 dark:border-red-400 hover:border-red-500 dark:hover:border-red-400",
|
|
146
146
|
icon: "w-8 h-8 text-gray-400 dark:text-gray-500",
|
|
147
147
|
text: "mt-2 text-sm text-gray-500 dark:text-gray-400",
|
|
148
148
|
hint: "mt-1 text-xs text-gray-500 dark:text-gray-400"
|
|
149
149
|
},
|
|
150
150
|
submit: {
|
|
151
|
-
base: "mt-1 flex items-center justify-center w-full px-4 py-2 border border-transparent rounded-md shadow-sm text-white bg-
|
|
151
|
+
base: "mt-1 flex items-center justify-center w-full px-4 py-2 border border-transparent rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-500 focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-gray-800 focus:ring-blue-500 transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
|
|
152
152
|
loading: "opacity-75",
|
|
153
153
|
spinner: "mr-3 -ml-1 size-5 animate-spin text-white"
|
|
154
154
|
},
|
|
@@ -161,18 +161,18 @@ var defaultTheme = {
|
|
|
161
161
|
info: "bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200 border-blue-200 dark:border-blue-800"
|
|
162
162
|
},
|
|
163
163
|
datetime: {
|
|
164
|
-
input: "block w-full px-3 py-2 pr-10 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-
|
|
164
|
+
input: "block w-full px-3 py-2 pr-10 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-400 dark:placeholder-gray-500 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 dark:disabled:bg-gray-700 disabled:cursor-not-allowed cursor-pointer",
|
|
165
165
|
dropdown: "absolute z-50 mt-2 p-4 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg shadow-lg w-80",
|
|
166
166
|
picker: "absolute z-50 mt-2 p-4 bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-600 rounded-lg shadow-lg w-80",
|
|
167
167
|
calendar: "grid grid-cols-7 gap-1 mb-4",
|
|
168
|
-
day: "p-2 text-sm rounded hover:bg-
|
|
169
|
-
daySelected: "bg-
|
|
170
|
-
dayButton: "p-2 text-sm rounded hover:bg-
|
|
171
|
-
dayButtonSelected: "bg-
|
|
168
|
+
day: "p-2 text-sm rounded hover:bg-blue-600 hover:text-white transition-colors text-gray-700 dark:text-gray-300",
|
|
169
|
+
daySelected: "bg-blue-600 text-white",
|
|
170
|
+
dayButton: "p-2 text-sm rounded hover:bg-blue-600 hover:text-white transition-colors text-gray-700 dark:text-gray-300",
|
|
171
|
+
dayButtonSelected: "bg-blue-600 text-white",
|
|
172
172
|
timeInput: "w-14 px-2 py-1 text-center border border-gray-300 dark:border-gray-600 rounded bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100",
|
|
173
173
|
timeLabel: "text-xs font-medium text-gray-700 dark:text-gray-300",
|
|
174
174
|
periodButton: "px-3 py-1 text-xs rounded bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300",
|
|
175
|
-
periodButtonActive: "bg-
|
|
175
|
+
periodButtonActive: "bg-blue-600 text-white",
|
|
176
176
|
iconButton: "absolute right-2 top-1/2 -translate-y-1/2 text-gray-500 dark:text-gray-400",
|
|
177
177
|
navButton: "p-1 hover:bg-gray-100 dark:hover:bg-gray-700 rounded text-gray-700 dark:text-white",
|
|
178
178
|
monthYear: "text-sm font-medium text-gray-900 dark:text-gray-100",
|
|
@@ -180,7 +180,7 @@ var defaultTheme = {
|
|
|
180
180
|
formatButton: "px-2 py-1 text-xs bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded hover:bg-gray-200 dark:hover:bg-gray-600"
|
|
181
181
|
},
|
|
182
182
|
button: {
|
|
183
|
-
primary: "flex-1 px-3 py-2 text-sm bg-
|
|
183
|
+
primary: "flex-1 px-3 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
|
|
184
184
|
secondary: "flex-1 px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300"
|
|
185
185
|
},
|
|
186
186
|
readonly: "mt-1 block w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md shadow-sm bg-gray-100 dark:bg-gray-700 text-gray-900 dark:text-gray-100",
|
|
@@ -200,48 +200,48 @@ var lightOnlyTheme = {
|
|
|
200
200
|
required: "text-red-500 ml-1"
|
|
201
201
|
},
|
|
202
202
|
input: {
|
|
203
|
-
base: "block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-
|
|
203
|
+
base: "block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500",
|
|
204
204
|
error: "border-red-500",
|
|
205
205
|
disabled: "disabled:bg-gray-100 disabled:cursor-not-allowed",
|
|
206
|
-
focus: "focus:outline-none focus:ring focus:ring-
|
|
206
|
+
focus: "focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500"
|
|
207
207
|
},
|
|
208
208
|
select: {
|
|
209
|
-
base: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 focus:outline-none focus:ring focus:ring-
|
|
209
|
+
base: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed",
|
|
210
210
|
error: "border-red-500",
|
|
211
211
|
disabled: "disabled:bg-gray-100 disabled:cursor-not-allowed",
|
|
212
212
|
option: "bg-white text-gray-900"
|
|
213
213
|
},
|
|
214
214
|
textarea: {
|
|
215
|
-
base: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-
|
|
215
|
+
base: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed",
|
|
216
216
|
error: "border-red-500",
|
|
217
217
|
disabled: "disabled:bg-gray-100 disabled:cursor-not-allowed"
|
|
218
218
|
},
|
|
219
219
|
checkbox: {
|
|
220
|
-
base: "h-4 w-4 text-
|
|
220
|
+
base: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded disabled:cursor-not-allowed",
|
|
221
221
|
error: "border-red-500",
|
|
222
222
|
label: "ml-2 block text-sm font-medium text-gray-700"
|
|
223
223
|
},
|
|
224
224
|
toggle: {
|
|
225
|
-
track: "absolute inset-0 rounded-full transition-colors duration-200 bg-gray-300 peer-focus:ring-2 peer-focus:ring-
|
|
226
|
-
trackActive: "peer-checked:bg-
|
|
225
|
+
track: "absolute inset-0 rounded-full transition-colors duration-200 bg-gray-300 peer-focus:ring-2 peer-focus:ring-blue-500 peer-focus:ring-offset-2",
|
|
226
|
+
trackActive: "peer-checked:bg-blue-600",
|
|
227
227
|
thumb: "absolute left-1 top-1 w-4 h-4 bg-white rounded-full transition-transform duration-200 peer-checked:translate-x-5",
|
|
228
228
|
label: "block text-sm font-medium text-gray-700"
|
|
229
229
|
},
|
|
230
230
|
radio: {
|
|
231
|
-
base: "h-4 w-4 text-
|
|
231
|
+
base: "h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 disabled:cursor-not-allowed",
|
|
232
232
|
label: "ml-2 text-sm text-gray-700",
|
|
233
233
|
group: "mt-1"
|
|
234
234
|
},
|
|
235
235
|
file: {
|
|
236
|
-
dropzone: "flex flex-col items-center justify-center w-full p-6 border-2 border-dashed rounded-md cursor-pointer border-gray-300 hover:border-
|
|
237
|
-
dropzoneActive: "border-
|
|
236
|
+
dropzone: "flex flex-col items-center justify-center w-full p-6 border-2 border-dashed rounded-md cursor-pointer border-gray-300 hover:border-blue-500 transition-colors duration-200",
|
|
237
|
+
dropzoneActive: "border-blue-500 bg-blue-50",
|
|
238
238
|
dropzoneError: "border-red-500 hover:border-red-500",
|
|
239
239
|
icon: "w-8 h-8 text-gray-400",
|
|
240
240
|
text: "mt-2 text-sm text-gray-500",
|
|
241
241
|
hint: "mt-1 text-xs text-gray-500"
|
|
242
242
|
},
|
|
243
243
|
submit: {
|
|
244
|
-
base: "mt-1 flex items-center justify-center w-full px-4 py-2 border border-transparent rounded-md shadow-sm text-white bg-
|
|
244
|
+
base: "mt-1 flex items-center justify-center w-full px-4 py-2 border border-transparent rounded-md shadow-sm text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors cursor-pointer disabled:opacity-50 disabled:cursor-not-allowed",
|
|
245
245
|
loading: "opacity-75",
|
|
246
246
|
spinner: "mr-3 -ml-1 size-5 animate-spin text-white"
|
|
247
247
|
},
|
|
@@ -254,18 +254,18 @@ var lightOnlyTheme = {
|
|
|
254
254
|
info: "bg-blue-50 text-blue-800 border-blue-200"
|
|
255
255
|
},
|
|
256
256
|
datetime: {
|
|
257
|
-
input: "block w-full px-3 py-2 pr-10 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-
|
|
257
|
+
input: "block w-full px-3 py-2 pr-10 border border-gray-300 rounded-md shadow-sm bg-white text-gray-900 placeholder-gray-400 focus:outline-none focus:ring focus:ring-blue-500 focus:border-blue-500 disabled:bg-gray-100 disabled:cursor-not-allowed cursor-pointer",
|
|
258
258
|
dropdown: "absolute z-50 mt-2 p-4 bg-white border border-gray-300 rounded-lg shadow-lg w-80",
|
|
259
259
|
picker: "absolute z-50 mt-2 p-4 bg-white border border-gray-300 rounded-lg shadow-lg w-80",
|
|
260
260
|
calendar: "grid grid-cols-7 gap-1 mb-4",
|
|
261
|
-
day: "p-2 text-sm rounded hover:bg-
|
|
262
|
-
daySelected: "bg-
|
|
263
|
-
dayButton: "p-2 text-sm rounded hover:bg-
|
|
264
|
-
dayButtonSelected: "bg-
|
|
261
|
+
day: "p-2 text-sm rounded hover:bg-blue-600 hover:text-white transition-colors text-gray-700",
|
|
262
|
+
daySelected: "bg-blue-600 text-white",
|
|
263
|
+
dayButton: "p-2 text-sm rounded hover:bg-blue-600 hover:text-white transition-colors text-gray-700",
|
|
264
|
+
dayButtonSelected: "bg-blue-600 text-white",
|
|
265
265
|
timeInput: "w-14 px-2 py-1 text-center border border-gray-300 rounded bg-white text-gray-900",
|
|
266
266
|
timeLabel: "text-xs font-medium text-gray-700",
|
|
267
267
|
periodButton: "px-3 py-1 text-xs rounded bg-gray-100 text-gray-700",
|
|
268
|
-
periodButtonActive: "bg-
|
|
268
|
+
periodButtonActive: "bg-blue-600 text-white",
|
|
269
269
|
iconButton: "absolute right-2 top-1/2 -translate-y-1/2 text-gray-500",
|
|
270
270
|
navButton: "p-1 hover:bg-gray-100 rounded text-gray-700",
|
|
271
271
|
monthYear: "text-sm font-medium text-gray-900",
|
|
@@ -273,7 +273,7 @@ var lightOnlyTheme = {
|
|
|
273
273
|
formatButton: "px-2 py-1 text-xs bg-gray-100 text-gray-700 rounded hover:bg-gray-200"
|
|
274
274
|
},
|
|
275
275
|
button: {
|
|
276
|
-
primary: "flex-1 px-3 py-2 text-sm bg-
|
|
276
|
+
primary: "flex-1 px-3 py-2 text-sm bg-blue-600 text-white rounded hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2",
|
|
277
277
|
secondary: "flex-1 px-3 py-2 text-sm border border-gray-300 rounded hover:bg-gray-50 text-gray-700"
|
|
278
278
|
},
|
|
279
279
|
readonly: "mt-1 block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm bg-gray-100 text-gray-900",
|
|
@@ -1173,7 +1173,7 @@ function FileInput({
|
|
|
1173
1173
|
)
|
|
1174
1174
|
}
|
|
1175
1175
|
),
|
|
1176
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: theme.file?.text, children: fileName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-
|
|
1176
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: theme.file?.text, children: fileName ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-blue-600 dark:text-blue-400", children: fileName }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1177
1177
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: labels.fileUpload?.clickToUpload }),
|
|
1178
1178
|
" ",
|
|
1179
1179
|
labels.fileUpload?.dragAndDrop
|
|
@@ -1210,7 +1210,7 @@ function FileInput({
|
|
|
1210
1210
|
href: fileUrl,
|
|
1211
1211
|
target: "_blank",
|
|
1212
1212
|
rel: "noopener noreferrer",
|
|
1213
|
-
className: "mt-2 inline-flex items-center text-xs text-
|
|
1213
|
+
className: "mt-2 inline-flex items-center text-xs text-blue-600 hover:underline dark:text-blue-400",
|
|
1214
1214
|
children: [
|
|
1215
1215
|
"View Current ",
|
|
1216
1216
|
label,
|