config-driven-form 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.
package/README.md ADDED
@@ -0,0 +1,46 @@
1
+ # Config-Driven Form
2
+
3
+ A highly scalable, config-driven React form library that dynamically generates beautiful, fully validated forms directly from JSON Schema.
4
+
5
+ ## Features
6
+
7
+ - **Performant**: Built on top of `react-hook-form` and `ajv` to minimize re-renders and handle complex schemas efficiently.
8
+ - **Extensible**: Easily add custom field types (like rich-text editors, maps, or file uploaders) using our custom `FieldRenderer` engine.
9
+ - **Rich Text Support**: Built-in integration with `Tiptap` for rich text editing.
10
+ - **Beautiful by Default**: Features a modern, glassmorphic design system out of the box using pure CSS.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ npm install config-driven-form react-hook-form
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ```tsx
21
+ import React from 'react';
22
+ import { SchemaForm, JSONSchema } from 'config-driven-form';
23
+ import 'config-driven-form/dist/index.css';
24
+
25
+ const mySchema: JSONSchema = {
26
+ type: 'object',
27
+ title: 'Contact Us',
28
+ properties: {
29
+ email: { type: 'string', format: 'email', title: 'Email Address' },
30
+ message: { type: 'string', format: 'rich-text', title: 'Your Message' },
31
+ },
32
+ required: ['email'],
33
+ };
34
+
35
+ export default function App() {
36
+ return (
37
+ <div style={{ padding: '2rem' }}>
38
+ <SchemaForm schema={mySchema} onSubmit={(data) => console.log(data)} />
39
+ </div>
40
+ );
41
+ }
42
+ ```
43
+
44
+ ## Contributing
45
+
46
+ We welcome contributions! If you want to fix a bug, add a new field type, or improve the documentation, please read our [Developer's Guide (CONTRIBUTING.md)](./CONTRIBUTING.md) to get started with your local development environment.
package/dist/index.css ADDED
@@ -0,0 +1,176 @@
1
+ /* src/styles/form.css */
2
+ :root {
3
+ --cdf-primary: #6366f1;
4
+ --cdf-primary-hover: #4f46e5;
5
+ --cdf-primary-light: rgba(99, 102, 241, 0.1);
6
+ --cdf-error: #ef4444;
7
+ --cdf-error-light: rgba(239, 68, 68, 0.1);
8
+ --cdf-bg: #ffffff;
9
+ --cdf-surface: #f8fafc;
10
+ --cdf-border: #e2e8f0;
11
+ --cdf-border-focus: #94a3b8;
12
+ --cdf-text: #0f172a;
13
+ --cdf-text-muted: #64748b;
14
+ --cdf-radius: 12px;
15
+ --cdf-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05);
16
+ --cdf-shadow-focus: 0 0 0 4px rgba(99, 102, 241, 0.15);
17
+ --cdf-font:
18
+ "Inter",
19
+ -apple-system,
20
+ BlinkMacSystemFont,
21
+ "Segoe UI",
22
+ Roboto,
23
+ sans-serif;
24
+ --cdf-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
25
+ }
26
+ .cdf-form-container {
27
+ font-family: var(--cdf-font);
28
+ color: var(--cdf-text);
29
+ background: var(--cdf-bg);
30
+ border-radius: var(--cdf-radius);
31
+ padding: 2rem;
32
+ box-shadow: var(--cdf-shadow);
33
+ max-width: 600px;
34
+ margin: 0 auto;
35
+ border: 1px solid var(--cdf-border);
36
+ }
37
+ .cdf-form-title {
38
+ font-size: 1.5rem;
39
+ font-weight: 600;
40
+ margin-bottom: 1.5rem;
41
+ color: var(--cdf-text);
42
+ }
43
+ .cdf-field-group {
44
+ margin-bottom: 1.25rem;
45
+ display: flex;
46
+ flex-direction: column;
47
+ }
48
+ .cdf-label {
49
+ font-size: 0.875rem;
50
+ font-weight: 500;
51
+ margin-bottom: 0.5rem;
52
+ color: var(--cdf-text);
53
+ display: flex;
54
+ align-items: center;
55
+ gap: 0.25rem;
56
+ }
57
+ .cdf-required-mark {
58
+ color: var(--cdf-error);
59
+ }
60
+ .cdf-input-wrapper {
61
+ position: relative;
62
+ display: flex;
63
+ align-items: center;
64
+ }
65
+ .cdf-input {
66
+ width: 100%;
67
+ padding: 0.75rem 1rem;
68
+ font-size: 0.9375rem;
69
+ font-family: var(--cdf-font);
70
+ color: var(--cdf-text);
71
+ background-color: var(--cdf-surface);
72
+ border: 1px solid var(--cdf-border);
73
+ border-radius: var(--cdf-radius);
74
+ transition: var(--cdf-transition);
75
+ outline: none;
76
+ box-sizing: border-box;
77
+ }
78
+ .cdf-input:hover {
79
+ border-color: var(--cdf-border-focus);
80
+ }
81
+ .cdf-input:focus {
82
+ border-color: var(--cdf-primary);
83
+ background-color: var(--cdf-bg);
84
+ box-shadow: var(--cdf-shadow-focus);
85
+ }
86
+ .cdf-input--error {
87
+ border-color: var(--cdf-error);
88
+ background-color: var(--cdf-error-light);
89
+ }
90
+ .cdf-input--error:focus {
91
+ border-color: var(--cdf-error);
92
+ box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.15);
93
+ }
94
+ .cdf-error-message {
95
+ font-size: 0.75rem;
96
+ color: var(--cdf-error);
97
+ margin-top: 0.375rem;
98
+ display: flex;
99
+ align-items: center;
100
+ gap: 0.25rem;
101
+ }
102
+ .cdf-submit-btn {
103
+ width: 100%;
104
+ padding: 0.875rem 1.5rem;
105
+ font-size: 1rem;
106
+ font-weight: 600;
107
+ font-family: var(--cdf-font);
108
+ color: #ffffff;
109
+ background-color: var(--cdf-primary);
110
+ border: none;
111
+ border-radius: var(--cdf-radius);
112
+ cursor: pointer;
113
+ transition: var(--cdf-transition);
114
+ margin-top: 1rem;
115
+ box-shadow: 0 4px 14px 0 rgba(99, 102, 241, 0.39);
116
+ }
117
+ .cdf-submit-btn:hover {
118
+ background-color: var(--cdf-primary-hover);
119
+ transform: translateY(-1px);
120
+ box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4);
121
+ }
122
+ .cdf-submit-btn:active {
123
+ transform: translateY(1px);
124
+ box-shadow: 0 2px 10px rgba(99, 102, 241, 0.3);
125
+ }
126
+ .cdf-rich-text-wrapper {
127
+ border: 1px solid var(--cdf-border);
128
+ border-radius: var(--cdf-radius);
129
+ overflow: hidden;
130
+ transition: var(--cdf-transition);
131
+ }
132
+ .cdf-rich-text-wrapper:focus-within {
133
+ border-color: var(--cdf-primary);
134
+ box-shadow: var(--cdf-shadow-focus);
135
+ }
136
+ .cdf-rich-text-toolbar {
137
+ display: flex;
138
+ gap: 0.25rem;
139
+ padding: 0.5rem;
140
+ background: var(--cdf-surface);
141
+ border-bottom: 1px solid var(--cdf-border);
142
+ }
143
+ .cdf-toolbar-btn {
144
+ padding: 0.375rem;
145
+ background: transparent;
146
+ border: none;
147
+ border-radius: 4px;
148
+ cursor: pointer;
149
+ color: var(--cdf-text-muted);
150
+ transition: var(--cdf-transition);
151
+ }
152
+ .cdf-toolbar-btn:hover {
153
+ background: rgba(0, 0, 0, 0.05);
154
+ color: var(--cdf-text);
155
+ }
156
+ .cdf-toolbar-btn.is-active {
157
+ background: var(--cdf-primary-light);
158
+ color: var(--cdf-primary);
159
+ }
160
+ .cdf-rich-text-content {
161
+ padding: 1rem;
162
+ min-height: 120px;
163
+ background: var(--cdf-bg);
164
+ outline: none;
165
+ }
166
+ .cdf-rich-text-content .ProseMirror {
167
+ outline: none;
168
+ }
169
+ .cdf-rich-text-content .ProseMirror p.is-editor-empty:first-child::before {
170
+ color: var(--cdf-text-muted);
171
+ content: attr(data-placeholder);
172
+ float: left;
173
+ height: 0;
174
+ pointer-events: none;
175
+ }
176
+ /*# sourceMappingURL=index.css.map */
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/styles/form.css"],"sourcesContent":[":root {\n --cdf-primary: #6366f1;\n --cdf-primary-hover: #4f46e5;\n --cdf-primary-light: rgba(99, 102, 241, 0.1);\n --cdf-error: #ef4444;\n --cdf-error-light: rgba(239, 68, 68, 0.1);\n --cdf-bg: #ffffff;\n --cdf-surface: #f8fafc;\n --cdf-border: #e2e8f0;\n --cdf-border-focus: #94a3b8;\n --cdf-text: #0f172a;\n --cdf-text-muted: #64748b;\n --cdf-radius: 12px;\n --cdf-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -2px rgba(0, 0, 0, 0.05);\n --cdf-shadow-focus: 0 0 0 4px rgba(99, 102, 241, 0.15);\n --cdf-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --cdf-transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n}\n\n.cdf-form-container {\n font-family: var(--cdf-font);\n color: var(--cdf-text);\n background: var(--cdf-bg);\n border-radius: var(--cdf-radius);\n padding: 2rem;\n box-shadow: var(--cdf-shadow);\n max-width: 600px;\n margin: 0 auto;\n border: 1px solid var(--cdf-border);\n}\n\n.cdf-form-title {\n font-size: 1.5rem;\n font-weight: 600;\n margin-bottom: 1.5rem;\n color: var(--cdf-text);\n}\n\n.cdf-field-group {\n margin-bottom: 1.25rem;\n display: flex;\n flex-direction: column;\n}\n\n.cdf-label {\n font-size: 0.875rem;\n font-weight: 500;\n margin-bottom: 0.5rem;\n color: var(--cdf-text);\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.cdf-required-mark {\n color: var(--cdf-error);\n}\n\n.cdf-input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n}\n\n.cdf-input {\n width: 100%;\n padding: 0.75rem 1rem;\n font-size: 0.9375rem;\n font-family: var(--cdf-font);\n color: var(--cdf-text);\n background-color: var(--cdf-surface);\n border: 1px solid var(--cdf-border);\n border-radius: var(--cdf-radius);\n transition: var(--cdf-transition);\n outline: none;\n box-sizing: border-box;\n}\n\n.cdf-input:hover {\n border-color: var(--cdf-border-focus);\n}\n\n.cdf-input:focus {\n border-color: var(--cdf-primary);\n background-color: var(--cdf-bg);\n box-shadow: var(--cdf-shadow-focus);\n}\n\n.cdf-input--error {\n border-color: var(--cdf-error);\n background-color: var(--cdf-error-light);\n}\n\n.cdf-input--error:focus {\n border-color: var(--cdf-error);\n box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.15);\n}\n\n.cdf-error-message {\n font-size: 0.75rem;\n color: var(--cdf-error);\n margin-top: 0.375rem;\n display: flex;\n align-items: center;\n gap: 0.25rem;\n}\n\n.cdf-submit-btn {\n width: 100%;\n padding: 0.875rem 1.5rem;\n font-size: 1rem;\n font-weight: 600;\n font-family: var(--cdf-font);\n color: #ffffff;\n background-color: var(--cdf-primary);\n border: none;\n border-radius: var(--cdf-radius);\n cursor: pointer;\n transition: var(--cdf-transition);\n margin-top: 1rem;\n box-shadow: 0 4px 14px 0 rgba(99, 102, 241, 0.39);\n}\n\n.cdf-submit-btn:hover {\n background-color: var(--cdf-primary-hover);\n transform: translateY(-1px);\n box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4);\n}\n\n.cdf-submit-btn:active {\n transform: translateY(1px);\n box-shadow: 0 2px 10px rgba(99, 102, 241, 0.3);\n}\n\n/* Rich Text Editor Overrides */\n.cdf-rich-text-wrapper {\n border: 1px solid var(--cdf-border);\n border-radius: var(--cdf-radius);\n overflow: hidden;\n transition: var(--cdf-transition);\n}\n\n.cdf-rich-text-wrapper:focus-within {\n border-color: var(--cdf-primary);\n box-shadow: var(--cdf-shadow-focus);\n}\n\n.cdf-rich-text-toolbar {\n display: flex;\n gap: 0.25rem;\n padding: 0.5rem;\n background: var(--cdf-surface);\n border-bottom: 1px solid var(--cdf-border);\n}\n\n.cdf-toolbar-btn {\n padding: 0.375rem;\n background: transparent;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n color: var(--cdf-text-muted);\n transition: var(--cdf-transition);\n}\n\n.cdf-toolbar-btn:hover {\n background: rgba(0, 0, 0, 0.05);\n color: var(--cdf-text);\n}\n\n.cdf-toolbar-btn.is-active {\n background: var(--cdf-primary-light);\n color: var(--cdf-primary);\n}\n\n.cdf-rich-text-content {\n padding: 1rem;\n min-height: 120px;\n background: var(--cdf-bg);\n outline: none;\n}\n\n.cdf-rich-text-content .ProseMirror {\n outline: none;\n}\n\n.cdf-rich-text-content .ProseMirror p.is-editor-empty:first-child::before {\n color: var(--cdf-text-muted);\n content: attr(data-placeholder);\n float: left;\n height: 0;\n pointer-events: none;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+
3
+ type FieldType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
4
+ type FieldFormat = 'email' | 'password' | 'date' | 'time' | 'uri' | 'rich-text' | string;
5
+ interface JSONSchema {
6
+ type: FieldType;
7
+ title?: string;
8
+ description?: string;
9
+ format?: FieldFormat;
10
+ properties?: Record<string, JSONSchema>;
11
+ required?: string[];
12
+ minLength?: number;
13
+ maxLength?: number;
14
+ minimum?: number;
15
+ maximum?: number;
16
+ pattern?: string;
17
+ enum?: any[];
18
+ items?: JSONSchema | JSONSchema[];
19
+ default?: any;
20
+ }
21
+
22
+ interface SchemaFormProps {
23
+ schema: JSONSchema;
24
+ onSubmit: (data: any) => void;
25
+ defaultValues?: any;
26
+ }
27
+ declare const SchemaForm: React.FC<SchemaFormProps>;
28
+
29
+ interface FieldRendererProps {
30
+ name: string;
31
+ schema: JSONSchema;
32
+ isRequired?: boolean;
33
+ }
34
+ declare const FieldRenderer: React.FC<FieldRendererProps>;
35
+
36
+ export { type FieldFormat, FieldRenderer, type FieldType, type JSONSchema, SchemaForm };
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+
3
+ type FieldType = 'string' | 'number' | 'integer' | 'boolean' | 'object' | 'array';
4
+ type FieldFormat = 'email' | 'password' | 'date' | 'time' | 'uri' | 'rich-text' | string;
5
+ interface JSONSchema {
6
+ type: FieldType;
7
+ title?: string;
8
+ description?: string;
9
+ format?: FieldFormat;
10
+ properties?: Record<string, JSONSchema>;
11
+ required?: string[];
12
+ minLength?: number;
13
+ maxLength?: number;
14
+ minimum?: number;
15
+ maximum?: number;
16
+ pattern?: string;
17
+ enum?: any[];
18
+ items?: JSONSchema | JSONSchema[];
19
+ default?: any;
20
+ }
21
+
22
+ interface SchemaFormProps {
23
+ schema: JSONSchema;
24
+ onSubmit: (data: any) => void;
25
+ defaultValues?: any;
26
+ }
27
+ declare const SchemaForm: React.FC<SchemaFormProps>;
28
+
29
+ interface FieldRendererProps {
30
+ name: string;
31
+ schema: JSONSchema;
32
+ isRequired?: boolean;
33
+ }
34
+ declare const FieldRenderer: React.FC<FieldRendererProps>;
35
+
36
+ export { type FieldFormat, FieldRenderer, type FieldType, type JSONSchema, SchemaForm };
package/dist/index.js ADDED
@@ -0,0 +1,250 @@
1
+ 'use strict';
2
+
3
+ var reactHookForm = require('react-hook-form');
4
+ var ajv = require('@hookform/resolvers/ajv');
5
+ var lucideReact = require('lucide-react');
6
+ var jsxRuntime = require('react/jsx-runtime');
7
+ var react = require('react');
8
+ var react$1 = require('@tiptap/react');
9
+ var StarterKit = require('@tiptap/starter-kit');
10
+
11
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
12
+
13
+ var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
14
+
15
+ // src/components/SchemaForm.tsx
16
+ var TextField = ({ name, schema, isRequired }) => {
17
+ const {
18
+ register,
19
+ formState: { errors }
20
+ } = reactHookForm.useFormContext();
21
+ const error = errors[name];
22
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-field-group", children: [
23
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "cdf-label", htmlFor: name, children: [
24
+ schema.title || name,
25
+ isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
26
+ ] }),
27
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdf-input-wrapper", children: /* @__PURE__ */ jsxRuntime.jsx(
28
+ "input",
29
+ {
30
+ id: name,
31
+ type: schema.format === "email" ? "email" : "text",
32
+ className: `cdf-input ${error ? "cdf-input--error" : ""}`,
33
+ placeholder: `Enter ${schema.title || name}`,
34
+ ...register(name)
35
+ }
36
+ ) }),
37
+ error && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "cdf-error-message", children: [
38
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 14 }),
39
+ error.message
40
+ ] })
41
+ ] });
42
+ };
43
+ var PasswordField = ({ name, schema, isRequired }) => {
44
+ const {
45
+ register,
46
+ formState: { errors }
47
+ } = reactHookForm.useFormContext();
48
+ const [showPassword, setShowPassword] = react.useState(false);
49
+ const error = errors[name];
50
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-field-group", children: [
51
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "cdf-label", htmlFor: name, children: [
52
+ schema.title || name,
53
+ isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
54
+ ] }),
55
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-input-wrapper", children: [
56
+ /* @__PURE__ */ jsxRuntime.jsx(
57
+ "input",
58
+ {
59
+ id: name,
60
+ type: showPassword ? "text" : "password",
61
+ className: `cdf-input ${error ? "cdf-input--error" : ""}`,
62
+ style: { paddingRight: "2.5rem" },
63
+ placeholder: `Enter ${schema.title || name}`,
64
+ ...register(name)
65
+ }
66
+ ),
67
+ /* @__PURE__ */ jsxRuntime.jsx(
68
+ "button",
69
+ {
70
+ type: "button",
71
+ className: "cdf-toolbar-btn",
72
+ style: { position: "absolute", right: "0.5rem" },
73
+ onClick: () => setShowPassword(!showPassword),
74
+ children: showPassword ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: 16 })
75
+ }
76
+ )
77
+ ] }),
78
+ error && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "cdf-error-message", children: [
79
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 14 }),
80
+ error.message
81
+ ] })
82
+ ] });
83
+ };
84
+ var NumberField = ({ name, schema, isRequired }) => {
85
+ const {
86
+ register,
87
+ formState: { errors }
88
+ } = reactHookForm.useFormContext();
89
+ const error = errors[name];
90
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-field-group", children: [
91
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "cdf-label", htmlFor: name, children: [
92
+ schema.title || name,
93
+ isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
94
+ ] }),
95
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdf-input-wrapper", children: /* @__PURE__ */ jsxRuntime.jsx(
96
+ "input",
97
+ {
98
+ id: name,
99
+ type: "number",
100
+ className: `cdf-input ${error ? "cdf-input--error" : ""}`,
101
+ placeholder: `Enter ${schema.title || name}`,
102
+ ...register(name, {
103
+ valueAsNumber: true
104
+ })
105
+ }
106
+ ) }),
107
+ error && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "cdf-error-message", children: [
108
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 14 }),
109
+ error.message
110
+ ] })
111
+ ] });
112
+ };
113
+ var RichTextField = ({ name, schema, isRequired }) => {
114
+ const {
115
+ setValue,
116
+ watch,
117
+ formState: { errors }
118
+ } = reactHookForm.useFormContext();
119
+ const error = errors[name];
120
+ const value = watch(name);
121
+ const editor = react$1.useEditor({
122
+ extensions: [StarterKit__default.default],
123
+ content: value || "",
124
+ onUpdate: ({ editor: editor2 }) => {
125
+ setValue(name, editor2.getHTML(), { shouldValidate: true, shouldDirty: true });
126
+ }
127
+ });
128
+ react.useEffect(() => {
129
+ if (editor && value !== editor.getHTML()) {
130
+ editor.commands.setContent(value || "");
131
+ }
132
+ }, [value, editor]);
133
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-field-group", children: [
134
+ /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "cdf-label", htmlFor: name, children: [
135
+ schema.title || name,
136
+ isRequired && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "cdf-required-mark", children: "*" })
137
+ ] }),
138
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `cdf-rich-text-wrapper ${error ? "cdf-input--error" : ""}`, children: [
139
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-rich-text-toolbar", children: [
140
+ /* @__PURE__ */ jsxRuntime.jsx(
141
+ "button",
142
+ {
143
+ type: "button",
144
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleBold().run(),
145
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("bold")) ? "is-active" : ""}`,
146
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Bold, { size: 16 })
147
+ }
148
+ ),
149
+ /* @__PURE__ */ jsxRuntime.jsx(
150
+ "button",
151
+ {
152
+ type: "button",
153
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleItalic().run(),
154
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("italic")) ? "is-active" : ""}`,
155
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Italic, { size: 16 })
156
+ }
157
+ ),
158
+ /* @__PURE__ */ jsxRuntime.jsx(
159
+ "button",
160
+ {
161
+ type: "button",
162
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleHeading({ level: 2 }).run(),
163
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("heading", { level: 2 })) ? "is-active" : ""}`,
164
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Heading2, { size: 16 })
165
+ }
166
+ ),
167
+ /* @__PURE__ */ jsxRuntime.jsx(
168
+ "button",
169
+ {
170
+ type: "button",
171
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleBulletList().run(),
172
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("bulletList")) ? "is-active" : ""}`,
173
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.List, { size: 16 })
174
+ }
175
+ ),
176
+ /* @__PURE__ */ jsxRuntime.jsx(
177
+ "button",
178
+ {
179
+ type: "button",
180
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleOrderedList().run(),
181
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("orderedList")) ? "is-active" : ""}`,
182
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListOrdered, { size: 16 })
183
+ }
184
+ )
185
+ ] }),
186
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.EditorContent, { editor, className: "cdf-rich-text-content" })
187
+ ] }),
188
+ error && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "cdf-error-message", children: [
189
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { size: 14 }),
190
+ error.message
191
+ ] })
192
+ ] });
193
+ };
194
+ var FieldRenderer = ({ name, schema, isRequired }) => {
195
+ if (schema.type === "string") {
196
+ if (schema.format === "password") {
197
+ return /* @__PURE__ */ jsxRuntime.jsx(PasswordField, { name, schema, isRequired });
198
+ }
199
+ if (schema.format === "rich-text") {
200
+ return /* @__PURE__ */ jsxRuntime.jsx(RichTextField, { name, schema, isRequired });
201
+ }
202
+ return /* @__PURE__ */ jsxRuntime.jsx(TextField, { name, schema, isRequired });
203
+ }
204
+ if (schema.type === "number" || schema.type === "integer") {
205
+ return /* @__PURE__ */ jsxRuntime.jsx(NumberField, { name, schema, isRequired });
206
+ }
207
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdf-field-group", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "cdf-error-message", children: [
208
+ "Unsupported field type: ",
209
+ schema.type
210
+ ] }) });
211
+ };
212
+ var SchemaForm = ({ schema, onSubmit, defaultValues }) => {
213
+ const methods = reactHookForm.useForm({
214
+ resolver: ajv.ajvResolver(schema, {
215
+ formats: {
216
+ "rich-text": true,
217
+ password: true,
218
+ email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
219
+ }
220
+ }),
221
+ defaultValues
222
+ });
223
+ if (schema.type !== "object" || !schema.properties) {
224
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "cdf-error-message", children: "Root schema must be an object with properties." });
225
+ }
226
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cdf-form-container", children: [
227
+ schema.title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "cdf-form-title", children: schema.title }),
228
+ schema.description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "var(--cdf-text-muted)", marginBottom: "1.5rem" }, children: schema.description }),
229
+ /* @__PURE__ */ jsxRuntime.jsx(reactHookForm.FormProvider, { ...methods, children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: methods.handleSubmit(onSubmit), noValidate: true, children: [
230
+ Object.entries(schema.properties).map(([key, propSchema]) => {
231
+ var _a;
232
+ return /* @__PURE__ */ jsxRuntime.jsx(
233
+ FieldRenderer,
234
+ {
235
+ name: key,
236
+ schema: propSchema,
237
+ isRequired: (_a = schema.required) == null ? void 0 : _a.includes(key)
238
+ },
239
+ key
240
+ );
241
+ }),
242
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "cdf-submit-btn", children: "Submit" })
243
+ ] }) })
244
+ ] });
245
+ };
246
+
247
+ exports.FieldRenderer = FieldRenderer;
248
+ exports.SchemaForm = SchemaForm;
249
+ //# sourceMappingURL=index.js.map
250
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/fields/TextField.tsx","../src/components/fields/PasswordField.tsx","../src/components/fields/NumberField.tsx","../src/components/fields/RichTextField.tsx","../src/components/FieldRenderer.tsx","../src/components/SchemaForm.tsx"],"names":["useFormContext","jsxs","jsx","AlertCircle","useState","EyeOff","Eye","useEditor","StarterKit","editor","useEffect","Bold","Italic","Heading2","List","ListOrdered","EditorContent","useForm","ajvResolver","FormProvider"],"mappings":"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","file":"index.js","sourcesContent":["import React from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle } from 'lucide-react';\n\ninterface TextFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const TextField: React.FC<TextFieldProps> = ({ name, schema, isRequired }) => {\n const {\n register,\n formState: { errors },\n } = useFormContext();\n const error = errors[name];\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n <div className=\"cdf-input-wrapper\">\n <input\n id={name}\n type={schema.format === 'email' ? 'email' : 'text'}\n className={`cdf-input ${error ? 'cdf-input--error' : ''}`}\n placeholder={`Enter ${schema.title || name}`}\n {...register(name)}\n />\n </div>\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle, Eye, EyeOff } from 'lucide-react';\n\ninterface PasswordFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const PasswordField: React.FC<PasswordFieldProps> = ({ name, schema, isRequired }) => {\n const {\n register,\n formState: { errors },\n } = useFormContext();\n const [showPassword, setShowPassword] = useState(false);\n const error = errors[name];\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n <div className=\"cdf-input-wrapper\">\n <input\n id={name}\n type={showPassword ? 'text' : 'password'}\n className={`cdf-input ${error ? 'cdf-input--error' : ''}`}\n style={{ paddingRight: '2.5rem' }}\n placeholder={`Enter ${schema.title || name}`}\n {...register(name)}\n />\n <button\n type=\"button\"\n className=\"cdf-toolbar-btn\"\n style={{ position: 'absolute', right: '0.5rem' }}\n onClick={() => setShowPassword(!showPassword)}\n >\n {showPassword ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle } from 'lucide-react';\n\ninterface NumberFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const NumberField: React.FC<NumberFieldProps> = ({ name, schema, isRequired }) => {\n const {\n register,\n formState: { errors },\n } = useFormContext();\n const error = errors[name];\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n <div className=\"cdf-input-wrapper\">\n <input\n id={name}\n type=\"number\"\n className={`cdf-input ${error ? 'cdf-input--error' : ''}`}\n placeholder={`Enter ${schema.title || name}`}\n {...register(name, {\n valueAsNumber: true,\n })}\n />\n </div>\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React, { useEffect } from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle, Bold, Italic, List, ListOrdered, Heading2 } from 'lucide-react';\n\ninterface RichTextFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const RichTextField: React.FC<RichTextFieldProps> = ({ name, schema, isRequired }) => {\n const {\n setValue,\n watch,\n formState: { errors },\n } = useFormContext();\n const error = errors[name];\n const value = watch(name);\n\n const editor = useEditor({\n extensions: [StarterKit],\n content: value || '',\n onUpdate: ({ editor }) => {\n setValue(name, editor.getHTML(), { shouldValidate: true, shouldDirty: true });\n },\n });\n\n // Keep editor in sync with external form changes (if any)\n useEffect(() => {\n if (editor && value !== editor.getHTML()) {\n editor.commands.setContent(value || '');\n }\n }, [value, editor]);\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n\n <div className={`cdf-rich-text-wrapper ${error ? 'cdf-input--error' : ''}`}>\n <div className=\"cdf-rich-text-toolbar\">\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleBold().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('bold') ? 'is-active' : ''}`}\n >\n <Bold size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleItalic().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('italic') ? 'is-active' : ''}`}\n >\n <Italic size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}\n className={`cdf-toolbar-btn ${editor?.isActive('heading', { level: 2 }) ? 'is-active' : ''}`}\n >\n <Heading2 size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleBulletList().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('bulletList') ? 'is-active' : ''}`}\n >\n <List size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleOrderedList().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('orderedList') ? 'is-active' : ''}`}\n >\n <ListOrdered size={16} />\n </button>\n </div>\n\n <EditorContent editor={editor} className=\"cdf-rich-text-content\" />\n </div>\n\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React from 'react';\nimport { JSONSchema } from '../types/schema';\nimport { TextField } from './fields/TextField';\nimport { PasswordField } from './fields/PasswordField';\nimport { NumberField } from './fields/NumberField';\nimport { RichTextField } from './fields/RichTextField';\n\ninterface FieldRendererProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const FieldRenderer: React.FC<FieldRendererProps> = ({ name, schema, isRequired }) => {\n if (schema.type === 'string') {\n if (schema.format === 'password') {\n return <PasswordField name={name} schema={schema} isRequired={isRequired} />;\n }\n if (schema.format === 'rich-text') {\n return <RichTextField name={name} schema={schema} isRequired={isRequired} />;\n }\n return <TextField name={name} schema={schema} isRequired={isRequired} />;\n }\n\n if (schema.type === 'number' || schema.type === 'integer') {\n return <NumberField name={name} schema={schema} isRequired={isRequired} />;\n }\n\n // Fallback for unsupported types\n return (\n <div className=\"cdf-field-group\">\n <p className=\"cdf-error-message\">Unsupported field type: {schema.type}</p>\n </div>\n );\n};\n","import React from 'react';\nimport { useForm, FormProvider } from 'react-hook-form';\nimport { ajvResolver } from '@hookform/resolvers/ajv';\nimport { JSONSchema } from '../types/schema';\nimport { FieldRenderer } from './FieldRenderer';\nimport '../styles/form.css';\n\ninterface SchemaFormProps {\n schema: JSONSchema;\n onSubmit: (data: any) => void;\n defaultValues?: any;\n}\n\nexport const SchemaForm: React.FC<SchemaFormProps> = ({ schema, onSubmit, defaultValues }) => {\n const methods = useForm({\n resolver: ajvResolver(schema as any, {\n formats: {\n 'rich-text': true,\n password: true,\n email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/,\n },\n }),\n defaultValues,\n });\n\n if (schema.type !== 'object' || !schema.properties) {\n return <div className=\"cdf-error-message\">Root schema must be an object with properties.</div>;\n }\n\n return (\n <div className=\"cdf-form-container\">\n {schema.title && <h2 className=\"cdf-form-title\">{schema.title}</h2>}\n {schema.description && (\n <p style={{ color: 'var(--cdf-text-muted)', marginBottom: '1.5rem' }}>\n {schema.description}\n </p>\n )}\n\n <FormProvider {...methods}>\n <form onSubmit={methods.handleSubmit(onSubmit)} noValidate>\n {Object.entries(schema.properties).map(([key, propSchema]) => (\n <FieldRenderer\n key={key}\n name={key}\n schema={propSchema}\n isRequired={schema.required?.includes(key)}\n />\n ))}\n <button type=\"submit\" className=\"cdf-submit-btn\">\n Submit\n </button>\n </form>\n </FormProvider>\n </div>\n );\n};\n"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,243 @@
1
+ import { useForm, FormProvider, useFormContext } from 'react-hook-form';
2
+ import { ajvResolver } from '@hookform/resolvers/ajv';
3
+ import { EyeOff, Eye, AlertCircle, Bold, Italic, Heading2, List, ListOrdered } from 'lucide-react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+ import { useState, useEffect } from 'react';
6
+ import { useEditor, EditorContent } from '@tiptap/react';
7
+ import StarterKit from '@tiptap/starter-kit';
8
+
9
+ // src/components/SchemaForm.tsx
10
+ var TextField = ({ name, schema, isRequired }) => {
11
+ const {
12
+ register,
13
+ formState: { errors }
14
+ } = useFormContext();
15
+ const error = errors[name];
16
+ return /* @__PURE__ */ jsxs("div", { className: "cdf-field-group", children: [
17
+ /* @__PURE__ */ jsxs("label", { className: "cdf-label", htmlFor: name, children: [
18
+ schema.title || name,
19
+ isRequired && /* @__PURE__ */ jsx("span", { className: "cdf-required-mark", children: "*" })
20
+ ] }),
21
+ /* @__PURE__ */ jsx("div", { className: "cdf-input-wrapper", children: /* @__PURE__ */ jsx(
22
+ "input",
23
+ {
24
+ id: name,
25
+ type: schema.format === "email" ? "email" : "text",
26
+ className: `cdf-input ${error ? "cdf-input--error" : ""}`,
27
+ placeholder: `Enter ${schema.title || name}`,
28
+ ...register(name)
29
+ }
30
+ ) }),
31
+ error && /* @__PURE__ */ jsxs("span", { className: "cdf-error-message", children: [
32
+ /* @__PURE__ */ jsx(AlertCircle, { size: 14 }),
33
+ error.message
34
+ ] })
35
+ ] });
36
+ };
37
+ var PasswordField = ({ name, schema, isRequired }) => {
38
+ const {
39
+ register,
40
+ formState: { errors }
41
+ } = useFormContext();
42
+ const [showPassword, setShowPassword] = useState(false);
43
+ const error = errors[name];
44
+ return /* @__PURE__ */ jsxs("div", { className: "cdf-field-group", children: [
45
+ /* @__PURE__ */ jsxs("label", { className: "cdf-label", htmlFor: name, children: [
46
+ schema.title || name,
47
+ isRequired && /* @__PURE__ */ jsx("span", { className: "cdf-required-mark", children: "*" })
48
+ ] }),
49
+ /* @__PURE__ */ jsxs("div", { className: "cdf-input-wrapper", children: [
50
+ /* @__PURE__ */ jsx(
51
+ "input",
52
+ {
53
+ id: name,
54
+ type: showPassword ? "text" : "password",
55
+ className: `cdf-input ${error ? "cdf-input--error" : ""}`,
56
+ style: { paddingRight: "2.5rem" },
57
+ placeholder: `Enter ${schema.title || name}`,
58
+ ...register(name)
59
+ }
60
+ ),
61
+ /* @__PURE__ */ jsx(
62
+ "button",
63
+ {
64
+ type: "button",
65
+ className: "cdf-toolbar-btn",
66
+ style: { position: "absolute", right: "0.5rem" },
67
+ onClick: () => setShowPassword(!showPassword),
68
+ children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { size: 16 }) : /* @__PURE__ */ jsx(Eye, { size: 16 })
69
+ }
70
+ )
71
+ ] }),
72
+ error && /* @__PURE__ */ jsxs("span", { className: "cdf-error-message", children: [
73
+ /* @__PURE__ */ jsx(AlertCircle, { size: 14 }),
74
+ error.message
75
+ ] })
76
+ ] });
77
+ };
78
+ var NumberField = ({ name, schema, isRequired }) => {
79
+ const {
80
+ register,
81
+ formState: { errors }
82
+ } = useFormContext();
83
+ const error = errors[name];
84
+ return /* @__PURE__ */ jsxs("div", { className: "cdf-field-group", children: [
85
+ /* @__PURE__ */ jsxs("label", { className: "cdf-label", htmlFor: name, children: [
86
+ schema.title || name,
87
+ isRequired && /* @__PURE__ */ jsx("span", { className: "cdf-required-mark", children: "*" })
88
+ ] }),
89
+ /* @__PURE__ */ jsx("div", { className: "cdf-input-wrapper", children: /* @__PURE__ */ jsx(
90
+ "input",
91
+ {
92
+ id: name,
93
+ type: "number",
94
+ className: `cdf-input ${error ? "cdf-input--error" : ""}`,
95
+ placeholder: `Enter ${schema.title || name}`,
96
+ ...register(name, {
97
+ valueAsNumber: true
98
+ })
99
+ }
100
+ ) }),
101
+ error && /* @__PURE__ */ jsxs("span", { className: "cdf-error-message", children: [
102
+ /* @__PURE__ */ jsx(AlertCircle, { size: 14 }),
103
+ error.message
104
+ ] })
105
+ ] });
106
+ };
107
+ var RichTextField = ({ name, schema, isRequired }) => {
108
+ const {
109
+ setValue,
110
+ watch,
111
+ formState: { errors }
112
+ } = useFormContext();
113
+ const error = errors[name];
114
+ const value = watch(name);
115
+ const editor = useEditor({
116
+ extensions: [StarterKit],
117
+ content: value || "",
118
+ onUpdate: ({ editor: editor2 }) => {
119
+ setValue(name, editor2.getHTML(), { shouldValidate: true, shouldDirty: true });
120
+ }
121
+ });
122
+ useEffect(() => {
123
+ if (editor && value !== editor.getHTML()) {
124
+ editor.commands.setContent(value || "");
125
+ }
126
+ }, [value, editor]);
127
+ return /* @__PURE__ */ jsxs("div", { className: "cdf-field-group", children: [
128
+ /* @__PURE__ */ jsxs("label", { className: "cdf-label", htmlFor: name, children: [
129
+ schema.title || name,
130
+ isRequired && /* @__PURE__ */ jsx("span", { className: "cdf-required-mark", children: "*" })
131
+ ] }),
132
+ /* @__PURE__ */ jsxs("div", { className: `cdf-rich-text-wrapper ${error ? "cdf-input--error" : ""}`, children: [
133
+ /* @__PURE__ */ jsxs("div", { className: "cdf-rich-text-toolbar", children: [
134
+ /* @__PURE__ */ jsx(
135
+ "button",
136
+ {
137
+ type: "button",
138
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleBold().run(),
139
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("bold")) ? "is-active" : ""}`,
140
+ children: /* @__PURE__ */ jsx(Bold, { size: 16 })
141
+ }
142
+ ),
143
+ /* @__PURE__ */ jsx(
144
+ "button",
145
+ {
146
+ type: "button",
147
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleItalic().run(),
148
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("italic")) ? "is-active" : ""}`,
149
+ children: /* @__PURE__ */ jsx(Italic, { size: 16 })
150
+ }
151
+ ),
152
+ /* @__PURE__ */ jsx(
153
+ "button",
154
+ {
155
+ type: "button",
156
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleHeading({ level: 2 }).run(),
157
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("heading", { level: 2 })) ? "is-active" : ""}`,
158
+ children: /* @__PURE__ */ jsx(Heading2, { size: 16 })
159
+ }
160
+ ),
161
+ /* @__PURE__ */ jsx(
162
+ "button",
163
+ {
164
+ type: "button",
165
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleBulletList().run(),
166
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("bulletList")) ? "is-active" : ""}`,
167
+ children: /* @__PURE__ */ jsx(List, { size: 16 })
168
+ }
169
+ ),
170
+ /* @__PURE__ */ jsx(
171
+ "button",
172
+ {
173
+ type: "button",
174
+ onClick: () => editor == null ? void 0 : editor.chain().focus().toggleOrderedList().run(),
175
+ className: `cdf-toolbar-btn ${(editor == null ? void 0 : editor.isActive("orderedList")) ? "is-active" : ""}`,
176
+ children: /* @__PURE__ */ jsx(ListOrdered, { size: 16 })
177
+ }
178
+ )
179
+ ] }),
180
+ /* @__PURE__ */ jsx(EditorContent, { editor, className: "cdf-rich-text-content" })
181
+ ] }),
182
+ error && /* @__PURE__ */ jsxs("span", { className: "cdf-error-message", children: [
183
+ /* @__PURE__ */ jsx(AlertCircle, { size: 14 }),
184
+ error.message
185
+ ] })
186
+ ] });
187
+ };
188
+ var FieldRenderer = ({ name, schema, isRequired }) => {
189
+ if (schema.type === "string") {
190
+ if (schema.format === "password") {
191
+ return /* @__PURE__ */ jsx(PasswordField, { name, schema, isRequired });
192
+ }
193
+ if (schema.format === "rich-text") {
194
+ return /* @__PURE__ */ jsx(RichTextField, { name, schema, isRequired });
195
+ }
196
+ return /* @__PURE__ */ jsx(TextField, { name, schema, isRequired });
197
+ }
198
+ if (schema.type === "number" || schema.type === "integer") {
199
+ return /* @__PURE__ */ jsx(NumberField, { name, schema, isRequired });
200
+ }
201
+ return /* @__PURE__ */ jsx("div", { className: "cdf-field-group", children: /* @__PURE__ */ jsxs("p", { className: "cdf-error-message", children: [
202
+ "Unsupported field type: ",
203
+ schema.type
204
+ ] }) });
205
+ };
206
+ var SchemaForm = ({ schema, onSubmit, defaultValues }) => {
207
+ const methods = useForm({
208
+ resolver: ajvResolver(schema, {
209
+ formats: {
210
+ "rich-text": true,
211
+ password: true,
212
+ email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
213
+ }
214
+ }),
215
+ defaultValues
216
+ });
217
+ if (schema.type !== "object" || !schema.properties) {
218
+ return /* @__PURE__ */ jsx("div", { className: "cdf-error-message", children: "Root schema must be an object with properties." });
219
+ }
220
+ return /* @__PURE__ */ jsxs("div", { className: "cdf-form-container", children: [
221
+ schema.title && /* @__PURE__ */ jsx("h2", { className: "cdf-form-title", children: schema.title }),
222
+ schema.description && /* @__PURE__ */ jsx("p", { style: { color: "var(--cdf-text-muted)", marginBottom: "1.5rem" }, children: schema.description }),
223
+ /* @__PURE__ */ jsx(FormProvider, { ...methods, children: /* @__PURE__ */ jsxs("form", { onSubmit: methods.handleSubmit(onSubmit), noValidate: true, children: [
224
+ Object.entries(schema.properties).map(([key, propSchema]) => {
225
+ var _a;
226
+ return /* @__PURE__ */ jsx(
227
+ FieldRenderer,
228
+ {
229
+ name: key,
230
+ schema: propSchema,
231
+ isRequired: (_a = schema.required) == null ? void 0 : _a.includes(key)
232
+ },
233
+ key
234
+ );
235
+ }),
236
+ /* @__PURE__ */ jsx("button", { type: "submit", className: "cdf-submit-btn", children: "Submit" })
237
+ ] }) })
238
+ ] });
239
+ };
240
+
241
+ export { FieldRenderer, SchemaForm };
242
+ //# sourceMappingURL=index.mjs.map
243
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/fields/TextField.tsx","../src/components/fields/PasswordField.tsx","../src/components/fields/NumberField.tsx","../src/components/fields/RichTextField.tsx","../src/components/FieldRenderer.tsx","../src/components/SchemaForm.tsx"],"names":["useFormContext","jsxs","jsx","AlertCircle","editor"],"mappings":"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","file":"index.mjs","sourcesContent":["import React from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle } from 'lucide-react';\n\ninterface TextFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const TextField: React.FC<TextFieldProps> = ({ name, schema, isRequired }) => {\n const {\n register,\n formState: { errors },\n } = useFormContext();\n const error = errors[name];\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n <div className=\"cdf-input-wrapper\">\n <input\n id={name}\n type={schema.format === 'email' ? 'email' : 'text'}\n className={`cdf-input ${error ? 'cdf-input--error' : ''}`}\n placeholder={`Enter ${schema.title || name}`}\n {...register(name)}\n />\n </div>\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle, Eye, EyeOff } from 'lucide-react';\n\ninterface PasswordFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const PasswordField: React.FC<PasswordFieldProps> = ({ name, schema, isRequired }) => {\n const {\n register,\n formState: { errors },\n } = useFormContext();\n const [showPassword, setShowPassword] = useState(false);\n const error = errors[name];\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n <div className=\"cdf-input-wrapper\">\n <input\n id={name}\n type={showPassword ? 'text' : 'password'}\n className={`cdf-input ${error ? 'cdf-input--error' : ''}`}\n style={{ paddingRight: '2.5rem' }}\n placeholder={`Enter ${schema.title || name}`}\n {...register(name)}\n />\n <button\n type=\"button\"\n className=\"cdf-toolbar-btn\"\n style={{ position: 'absolute', right: '0.5rem' }}\n onClick={() => setShowPassword(!showPassword)}\n >\n {showPassword ? <EyeOff size={16} /> : <Eye size={16} />}\n </button>\n </div>\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle } from 'lucide-react';\n\ninterface NumberFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const NumberField: React.FC<NumberFieldProps> = ({ name, schema, isRequired }) => {\n const {\n register,\n formState: { errors },\n } = useFormContext();\n const error = errors[name];\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n <div className=\"cdf-input-wrapper\">\n <input\n id={name}\n type=\"number\"\n className={`cdf-input ${error ? 'cdf-input--error' : ''}`}\n placeholder={`Enter ${schema.title || name}`}\n {...register(name, {\n valueAsNumber: true,\n })}\n />\n </div>\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React, { useEffect } from 'react';\nimport { useFormContext } from 'react-hook-form';\nimport { useEditor, EditorContent } from '@tiptap/react';\nimport StarterKit from '@tiptap/starter-kit';\nimport { JSONSchema } from '../../types/schema';\nimport { AlertCircle, Bold, Italic, List, ListOrdered, Heading2 } from 'lucide-react';\n\ninterface RichTextFieldProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const RichTextField: React.FC<RichTextFieldProps> = ({ name, schema, isRequired }) => {\n const {\n setValue,\n watch,\n formState: { errors },\n } = useFormContext();\n const error = errors[name];\n const value = watch(name);\n\n const editor = useEditor({\n extensions: [StarterKit],\n content: value || '',\n onUpdate: ({ editor }) => {\n setValue(name, editor.getHTML(), { shouldValidate: true, shouldDirty: true });\n },\n });\n\n // Keep editor in sync with external form changes (if any)\n useEffect(() => {\n if (editor && value !== editor.getHTML()) {\n editor.commands.setContent(value || '');\n }\n }, [value, editor]);\n\n return (\n <div className=\"cdf-field-group\">\n <label className=\"cdf-label\" htmlFor={name}>\n {schema.title || name}\n {isRequired && <span className=\"cdf-required-mark\">*</span>}\n </label>\n\n <div className={`cdf-rich-text-wrapper ${error ? 'cdf-input--error' : ''}`}>\n <div className=\"cdf-rich-text-toolbar\">\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleBold().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('bold') ? 'is-active' : ''}`}\n >\n <Bold size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleItalic().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('italic') ? 'is-active' : ''}`}\n >\n <Italic size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleHeading({ level: 2 }).run()}\n className={`cdf-toolbar-btn ${editor?.isActive('heading', { level: 2 }) ? 'is-active' : ''}`}\n >\n <Heading2 size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleBulletList().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('bulletList') ? 'is-active' : ''}`}\n >\n <List size={16} />\n </button>\n <button\n type=\"button\"\n onClick={() => editor?.chain().focus().toggleOrderedList().run()}\n className={`cdf-toolbar-btn ${editor?.isActive('orderedList') ? 'is-active' : ''}`}\n >\n <ListOrdered size={16} />\n </button>\n </div>\n\n <EditorContent editor={editor} className=\"cdf-rich-text-content\" />\n </div>\n\n {error && (\n <span className=\"cdf-error-message\">\n <AlertCircle size={14} />\n {error.message as string}\n </span>\n )}\n </div>\n );\n};\n","import React from 'react';\nimport { JSONSchema } from '../types/schema';\nimport { TextField } from './fields/TextField';\nimport { PasswordField } from './fields/PasswordField';\nimport { NumberField } from './fields/NumberField';\nimport { RichTextField } from './fields/RichTextField';\n\ninterface FieldRendererProps {\n name: string;\n schema: JSONSchema;\n isRequired?: boolean;\n}\n\nexport const FieldRenderer: React.FC<FieldRendererProps> = ({ name, schema, isRequired }) => {\n if (schema.type === 'string') {\n if (schema.format === 'password') {\n return <PasswordField name={name} schema={schema} isRequired={isRequired} />;\n }\n if (schema.format === 'rich-text') {\n return <RichTextField name={name} schema={schema} isRequired={isRequired} />;\n }\n return <TextField name={name} schema={schema} isRequired={isRequired} />;\n }\n\n if (schema.type === 'number' || schema.type === 'integer') {\n return <NumberField name={name} schema={schema} isRequired={isRequired} />;\n }\n\n // Fallback for unsupported types\n return (\n <div className=\"cdf-field-group\">\n <p className=\"cdf-error-message\">Unsupported field type: {schema.type}</p>\n </div>\n );\n};\n","import React from 'react';\nimport { useForm, FormProvider } from 'react-hook-form';\nimport { ajvResolver } from '@hookform/resolvers/ajv';\nimport { JSONSchema } from '../types/schema';\nimport { FieldRenderer } from './FieldRenderer';\nimport '../styles/form.css';\n\ninterface SchemaFormProps {\n schema: JSONSchema;\n onSubmit: (data: any) => void;\n defaultValues?: any;\n}\n\nexport const SchemaForm: React.FC<SchemaFormProps> = ({ schema, onSubmit, defaultValues }) => {\n const methods = useForm({\n resolver: ajvResolver(schema as any, {\n formats: {\n 'rich-text': true,\n password: true,\n email: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/,\n },\n }),\n defaultValues,\n });\n\n if (schema.type !== 'object' || !schema.properties) {\n return <div className=\"cdf-error-message\">Root schema must be an object with properties.</div>;\n }\n\n return (\n <div className=\"cdf-form-container\">\n {schema.title && <h2 className=\"cdf-form-title\">{schema.title}</h2>}\n {schema.description && (\n <p style={{ color: 'var(--cdf-text-muted)', marginBottom: '1.5rem' }}>\n {schema.description}\n </p>\n )}\n\n <FormProvider {...methods}>\n <form onSubmit={methods.handleSubmit(onSubmit)} noValidate>\n {Object.entries(schema.properties).map(([key, propSchema]) => (\n <FieldRenderer\n key={key}\n name={key}\n schema={propSchema}\n isRequired={schema.required?.includes(key)}\n />\n ))}\n <button type=\"submit\" className=\"cdf-submit-btn\">\n Submit\n </button>\n </form>\n </FormProvider>\n </div>\n );\n};\n"]}
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "config-driven-form",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsup",
20
+ "dev": "tsup --watch",
21
+ "lint": "eslint 'src/**/*.{ts,tsx}'",
22
+ "format": "prettier --write 'src/**/*.{ts,tsx,css}'",
23
+ "prepare": "husky",
24
+ "storybook": "storybook dev -p 6006",
25
+ "build-storybook": "storybook build"
26
+ },
27
+ "keywords": [],
28
+ "author": "",
29
+ "license": "ISC",
30
+ "type": "commonjs",
31
+ "engines": {
32
+ "node": ">=20.0.0"
33
+ },
34
+ "dependencies": {
35
+ "@hookform/resolvers": "^5.4.0",
36
+ "@tiptap/pm": "^3.26.1",
37
+ "@tiptap/react": "^3.26.1",
38
+ "@tiptap/starter-kit": "^3.26.1",
39
+ "ajv": "^8.20.0",
40
+ "ajv-errors": "^3.0.0",
41
+ "ajv-formats": "^3.0.1",
42
+ "lucide-react": "^1.18.0",
43
+ "react-hook-form": "^7.79.0"
44
+ },
45
+ "devDependencies": {
46
+ "@changesets/cli": "^2.31.0",
47
+ "@chromatic-com/storybook": "^5.2.1",
48
+ "@commitlint/cli": "^21.0.2",
49
+ "@commitlint/config-conventional": "^21.0.2",
50
+ "@storybook/addon-a11y": "^10.4.5",
51
+ "@storybook/addon-docs": "^10.4.5",
52
+ "@storybook/addon-mcp": "^0.6.0",
53
+ "@storybook/addon-vitest": "^10.4.5",
54
+ "@storybook/react-vite": "^10.4.5",
55
+ "@types/react": "^19.2.17",
56
+ "@types/react-dom": "^19.2.3",
57
+ "@typescript-eslint/eslint-plugin": "^8.61.1",
58
+ "@typescript-eslint/parser": "^8.61.1",
59
+ "@vitest/browser-playwright": "^4.1.9",
60
+ "@vitest/coverage-v8": "^4.1.9",
61
+ "eslint": "^8.57.1",
62
+ "eslint-config-prettier": "^10.1.8",
63
+ "eslint-plugin-react": "^7.37.5",
64
+ "eslint-plugin-react-hooks": "^7.1.1",
65
+ "eslint-plugin-storybook": "^10.4.5",
66
+ "husky": "^9.1.7",
67
+ "lint-staged": "^17.0.7",
68
+ "playwright": "^1.61.0",
69
+ "prettier": "^3.8.4",
70
+ "react": "^19.2.7",
71
+ "react-dom": "^19.2.7",
72
+ "storybook": "^10.4.5",
73
+ "tsup": "^8.5.1",
74
+ "typescript": "^6.0.3",
75
+ "vite": "^8.0.16",
76
+ "vitest": "^4.1.9"
77
+ }
78
+ }