@ht-rnd/json-schema-editor 1.0.8 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,20 +1,13 @@
1
1
  # @ht-rnd/json-schema-editor
2
2
 
3
- A modern, highly customizable, and themeable JSON Schema editor built with React, TypeScript, and shadcn/ui.
3
+ A headless JSON Schema editor library for React. This package provides the core logic, hooks, and utilities for building JSON Schema editors, while allowing complete control over the UI.
4
4
 
5
- This component provides a clean, intuitive interface for visually building and editing JSON Schemas. It features real-time JSON output and live validation against the official JSON Schema specification, powered by AJV.
5
+ ## Architecture
6
6
 
7
- ## Features
7
+ This library follows the **headless UI pattern**:
8
8
 
9
- - **Modern Stack:** Built with React, TypeScript, Tailwind CSS, and `shadcn/ui`.
10
- - **Visual Editing:** Add, remove, and configure schema properties in a clear, row-based UI.
11
- - **Deeply Nested Schemas:** Full support for nested `object` and `array` types with recursion.
12
- - **Advanced Settings:** A detailed settings dialog for each property type (string, number, boolean, object, array).
13
- - **Real-time Output:** Instantly see the generated JSON Schema as you build.
14
- - **Live Schema Validation:** Integrated `ajv` validator provides real-time feedback and inline errors if your schema violates the JSON Schema specification.
15
- - **Highly Configurable:** Control the root type (`object` or `array`) and layout via props.
16
- - **Themeable:** Supports dark/light themes and custom styling.
17
- - **Read-Only Mode:** A prop to disable all interactions for display purposes.
9
+ - **NPM Package**: Contains only the headless core - hooks, types, validation, and utilities
10
+ - **Components Folder**: Contains copy-paste shadcn-style React components for the UI
18
11
 
19
12
  ## Installation
20
13
 
@@ -22,283 +15,368 @@ This component provides a clean, intuitive interface for visually building and e
22
15
  npm install @ht-rnd/json-schema-editor
23
16
  ```
24
17
 
25
- ## Usage and Setup
18
+ ### For UI Components
26
19
 
27
- Integration requires two simple steps: configuring Tailwind and then using the component.
20
+ Copy the `components/json-schema-editor/` folder from this repository into your project. These components are designed to be customized and follow [shadcn/ui](https://ui.shadcn.com/) principles.
28
21
 
29
- ### Step 1: Configure Tailwind CSS
22
+ **Required peer dependencies for UI components:**
30
23
 
31
- Because this library is built with Tailwind, your project's Tailwind process needs to know to scan this library's files for class names.
24
+ ```bash
25
+ npm install @radix-ui/react-alert-dialog @radix-ui/react-checkbox @radix-ui/react-dialog \
26
+ @radix-ui/react-label @radix-ui/react-radio-group @radix-ui/react-select \
27
+ @radix-ui/react-separator @radix-ui/react-slot @radix-ui/react-tooltip \
28
+ class-variance-authority clsx lucide-react tailwind-merge tailwindcss-animate
29
+ ```
32
30
 
33
- In your project's tailwind.config.js (or .cjs), add the path to the library within your content array:
31
+ ## Features
34
32
 
35
- ```ts
36
- /** @type {import('tailwindcss').Config} */
37
- module.exports = {
38
- content: [
39
- "./src/**/*.{js,ts,jsx,tsx}", // Your app's files
33
+ ### Core Capabilities
40
34
 
41
- // Add this line
42
- "./node_modules/@ht-rnd/json-schema-editor/dist/**/*.{js,ts,jsx,tsx}",
43
- ],
44
- theme: {
45
- // ...
46
- },
47
- plugins: [],
48
- };
49
- ```
35
+ - **JSON Schema 2020-12** - Full support for draft 2020-12 specification
36
+ - **Multiple Data Types** - string, number, integer, boolean, object, array, and $ref
37
+ - **Nested Schemas** - Support for nested objects and arrays with unlimited depth
38
+ - **Definitions ($defs)** - Create reusable schema definitions with $ref support
39
+ - **Validation Constraints** - min/max, length, format, pattern, enum, and more
40
+ - **Boolean Combinators** - allOf, anyOf, oneOf, not for complex schema logic
41
+ - **Real-time Validation** - AJV-based validation with inline error messages
42
+ - **Type Safety** - Full TypeScript support with comprehensive type definitions
43
+
44
+ ### UI Features (Pre-built Components)
45
+
46
+ - **Responsive Layout** - Configurable form and output positioning (top/bottom/left/right)
47
+ - **Customizable Sizing** - Flexible width and height options (sm/md/lg/full)
48
+ - **Dark Mode Ready** - Theme prop support for dark/light mode
49
+ - **Read-only Mode** - View-only mode for displaying schemas
50
+ - **Settings Dialogs** - Rich settings for each field type with type-specific options
51
+ - **Inline Editing** - Direct field manipulation with instant feedback
50
52
 
51
- ### Step 2: Use the Component
53
+ ## Usage
54
+
55
+ ### Option 1: Using the Headless Hook (Full Control)
56
+
57
+ Use the `useJsonSchemaEditor` hook directly for complete control over the UI:
52
58
 
53
59
  ```tsx
54
- import { JsonSchemaEditor } from "@ht-rnd/json-schema-editor";
55
- function MySchema() {
56
- const existingSchema: any = {
57
- type: "object",
58
- title: "Existing User Schema",
59
- properties: {
60
- name: { type: "string" },
61
- age: { type: "number", minimum: 0 },
62
- },
63
- required: ["name"],
64
- };
60
+ import { useJsonSchemaEditor } from "@ht-rnd/json-schema-editor";
61
+ import { FormProvider } from "react-hook-form";
62
+
63
+ function MyCustomEditor() {
64
+ const editor = useJsonSchemaEditor({
65
+ rootType: "object",
66
+ onChange: (schema) => console.log("Schema changed:", schema),
67
+ });
65
68
 
66
69
  return (
67
- <div className="p-8">
68
- <JsonSchemaEditor
69
- rootType="object"
70
- theme="light"
71
- readOnly={false}
72
- defaultValue={existingSchema}
73
- onChange={(jsonSchema) => {
74
- console.log(jsonSchema);
75
- }}
76
- />
77
- </div>
70
+ <FormProvider {...editor.form}>
71
+ <div>
72
+ {/* Your custom UI here */}
73
+ <pre>{JSON.stringify(editor.schema, null, 2)}</pre>
74
+
75
+ <button onClick={editor.addField}>Add Field</button>
76
+ <button onClick={editor.addDefinition}>Add Definition</button>
77
+
78
+ {editor.fields.map((field, index) => (
79
+ <div key={field.id}>
80
+ {/* Render your custom field UI */}
81
+ <input value={field.key} />
82
+ <button onClick={() => editor.removeField(index)}>Remove</button>
83
+ <button onClick={() => editor.openSettings(`properties.${index}`)}>Settings</button>
84
+ </div>
85
+ ))}
86
+
87
+ {editor.definitions.map((def, index) => (
88
+ <div key={def.id}>
89
+ <input value={def.key} />
90
+ <button onClick={() => editor.removeDefinition(index)}>Remove</button>
91
+ </div>
92
+ ))}
93
+
94
+ {editor.errors && (
95
+ <div>
96
+ {editor.errors.map((error, i) => (
97
+ <p key={i}>{error.message}</p>
98
+ ))}
99
+ </div>
100
+ )}
101
+ </div>
102
+ </FormProvider>
78
103
  );
79
104
  }
80
- export default MySchema;
81
105
  ```
82
106
 
83
- ## Theming and Customization
84
-
85
- This library is built on the `shadcn/ui` theming architecture, which relies on CSS variables for colors, borders, spacing, and radius. You can easily override these variables in your own project to match your application's design system.
86
-
87
- 1. In your project's global CSS file (e.g., `src/index.css`), define your custom theme variables inside a `@layer base` block.
88
- 2. Your definitions will automatically override the library's default theme.
89
-
90
- When you pass the `theme="dark"` prop to the JsonSchemaEditor, it will apply a `.dark` class to its root element, causing the browser to use the variables defined in your `.dark { ... }` block.
91
-
92
- ### Example `index.css`:
93
-
94
- ```css
95
- @tailwind base;
96
- @tailwind components;
97
- @tailwind utilities;
98
-
99
- @layer base {
100
- :root {
101
- --background: 0 0% 100%;
102
- --foreground: 240 10% 3.9%;
103
- --primary: 329 100% 44%;
104
- --primary-hover: 329 100% 38%;
105
- --primary-pressed: 329 100% 31%;
106
- --primary-foreground: 0 0% 100%;
107
- --secondary: 240 4.8% 95.9%;
108
- --secondary-foreground: 240 5.9% 10%;
109
- --muted: 240 3.8% 80%;
110
- --muted-foreground: 240 3.8% 46.1%;
111
- --accent: 240 4.8% 95.9%;
112
- --accent-foreground: 240 5.9% 10%;
113
- --destructive: 0 100% 50%;
114
- --destructive-foreground: 0 0% 98%;
115
- --border: 240 5.9% 90%;
116
- --input: 240 5.9% 90%;
117
- --radius: 0.75rem;
118
- }
107
+ ### Option 2: Using the Pre-built Components
119
108
 
120
- .dark {
121
- --background: 240 5.9% 10%;
122
- --foreground: 0 0% 92%;
123
- --primary: 330 96% 35%;
124
- --primary-hover: 330 96% 41%;
125
- --primary-pressed: 330 96% 48%;
126
- --primary-foreground: 240 17.1% 92%;
127
- --secondary: 240 3.7% 15.9%;
128
- --secondary-foreground: 0 0% 92%;
129
- --muted: 240 3.8% 40%;
130
- --muted-foreground: 240 5% 64.9%;
131
- --accent: 240 3.7% 15.9%;
132
- --accent-foreground: 0 0% 92%;
133
- --destructive: 0 100% 60%;
134
- --destructive-foreground: 0 0% 98%;
135
- --border: 240 3.7% 30%;
136
- --input: 240 3.7% 30%;
137
- }
138
- }
109
+ Copy the components from `components/json-schema-editor/` and use them directly:
110
+
111
+ ```tsx
112
+ import { JsonSchemaEditor } from "@/components/json-schema-editor";
139
113
 
140
- /* You can also add global styles like scrollbar theming */
141
- * {
142
- scrollbar-color: hsl(var(--muted)) hsl(var(--background));
114
+ function App() {
115
+ return (
116
+ <JsonSchemaEditor
117
+ rootType="object"
118
+ theme="light"
119
+ readOnly={false}
120
+ showOutput={true}
121
+ onChange={(schema) => console.log(schema)}
122
+ styles={{
123
+ form: { width: "full", height: "md" },
124
+ output: { position: "bottom", showJson: true, width: "full", height: "md" },
125
+ settings: { width: "md" },
126
+ spacing: "md",
127
+ }}
128
+ />
129
+ );
143
130
  }
144
131
  ```
145
132
 
146
- ### Tailwind Configuration
147
-
148
- For theming to work correctly you should ensure your project's `tailwind.config.js` (or `tailwind.config.ts`) includes the color tokens and `borderRadius` settings used by this library. Below is an example you can merge into your `theme.extend` section.
149
-
150
- ```ts
151
- colors: {
152
- magenta: {
153
- 50: "#ffe5ed",
154
- 100: "#ffcddb",
155
- 200: "#ffa3be",
156
- 300: "#ff79a2",
157
- 400: "#ff4f85",
158
- 500: "#e6004e",
159
- 600: "#b8003f",
160
- 700: "#8f0033",
161
- 800: "#660026",
162
- 900: "#3d0019",
163
- 950: "#260010",
164
- },
165
- magentaHover: "hsl(var(--magentaHover))",
166
- border: "hsl(var(--border))",
167
- input: "hsl(var(--input))",
168
- ring: "hsl(var(--ring))",
169
- background: "hsl(var(--background))",
170
- foreground: "hsl(var(--foreground))",
171
- primary: {
172
- DEFAULT: "hsl(var(--primary))",
173
- foreground: "hsl(var(--primary-foreground))",
174
- hover: "hsl(var(--primary-hover))",
175
- pressed: "hsl(var(--primary-pressed))",
176
- },
177
- secondary: {
178
- DEFAULT: "hsl(var(--secondary))",
179
- foreground: "hsl(var(--secondary-foreground))",
180
- },
181
- destructive: {
182
- DEFAULT: "hsl(var(--destructive) / <alpha-value>)",
183
- foreground: "hsl(var(--destructive-foreground) / <alpha-value>)",
184
- },
185
- muted: {
186
- DEFAULT: "hsl(var(--muted))",
187
- foreground: "hsl(var(--muted-foreground))",
188
- },
189
- accent: {
190
- DEFAULT: "hsl(var(--accent))",
191
- foreground: "hsl(var(--accent-foreground))",
192
- },
193
- popover: {
194
- DEFAULT: "hsl(var(--popover))",
195
- foreground: "hsl(var(--popover-foreground))",
196
- },
197
- card: {
198
- DEFAULT: "hsl(var(--card))",
199
- foreground: "hsl(var(--card-foreground))",
200
- },
201
- sidebar: {
202
- DEFAULT: "hsl(var(--sidebar-background))",
203
- foreground: "hsl(var(--sidebar-foreground))",
204
- primary: "hsl(var(--sidebar-primary))",
205
- "primary-foreground": "hsl(var(--sidebar-primary-foreground))",
206
- accent: "hsl(var(--sidebar-accent))",
207
- "accent-foreground": "hsl(var(--sidebar-accent-foreground))",
208
- border: "hsl(var(--sidebar-border))",
209
- ring: "hsl(var(--sidebar-ring))",
210
- },
211
- },
212
- borderRadius: {
213
- "2xl": "calc(var(--radius) + 6px)",
214
- xl: "calc(var(--radius) + 4px)",
215
- lg: "var(--radius)",
216
- md: "calc(var(--radius) - 2px)",
217
- sm: "calc(var(--radius) - 4px)",
218
- xs: "calc(var(--radius) - 5px)",
219
- "2xs": "calc(var(--radius) - 7px)",
220
- },
133
+ ### Option 3: Mix and Match
134
+
135
+ Use the headless hook with some pre-built components:
136
+
137
+ ```tsx
138
+ import { useJsonSchemaEditor } from "@ht-rnd/json-schema-editor";
139
+ import { Root, FieldList, SettingsDialog } from "@/components/json-schema-editor";
140
+ import { FormProvider } from "react-hook-form";
141
+
142
+ function HybridEditor() {
143
+ const editor = useJsonSchemaEditor({ rootType: "object" });
144
+
145
+ return (
146
+ <FormProvider {...editor.form}>
147
+ <div className="space-y-4">
148
+ <Root
149
+ rootType="object"
150
+ onAddField={editor.addField}
151
+ onOpenSettings={editor.openSettings}
152
+ />
153
+
154
+ <FieldList
155
+ fields={editor.fields}
156
+ onRemove={editor.removeField}
157
+ onOpenSettings={editor.openSettings}
158
+ />
159
+
160
+ {/* Add definitions support */}
161
+ {editor.definitions.length > 0 && (
162
+ <div className="mt-4">
163
+ <h3>Definitions ($defs)</h3>
164
+ {editor.definitions.map((def, index) => (
165
+ <div key={def.id}>
166
+ <span>{def.key}</span>
167
+ <button onClick={() => editor.removeDefinition(index)}>Remove</button>
168
+ </div>
169
+ ))}
170
+ </div>
171
+ )}
172
+
173
+ {/* Your custom JSON output */}
174
+ <textarea value={JSON.stringify(editor.schema, null, 2)} readOnly />
175
+
176
+ <SettingsDialog
177
+ isOpen={editor.settingsState.isOpen}
178
+ fieldPath={editor.settingsState.fieldPath}
179
+ onClose={editor.closeSettings}
180
+ />
181
+ </div>
182
+ </FormProvider>
183
+ );
184
+ }
221
185
  ```
222
186
 
223
187
  ## API Reference
224
188
 
225
- ### `<JsonSchemaEditor />` Props
189
+ ### `JsonSchemaEditor` Component (Pre-built)
226
190
 
227
- | Prop | Type | Default | Description |
228
- | :------------- | :------------------------------ | :--------- | :----------------------------------------------------------------------------------------------------------- |
229
- | `rootType` | `'object'` \| `'array'` | `'object'` | Sets the root type of the schema. |
230
- | `readOnly` | `boolean` | `false` | Disables all user interactions, making the editor a display-only component. |
231
- | `theme` | `string` (e.g., `'dark'`) | `''` | A class name to apply for theming (e.g., pass `"dark"` for dark mode). |
232
- | `styles` | `Styles` | `{...}` | An object to control the layout, width, and spacing of the editor panels. |
233
- | `onChange` | `(schema: JSONSchema) => void` | `none` | A callback function that is invoked with the final schema object on any change. |
234
- | `defaultValue` | `JSONSchema` | `none` | An existing JSON Schema object to load into the editor. When provided, this will override the rootType prop. |
191
+ The pre-built React component with full UI implementation.
235
192
 
236
- ### The `styles` Prop
193
+ #### Props
237
194
 
238
- You can customize the layout and dimensions of the editor using the `styles` prop. You only need to provide the properties you wish to override.
195
+ | Property | Type | Default | Description |
196
+ |----------|------|---------|-------------|
197
+ | `rootType` | `"object" \| "array"` | `"object"` | Root schema type |
198
+ | `defaultValue` | `JSONSchema` | - | Initial schema value |
199
+ | `onChange` | `(schema: JSONSchema) => void` | - | Callback when schema changes |
200
+ | `readOnly` | `boolean` | `false` | Make all inputs read-only |
201
+ | `showOutput` | `boolean` | `true` | Show/hide output panel |
202
+ | `theme` | `string` | `"light"` | Theme class for styling |
203
+ | `styles` | `Partial<Styles>` | - | Layout and sizing configuration |
204
+ | `className` | `string` | - | Additional CSS classes |
239
205
 
240
- **Type Definition:**
206
+ #### Styles Configuration
241
207
 
242
- ```ts
208
+ ```typescript
243
209
  interface Styles {
244
- form: {
245
- width: "sm" | "md" | "lg" | "full";
246
- height: "sm" | "md" | "lg" | "full";
247
- };
210
+ form: { width: "sm" | "md" | "lg" | "full"; height: "sm" | "md" | "lg" | "full" };
248
211
  output: {
249
212
  position: "top" | "bottom" | "left" | "right";
250
213
  showJson: boolean;
251
214
  width: "sm" | "md" | "lg" | "full";
252
215
  height: "sm" | "md" | "lg" | "full";
253
216
  };
254
- settings: {
255
- width: "sm" | "md" | "lg" | "full";
256
- };
217
+ settings: { width: "sm" | "md" | "lg" | "full" };
257
218
  spacing: "sm" | "md" | "lg";
258
219
  }
259
220
  ```
260
221
 
261
- **Example Usage:**
262
-
263
- ```tsx
264
- // Example 1: Move the JSON output to the right side
265
- <JsonSchemaEditor
266
- styles={{
267
- output: { position: "right" },
268
- }}
269
- />
222
+ ### `useJsonSchemaEditor(options)`
223
+
224
+ The main headless hook for managing JSON Schema editor state.
225
+
226
+ #### Options
227
+
228
+ | Property | Type | Default | Description |
229
+ |----------|------|---------|-------------|
230
+ | `rootType` | `"object" \| "array"` | `"object"` | Root schema type |
231
+ | `defaultValue` | `JSONSchema` | - | Initial schema value |
232
+ | `onChange` | `(schema: JSONSchema) => void` | - | Callback when schema changes |
233
+
234
+ #### Returns
235
+
236
+ | Property | Type | Description |
237
+ |----------|------|-------------|
238
+ | `schema` | `JSONSchema` | Current JSON Schema output |
239
+ | `errors` | `ErrorObject[] \| null` | AJV validation errors |
240
+ | `fields` | `FieldItem[]` | Field array for iteration |
241
+ | `definitions` | `DefinitionItem[]` | Definition array for $defs |
242
+ | `form` | `UseFormReturn` | React Hook Form methods |
243
+ | `settingsState` | `{ isOpen, fieldPath }` | Settings dialog state |
244
+ | `addField()` | `() => void` | Add a new field |
245
+ | `removeField(index)` | `(index: number) => void` | Remove field by index |
246
+ | `addDefinition()` | `() => void` | Add a new definition to $defs |
247
+ | `removeDefinition(index)` | `(index: number) => void` | Remove definition by index |
248
+ | `updateReferences(oldKey, newKey)` | `(oldKey: string, newKey: string \| null) => void` | Update $ref references when definition key changes |
249
+ | `openSettings(path)` | `(path: string) => void` | Open settings for a field |
250
+ | `closeSettings()` | `() => void` | Close settings dialog |
251
+ | `handleTypeChange(path, type)` | `(path: string, type: string) => void` | Change field type |
252
+ | `addNestedField(parentPath)` | `(parentPath: string) => void` | Add a nested field to an object |
253
+ | `reset()` | `() => void` | Reset to default state |
254
+
255
+ ### Exports
256
+
257
+ ```typescript
258
+ // Main hook
259
+ export { useJsonSchemaEditor } from "@ht-rnd/json-schema-editor";
260
+
261
+ // Types
262
+ export type {
263
+ JSONSchema,
264
+ FormSchema,
265
+ JsonSchemaEditorOptions,
266
+ SettingsState,
267
+ FieldItem,
268
+ DefinitionItem,
269
+ SchemaType,
270
+ SchemaTypeValue,
271
+ SchemaTypeWithRefValue,
272
+ UseJsonSchemaEditorReturn,
273
+ } from "@ht-rnd/json-schema-editor";
274
+
275
+ // Validation
276
+ export { validateSchema } from "@ht-rnd/json-schema-editor";
277
+ export { jsonSchemaZod } from "@ht-rnd/json-schema-editor";
278
+
279
+ // Constants
280
+ export {
281
+ SCHEMA_TYPES,
282
+ SCHEMA_TYPES_WITH_REF,
283
+ INTEGER_FORMATS,
284
+ NUMBER_FORMATS,
285
+ STRING_FORMATS,
286
+ DEFAULT_SCHEMA_URI,
287
+ } from "@ht-rnd/json-schema-editor";
288
+
289
+ // Transforms and utilities
290
+ export { formToSchema, schemaToForm } from "@ht-rnd/json-schema-editor";
291
+ export {
292
+ createDefaultObjectSchema,
293
+ createDefaultArraySchema,
294
+ createDefaultField,
295
+ } from "@ht-rnd/json-schema-editor";
270
296
  ```
271
297
 
298
+ ## Component Architecture
299
+
300
+ ### Available Components
301
+
302
+ The `components/json-schema-editor/` folder includes these ready-to-use components:
303
+
304
+ #### Form Components
305
+ - `JsonSchemaEditor` - Complete editor with form and output
306
+ - `Root` - Root field component with type selector
307
+ - `FieldList` - List of field rows
308
+ - `FieldRow` - Individual field row with controls
309
+ - `Field` - Recursive field component for nested schemas
310
+
311
+ #### Settings Components
312
+ - `SettingsDialog` - Modal dialog for field settings
313
+ - `Settings` - Main settings router component
314
+ - `StringSettings`, `NumberSettings`, `IntegerSettings`, `BooleanSettings` - Type-specific settings
315
+ - `ObjectSettings`, `ArraySettings` - Complex type settings
316
+ - `BoolCombSettings` - allOf/anyOf/oneOf/not settings
317
+ - `DefinitionsSettings` - $defs management
318
+ - `RootSettings` - Root schema settings
319
+
320
+ #### UI Primitives
321
+ All based on [shadcn/ui](https://ui.shadcn.com/): `Button`, `Input`, `Select`, `Checkbox`, `Dialog`, `Badge`, `Tooltip`, etc.
322
+
323
+ ## Customizing Components
324
+
325
+ The components in `components/json-schema-editor/` follow shadcn/ui patterns:
326
+
327
+ 1. **`cn()` utility**: All components use the `cn()` function to merge Tailwind classes
328
+ 2. **`className` prop**: Every component accepts a `className` prop for customization
329
+ 3. **`forwardRef`**: Components forward refs for DOM access
330
+ 4. **Composable**: Use individual components or compose your own
331
+ 5. **Copy & Modify**: Copy components into your project and customize as needed
332
+
333
+ ### Example: Customizing the FieldRow
334
+
272
335
  ```tsx
273
- // Example 2: Make the form wider and use less spacing
274
- <JsonSchemaEditor
275
- styles={{
276
- form: { width: "lg" },
277
- spacing: "sm",
278
- }}
336
+ import { FieldRow } from "@/components/json-schema-editor";
337
+
338
+ <FieldRow
339
+ className="bg-slate-50 dark:bg-slate-900 rounded-lg"
340
+ fieldPath="properties.0"
341
+ theme="dark"
342
+ // ... other props
279
343
  />
280
344
  ```
281
345
 
346
+ ### Example: Creating a Custom Field Component
347
+
282
348
  ```tsx
283
- // Example 3: Hide the JSON output entirely
284
- <JsonSchemaEditor
285
- styles={{
286
- output: { showJson: false },
287
- }}
288
- />
289
- ```
349
+ import * as React from "react";
350
+ import { Controller, useFormContext } from "react-hook-form";
351
+ import { cn } from "./lib/utils";
352
+ import { Input } from "./ui/input";
353
+
354
+ interface MyCustomFieldProps extends React.HTMLAttributes<HTMLDivElement> {
355
+ fieldPath: string;
356
+ }
290
357
 
291
- ## Technology Stack
358
+ const MyCustomField = React.forwardRef<HTMLDivElement, MyCustomFieldProps>(
359
+ ({ className, fieldPath, ...props }, ref) => {
360
+ const { control } = useFormContext();
361
+
362
+ return (
363
+ <div ref={ref} className={cn("flex gap-2", className)} {...props}>
364
+ <Controller
365
+ control={control}
366
+ name={`${fieldPath}.key`}
367
+ render={({ field }) => (
368
+ <Input {...field} placeholder="Field name" />
369
+ )}
370
+ />
371
+ </div>
372
+ );
373
+ }
374
+ );
375
+ MyCustomField.displayName = "MyCustomField";
292
376
 
293
- - React
294
- - TypeScript
295
- - React Hook Form for powerful and performant form state management.
296
- - Zod for schema validation and type inference.
297
- - AJV for real-time validation against the JSON Schema specification.
298
- - Tailwind CSS for utility-first styling.
299
- - shadcn/ui for the base component primitives.
300
- - Vite for the build tooling.
377
+ export { MyCustomField };
378
+ ```
301
379
 
302
380
  ## License
303
381
 
304
- Licensed under the Apache License 2.0
382
+ Apache-2.0