|
| 1 | +# @ht-rnd/json-schema-editor |
| 2 | + |
| 3 | +A modern, highly customizable, and themeable JSON Schema editor built with React, TypeScript, and shadcn/ui. |
| 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. |
| 6 | + |
| 7 | +## Features |
| 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. |
| 18 | + |
| 19 | +## Installation |
| 20 | + |
| 21 | +```bash |
| 22 | +npm install @ht-rnd/json-schema-editor |
| 23 | +``` |
| 24 | + |
| 25 | +## Usage and Setup |
| 26 | + |
| 27 | +Integration requires two simple steps: configuring Tailwind and then using the component. |
| 28 | + |
| 29 | +### Step 1: Configure Tailwind CSS |
| 30 | + |
| 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. |
| 32 | + |
| 33 | +In your project's tailwind.config.js (or .cjs), add the path to the library within your content array: |
| 34 | + |
| 35 | +```ts |
| 36 | +/** @type {import('tailwindcss').Config} */ |
| 37 | +module.exports = { |
| 38 | + content: [ |
| 39 | + "./src/**/*.{js,ts,jsx,tsx}", // Your app's files |
| 40 | + |
| 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 | +``` |
| 50 | + |
| 51 | +### Step 2: Use the Component |
| 52 | + |
| 53 | +```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 | + }; |
| 65 | + |
| 66 | + 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> |
| 78 | + ); |
| 79 | +} |
| 80 | +export default MySchema; |
| 81 | +``` |
| 82 | + |
| 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 | + } |
| 119 | + |
| 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 | +} |
| 139 | + |
| 140 | +/* You can also add global styles like scrollbar theming */ |
| 141 | +* { |
| 142 | + scrollbar-color: hsl(var(--muted)) hsl(var(--background)); |
| 143 | +} |
| 144 | +``` |
| 145 | + |
| 146 | +## API Reference |
| 147 | + |
| 148 | +### `<JsonSchemaEditor />` Props |
| 149 | + |
| 150 | +| Prop | Type | Default | Description | |
| 151 | +| :------------- | :------------------------------ | :--------- | :----------------------------------------------------------------------------------------------------------- | |
| 152 | +| `rootType` | `'object'` \| `'array'` | `'object'` | Sets the root type of the schema. | |
| 153 | +| `readOnly` | `boolean` | `false` | Disables all user interactions, making the editor a display-only component. | |
| 154 | +| `theme` | `string` (e.g., `'dark'`) | `''` | A class name to apply for theming (e.g., pass `"dark"` for dark mode). | |
| 155 | +| `styles` | `Styles` | `{...}` | An object to control the layout, width, and spacing of the editor panels. | |
| 156 | +| `onChange` | `(schema: JSONSchema) => void` | `none` | A callback function that is invoked with the final schema object on any change. | |
| 157 | +| `defaultValue` | `JSONSchema` | `none` | An existing JSON Schema object to load into the editor. When provided, this will override the rootType prop. | |
| 158 | + |
| 159 | +### The `styles` Prop |
| 160 | + |
| 161 | +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. |
| 162 | + |
| 163 | +**Type Definition:** |
| 164 | + |
| 165 | +```ts |
| 166 | +interface Styles { |
| 167 | + form: { |
| 168 | + width: "sm" | "md" | "lg" | "full"; |
| 169 | + height: "sm" | "md" | "lg" | "full"; |
| 170 | + }; |
| 171 | + output: { |
| 172 | + position: "top" | "bottom" | "left" | "right"; |
| 173 | + showJson: boolean; |
| 174 | + width: "sm" | "md" | "lg" | "full"; |
| 175 | + height: "sm" | "md" | "lg" | "full"; |
| 176 | + }; |
| 177 | + settings: { |
| 178 | + width: "sm" | "md" | "lg" | "full"; |
| 179 | + }; |
| 180 | + spacing: "sm" | "md" | "lg"; |
| 181 | +} |
| 182 | +``` |
| 183 | + |
| 184 | +**Example Usage:** |
| 185 | + |
| 186 | +```tsx |
| 187 | +// Example 1: Move the JSON output to the right side |
| 188 | +<JsonSchemaEditor |
| 189 | + styles={{ |
| 190 | + output: { position: "right" }, |
| 191 | + }} |
| 192 | +/> |
| 193 | +``` |
| 194 | + |
| 195 | +```tsx |
| 196 | +// Example 2: Make the form wider and use less spacing |
| 197 | +<JsonSchemaEditor |
| 198 | + styles={{ |
| 199 | + form: { width: "lg" }, |
| 200 | + spacing: "sm", |
| 201 | + }} |
| 202 | +/> |
| 203 | +``` |
| 204 | + |
| 205 | +```tsx |
| 206 | +// Example 3: Hide the JSON output entirely |
| 207 | +<JsonSchemaEditor |
| 208 | + styles={{ |
| 209 | + output: { showJson: false }, |
| 210 | + }} |
| 211 | +/> |
| 212 | +``` |
| 213 | + |
| 214 | +## Technology Stack |
| 215 | + |
| 216 | +- React |
| 217 | +- TypeScript |
| 218 | +- React Hook Form for powerful and performant form state management. |
| 219 | +- Zod for schema validation and type inference. |
| 220 | +- AJV for real-time validation against the JSON Schema specification. |
| 221 | +- Tailwind CSS for utility-first styling. |
| 222 | +- shadcn/ui for the base component primitives. |
| 223 | +- Vite for the build tooling. |
| 224 | + |
| 225 | +## License |
| 226 | + |
| 227 | +Licensed under the Apache License 2.0 |
0 commit comments