json-schema-builder-react 0.0.3 → 0.0.5

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
@@ -6,14 +6,13 @@ A beautiful, interactive React component for building and editing JSON schemas v
6
6
 
7
7
  ## Features
8
8
 
9
- - 🎨 **Visual Editor** - Build JSON schemas with an intuitive drag-and-drop interface
9
+ - 🎨 **Visual Editor** - Build JSON schemas with an intuitive interface
10
10
  - 📝 **Full JSON Schema Support** - Support for all JSON Schema types and constraints
11
11
  - 🎯 **Type-Safe** - Written in TypeScript with full type definitions
12
- - ✅ **Official JSON Schema Types** - Uses `@types/json-schema` for spec compliance
12
+ - ✅ **Controlled Component** - Full control over state management
13
13
  - 🎨 **Customizable** - Flexible API with extensive customization options
14
- - 📦 **Headless Options** - Use just the hooks and utilities without UI
15
14
  - 🌗 **Theme Support** - Built-in dark mode support
16
- - ⚡ **Lightweight** - Tree-shakeable with minimal bundle size impact
15
+ - ⚡ **Lightweight** - Minimal bundle size with focused API
17
16
 
18
17
  ## Installation
19
18
 
@@ -84,16 +83,20 @@ Add to your main CSS file (e.g., `src/index.css`):
84
83
  ### Basic Example
85
84
 
86
85
  ```tsx
86
+ import { useState } from 'react';
87
87
  import { JsonSchemaBuilder } from 'json-schema-builder-react';
88
88
 
89
89
  function App() {
90
- const handleSchemaChange = (schema) => {
91
- console.log('Schema updated:', schema);
92
- };
90
+ const [schema, setSchema] = useState({
91
+ type: 'object',
92
+ properties: {},
93
+ required: []
94
+ });
93
95
 
94
96
  return (
95
97
  <JsonSchemaBuilder
96
- onSchemaChange={handleSchemaChange}
98
+ schema={schema}
99
+ onChange={setSchema}
97
100
  />
98
101
  );
99
102
  }
@@ -102,24 +105,35 @@ function App() {
102
105
  ### With Initial Schema
103
106
 
104
107
  ```tsx
108
+ import { useState } from 'react';
105
109
  import { JsonSchemaBuilder } from 'json-schema-builder-react';
106
110
 
107
- const initialSchema = {
108
- type: 'object',
109
- properties: {
110
- name: { type: 'string' },
111
- age: { type: 'number' }
112
- },
113
- required: ['name']
114
- };
115
-
116
111
  function App() {
112
+ const [schema, setSchema] = useState({
113
+ type: 'object',
114
+ title: 'User Profile',
115
+ properties: {
116
+ name: {
117
+ type: 'string',
118
+ minLength: 2,
119
+ maxLength: 50
120
+ },
121
+ age: {
122
+ type: 'integer',
123
+ minimum: 0,
124
+ maximum: 120
125
+ }
126
+ },
127
+ required: ['name']
128
+ });
129
+
117
130
  return (
118
131
  <JsonSchemaBuilder
119
- initialSchema={initialSchema}
120
- onSchemaChange={(schema) => {
132
+ schema={schema}
133
+ onChange={(newSchema) => {
134
+ setSchema(newSchema);
121
135
  // Save to backend, localStorage, etc.
122
- console.log(schema);
136
+ localStorage.setItem('schema', JSON.stringify(newSchema));
123
137
  }}
124
138
  />
125
139
  );
@@ -129,14 +143,21 @@ function App() {
129
143
  ### Customized Layout
130
144
 
131
145
  ```tsx
146
+ import { useState } from 'react';
132
147
  import { JsonSchemaBuilder } from 'json-schema-builder-react';
133
148
 
134
149
  function App() {
150
+ const [schema, setSchema] = useState({
151
+ type: 'object',
152
+ properties: {},
153
+ required: []
154
+ });
155
+
135
156
  return (
136
157
  <JsonSchemaBuilder
158
+ schema={schema}
159
+ onChange={setSchema}
137
160
  showMetadata={true}
138
- showImport={false}
139
- showClear={true}
140
161
  showOutput={true}
141
162
  className="h-[600px]"
142
163
  typeLabels={{
@@ -145,33 +166,130 @@ function App() {
145
166
  object: 'Form',
146
167
  array: 'List',
147
168
  }}
169
+ propertyLabel={{
170
+ singular: 'field',
171
+ plural: 'fields'
172
+ }}
173
+ />
174
+ );
175
+ }
176
+ ```
177
+
178
+ ### With Undo/Redo
179
+
180
+ Since the component is fully controlled, you can implement undo/redo easily:
181
+
182
+ ```tsx
183
+ import { useState } from 'react';
184
+ import { JsonSchemaBuilder } from 'json-schema-builder-react';
185
+
186
+ function App() {
187
+ const [history, setHistory] = useState([{
188
+ type: 'object',
189
+ properties: {},
190
+ required: []
191
+ }]);
192
+ const [currentIndex, setCurrentIndex] = useState(0);
193
+
194
+ const currentSchema = history[currentIndex];
195
+
196
+ const handleChange = (newSchema) => {
197
+ const newHistory = history.slice(0, currentIndex + 1);
198
+ newHistory.push(newSchema);
199
+ setHistory(newHistory);
200
+ setCurrentIndex(currentIndex + 1);
201
+ };
202
+
203
+ const undo = () => {
204
+ if (currentIndex > 0) {
205
+ setCurrentIndex(currentIndex - 1);
206
+ }
207
+ };
208
+
209
+ const redo = () => {
210
+ if (currentIndex < history.length - 1) {
211
+ setCurrentIndex(currentIndex + 1);
212
+ }
213
+ };
214
+
215
+ return (
216
+ <div>
217
+ <div className="toolbar">
218
+ <button onClick={undo} disabled={currentIndex === 0}>
219
+ Undo
220
+ </button>
221
+ <button onClick={redo} disabled={currentIndex === history.length - 1}>
222
+ Redo
223
+ </button>
224
+ </div>
225
+
226
+ <JsonSchemaBuilder
227
+ schema={currentSchema}
228
+ onChange={handleChange}
229
+ />
230
+ </div>
231
+ );
232
+ }
233
+ ```
234
+
235
+ ### Editable Property Keys (Advanced)
236
+
237
+ By default, property keys are **immutable after creation** to prevent breaking existing references in your codebase. However, you can enable key editing with the `keyEditable` prop:
238
+
239
+ ```tsx
240
+ import { useState } from 'react';
241
+ import { JsonSchemaBuilder } from 'json-schema-builder-react';
242
+
243
+ function App() {
244
+ const [schema, setSchema] = useState({
245
+ type: 'object',
246
+ properties: {
247
+ user_name: {
248
+ type: 'string',
249
+ title: 'User Name'
250
+ }
251
+ },
252
+ required: []
253
+ });
254
+
255
+ return (
256
+ <JsonSchemaBuilder
257
+ schema={schema}
258
+ onChange={setSchema}
259
+ keyEditable={true} // ⚠️ Allows changing keys after creation
148
260
  />
149
261
  );
150
262
  }
151
263
  ```
152
264
 
265
+ **⚠️ Warning:** Enabling `keyEditable` allows users to change property keys even after they've been created. This can break existing code that references these keys. Use with caution, primarily in development environments or when you have proper migration strategies in place.
266
+
153
267
  ## API Reference
154
268
 
155
269
  ### JsonSchemaBuilder Props
156
270
 
157
271
  | Prop | Type | Default | Description |
158
272
  |------|------|---------|-------------|
159
- | `initialSchema` | `object` | `undefined` | Initial JSON schema to load |
160
- | `onSchemaChange` | `(schema: any) => void` | `undefined` | Callback when schema changes |
161
- | `showMetadata` | `boolean` | `true` | Show metadata fields (title, description, version) |
273
+ | `schema` | `object` | **Required** | The JSON schema object (controlled) |
274
+ | `onChange` | `(schema: any) => void` | **Required** | Callback when schema changes |
275
+ | `showMetadata` | `boolean` | `false` | Show metadata fields (title, description, version) |
162
276
  | `showImport` | `boolean` | `true` | Show import button |
163
277
  | `showClear` | `boolean` | `true` | Show clear all button |
164
278
  | `showOutput` | `boolean` | `true` | Show JSON output panel |
165
- | `headerContent` | `ReactNode` | `undefined` | Custom header content |
279
+ | `showHeader` | `boolean` | `true` | Show header with action buttons |
280
+ | `showSummary` | `boolean` | `false` | Show summary at bottom |
281
+ | `showRegex` | `boolean` | `false` | Show regex pattern field for strings |
282
+ | `keyEditable` | `boolean` | `false` | Allow editing property keys after initialization (⚠️ may break references) |
166
283
  | `className` | `string` | `"h-screen"` | Custom className for container |
167
- | `typeLabels` | `TypeLabels` | Default labels | Custom labels for property types (e.g., `{ string: 'Text', boolean: 'Yes/No' }`) |
168
- | `propertyLabel` | `{ singular: string, plural: string }` | `{ singular: 'property', plural: 'properties' }` | Custom labels for top-level properties (e.g., `{ singular: 'input', plural: 'inputs' }`) |
284
+ | `typeLabels` | `TypeLabels` | Default labels | Custom labels for property types |
285
+ | `propertyLabel` | `{ singular: string, plural: string }` | `{ singular: 'property', plural: 'properties' }` | Custom labels for properties |
169
286
 
170
287
  ### Customizing Type Labels
171
288
 
172
289
  You can customize how property types are displayed to your users:
173
290
 
174
291
  ```tsx
292
+ import { useState } from 'react';
175
293
  import { JsonSchemaBuilder } from 'json-schema-builder-react';
176
294
  import type { TypeLabels } from 'json-schema-builder-react';
177
295
 
@@ -186,10 +304,17 @@ const customLabels: TypeLabels = {
186
304
  };
187
305
 
188
306
  function App() {
307
+ const [schema, setSchema] = useState({
308
+ type: 'object',
309
+ properties: {},
310
+ required: []
311
+ });
312
+
189
313
  return (
190
314
  <JsonSchemaBuilder
315
+ schema={schema}
316
+ onChange={setSchema}
191
317
  typeLabels={customLabels}
192
- onSchemaChange={(schema) => console.log(schema)}
193
318
  />
194
319
  );
195
320
  }
@@ -209,132 +334,55 @@ This affects:
209
334
  - `array` - Default: "Array"
210
335
  - `null` - Default: "Null"
211
336
 
212
- ## Headless Usage
213
-
214
- Use just the hooks and utilities without the UI components:
215
-
216
- ```tsx
217
- import { useSchemaBuilder, generateSchema } from 'json-schema-builder-react';
218
-
219
- function MyCustomEditor() {
220
- const {
221
- properties,
222
- metadata,
223
- schema,
224
- addProperty,
225
- updateProperty,
226
- deleteProperty,
227
- } = useSchemaBuilder(true);
228
-
229
- return (
230
- <div>
231
- {/* Build your own custom UI */}
232
- <button onClick={() => {
233
- const newProp = addProperty();
234
- updateProperty(newProp.id, {
235
- ...newProp,
236
- key: 'myProperty',
237
- type: 'string'
238
- });
239
- }}>
240
- Add Property
241
- </button>
242
-
243
- <pre>{JSON.stringify(schema, null, 2)}</pre>
244
- </div>
245
- );
246
- }
247
- ```
248
-
249
337
  ## Available Exports
250
338
 
251
- ### Components
252
- - `JsonSchemaBuilder` - Main builder component
253
- - `PropertyDocument` - Individual property card
254
- - `PropertyEditDialog` - Property edit modal
255
- - `JsonOutput` - JSON output display
256
- - `SchemaMetadataComponent` - Schema metadata fields
257
-
258
- ### Hooks
259
- - `useSchemaBuilder` - Main schema builder logic
260
- - `usePropertyEditor` - Property editing logic
261
-
262
- ### Utilities
263
- - `generateSchema` - Generate JSON schema from properties
264
- - `parseSchema` - Parse JSON schema into properties
265
- - `downloadJsonFile` - Download schema as JSON file
266
- - `importJsonFile` - Import schema from file
339
+ ### Component
340
+ - `JsonSchemaBuilder` - Main builder component (controlled)
267
341
 
268
342
  ### Types
269
- - `PropertyData` - Internal UI representation of a JSON Schema property (extends JSON Schema fields)
270
- - `PropertyType` - JSON Schema type names (from `@types/json-schema`)
271
- - `SchemaMetadata` - Schema metadata structure
272
- - `JSONSchema7` - Official JSON Schema Draft 7 type (from `@types/json-schema`)
273
- - `JSONSchema7TypeName` - JSON Schema type names (from `@types/json-schema`)
343
+ - `JsonSchemaBuilderProps` - Props for the main component
344
+ - `TypeLabels` - Type for customizing property type labels
274
345
 
275
- **Note**: This library uses official JSON Schema types from `@types/json-schema` to ensure compatibility with the JSON Schema specification.
346
+ ## Advanced Usage
276
347
 
277
- ## Examples
348
+ ### Integration with State Management
278
349
 
279
- ### Using Individual Components
350
+ The controlled component pattern makes it easy to integrate with any state management solution:
280
351
 
352
+ #### Redux
281
353
  ```tsx
282
- import {
283
- PropertyDocument,
284
- useSchemaBuilder
285
- } from 'json-schema-builder-react';
354
+ import { useSelector, useDispatch } from 'react-redux';
355
+ import { JsonSchemaBuilder } from 'json-schema-builder-react';
356
+ import { updateSchema } from './schemaSlice';
286
357
 
287
- function CustomEditor() {
288
- const { properties, updateProperty, deleteProperty } = useSchemaBuilder();
358
+ function App() {
359
+ const schema = useSelector(state => state.schema);
360
+ const dispatch = useDispatch();
289
361
 
290
362
  return (
291
- <div>
292
- {properties.map(property => (
293
- <PropertyDocument
294
- key={property.id}
295
- property={property}
296
- onUpdate={(updated) => updateProperty(property.id, updated)}
297
- onDelete={() => deleteProperty(property.id)}
298
- />
299
- ))}
300
- </div>
363
+ <JsonSchemaBuilder
364
+ schema={schema}
365
+ onChange={(newSchema) => dispatch(updateSchema(newSchema))}
366
+ />
301
367
  );
302
368
  }
303
369
  ```
304
370
 
305
- ### Programmatic Schema Generation
306
-
371
+ #### Zustand
307
372
  ```tsx
308
- import { generateSchema } from 'json-schema-builder-react';
309
- import type { PropertyData } from 'json-schema-builder-react';
310
-
311
- const properties: PropertyData[] = [
312
- {
313
- id: '1',
314
- key: 'username',
315
- type: 'string',
316
- required: true,
317
- constraints: {
318
- minLength: 3,
319
- maxLength: 20
320
- }
321
- },
322
- {
323
- id: '2',
324
- key: 'email',
325
- type: 'string',
326
- required: true,
327
- constraints: {
328
- pattern: '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$'
329
- }
330
- }
331
- ];
332
-
333
- const schema = generateSchema(
334
- properties,
335
- { title: 'User Schema', description: 'User registration', version: '1.0.0' },
336
- true
337
- );
373
+ import { useSchemaStore } from './store';
374
+ import { JsonSchemaBuilder } from 'json-schema-builder-react';
375
+
376
+ function App() {
377
+ const { schema, setSchema } = useSchemaStore();
378
+
379
+ return (
380
+ <JsonSchemaBuilder
381
+ schema={schema}
382
+ onChange={setSchema}
383
+ />
384
+ );
385
+ }
338
386
  ```
339
387
 
340
388
  ## Development
@@ -57,8 +57,13 @@ export interface JsonSchemaBuilderProps {
57
57
  * @default false
58
58
  */
59
59
  showRegex?: boolean;
60
+ /**
61
+ * Whether to allow editing property keys after initialization
62
+ * @default false
63
+ */
64
+ keyEditable?: boolean;
60
65
  }
61
66
  /**
62
67
  * A visual JSON Schema builder component that allows building JSON schemas interactively
63
68
  */
64
- export declare function JsonSchemaBuilder({ schema, onChange, showMetadata, showImport, showClear, showOutput, showHeader, className, showSummary, typeLabels, propertyLabel, showRegex, }: JsonSchemaBuilderProps): import("react/jsx-runtime").JSX.Element;
69
+ export declare function JsonSchemaBuilder({ schema, onChange, showMetadata, showImport, showClear, showOutput, showHeader, className, showSummary, typeLabels, propertyLabel, showRegex, keyEditable, }: JsonSchemaBuilderProps): import("react/jsx-runtime").JSX.Element;
@@ -6,6 +6,7 @@ interface PropertyDocumentProps {
6
6
  level?: number;
7
7
  isArrayItem?: boolean;
8
8
  showRegex?: boolean;
9
+ keyEditable?: boolean;
9
10
  }
10
- export default function PropertyDocument({ property, onUpdate, onDelete, level, isArrayItem, showRegex, }: PropertyDocumentProps): import("react/jsx-runtime").JSX.Element;
11
+ export default function PropertyDocument({ property, onUpdate, onDelete, level, isArrayItem, showRegex, keyEditable, }: PropertyDocumentProps): import("react/jsx-runtime").JSX.Element;
11
12
  export {};
@@ -11,6 +11,7 @@ interface PropertyEditDialogProps {
11
11
  plural: string;
12
12
  };
13
13
  showRegex?: boolean;
14
+ keyEditable?: boolean;
14
15
  }
15
- export default function PropertyEditDialog({ property, open, onOpenChange, onUpdate, isArrayItem, isNewProperty, propertyLabel, showRegex, }: PropertyEditDialogProps): import("react/jsx-runtime").JSX.Element;
16
+ export default function PropertyEditDialog({ property, open, onOpenChange, onUpdate, isArrayItem, isNewProperty, propertyLabel, showRegex, keyEditable, }: PropertyEditDialogProps): import("react/jsx-runtime").JSX.Element;
16
17
  export {};
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const buttonVariants: (props?: ({
4
- variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
4
+ variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
5
5
  size?: "default" | "sm" | "lg" | "icon" | null | undefined;
6
6
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
7
7
  export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
@@ -16,4 +16,4 @@ declare const DialogFooter: {
16
16
  };
17
17
  declare const DialogTitle: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React.RefAttributes<HTMLHeadingElement>, "ref"> & React.RefAttributes<HTMLHeadingElement>>;
18
18
  declare const DialogDescription: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React.RefAttributes<HTMLParagraphElement>, "ref"> & React.RefAttributes<HTMLParagraphElement>>;
19
- export { Dialog, DialogPortal, DialogOverlay, DialogClose, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, };
19
+ export { Dialog, DialogPortal, DialogOverlay, DialogTrigger, DialogClose, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription, };
@@ -0,0 +1,60 @@
1
+ import type { PropertyData } from "@/types/schema";
2
+ export interface UseChildManagerReturn {
3
+ /**
4
+ * Add a new child property (opens dialog)
5
+ */
6
+ addChild: () => void;
7
+ /**
8
+ * Update an existing child property
9
+ */
10
+ updateChild: (childId: string, updated: PropertyData) => void;
11
+ /**
12
+ * Delete a child property
13
+ */
14
+ deleteChild: (childId: string) => void;
15
+ /**
16
+ * Dialog manager for adding new children
17
+ */
18
+ addChildDialog: {
19
+ isOpen: boolean;
20
+ data: PropertyData | null;
21
+ setIsOpen: (isOpen: boolean) => void;
22
+ confirm: (data: PropertyData) => void;
23
+ };
24
+ }
25
+ /**
26
+ * Hook for managing child properties (nested properties within an object).
27
+ * Handles adding, updating, and deleting children with dialog state management.
28
+ *
29
+ * @param property - The parent property that contains children
30
+ * @param onUpdate - Callback to update the parent property
31
+ *
32
+ * @example
33
+ * ```tsx
34
+ * const childManager = useChildManager(property, onUpdate);
35
+ *
36
+ * // Add child button
37
+ * <Button onClick={childManager.addChild}>Add Child</Button>
38
+ *
39
+ * // Render children
40
+ * {property.children?.map((child) => (
41
+ * <PropertyDocument
42
+ * key={child.id}
43
+ * property={child}
44
+ * onUpdate={(updated) => childManager.updateChild(child.id, updated)}
45
+ * onDelete={() => childManager.deleteChild(child.id)}
46
+ * />
47
+ * ))}
48
+ *
49
+ * // Add child dialog
50
+ * {childManager.addChildDialog.isOpen && childManager.addChildDialog.data && (
51
+ * <PropertyEditDialog
52
+ * property={childManager.addChildDialog.data}
53
+ * open={childManager.addChildDialog.isOpen}
54
+ * onOpenChange={childManager.addChildDialog.setIsOpen}
55
+ * onUpdate={childManager.addChildDialog.confirm}
56
+ * />
57
+ * )}
58
+ * ```
59
+ */
60
+ export declare function useChildManager(property: PropertyData, onUpdate: (property: PropertyData) => void): UseChildManagerReturn;
@@ -0,0 +1,75 @@
1
+ export interface UseDialogManagerReturn<T> {
2
+ /**
3
+ * Whether the dialog is currently open
4
+ */
5
+ isOpen: boolean;
6
+ /**
7
+ * The data associated with the dialog (e.g., the item being edited/created)
8
+ */
9
+ data: T | null;
10
+ /**
11
+ * Open the dialog with optional data
12
+ */
13
+ open: (data?: T) => void;
14
+ /**
15
+ * Close the dialog without saving
16
+ */
17
+ close: () => void;
18
+ /**
19
+ * Confirm and close the dialog (typically calls the onConfirm callback)
20
+ */
21
+ confirm: (data: T) => void;
22
+ /**
23
+ * Set the dialog open state directly
24
+ */
25
+ setIsOpen: (isOpen: boolean) => void;
26
+ }
27
+ export interface UseDialogManagerOptions<T> {
28
+ /**
29
+ * Callback when dialog is confirmed/saved
30
+ */
31
+ onConfirm?: (data: T) => void;
32
+ /**
33
+ * Callback when dialog is cancelled/closed without saving
34
+ */
35
+ onCancel?: () => void;
36
+ /**
37
+ * Factory function to create initial data when opening dialog
38
+ */
39
+ createInitialData?: () => T;
40
+ }
41
+ /**
42
+ * Generic hook for managing dialog state with associated data.
43
+ * Useful for dialogs that create/edit items with temporary state.
44
+ *
45
+ * @param options - Configuration options
46
+ *
47
+ * @example
48
+ * ```tsx
49
+ * // For adding a new property
50
+ * const addDialog = useDialogManager<PropertyData>({
51
+ * createInitialData: () => ({
52
+ * id: generateId(),
53
+ * key: "",
54
+ * type: "string",
55
+ * required: false
56
+ * }),
57
+ * onConfirm: (property) => {
58
+ * updateProperty(property.id, property);
59
+ * }
60
+ * });
61
+ *
62
+ * // Usage in JSX
63
+ * <Button onClick={() => addDialog.open()}>Add Property</Button>
64
+ *
65
+ * {addDialog.isOpen && addDialog.data && (
66
+ * <PropertyEditDialog
67
+ * property={addDialog.data}
68
+ * open={addDialog.isOpen}
69
+ * onOpenChange={addDialog.setIsOpen}
70
+ * onUpdate={addDialog.confirm}
71
+ * />
72
+ * )}
73
+ * ```
74
+ */
75
+ export declare function useDialogManager<T>(options?: UseDialogManagerOptions<T>): UseDialogManagerReturn<T>;
@@ -0,0 +1,71 @@
1
+ export interface UseInlineEditorOptions {
2
+ /**
3
+ * Whether to allow empty values. If false, reverts to original value on blur when empty.
4
+ * @default false
5
+ */
6
+ allowEmpty?: boolean;
7
+ /**
8
+ * Callback when editing starts
9
+ */
10
+ onEditStart?: () => void;
11
+ /**
12
+ * Callback when editing is cancelled
13
+ */
14
+ onEditCancel?: () => void;
15
+ }
16
+ export interface UseInlineEditorReturn {
17
+ /**
18
+ * Whether the field is currently being edited
19
+ */
20
+ isEditing: boolean;
21
+ /**
22
+ * The current edited value
23
+ */
24
+ value: string;
25
+ /**
26
+ * Start editing mode
27
+ */
28
+ startEdit: () => void;
29
+ /**
30
+ * Handle value changes
31
+ */
32
+ handleChange: (newValue: string) => void;
33
+ /**
34
+ * Handle blur event - saves or reverts changes
35
+ */
36
+ handleBlur: () => void;
37
+ /**
38
+ * Handle keyboard events (Enter to save, Escape to cancel)
39
+ */
40
+ handleKeyDown: (e: React.KeyboardEvent<HTMLInputElement>) => void;
41
+ }
42
+ /**
43
+ * Hook for managing inline editing state and behavior.
44
+ * Handles common patterns like Enter/Escape keys, blur to save, and syncing with external value changes.
45
+ *
46
+ * @param initialValue - The initial/current value from props
47
+ * @param onSave - Callback when value should be saved (on blur or Enter)
48
+ * @param options - Optional configuration
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * const titleEditor = useInlineEditor(
53
+ * property.title || "",
54
+ * (newValue) => onUpdate({ ...property, title: newValue }),
55
+ * { allowEmpty: false }
56
+ * );
57
+ *
58
+ * {titleEditor.isEditing ? (
59
+ * <Input
60
+ * value={titleEditor.value}
61
+ * onChange={(e) => titleEditor.handleChange(e.target.value)}
62
+ * onBlur={titleEditor.handleBlur}
63
+ * onKeyDown={titleEditor.handleKeyDown}
64
+ * autoFocus
65
+ * />
66
+ * ) : (
67
+ * <span onClick={titleEditor.startEdit}>{property.title}</span>
68
+ * )}
69
+ * ```
70
+ */
71
+ export declare function useInlineEditor(initialValue: string, onSave: (value: string) => void, options?: UseInlineEditorOptions): UseInlineEditorReturn;