@object-ui/react 3.3.0 → 3.3.2

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 (103) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +21 -1
  3. package/dist/SchemaRenderer.js +19 -2
  4. package/dist/context/AppShellContext.d.ts +26 -0
  5. package/dist/context/AppShellContext.js +67 -0
  6. package/dist/context/index.d.ts +1 -7
  7. package/dist/context/index.js +1 -7
  8. package/package.json +32 -9
  9. package/.turbo/turbo-build.log +0 -4
  10. package/src/LazyPluginLoader.tsx +0 -174
  11. package/src/SchemaRenderer.tsx +0 -266
  12. package/src/__tests__/LazyPluginLoader.test.tsx +0 -176
  13. package/src/__tests__/SchemaRenderer.aria.test.tsx +0 -118
  14. package/src/__tests__/SchemaRenderer.debug.test.tsx +0 -69
  15. package/src/__tests__/SchemaRenderer.errorBoundary.test.tsx +0 -114
  16. package/src/__tests__/SchemaRenderer.expressions.test.tsx +0 -131
  17. package/src/__tests__/SchemaRendererProvider.smoke.test.tsx +0 -132
  18. package/src/__tests__/ThemeProvider.test.tsx +0 -451
  19. package/src/__tests__/useNavigationOverlay.test.ts +0 -578
  20. package/src/__tests__/useOffline.test.ts +0 -198
  21. package/src/__tests__/usePageTransition.test.ts +0 -214
  22. package/src/__tests__/usePageVariables.test.tsx +0 -334
  23. package/src/__tests__/usePerformance.test.ts +0 -137
  24. package/src/__tests__/useViewData.test.tsx +0 -422
  25. package/src/__tests__/view-switching.test.tsx +0 -456
  26. package/src/components/form/FieldFactory.tsx +0 -516
  27. package/src/components/form/FormRenderer.test.tsx +0 -744
  28. package/src/components/form/FormRenderer.tsx +0 -258
  29. package/src/components/form/README.md +0 -352
  30. package/src/components/form/index.ts +0 -12
  31. package/src/context/ActionContext.tsx +0 -213
  32. package/src/context/DndContext.tsx +0 -260
  33. package/src/context/NotificationContext.tsx +0 -280
  34. package/src/context/SchemaRendererContext.tsx +0 -48
  35. package/src/context/ThemeContext.tsx +0 -325
  36. package/src/context/__tests__/ActionContext.test.tsx +0 -174
  37. package/src/context/__tests__/DndContext.test.tsx +0 -150
  38. package/src/context/__tests__/NotificationContext.test.tsx +0 -176
  39. package/src/context/__tests__/useDataScope.test.tsx +0 -91
  40. package/src/context/index.ts +0 -13
  41. package/src/hooks/__tests__/useActionEngine.test.ts +0 -170
  42. package/src/hooks/__tests__/useActionRunner.test.ts +0 -153
  43. package/src/hooks/__tests__/useAnimation.test.ts +0 -82
  44. package/src/hooks/__tests__/useColumnSummary.test.ts +0 -93
  45. package/src/hooks/__tests__/useCrudShortcuts.test.ts +0 -85
  46. package/src/hooks/__tests__/useDataRefresh.test.ts +0 -115
  47. package/src/hooks/__tests__/useDebugMode.test.ts +0 -83
  48. package/src/hooks/__tests__/useDensityMode.test.ts +0 -81
  49. package/src/hooks/__tests__/useDiscovery.test.tsx +0 -247
  50. package/src/hooks/__tests__/useDynamicApp.test.ts +0 -161
  51. package/src/hooks/__tests__/useETagCache.test.ts +0 -153
  52. package/src/hooks/__tests__/useExpression.test.ts +0 -86
  53. package/src/hooks/__tests__/useFocusTrap.test.ts +0 -294
  54. package/src/hooks/__tests__/useKeyboardShortcuts.test.ts +0 -144
  55. package/src/hooks/__tests__/usePageTransition.test.ts +0 -158
  56. package/src/hooks/__tests__/usePerformanceBudget.test.ts +0 -157
  57. package/src/hooks/__tests__/useReducedMotion.test.ts +0 -104
  58. package/src/hooks/__tests__/useSchemaPersistence.test.ts +0 -220
  59. package/src/hooks/__tests__/useViewSharing.test.ts +0 -121
  60. package/src/hooks/__tests__/useViewTransition.test.ts +0 -61
  61. package/src/hooks/index.ts +0 -36
  62. package/src/hooks/useActionEngine.ts +0 -84
  63. package/src/hooks/useActionRunner.ts +0 -119
  64. package/src/hooks/useAnimation.ts +0 -117
  65. package/src/hooks/useClientNotifications.ts +0 -251
  66. package/src/hooks/useColumnSummary.ts +0 -87
  67. package/src/hooks/useCrudShortcuts.ts +0 -126
  68. package/src/hooks/useDataRefresh.ts +0 -58
  69. package/src/hooks/useDebugMode.ts +0 -95
  70. package/src/hooks/useDensityMode.ts +0 -102
  71. package/src/hooks/useDiscovery.ts +0 -168
  72. package/src/hooks/useDynamicApp.ts +0 -142
  73. package/src/hooks/useETagCache.ts +0 -404
  74. package/src/hooks/useExpression.ts +0 -56
  75. package/src/hooks/useFocusManagement.ts +0 -248
  76. package/src/hooks/useFocusTrap.ts +0 -138
  77. package/src/hooks/useGlobalUndo.ts +0 -98
  78. package/src/hooks/useKeyboardShortcuts.ts +0 -119
  79. package/src/hooks/useNavigationOverlay.ts +0 -190
  80. package/src/hooks/useOffline.ts +0 -301
  81. package/src/hooks/usePageTransition.ts +0 -187
  82. package/src/hooks/usePageVariables.tsx +0 -157
  83. package/src/hooks/usePerformance.ts +0 -246
  84. package/src/hooks/usePerformanceBudget.ts +0 -313
  85. package/src/hooks/useReducedMotion.ts +0 -53
  86. package/src/hooks/useSchemaPersistence.ts +0 -222
  87. package/src/hooks/useViewData.ts +0 -201
  88. package/src/hooks/useViewSharing.ts +0 -140
  89. package/src/hooks/useViewTransition.ts +0 -144
  90. package/src/index.ts +0 -41
  91. package/src/spec-bridge/SpecBridge.ts +0 -64
  92. package/src/spec-bridge/__tests__/P1SpecBridge.test.ts +0 -855
  93. package/src/spec-bridge/__tests__/SpecBridge.test.ts +0 -550
  94. package/src/spec-bridge/bridges/dashboard.ts +0 -180
  95. package/src/spec-bridge/bridges/form-view.ts +0 -109
  96. package/src/spec-bridge/bridges/list-view.ts +0 -187
  97. package/src/spec-bridge/bridges/page.ts +0 -136
  98. package/src/spec-bridge/index.ts +0 -14
  99. package/src/spec-bridge/types.ts +0 -38
  100. package/src/utils/i18n.ts +0 -10
  101. package/tsconfig.json +0 -17
  102. package/tsconfig.tsbuildinfo +0 -1
  103. 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';