@esheet/renderer 0.0.1 → 0.0.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.
package/README.md CHANGED
@@ -1,212 +1,212 @@
1
- # @esheet/renderer
2
-
3
- Read-only questionnaire form renderer for eSheet. Renders forms in fill-out mode with conditional visibility logic.
4
-
5
- ## Features
6
-
7
- - ✅ Renders all 19 eSheet field types (reuses `@esheet/fields` components)
8
- - ✅ Conditional visibility enforcement (fields/sections hide based on logic rules)
9
- - ✅ Section nesting with recursive rendering
10
- - ✅ Initial response pre-fill support
11
- - ✅ YAML/JSON schema parsing with Zod validation
12
- - ✅ Ref API for collecting responses
13
- - ✅ TypeScript-first with full type safety
14
-
15
- ## Installation
16
-
17
- ```bash
18
- npm install @esheet/renderer @esheet/fields @esheet/core
19
- ```
20
-
21
- Standalone and Blaze integrations now ship as separate packages:
22
-
23
- ```bash
24
- npm install @esheet/renderer-standalone
25
- npm install @esheet/renderer-blaze
26
- ```
27
-
28
- Migration for old subpath imports:
29
-
30
- - `@esheet/renderer/standalone` -> `@esheet/renderer-standalone`
31
- - `@esheet/renderer/blaze` -> `@esheet/renderer-blaze`
32
-
33
- ## Usage
34
-
35
- ### Basic Example
36
-
37
- ```tsx
38
- import { EsheetRenderer } from '@esheet/renderer';
39
- import type { FormDefinition } from '@esheet/core';
40
-
41
- const myForm: FormDefinition = {
42
- schemaType: 'mieforms-v1.0',
43
- title: 'Patient Intake',
44
- fields: [
45
- {
46
- id: 'name',
47
- fieldType: 'text',
48
- question: 'Full Name',
49
- required: true,
50
- },
51
- {
52
- id: 'age',
53
- fieldType: 'text',
54
- question: 'Age',
55
- },
56
- ],
57
- };
58
-
59
- function App() {
60
- return (
61
- <div className="app-container">
62
- <EsheetRenderer formData={myForm} />
63
- </div>
64
- );
65
- }
66
- ```
67
-
68
- ### With Response Collection
69
-
70
- ```tsx
71
- import { useRef } from 'react';
72
- import { EsheetRenderer, type EsheetRendererHandle } from '@esheet/renderer';
73
-
74
- function App() {
75
- const rendererRef = useRef<EsheetRendererHandle>(null);
76
-
77
- const handleSubmit = () => {
78
- const responses = rendererRef.current?.getResponse();
79
- console.log('Form responses:', responses);
80
- // { name: '...', age: '...' }
81
- };
82
-
83
- return (
84
- <>
85
- <EsheetRenderer formData={myForm} ref={rendererRef} />
86
- <button onClick={handleSubmit}>Submit</button>
87
- </>
88
- );
89
- }
90
- ```
91
-
92
- ### With Pre-filled Data
93
-
94
- ```tsx
95
- <EsheetRenderer
96
- formData={myForm}
97
- initialResponses={{
98
- name: 'John Doe',
99
- age: '42',
100
- }}
101
- />
102
- ```
103
-
104
- ### With YAML/JSON String
105
-
106
- ```tsx
107
- const yamlSchema = `
108
- schemaType: mieforms-v1.0
109
- title: Simple Form
110
- fields:
111
- - id: q1
112
- fieldType: text
113
- question: Your name?
114
- `;
115
-
116
- <EsheetRenderer formData={yamlSchema} />;
117
- ```
118
-
119
- ## API
120
-
121
- ### `<EsheetRenderer>`
122
-
123
- **Props:**
124
-
125
- - `formData: FormDefinition | string` - Form schema (object, JSON string, or YAML string)
126
- - `initialResponses?: FormResponse` - Pre-fill form with initial data
127
- - `className?: string` - Additional CSS classes for root container
128
- - `ref?: Ref<EsheetRendererHandle>` - Access ref API for collecting responses
129
-
130
- **Ref API:**
131
-
132
- ```tsx
133
- interface EsheetRendererHandle {
134
- getResponse: () => FormResponse;
135
- getFormStore: () => FormStore;
136
- getUIStore: () => UIStore;
137
- }
138
- ```
139
-
140
- ## Architecture
141
-
142
- EsheetRenderer is a thin wrapper that:
143
-
144
- 1. Creates form and UI stores (vanilla Zustand)
145
- 2. Parses and validates input (YAML/JSON → Zod schema check)
146
- 3. Loads definition into store
147
- 4. Sets preview mode (read-only, no editing UI)
148
- 5. Iterates over visible fields via `RendererBody`
149
- 6. Renders each field via `FieldNode` (uses `@esheet/fields` components)
150
-
151
- **Conditional Logic:**
152
-
153
- - Reuses `form.isVisible()`, `form.isEnabled()`, `form.isRequired()` from core
154
- - Sections auto-hide when all children are invisible
155
- - Field visibility updates reactively when responses change
156
-
157
- **Section Nesting:**
158
-
159
- - `FieldNode` recursively renders section children
160
- - Each depth level adds left border and padding
161
- - Respects visibility rules at every level
162
-
163
- ## Example: Conditional Visibility
164
-
165
- ```tsx
166
- const conditionalForm: FormDefinition = {
167
- schemaType: 'mieforms-v1.0',
168
- title: 'Conditional Form',
169
- fields: [
170
- {
171
- id: 'hasAllergies',
172
- fieldType: 'boolean',
173
- question: 'Do you have any allergies?',
174
- },
175
- {
176
- id: 'allergyList',
177
- fieldType: 'longtext',
178
- question: 'Please list your allergies',
179
- visible: {
180
- conditions: [
181
- {
182
- conditionType: 'comparison',
183
- fieldId: 'hasAllergies',
184
- operator: '==',
185
- value: true,
186
- },
187
- ],
188
- logicalOperator: 'AND',
189
- },
190
- },
191
- ],
192
- };
193
-
194
- // "allergyList" only shows when "hasAllergies" is checked
195
- <EsheetRenderer formData={conditionalForm} />;
196
- ```
197
-
198
- ## CSS Architecture
199
-
200
- The renderer uses Tailwind CSS v4 with `ms:` prefix. CSS is compiled via `@tailwindcss/cli` and embedded into the JS bundle at build time — consumers never need to import a stylesheet. A scoped reset on `.esheet-renderer-root` prevents style leakage in either direction. Dark mode is supported via `.dark` class on the root.
201
-
202
- ## License
203
-
204
- MIT
205
-
206
- ## Building
207
-
208
- Run `nx build @esheet/renderer` to build the library.
209
-
210
- ## Running unit tests
211
-
212
- Run `nx test @esheet/renderer` to execute the unit tests via [Vitest](https://vitest.dev/).
1
+ # @esheet/renderer
2
+
3
+ Read-only questionnaire form renderer for eSheet. Renders forms in fill-out mode with conditional visibility logic.
4
+
5
+ ## Features
6
+
7
+ - ✅ Renders all 19 eSheet field types (reuses `@esheet/fields` components)
8
+ - ✅ Conditional visibility enforcement (fields/sections hide based on logic rules)
9
+ - ✅ Section nesting with recursive rendering
10
+ - ✅ Initial response pre-fill support
11
+ - ✅ YAML/JSON schema parsing with Zod validation
12
+ - ✅ Ref API for collecting responses
13
+ - ✅ TypeScript-first with full type safety
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install @esheet/renderer @esheet/fields @esheet/core
19
+ ```
20
+
21
+ Standalone and Blaze integrations now ship as separate packages:
22
+
23
+ ```bash
24
+ npm install @esheet/renderer-standalone
25
+ npm install @esheet/renderer-blaze
26
+ ```
27
+
28
+ Migration for old subpath imports:
29
+
30
+ - `@esheet/renderer/standalone` -> `@esheet/renderer-standalone`
31
+ - `@esheet/renderer/blaze` -> `@esheet/renderer-blaze`
32
+
33
+ ## Usage
34
+
35
+ ### Basic Example
36
+
37
+ ```tsx
38
+ import { EsheetRenderer } from '@esheet/renderer';
39
+ import type { FormDefinition } from '@esheet/core';
40
+
41
+ const myForm: FormDefinition = {
42
+ schemaType: 'mieforms-v1.0',
43
+ title: 'Patient Intake',
44
+ fields: [
45
+ {
46
+ id: 'name',
47
+ fieldType: 'text',
48
+ question: 'Full Name',
49
+ required: true,
50
+ },
51
+ {
52
+ id: 'age',
53
+ fieldType: 'text',
54
+ question: 'Age',
55
+ },
56
+ ],
57
+ };
58
+
59
+ function App() {
60
+ return (
61
+ <div className="app-container">
62
+ <EsheetRenderer formData={myForm} />
63
+ </div>
64
+ );
65
+ }
66
+ ```
67
+
68
+ ### With Response Collection
69
+
70
+ ```tsx
71
+ import { useRef } from 'react';
72
+ import { EsheetRenderer, type EsheetRendererHandle } from '@esheet/renderer';
73
+
74
+ function App() {
75
+ const rendererRef = useRef<EsheetRendererHandle>(null);
76
+
77
+ const handleSubmit = () => {
78
+ const responses = rendererRef.current?.getResponse();
79
+ console.log('Form responses:', responses);
80
+ // { name: '...', age: '...' }
81
+ };
82
+
83
+ return (
84
+ <>
85
+ <EsheetRenderer formData={myForm} ref={rendererRef} />
86
+ <button onClick={handleSubmit}>Submit</button>
87
+ </>
88
+ );
89
+ }
90
+ ```
91
+
92
+ ### With Pre-filled Data
93
+
94
+ ```tsx
95
+ <EsheetRenderer
96
+ formData={myForm}
97
+ initialResponses={{
98
+ name: 'John Doe',
99
+ age: '42',
100
+ }}
101
+ />
102
+ ```
103
+
104
+ ### With YAML/JSON String
105
+
106
+ ```tsx
107
+ const yamlSchema = `
108
+ schemaType: mieforms-v1.0
109
+ title: Simple Form
110
+ fields:
111
+ - id: q1
112
+ fieldType: text
113
+ question: Your name?
114
+ `;
115
+
116
+ <EsheetRenderer formData={yamlSchema} />;
117
+ ```
118
+
119
+ ## API
120
+
121
+ ### `<EsheetRenderer>`
122
+
123
+ **Props:**
124
+
125
+ - `formData: FormDefinition | string` - Form schema (object, JSON string, or YAML string)
126
+ - `initialResponses?: FormResponse` - Pre-fill form with initial data
127
+ - `className?: string` - Additional CSS classes for root container
128
+ - `ref?: Ref<EsheetRendererHandle>` - Access ref API for collecting responses
129
+
130
+ **Ref API:**
131
+
132
+ ```tsx
133
+ interface EsheetRendererHandle {
134
+ getResponse: () => FormResponse;
135
+ getFormStore: () => FormStore;
136
+ getUIStore: () => UIStore;
137
+ }
138
+ ```
139
+
140
+ ## Architecture
141
+
142
+ EsheetRenderer is a thin wrapper that:
143
+
144
+ 1. Creates form and UI stores (vanilla Zustand)
145
+ 2. Parses and validates input (YAML/JSON → Zod schema check)
146
+ 3. Loads definition into store
147
+ 4. Sets preview mode (read-only, no editing UI)
148
+ 5. Iterates over visible fields via `RendererBody`
149
+ 6. Renders each field via `FieldNode` (uses `@esheet/fields` components)
150
+
151
+ **Conditional Logic:**
152
+
153
+ - Reuses `form.isVisible()`, `form.isEnabled()`, `form.isRequired()` from core
154
+ - Sections auto-hide when all children are invisible
155
+ - Field visibility updates reactively when responses change
156
+
157
+ **Section Nesting:**
158
+
159
+ - `FieldNode` recursively renders section children
160
+ - Each depth level adds left border and padding
161
+ - Respects visibility rules at every level
162
+
163
+ ## Example: Conditional Visibility
164
+
165
+ ```tsx
166
+ const conditionalForm: FormDefinition = {
167
+ schemaType: 'mieforms-v1.0',
168
+ title: 'Conditional Form',
169
+ fields: [
170
+ {
171
+ id: 'hasAllergies',
172
+ fieldType: 'boolean',
173
+ question: 'Do you have any allergies?',
174
+ },
175
+ {
176
+ id: 'allergyList',
177
+ fieldType: 'longtext',
178
+ question: 'Please list your allergies',
179
+ visible: {
180
+ conditions: [
181
+ {
182
+ conditionType: 'comparison',
183
+ fieldId: 'hasAllergies',
184
+ operator: '==',
185
+ value: true,
186
+ },
187
+ ],
188
+ logicalOperator: 'AND',
189
+ },
190
+ },
191
+ ],
192
+ };
193
+
194
+ // "allergyList" only shows when "hasAllergies" is checked
195
+ <EsheetRenderer formData={conditionalForm} />;
196
+ ```
197
+
198
+ ## CSS Architecture
199
+
200
+ The renderer uses Tailwind CSS v4 with `ms:` prefix. CSS is compiled via `@tailwindcss/cli` and embedded into the JS bundle at build time — consumers never need to import a stylesheet. A scoped reset on `.esheet-renderer-root` prevents style leakage in either direction. Dark mode is supported via `.dark` class on the root.
201
+
202
+ ## License
203
+
204
+ MIT
205
+
206
+ ## Building
207
+
208
+ Run `nx build @esheet/renderer` to build the library.
209
+
210
+ ## Running unit tests
211
+
212
+ Run `nx test @esheet/renderer` to execute the unit tests via [Vitest](https://vitest.dev/).
package/dist/index.d.ts CHANGED
@@ -23,14 +23,14 @@ import { ValidationError } from '@esheet/core';
23
23
  * />
24
24
  *
25
25
  * // Later: get responses
26
- * const responses = rendererRef.current?.getResponse();
26
+ * const responses = rendererRef.current?.getRawResponse();
27
27
  * ```
28
28
  */
29
29
  export declare const EsheetRenderer: default_2.ForwardRefExoticComponent<EsheetRendererProps & default_2.RefAttributes<EsheetRendererHandle>>;
30
30
 
31
31
  export declare interface EsheetRendererHandle {
32
32
  /** Get current form responses */
33
- getResponse: () => FormResponse;
33
+ getRawResponse: () => FormResponse;
34
34
  /** Get form store instance */
35
35
  getFormStore: () => FormStore;
36
36
  /** Get UI store instance */
@@ -89,8 +89,9 @@ declare interface RendererBodyProps {
89
89
  * - Loads definition into form store
90
90
  * - Sets UI to preview mode
91
91
  * - Applies initial responses if provided
92
+ * - Calls onValidationError with schema validation issues if validation fails
92
93
  */
93
- export declare function useRendererInit(form: FormStore, ui: UIStore, formData: FormDefinition | string, initialResponses?: FormResponse): void;
94
+ export declare function useRendererInit(form: FormStore, ui: UIStore, formData: FormDefinition | string, initialResponses?: FormResponse, onValidationError?: (errors: string[]) => void): void;
94
95
 
95
96
  export { ValidationError }
96
97