@object-ui/react 3.3.0 → 3.3.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.
Files changed (102) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +21 -1
  3. package/dist/context/AppShellContext.d.ts +26 -0
  4. package/dist/context/AppShellContext.js +67 -0
  5. package/dist/context/index.d.ts +1 -7
  6. package/dist/context/index.js +1 -7
  7. package/package.json +32 -9
  8. package/.turbo/turbo-build.log +0 -4
  9. package/src/LazyPluginLoader.tsx +0 -174
  10. package/src/SchemaRenderer.tsx +0 -266
  11. package/src/__tests__/LazyPluginLoader.test.tsx +0 -176
  12. package/src/__tests__/SchemaRenderer.aria.test.tsx +0 -118
  13. package/src/__tests__/SchemaRenderer.debug.test.tsx +0 -69
  14. package/src/__tests__/SchemaRenderer.errorBoundary.test.tsx +0 -114
  15. package/src/__tests__/SchemaRenderer.expressions.test.tsx +0 -131
  16. package/src/__tests__/SchemaRendererProvider.smoke.test.tsx +0 -132
  17. package/src/__tests__/ThemeProvider.test.tsx +0 -451
  18. package/src/__tests__/useNavigationOverlay.test.ts +0 -578
  19. package/src/__tests__/useOffline.test.ts +0 -198
  20. package/src/__tests__/usePageTransition.test.ts +0 -214
  21. package/src/__tests__/usePageVariables.test.tsx +0 -334
  22. package/src/__tests__/usePerformance.test.ts +0 -137
  23. package/src/__tests__/useViewData.test.tsx +0 -422
  24. package/src/__tests__/view-switching.test.tsx +0 -456
  25. package/src/components/form/FieldFactory.tsx +0 -516
  26. package/src/components/form/FormRenderer.test.tsx +0 -744
  27. package/src/components/form/FormRenderer.tsx +0 -258
  28. package/src/components/form/README.md +0 -352
  29. package/src/components/form/index.ts +0 -12
  30. package/src/context/ActionContext.tsx +0 -213
  31. package/src/context/DndContext.tsx +0 -260
  32. package/src/context/NotificationContext.tsx +0 -280
  33. package/src/context/SchemaRendererContext.tsx +0 -48
  34. package/src/context/ThemeContext.tsx +0 -325
  35. package/src/context/__tests__/ActionContext.test.tsx +0 -174
  36. package/src/context/__tests__/DndContext.test.tsx +0 -150
  37. package/src/context/__tests__/NotificationContext.test.tsx +0 -176
  38. package/src/context/__tests__/useDataScope.test.tsx +0 -91
  39. package/src/context/index.ts +0 -13
  40. package/src/hooks/__tests__/useActionEngine.test.ts +0 -170
  41. package/src/hooks/__tests__/useActionRunner.test.ts +0 -153
  42. package/src/hooks/__tests__/useAnimation.test.ts +0 -82
  43. package/src/hooks/__tests__/useColumnSummary.test.ts +0 -93
  44. package/src/hooks/__tests__/useCrudShortcuts.test.ts +0 -85
  45. package/src/hooks/__tests__/useDataRefresh.test.ts +0 -115
  46. package/src/hooks/__tests__/useDebugMode.test.ts +0 -83
  47. package/src/hooks/__tests__/useDensityMode.test.ts +0 -81
  48. package/src/hooks/__tests__/useDiscovery.test.tsx +0 -247
  49. package/src/hooks/__tests__/useDynamicApp.test.ts +0 -161
  50. package/src/hooks/__tests__/useETagCache.test.ts +0 -153
  51. package/src/hooks/__tests__/useExpression.test.ts +0 -86
  52. package/src/hooks/__tests__/useFocusTrap.test.ts +0 -294
  53. package/src/hooks/__tests__/useKeyboardShortcuts.test.ts +0 -144
  54. package/src/hooks/__tests__/usePageTransition.test.ts +0 -158
  55. package/src/hooks/__tests__/usePerformanceBudget.test.ts +0 -157
  56. package/src/hooks/__tests__/useReducedMotion.test.ts +0 -104
  57. package/src/hooks/__tests__/useSchemaPersistence.test.ts +0 -220
  58. package/src/hooks/__tests__/useViewSharing.test.ts +0 -121
  59. package/src/hooks/__tests__/useViewTransition.test.ts +0 -61
  60. package/src/hooks/index.ts +0 -36
  61. package/src/hooks/useActionEngine.ts +0 -84
  62. package/src/hooks/useActionRunner.ts +0 -119
  63. package/src/hooks/useAnimation.ts +0 -117
  64. package/src/hooks/useClientNotifications.ts +0 -251
  65. package/src/hooks/useColumnSummary.ts +0 -87
  66. package/src/hooks/useCrudShortcuts.ts +0 -126
  67. package/src/hooks/useDataRefresh.ts +0 -58
  68. package/src/hooks/useDebugMode.ts +0 -95
  69. package/src/hooks/useDensityMode.ts +0 -102
  70. package/src/hooks/useDiscovery.ts +0 -168
  71. package/src/hooks/useDynamicApp.ts +0 -142
  72. package/src/hooks/useETagCache.ts +0 -404
  73. package/src/hooks/useExpression.ts +0 -56
  74. package/src/hooks/useFocusManagement.ts +0 -248
  75. package/src/hooks/useFocusTrap.ts +0 -138
  76. package/src/hooks/useGlobalUndo.ts +0 -98
  77. package/src/hooks/useKeyboardShortcuts.ts +0 -119
  78. package/src/hooks/useNavigationOverlay.ts +0 -190
  79. package/src/hooks/useOffline.ts +0 -301
  80. package/src/hooks/usePageTransition.ts +0 -187
  81. package/src/hooks/usePageVariables.tsx +0 -157
  82. package/src/hooks/usePerformance.ts +0 -246
  83. package/src/hooks/usePerformanceBudget.ts +0 -313
  84. package/src/hooks/useReducedMotion.ts +0 -53
  85. package/src/hooks/useSchemaPersistence.ts +0 -222
  86. package/src/hooks/useViewData.ts +0 -201
  87. package/src/hooks/useViewSharing.ts +0 -140
  88. package/src/hooks/useViewTransition.ts +0 -144
  89. package/src/index.ts +0 -41
  90. package/src/spec-bridge/SpecBridge.ts +0 -64
  91. package/src/spec-bridge/__tests__/P1SpecBridge.test.ts +0 -855
  92. package/src/spec-bridge/__tests__/SpecBridge.test.ts +0 -550
  93. package/src/spec-bridge/bridges/dashboard.ts +0 -180
  94. package/src/spec-bridge/bridges/form-view.ts +0 -109
  95. package/src/spec-bridge/bridges/list-view.ts +0 -187
  96. package/src/spec-bridge/bridges/page.ts +0 -136
  97. package/src/spec-bridge/index.ts +0 -14
  98. package/src/spec-bridge/types.ts +0 -38
  99. package/src/utils/i18n.ts +0 -10
  100. package/tsconfig.json +0 -17
  101. package/tsconfig.tsbuildinfo +0 -1
  102. package/vitest.config.ts +0 -2
@@ -1,258 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- import React from 'react';
10
- import { useForm, FormProvider, UseFormReturn } from 'react-hook-form';
11
- import type { FormView, FormSection } from '@objectstack/spec/ui';
12
- import { FieldFactory } from './FieldFactory';
13
- import { ExpressionEvaluator } from '@object-ui/core';
14
- import { resolveI18nLabel } from '../../utils/i18n';
15
-
16
- export interface FormRendererProps {
17
- /**
18
- * The FormView schema from @objectstack/spec
19
- */
20
- schema: FormView;
21
- /**
22
- * Initial form data
23
- */
24
- data?: Record<string, any>;
25
- /**
26
- * Form submission handler
27
- */
28
- onSubmit?: (data: Record<string, any>) => void | Promise<void>;
29
- /**
30
- * Form change handler
31
- */
32
- onChange?: (data: Record<string, any>) => void;
33
- /**
34
- * Custom class name for the form
35
- */
36
- className?: string;
37
- /**
38
- * Whether the form is disabled
39
- */
40
- disabled?: boolean;
41
- }
42
-
43
- /**
44
- * FormRenderer component that renders forms based on FormViewSchema
45
- * from @objectstack/spec
46
- */
47
- export const FormRenderer: React.FC<FormRendererProps> = ({
48
- schema,
49
- data = {},
50
- onSubmit,
51
- onChange,
52
- className = '',
53
- disabled = false,
54
- }) => {
55
- // Create form methods with react-hook-form
56
- const methods = useForm({
57
- defaultValues: data,
58
- mode: 'onChange',
59
- });
60
-
61
- const { handleSubmit, watch } = methods;
62
-
63
- // Watch for form changes
64
- React.useEffect(() => {
65
- if (onChange) {
66
- const subscription = watch((value) => {
67
- onChange(value as Record<string, any>);
68
- });
69
- return () => subscription.unsubscribe();
70
- }
71
- }, [watch, onChange]);
72
-
73
- // Handle form submission
74
- const onSubmitForm = handleSubmit(async (formData) => {
75
- if (onSubmit) {
76
- await onSubmit(formData);
77
- }
78
- });
79
-
80
- // Render sections or fields
81
- const renderContent = () => {
82
- if (!schema.sections || schema.sections.length === 0) {
83
- return null;
84
- }
85
-
86
- return (
87
- <div className="space-y-6">
88
- {schema.sections.map((section, index) => (
89
- <FormSectionRenderer
90
- key={index}
91
- section={section}
92
- methods={methods}
93
- disabled={disabled}
94
- />
95
- ))}
96
- </div>
97
- );
98
- };
99
-
100
- return (
101
- <FormProvider {...methods}>
102
- <form onSubmit={onSubmitForm} className={`space-y-6 ${className}`}>
103
- {renderContent()}
104
-
105
- {/* Submit button - optional, can be customized */}
106
- <div className="flex justify-end gap-2">
107
- <button
108
- type="submit"
109
- disabled={disabled}
110
- className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed"
111
- >
112
- Submit
113
- </button>
114
- </div>
115
- </form>
116
- </FormProvider>
117
- );
118
- };
119
-
120
- interface FormSectionRendererProps {
121
- section: FormSection;
122
- methods: UseFormReturn<any>;
123
- disabled?: boolean;
124
- }
125
-
126
- // Grid column classes for different column counts
127
- const GRID_COLS = {
128
- 1: 'grid-cols-1',
129
- 2: 'grid-cols-1 md:grid-cols-2',
130
- 3: 'grid-cols-1 md:grid-cols-3',
131
- 4: 'grid-cols-1 md:grid-cols-2 lg:grid-cols-4',
132
- } as const;
133
-
134
- // Column span classes
135
- const COL_SPAN = {
136
- 1: 'col-span-1',
137
- 2: 'col-span-2',
138
- 3: 'col-span-3',
139
- 4: 'col-span-4',
140
- } as const;
141
-
142
- /**
143
- * Evaluate whether a field should be visible based on visibleOn expression
144
- * and dependsOn parent field value.
145
- */
146
- function evaluateFieldVisibility(
147
- fieldConfig: any,
148
- formValues: Record<string, any>,
149
- ): boolean {
150
- // If explicitly hidden, skip
151
- if (fieldConfig.hidden) {
152
- return false;
153
- }
154
-
155
- // Evaluate visibleOn expression
156
- if (fieldConfig.visibleOn) {
157
- try {
158
- const evaluator = new ExpressionEvaluator({ data: formValues, form: formValues });
159
- return evaluator.evaluateCondition(fieldConfig.visibleOn);
160
- } catch {
161
- // On error, default to visible
162
- return true;
163
- }
164
- }
165
-
166
- // Evaluate dependsOn: field is hidden if parent field has no value
167
- if (fieldConfig.dependsOn) {
168
- const parentValue = formValues[fieldConfig.dependsOn];
169
- return parentValue !== undefined && parentValue !== null && parentValue !== '';
170
- }
171
-
172
- return true;
173
- }
174
-
175
- /**
176
- * Renders a form section with grid layout
177
- */
178
- const FormSectionRenderer: React.FC<FormSectionRendererProps> = ({
179
- section,
180
- methods,
181
- disabled = false,
182
- }) => {
183
- const [isCollapsed, setIsCollapsed] = React.useState(section.collapsed || false);
184
-
185
- // Determine grid columns based on section.columns
186
- const gridCols = GRID_COLS[section.columns || 1];
187
-
188
- // Collect whether there are any conditional fields
189
- const hasConditionalFields = React.useMemo(() => {
190
- return section.fields.some((field) => {
191
- if (typeof field === 'string') return false;
192
- return !!field.dependsOn || !!field.visibleOn;
193
- });
194
- }, [section.fields]);
195
-
196
- // Watch form values for conditional field evaluation
197
- // Only watch when there are fields with dependsOn or visibleOn to avoid
198
- // unnecessary re-renders in forms without conditional fields.
199
- const allFormValues = methods.watch();
200
- const formValues = hasConditionalFields ? allFormValues : undefined;
201
-
202
- const handleToggleCollapse = () => {
203
- if (section.collapsible) {
204
- setIsCollapsed(!isCollapsed);
205
- }
206
- };
207
-
208
- return (
209
- <div className="border rounded-lg p-4">
210
- {section.label && (
211
- <div
212
- className={`flex items-center justify-between mb-4 ${
213
- section.collapsible ? 'cursor-pointer' : ''
214
- }`}
215
- onClick={handleToggleCollapse}
216
- >
217
- <h3 className="text-lg font-semibold">{resolveI18nLabel(section.label)}</h3>
218
- {section.collapsible && (
219
- <span className="text-sm text-gray-500">
220
- {isCollapsed ? '▶' : '▼'}
221
- </span>
222
- )}
223
- </div>
224
- )}
225
-
226
- {!isCollapsed && (
227
- <div className={`grid ${gridCols} gap-4`}>
228
- {section.fields.map((field, index) => {
229
- // Handle both string fields (legacy) and FormFieldSchema objects
230
- const fieldName = typeof field === 'string' ? field : field.field;
231
- const fieldConfig = typeof field === 'string' ? { field: fieldName } : field;
232
-
233
- // Evaluate visibility: static hidden, visibleOn expression, dependsOn parent
234
- if (!evaluateFieldVisibility(fieldConfig, formValues || {})) {
235
- return null;
236
- }
237
-
238
- // Calculate colSpan for grid
239
- const colSpan = fieldConfig.colSpan || 1;
240
- const colSpanClass = COL_SPAN[Math.min(colSpan, section.columns || 1) as keyof typeof COL_SPAN];
241
-
242
- return (
243
- <div key={`${fieldName}-${index}`} className={colSpanClass}>
244
- <FieldFactory
245
- field={fieldConfig}
246
- methods={methods}
247
- disabled={disabled || fieldConfig.readonly}
248
- />
249
- </div>
250
- );
251
- })}
252
- </div>
253
- )}
254
- </div>
255
- );
256
- };
257
-
258
- FormRenderer.displayName = 'FormRenderer';
@@ -1,352 +0,0 @@
1
- # FormRenderer Component
2
-
3
- The `FormRenderer` component is a React component that renders forms based on the `FormView` schema from `@objectstack/spec`. It provides a flexible and powerful way to create forms with minimal code.
4
-
5
- ## Features
6
-
7
- - ✅ **Schema-driven**: Define forms using JSON schema from `@objectstack/spec`
8
- - ✅ **Multi-column layouts**: Support for 1-4 column grid layouts
9
- - ✅ **Collapsible sections**: Organize forms with collapsible sections
10
- - ✅ **Form state management**: Built-in state management using `react-hook-form`
11
- - ✅ **Multiple field types**: Text, Number, Checkbox, Textarea, Select, Date, DateTime, Time
12
- - ⏳ **Conditional fields**: Show/hide fields based on conditions (planned)
13
- - ⏳ **Schema validation**: Zod validation support (planned)
14
- - ✅ **Column spanning**: Fields can span multiple columns
15
- - ✅ **Help text**: Display helpful descriptions for fields
16
- - ✅ **Required fields**: Mark fields as required with validation
17
-
18
- ## Installation
19
-
20
- The FormRenderer component is part of the `@object-ui/react` package:
21
-
22
- ```bash
23
- npm install @object-ui/react @objectstack/spec react-hook-form
24
- ```
25
-
26
- Or with pnpm:
27
-
28
- ```bash
29
- pnpm add @object-ui/react @objectstack/spec react-hook-form
30
- ```
31
-
32
- ## Basic Usage
33
-
34
- ```tsx
35
- import { FormRenderer } from '@object-ui/react';
36
- import type { FormView } from '@objectstack/spec/ui';
37
-
38
- const schema: FormView = {
39
- type: 'simple',
40
- sections: [
41
- {
42
- label: 'Contact Information',
43
- collapsible: false,
44
- collapsed: false,
45
- columns: 2,
46
- fields: [
47
- {
48
- field: 'firstName',
49
- label: 'First Name',
50
- required: true,
51
- widget: 'text',
52
- },
53
- {
54
- field: 'lastName',
55
- label: 'Last Name',
56
- required: true,
57
- widget: 'text',
58
- },
59
- {
60
- field: 'email',
61
- label: 'Email',
62
- required: true,
63
- widget: 'email',
64
- helpText: 'We will never share your email',
65
- },
66
- ],
67
- },
68
- ],
69
- };
70
-
71
- function MyForm() {
72
- const handleSubmit = (data: Record<string, any>) => {
73
- console.log('Form submitted:', data);
74
- };
75
-
76
- return (
77
- <FormRenderer
78
- schema={schema}
79
- onSubmit={handleSubmit}
80
- />
81
- );
82
- }
83
- ```
84
-
85
- ## Props
86
-
87
- ### FormRendererProps
88
-
89
- | Prop | Type | Required | Description |
90
- |------|------|----------|-------------|
91
- | `schema` | `FormView` | Yes | The FormView schema from @objectstack/spec |
92
- | `data` | `Record<string, any>` | No | Initial form data |
93
- | `onSubmit` | `(data: Record<string, any>) => void \| Promise<void>` | No | Form submission handler |
94
- | `onChange` | `(data: Record<string, any>) => void` | No | Form change handler |
95
- | `className` | `string` | No | Custom CSS class for the form |
96
- | `disabled` | `boolean` | No | Whether the form is disabled |
97
-
98
- ## Schema Structure
99
-
100
- ### FormView
101
-
102
- The main schema that defines the entire form.
103
-
104
- ```typescript
105
- interface FormView {
106
- type: 'simple' | 'tabbed' | 'wizard';
107
- sections?: FormSection[];
108
- data?: DataSource; // Optional data source configuration
109
- }
110
- ```
111
-
112
- ### FormSection
113
-
114
- Defines a section of the form with its own layout.
115
-
116
- ```typescript
117
- interface FormSection {
118
- label?: string;
119
- collapsible?: boolean;
120
- collapsed?: boolean;
121
- columns: 1 | 2 | 3 | 4;
122
- fields: (string | FormField)[];
123
- }
124
- ```
125
-
126
- ### FormField
127
-
128
- Defines individual form fields.
129
-
130
- ```typescript
131
- interface FormField {
132
- field: string; // Field name
133
- label?: string;
134
- placeholder?: string;
135
- helpText?: string;
136
- readonly?: boolean;
137
- required?: boolean;
138
- hidden?: boolean;
139
- colSpan?: number; // Number of columns to span (1-4)
140
- widget?: string; // Widget type (text, number, checkbox, etc.)
141
- dependsOn?: string; // Field dependency
142
- visibleOn?: string; // Visibility condition
143
- }
144
- ```
145
-
146
- ## Supported Widget Types
147
-
148
- The `FieldFactory` component supports the following widget types:
149
-
150
- ### Text Input Types
151
- - `text`, `string` - Basic text input
152
- - `email` - Email input with validation
153
- - `password` - Password input (masked)
154
- - `url` - URL input
155
- - `tel`, `phone` - Telephone/phone number input
156
- - `textarea` - Multi-line text input
157
- - `markdown` - Markdown text editor (textarea with monospace font)
158
- - `html` - HTML/Rich text editor (textarea with monospace font)
159
-
160
- ### Numeric Input Types
161
- - `number`, `integer`, `float` - Number input
162
- - `currency` - Currency input with $ prefix
163
- - `percent` - Percentage input with % suffix
164
-
165
- ### Boolean & Selection Types
166
- - `checkbox`, `boolean` - Checkbox input
167
- - `select`, `dropdown` - Select dropdown
168
-
169
- ### Date & Time Types
170
- - `date` - Date picker
171
- - `datetime`, `datetime-local` - DateTime picker
172
- - `time` - Time picker
173
-
174
- ### File Upload Types
175
- - `file` - File upload input
176
- - `image` - Image upload input (defaults to image/* mime types)
177
-
178
- ### Relationship Types
179
- - `lookup` - Lookup/reference field (select with options)
180
- - `master_detail` - Master-detail relationship (select with options)
181
- - `user`, `owner` - User selection field (select with options)
182
-
183
- ### Complex & Special Types
184
- - `location` - Geographic location (latitude/longitude inputs)
185
- - `object` - JSON object editor (textarea with JSON validation)
186
- - `formula` - Read-only computed field
187
- - `summary` - Read-only aggregation/rollup field
188
- - `auto_number` - Read-only auto-generated number
189
- - `vector` - Vector/embedding display (read-only)
190
- - `grid` - Sub-table/grid editor (placeholder)
191
-
192
- ## Extended Field Properties
193
-
194
- Some field types support additional properties beyond the base FormField schema:
195
-
196
- ```typescript
197
- interface ExtendedFormField extends FormField {
198
- // For file/image uploads
199
- multiple?: boolean;
200
- accept?: string[];
201
-
202
- // For select/lookup/user fields
203
- options?: Array<{
204
- label: string;
205
- value: string;
206
- disabled?: boolean;
207
- }>;
208
- }
209
- ```
210
-
211
- Example usage with extended properties:
212
-
213
- ```tsx
214
- {
215
- field: 'avatar',
216
- label: 'Profile Picture',
217
- widget: 'image',
218
- accept: ['image/png', 'image/jpeg'],
219
- multiple: false
220
- }
221
-
222
- {
223
- field: 'account',
224
- label: 'Account',
225
- widget: 'lookup',
226
- options: [
227
- { label: 'Account 1', value: '1' },
228
- { label: 'Account 2', value: '2' }
229
- ]
230
- }
231
- ```
232
-
233
- ## Known Limitations
234
-
235
- ### Version 0.3.0
236
-
237
- - **Conditional Visibility**: The `visibleOn` and `dependsOn` properties are not yet implemented. Fields are visible by default unless explicitly marked as `hidden`.
238
- - **Advanced Select Options**: While select/lookup/user fields support options via the `ExtendedFormField` interface, they don't yet support advanced features like search, async loading, or custom rendering.
239
- - **Rich Text Editors**: The `markdown` and `html` widgets currently use plain textareas with monospace fonts. Full WYSIWYG editors are planned for future releases.
240
- - **File Upload Preview**: File and image widgets support uploads but don't yet show previews or provide upload progress indicators.
241
- - **Location Maps**: The location widget provides lat/lng inputs but doesn't include map visualization or geocoding.
242
- - **Grid Editor**: The grid widget is a placeholder and doesn't yet provide spreadsheet-like editing capabilities.
243
- - **Validation**: Currently only basic required field validation is supported via react-hook-form. Advanced Zod schema validation is planned for future releases.
244
-
245
- These features are planned for future releases.
246
-
247
- ## Examples
248
-
249
- ### Multi-Section Form
250
-
251
- ```tsx
252
- const schema: FormView = {
253
- type: 'simple',
254
- sections: [
255
- {
256
- label: 'Personal Information',
257
- collapsible: true,
258
- collapsed: false,
259
- columns: 2,
260
- fields: [
261
- { field: 'firstName', label: 'First Name', required: true, widget: 'text' },
262
- { field: 'lastName', label: 'Last Name', required: true, widget: 'text' },
263
- { field: 'email', label: 'Email', required: true, widget: 'email' },
264
- { field: 'phone', label: 'Phone', widget: 'tel' },
265
- ],
266
- },
267
- {
268
- label: 'Preferences',
269
- collapsible: true,
270
- collapsed: true,
271
- columns: 1,
272
- fields: [
273
- {
274
- field: 'newsletter',
275
- label: 'Subscribe to newsletter',
276
- widget: 'checkbox',
277
- helpText: 'Receive updates about our products',
278
- },
279
- ],
280
- },
281
- ],
282
- };
283
- ```
284
-
285
- ### Form with Initial Data
286
-
287
- ```tsx
288
- const initialData = {
289
- firstName: 'John',
290
- lastName: 'Doe',
291
- email: 'john@example.com',
292
- newsletter: true,
293
- };
294
-
295
- <FormRenderer
296
- schema={schema}
297
- data={initialData}
298
- onSubmit={handleSubmit}
299
- />
300
- ```
301
-
302
- ### Form with Column Spanning
303
-
304
- ```tsx
305
- const schema: FormView = {
306
- type: 'simple',
307
- sections: [
308
- {
309
- label: 'Contact',
310
- columns: 2,
311
- fields: [
312
- { field: 'name', label: 'Name', widget: 'text' },
313
- { field: 'email', label: 'Email', widget: 'email' },
314
- {
315
- field: 'message',
316
- label: 'Message',
317
- widget: 'textarea',
318
- colSpan: 2, // Spans both columns
319
- },
320
- ],
321
- },
322
- ],
323
- };
324
- ```
325
-
326
- ## Architecture
327
-
328
- The FormRenderer is built on top of:
329
-
330
- - **react-hook-form**: For form state management and validation
331
- - **@objectstack/spec**: For schema definitions
332
-
333
- ## Customization
334
-
335
- You can customize the appearance of the form by:
336
-
337
- 1. Using the `className` prop on the FormRenderer
338
- 2. Using Tailwind CSS classes in your application
339
- 3. Extending the FieldFactory component for custom widgets
340
-
341
- ## Related Components
342
-
343
- - `FieldFactory`: Renders individual form fields based on widget type
344
- - `SchemaRenderer`: General-purpose schema renderer for ObjectUI
345
-
346
- ## License
347
-
348
- MIT
349
-
350
- ## Contributing
351
-
352
- Contributions are welcome! Please read the [CONTRIBUTING.md](../../CONTRIBUTING.md) for details.
@@ -1,12 +0,0 @@
1
- /**
2
- * ObjectUI
3
- * Copyright (c) 2024-present ObjectStack Inc.
4
- *
5
- * This source code is licensed under the MIT license found in the
6
- * LICENSE file in the root directory of this source tree.
7
- */
8
-
9
- export { FormRenderer } from './FormRenderer';
10
- export type { FormRendererProps } from './FormRenderer';
11
- export { FieldFactory } from './FieldFactory';
12
- export type { FieldFactoryProps, ExtendedFormField } from './FieldFactory';