@connect-soft/form-generator 1.0.0

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 (3) hide show
  1. package/LICENSE.md +14 -0
  2. package/README.md +368 -0
  3. package/package.json +176 -0
package/LICENSE.md ADDED
@@ -0,0 +1,14 @@
1
+ # ISC License
2
+
3
+ [![License: ISC](https://img.shields.io/badge/License-ISC-blue.svg)](https://opensource.org/licenses/ISC)
4
+
5
+ Copyright (c) 2023 Connect Soft s.r.o.
6
+
7
+ ISC License
8
+
9
+ Copyright 2023 Connect Soft s.r.o.
10
+
11
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,368 @@
1
+ # @connect-soft/form-generator
2
+
3
+ > Type-safe form generator with Radix UI, Tailwind CSS, and react-hook-form
4
+
5
+ [![Version](https://img.shields.io/npm/v/@connect-soft/form-generator)](https://www.npmjs.com/package/@connect-soft/form-generator)
6
+ [![License](https://img.shields.io/npm/l/@connect-soft/form-generator)](./LICENSE)
7
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@connect-soft/form-generator)](https://bundlephobia.com/package/@connect-soft/form-generator)
8
+
9
+ **v2.0.0** - Complete rewrite with Radix UI + Tailwind CSS
10
+ **50-60% smaller bundle** | **No runtime CSS overhead** | **Modern, accessible UI**
11
+
12
+ ---
13
+
14
+ ## Features
15
+
16
+ ✨ **Modern UI Stack**: Radix UI primitives + Tailwind CSS (shadcn/ui approach)
17
+ 📦 **Lightweight**: <80 KB gzipped (50-60% reduction from v1)
18
+ 🎯 **Type-Safe**: Full TypeScript inference for form values
19
+ 🔧 **Flexible**: 10+ field types with extensible API
20
+ ♿ **Accessible**: Built on Radix UI's accessible primitives
21
+ 🎨 **Customizable**: Easy styling with Tailwind classes
22
+ 🚀 **Performance**: No runtime CSS-in-JS, field-level subscriptions
23
+ 🔄 **Backward Compatible**: v1→v2 adapter included
24
+
25
+ ---
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ npm install @connect-soft/form-generator react-hook-form zod
31
+ ```
32
+
33
+ ### Peer Dependencies
34
+
35
+ - `react` ^19.0.0
36
+ - `react-dom` ^19.0.0
37
+ - `zod` ^4.0.0
38
+
39
+ ### Tailwind CSS Setup
40
+
41
+ This library requires Tailwind CSS. If you don't have it set up:
42
+
43
+ ```bash
44
+ npm install -D tailwindcss postcss autoprefixer
45
+ npx tailwindcss init -p
46
+ ```
47
+
48
+ **tailwind.config.js:**
49
+ ```javascript
50
+ module.exports = {
51
+ content: [
52
+ './src/**/*.{js,ts,jsx,tsx}',
53
+ './node_modules/@connect-soft/form-generator/dist/**/*.{js,mjs}',
54
+ ],
55
+ theme: {
56
+ extend: {
57
+ // Your custom theme
58
+ },
59
+ },
60
+ plugins: [],
61
+ };
62
+ ```
63
+
64
+ **Import the styles in your main file:**
65
+ ```typescript
66
+ import '@connect-soft/form-generator/dist/styles.css';
67
+ ```
68
+
69
+ ---
70
+
71
+ ## Quick Start
72
+
73
+ ```typescript
74
+ import { FormGenerator, Field } from '@connect-soft/form-generator';
75
+
76
+ const fields: Field[] = [
77
+ {
78
+ type: 'text',
79
+ name: 'email',
80
+ label: 'Email',
81
+ fieldType: 'email',
82
+ required: true,
83
+ placeholder: 'Enter your email',
84
+ },
85
+ {
86
+ type: 'number',
87
+ name: 'age',
88
+ label: 'Age',
89
+ min: 18,
90
+ max: 120,
91
+ },
92
+ {
93
+ type: 'select',
94
+ name: 'country',
95
+ label: 'Country',
96
+ options: [
97
+ { label: 'United States', value: 'us' },
98
+ { label: 'United Kingdom', value: 'uk' },
99
+ { label: 'Germany', value: 'de' },
100
+ ],
101
+ },
102
+ {
103
+ type: 'checkbox',
104
+ name: 'subscribe',
105
+ label: 'Subscribe to newsletter',
106
+ },
107
+ ] as const;
108
+
109
+ function MyForm() {
110
+ return (
111
+ <FormGenerator
112
+ fields={fields}
113
+ onSubmit={(values) => {
114
+ // ✅ values is fully typed!
115
+ console.log(values.email); // string
116
+ console.log(values.age); // number
117
+ console.log(values.country); // string
118
+ console.log(values.subscribe);// boolean
119
+ }}
120
+ submitText="Create Account"
121
+ />
122
+ );
123
+ }
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Field Types
129
+
130
+ | Type | Description | Value Type |
131
+ |------|-------------|------------|
132
+ | `text` | Text input (email, password, url, tel) | `string` |
133
+ | `textarea` | Multi-line text input | `string` |
134
+ | `number` | Number input with min/max/step | `number` |
135
+ | `checkbox` | Checkbox input | `boolean` |
136
+ | `switch` | Toggle switch | `boolean` |
137
+ | `select` | Dropdown select | `string` |
138
+ | `radio` | Radio button group | `string` |
139
+ | `date` | Date picker (react-day-picker) | `Date` |
140
+ | `dateRange` | Date range picker | `{from: Date, to?: Date}` |
141
+ | `time` | Time picker (HH:mm) | `string` |
142
+
143
+ ---
144
+
145
+ ## Advanced Components
146
+
147
+ ### MultiSelect
148
+
149
+ ```typescript
150
+ import { MultiSelect } from '@connect-soft/form-generator/advanced';
151
+
152
+ <MultiSelect
153
+ options={[
154
+ { label: 'React', value: 'react' },
155
+ { label: 'Vue', value: 'vue' },
156
+ { label: 'Angular', value: 'angular' },
157
+ ]}
158
+ value={selected}
159
+ onChange={setSelected}
160
+ placeholder="Select frameworks..."
161
+ />
162
+ ```
163
+
164
+ ### ColorPicker
165
+
166
+ ```typescript
167
+ import { ColorPicker } from '@connect-soft/form-generator/advanced';
168
+
169
+ <ColorPicker
170
+ value={color}
171
+ onChange={setColor}
172
+ />
173
+ ```
174
+
175
+ ### TransferList
176
+
177
+ ```typescript
178
+ import { TransferList } from '@connect-soft/form-generator/advanced';
179
+
180
+ <TransferList
181
+ options={allOptions}
182
+ value={selectedValues}
183
+ onChange={setSelectedValues}
184
+ leftTitle="Available"
185
+ rightTitle="Selected"
186
+ searchable={true}
187
+ />
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Custom Validation
193
+
194
+ Use Zod for schema validation:
195
+
196
+ ```typescript
197
+ import { z } from 'zod';
198
+
199
+ const fields = [
200
+ {
201
+ type: 'text',
202
+ name: 'username',
203
+ label: 'Username',
204
+ validation: z.string().min(3).max(20).regex(/^[a-zA-Z0-9_]+$/),
205
+ },
206
+ {
207
+ type: 'text',
208
+ name: 'email',
209
+ label: 'Email',
210
+ fieldType: 'email',
211
+ validation: z.string().email().endsWith('@company.com'),
212
+ },
213
+ {
214
+ type: 'number',
215
+ name: 'age',
216
+ label: 'Age',
217
+ validation: z.number().min(18).max(120),
218
+ },
219
+ ] as const;
220
+ ```
221
+
222
+ ---
223
+
224
+ ## Styling
225
+
226
+ ### Using Tailwind Classes
227
+
228
+ ```typescript
229
+ {
230
+ type: 'text',
231
+ name: 'email',
232
+ className: 'bg-blue-50 border-blue-300 focus:ring-blue-500',
233
+ }
234
+ ```
235
+
236
+ ### Form-Level Styling
237
+
238
+ ```typescript
239
+ <FormGenerator
240
+ fields={fields}
241
+ onSubmit={handleSubmit}
242
+ className="max-w-md mx-auto p-6 bg-white rounded-lg shadow"
243
+ />
244
+ ```
245
+
246
+ ### Custom Theme
247
+
248
+ Override CSS variables in your global CSS:
249
+
250
+ ```css
251
+ :root {
252
+ --primary: 220 90% 56%;
253
+ --primary-foreground: 0 0% 100%;
254
+ --radius: 0.5rem;
255
+ }
256
+ ```
257
+
258
+ ---
259
+
260
+ ## TypeScript Type Inference
261
+
262
+ The library provides full type inference for form values:
263
+
264
+ ```typescript
265
+ const fields = [
266
+ { type: 'text', name: 'email', fieldType: 'email' },
267
+ { type: 'number', name: 'age' },
268
+ { type: 'checkbox', name: 'terms' },
269
+ { type: 'date', name: 'birthdate' },
270
+ ] as const;
271
+
272
+ <FormGenerator
273
+ fields={fields}
274
+ onSubmit={(values) => {
275
+ // ✅ Fully typed!
276
+ values.email; // string
277
+ values.age; // number
278
+ values.terms; // boolean
279
+ values.birthdate; // Date
280
+ }}
281
+ />
282
+ ```
283
+
284
+ ---
285
+
286
+ ## Migration from v1.x
287
+
288
+ Migrating from `@connect-soft/mui-hook-form` v1.x? See the [MIGRATION.md](./MIGRATION.md) guide.
289
+
290
+ ### Quick Migration with Adapter
291
+
292
+ ```typescript
293
+ import { FormGenerator } from '@connect-soft/form-generator';
294
+ import { adaptV1FieldsToV2 } from '@connect-soft/form-generator/adapters';
295
+
296
+ // Your existing v1 fields
297
+ const v1Fields = [
298
+ {
299
+ type: 'textField',
300
+ props: { name: 'email', label: 'Email', required: true },
301
+ },
302
+ ];
303
+
304
+ // Auto-convert to v2
305
+ const v2Fields = adaptV1FieldsToV2(v1Fields);
306
+
307
+ <FormGenerator fields={v2Fields} onSubmit={handleSubmit} />
308
+ ```
309
+
310
+ ---
311
+
312
+ ## API Reference
313
+
314
+ ### FormGenerator Props
315
+
316
+ | Prop | Type | Default | Description |
317
+ |------|------|---------|-------------|
318
+ | `fields` | `Field[]` | **required** | Array of field definitions |
319
+ | `onSubmit` | `(values) => void \| Promise<void>` | **required** | Form submission handler |
320
+ | `defaultValues` | `Partial<InferFormValues<TFields>>` | `{}` | Initial form values |
321
+ | `className` | `string` | - | Tailwind classes for form container |
322
+ | `submitText` | `string` | `'Submit'` | Submit button text |
323
+ | `submitButtonVariant` | `'default' \| 'destructive' \| 'outline' \| 'secondary' \| 'ghost' \| 'link'` | `'default'` | Submit button style |
324
+ | `disabled` | `boolean` | `false` | Disable entire form |
325
+ | `mode` | `'onChange' \| 'onBlur' \| 'onSubmit' \| 'onTouched' \| 'all'` | `'onChange'` | Validation trigger mode |
326
+
327
+ ### Field Base Properties
328
+
329
+ | Property | Type | Description |
330
+ |----------|------|-------------|
331
+ | `type` | `string` | Field type (text, number, select, etc.) |
332
+ | `name` | `string` | Field name (must be unique) |
333
+ | `label` | `string` | Field label |
334
+ | `description` | `string` | Helper text below field |
335
+ | `required` | `boolean` | Mark field as required |
336
+ | `disabled` | `boolean` | Disable field |
337
+ | `hidden` | `boolean` | Hide field |
338
+ | `defaultValue` | `any` | Default field value |
339
+ | `validation` | `ZodType` | Zod validation schema |
340
+ | `className` | `string` | Tailwind classes for field |
341
+
342
+ ---
343
+
344
+ ## Links
345
+
346
+ - [Migration Guide](./MIGRATION.md)
347
+ - [GitLab Repository](https://gitlab.com/connect-soft/components/form-generator)
348
+ - [Issues](https://gitlab.com/connect-soft/components/form-generator/issues)
349
+
350
+ ---
351
+
352
+ ## License
353
+
354
+ ISC © Connect Soft
355
+
356
+ ---
357
+
358
+ ## Acknowledgments
359
+
360
+ Built with:
361
+ - [Radix UI](https://www.radix-ui.com/) - Accessible UI primitives
362
+ - [Tailwind CSS](https://tailwindcss.com/) - Utility-first CSS framework
363
+ - [react-hook-form](https://react-hook-form.com/) - Performant form library
364
+ - [Zod](https://zod.dev/) - TypeScript-first schema validation
365
+ - [react-day-picker](https://react-day-picker.js.org/) - Flexible date picker
366
+ - [lucide-react](https://lucide.dev/) - Beautiful icons
367
+
368
+ Inspired by [shadcn/ui](https://ui.shadcn.com/) component architecture.
package/package.json ADDED
@@ -0,0 +1,176 @@
1
+ {
2
+ "name": "@connect-soft/form-generator",
3
+ "version": "1.0.0",
4
+ "author": "Lukáš Černý <lukas.cerny@connect-soft.cz>",
5
+ "description": "Type-safe form generator with Radix UI, Tailwind CSS, and react-hook-form",
6
+ "license": "ISC",
7
+ "main": "dist/index.js",
8
+ "module": "dist/index.m.js",
9
+ "unpkg": "dist/index.umd.js",
10
+ "umd:main": "dist/index.umd.js",
11
+ "keywords": [
12
+ "react",
13
+ "radix-ui",
14
+ "tailwind",
15
+ "shadcn",
16
+ "form",
17
+ "forms",
18
+ "form-generator",
19
+ "form-validation",
20
+ "validation",
21
+ "typescript",
22
+ "react-hooks",
23
+ "react-hook-form"
24
+ ],
25
+ "source": "packages/form-generator/src/index.ts",
26
+ "types": "dist/types/index.d.ts",
27
+ "sideEffects": false,
28
+ "exports": {
29
+ ".": {
30
+ "types": "./dist/types/index.d.ts",
31
+ "import": "./dist/index.m.js",
32
+ "require": "./dist/index.js"
33
+ },
34
+ "./package.json": "./package.json"
35
+ },
36
+ "files": [
37
+ "dist"
38
+ ],
39
+ "engines": {
40
+ "node": ">=18.18.0"
41
+ },
42
+ "browserslist": {
43
+ "production": [
44
+ ">0.2%",
45
+ "not dead",
46
+ "not op_mini all"
47
+ ],
48
+ "development": [
49
+ "last 1 chrome version",
50
+ "last 1 firefox version",
51
+ "last 1 safari version"
52
+ ]
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "git+https://gitlab.com/connect-soft/components/form-generator.git"
60
+ },
61
+ "bugs": {
62
+ "url": "https://gitlab.com/connect-soft/components/form-generator/issues"
63
+ },
64
+ "homepage": "https://gitlab.com/connect-soft/components/form-generator#readme",
65
+ "dependencies": {},
66
+ "devDependencies": {
67
+ "@babel/core": "7.28.5",
68
+ "@babel/preset-react": "7.28.5",
69
+ "@babel/preset-typescript": "7.28.5",
70
+ "@rollup/plugin-babel": "6.1.0",
71
+ "@rollup/plugin-commonjs": "^28.0.6",
72
+ "@rollup/plugin-node-resolve": "^16.0.1",
73
+ "@rollup/plugin-typescript": "^12.1.4",
74
+ "@storybook/addon-a11y": "^10.1.11",
75
+ "@storybook/addon-docs": "^10.1.11",
76
+ "@storybook/addon-links": "^10.1.11",
77
+ "@storybook/react-vite": "^10.1.11",
78
+ "@swc/core": "^1.3.102",
79
+ "@swc/jest": "^0.2.29",
80
+ "@testing-library/dom": "^10.4.1",
81
+ "@testing-library/jest-dom": "6.9.1",
82
+ "@testing-library/react": "^16.3.0",
83
+ "@types/jest": "^30.0.0",
84
+ "@types/node": "^20.0.0",
85
+ "@types/react": "^19.0.0",
86
+ "@types/react-dom": "^19.0.0",
87
+ "@types/react-transition-group": "4.4.12",
88
+ "@types/react-window": "^2.0.0",
89
+ "@types/rollup-plugin-peer-deps-external": "^2",
90
+ "@typescript-eslint/eslint-plugin": "^6.0.0",
91
+ "@typescript-eslint/parser": "^6.0.0",
92
+ "@vitejs/plugin-react": "5.1.2",
93
+ "@vitejs/plugin-react-swc": "^3.5.0",
94
+ "babel-plugin-react-compiler": "1.0.0",
95
+ "classnames": "^2.5.1",
96
+ "dayjs": "^1.11.19",
97
+ "eslint": "^8.56.0",
98
+ "eslint-config-airbnb-typescript": "^17.1.0",
99
+ "eslint-config-prettier": "^9.1.0",
100
+ "eslint-import-resolver-typescript": "^3.6.1",
101
+ "eslint-plugin-hooks": "^0.4.3",
102
+ "eslint-plugin-import": "^2.29.1",
103
+ "eslint-plugin-jest": "^27.6.2",
104
+ "eslint-plugin-jsx-a11y": "^6.8.0",
105
+ "eslint-plugin-local-rules": "^3.0.2",
106
+ "eslint-plugin-prettier": "^5.1.3",
107
+ "eslint-plugin-react": "^7.33.2",
108
+ "eslint-plugin-react-hooks": "^4.6.0",
109
+ "eslint-plugin-storybook": "^10.1.11",
110
+ "eslint-plugin-testing-library": "^6.2.0",
111
+ "jest": "^29.7.0",
112
+ "jest-canvas-mock": "^2.5.2",
113
+ "jest-environment-jsdom": "^29.7.0",
114
+ "jest-preview": "^0.3.1",
115
+ "jest-serializer-html": "^7.1.0",
116
+ "postcss": "8.5.6",
117
+ "prettier": "^3.0.0",
118
+ "react": "^19.0.0",
119
+ "react-colorful": "^5.6.1",
120
+ "react-dom": "^19.0.0",
121
+ "react-transition-group": "^4.4.5",
122
+ "require-json5": "^1.3.0",
123
+ "rimraf": "6.1.2",
124
+ "rollup": "^4.45.1",
125
+ "rollup-plugin-peer-deps-external": "^2.2.4",
126
+ "storybook": "^10.1.11",
127
+ "@tailwindcss/postcss": "^4.1.18",
128
+ "@tailwindcss/vite": "^4.1.18",
129
+ "tailwindcss": "^4.1.18",
130
+ "ts-jest": "^29.1.1",
131
+ "ts-jest-resolver": "^2.0.1",
132
+ "ts-node": "^10.9.2",
133
+ "tsc-alias": "^1.8.16",
134
+ "tsconfig": "^7.0.0",
135
+ "typescript": "^5.8.3",
136
+ "usehooks-ts": "^3.1.1",
137
+ "vite": "^5.0.0",
138
+ "vite-plugin-svgr": "^4.2.0",
139
+ "zod": "^4.0.15"
140
+ },
141
+ "peerDependencies": {
142
+ "dayjs": "^1.11.19",
143
+ "react": "^19.0.0",
144
+ "react-dom": "^19.0.0",
145
+ "zod": "^4.0.15"
146
+ },
147
+ "resolutions": {
148
+ "jackspeak": "2.1.1",
149
+ "eslint-plugin-import": "^2.25.3"
150
+ },
151
+ "scripts": {
152
+ "clean": "rimraf dist",
153
+ "prebuild": "pnpm clean",
154
+ "build": "rollup --config rollup.config.cjs && tsc-alias -p tsconfig.build.json",
155
+ "bundle:analyze": "rollup --config rollup.config.cjs --environment ANALYZE",
156
+ "bundle:size": "pnpm build && du -sh dist/*.js && gzip-size dist/index.m.js",
157
+ "prettier:fix": "prettier --config .prettierrc --write \"**/*.{js,ts,tsx,css}\"",
158
+ "type": "tsc --noEmit -p tsconfig.build.json",
159
+ "jest-preview": "jest-preview",
160
+ "test:coverage": "pnpm test -- --coverage",
161
+ "test:watch": "pnpm test -- --onlyChanged --watch",
162
+ "test": "TZ=UTC jest",
163
+ "test:type": "tsd src/__typetest__",
164
+ "postversion": "git push && git push origin v$npm_package_version",
165
+ "prepublishonly": "pnpm install && pnpm lint:fix && pnpm type && pnpm test",
166
+ "bundlewatch": "pnpm build && bundlewatch",
167
+ "start": "pnpm build && pnpm --dir ./example install && pnpm --dir ./example run dev",
168
+ "link": "(pnpm unlink | pnpm link) && pnpm link \"@connect-soft/react-file-upload\"",
169
+ "verify": "pnpm format && pnpm lint && pnpm type",
170
+ "reinstall": "rm -rf 'pnpm.lock' 'node_modules' && pnpm",
171
+ "release": "pnpm build && pnpm release:only",
172
+ "release:only": "pnpm publish",
173
+ "storybook": "storybook dev -p 6006",
174
+ "build-storybook": "storybook build"
175
+ }
176
+ }