@esheet/builder 0.0.3 → 0.0.4-0

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
@@ -45,7 +45,7 @@ function App() {
45
45
  import { EsheetBuilder } from '@esheet/builder';
46
46
 
47
47
  const initialForm: FormDefinition = {
48
- schemaType: 'mieforms-v1.0',
48
+ id: 'patient-intake',
49
49
  title: 'Patient Intake',
50
50
  fields: [
51
51
  { id: 'name', fieldType: 'text', question: 'Full Name', required: true },
package/dist/index.d.ts CHANGED
@@ -1,34 +1,118 @@
1
+ import { AddFieldOptions } from '@esheet/core';
1
2
  import { BuilderMode } from '@esheet/core';
2
3
  import { createUIStore } from '@esheet/core';
3
4
  import { default as default_2 } from 'react';
4
5
  import { EditTab } from '@esheet/core';
5
6
  import { FieldComponentProps } from '@esheet/core';
7
+ import { FieldDefinition } from '@esheet/core';
8
+ import { FieldNode } from '@esheet/core';
9
+ import { FieldResponse } from '@esheet/core';
10
+ import { FieldType } from '@esheet/core';
11
+ import { FieldTypeMeta } from '@esheet/core';
6
12
  import { FormDefinition } from '@esheet/core';
7
13
  import { FormStore } from '@esheet/core';
8
14
  import { FormStoreContext } from '@esheet/fields';
9
15
  import { getFieldComponent } from '@esheet/fields';
10
16
  import { getRegisteredComponentKeys } from '@esheet/fields';
11
17
  import { JSX } from 'react/jsx-runtime';
18
+ import { NormalizedDefinition } from '@esheet/core';
12
19
  import { registerCustomFieldTypes } from '@esheet/fields';
13
- import { resetComponentRegistry } from '@esheet/fields';
14
20
  import { UIContext } from '@esheet/fields';
15
21
  import { UIState } from '@esheet/core';
16
22
  import { UIStore } from '@esheet/core';
17
23
  import { useFormStore } from '@esheet/fields';
18
24
  import { useUI } from '@esheet/fields';
19
25
 
26
+ export declare const BUILDER_SYSTEM_PROMPT: string;
27
+
28
+ export declare const BUILDER_TOOL_DEFINITIONS: readonly ToolDefinition[];
29
+
20
30
  /**
21
31
  * BuilderHeader — top bar with Build/Code/Preview mode toggle and Import/Export actions.
22
32
  */
23
- export declare function BuilderHeader({ form, ui }: BuilderHeaderProps): JSX.Element;
33
+ export declare function BuilderHeader(_props: BuilderHeaderProps): JSX.Element;
24
34
 
25
35
  export declare interface BuilderHeaderProps {
26
- form: FormStore;
27
- ui: UIStore;
28
36
  }
29
37
 
30
38
  export { BuilderMode }
31
39
 
40
+ /**
41
+ * Narrow interface exposed to MCP / AI tools via `onBuilderToolsReady`.
42
+ * Only the operations an external AI agent needs — no raw store internals.
43
+ */
44
+ export declare interface BuilderTools {
45
+ /** Add a new field. Returns the generated ID, or null for unknown type. */
46
+ addField: (fieldType: FieldType, opts?: AddFieldOptions) => string | null;
47
+ /** Patch a field's properties. Returns false if the field was not found. */
48
+ updateField: (fieldId: string, patch: Record<string, unknown>) => boolean;
49
+ /** Remove a field. Returns false if not found. */
50
+ removeField: (fieldId: string) => boolean;
51
+ /** Find a field ID by exact ID or partial question match. */
52
+ resolveFieldId: (fieldId?: string, fieldQuestion?: string) => string | undefined;
53
+ /** Replace the entire form with a new definition. */
54
+ resetForm: (definition: {
55
+ id?: string;
56
+ fields: Record<string, unknown>[];
57
+ }) => void;
58
+ /** Generate a form from a list of plain question descriptors. */
59
+ generateForm: (questions: {
60
+ question: string;
61
+ fieldType?: string;
62
+ required?: boolean;
63
+ inputType?: string;
64
+ options?: string[];
65
+ }[]) => string;
66
+ /** Snapshot of the current form suitable for AI context. */
67
+ getFormSummary: () => {
68
+ formId: string;
69
+ fieldCount: number;
70
+ fields: FieldSummary[];
71
+ };
72
+ /** Set a response value for a field (for testing in preview mode). Returns true on success, false if field not found, or an error string if the value format is invalid. */
73
+ fillField: (fieldId: string, value: unknown) => boolean | string;
74
+ /** Clear all responses. */
75
+ clearResponses: () => void;
76
+ /** Get current responses keyed by field ID. */
77
+ getResponses: () => Record<string, unknown>;
78
+ /** Granular option mutations (radio, check, dropdown, etc.). */
79
+ option: {
80
+ add: (fieldId: string, value?: string) => string | null;
81
+ update: (fieldId: string, optionId: string, value: string) => boolean;
82
+ remove: (fieldId: string, optionId: string) => boolean;
83
+ };
84
+ /** Granular row mutations (matrix fields). */
85
+ row: {
86
+ add: (fieldId: string, value?: string) => string | null;
87
+ update: (fieldId: string, rowId: string, value: string) => boolean;
88
+ remove: (fieldId: string, rowId: string) => boolean;
89
+ };
90
+ /** Granular column mutations (matrix fields). */
91
+ column: {
92
+ add: (fieldId: string, value?: string) => string | null;
93
+ update: (fieldId: string, columnId: string, value: string) => boolean;
94
+ remove: (fieldId: string, columnId: string) => boolean;
95
+ };
96
+ /** Move a field to a new index. */
97
+ moveField: (fieldId: string, toIndex: number, toParentId?: string | null) => boolean;
98
+ /** Get a single field node by ID. */
99
+ getField: (fieldId: string) => FieldNode | undefined;
100
+ /** List all registered field type keys and their labels. */
101
+ getFieldTypes: () => {
102
+ key: string;
103
+ label: string;
104
+ category: string;
105
+ hasOptions: boolean;
106
+ hasMatrix: boolean;
107
+ }[];
108
+ /** Get full spec for a single field type (properties, capabilities, defaults). */
109
+ getFieldSpec: (fieldType: string) => FieldTypeMeta | undefined;
110
+ /** Export the full form definition tree (inverse of loadDefinition). */
111
+ getDefinition: () => FormDefinition;
112
+ /** Update the form's top-level ID without replacing fields. */
113
+ setFormId: (id: string) => void;
114
+ }
115
+
32
116
  /**
33
117
  * CodeView — Monaco-based JSON/YAML editor for the form definition.
34
118
  *
@@ -45,23 +129,84 @@ export { createUIStore }
45
129
 
46
130
  export { EditTab }
47
131
 
48
- export declare function EsheetBuilder({ definition, onChange, dragEnabled, className, children, }: EsheetBuilderProps): JSX.Element;
132
+ export declare const EsheetBuilder: default_2.ForwardRefExoticComponent<EsheetBuilderProps & default_2.RefAttributes<EsheetBuilderHandle>>;
133
+
134
+ declare interface EsheetBuilderHandle {
135
+ /** Returns true if touch mode is currently enabled */
136
+ isTouchModeEnabled: () => boolean;
137
+ /** Toggle touch mode on/off. Only works when touchMode prop is 'auto' or undefined. */
138
+ setTouchMode: (enabled: boolean) => void;
139
+ /** Reset to auto-detection mode (clears manual override). Only works when touchMode='auto'. */
140
+ resetTouchMode: () => void;
141
+ }
49
142
 
50
143
  export declare interface EsheetBuilderProps {
51
- /** Initial form definition to load. */
52
- definition?: FormDefinition;
144
+ /** Initial form definition to load. Also accepts SurveyJS, MCP elicitation, or FHIR Questionnaire schemas, which are auto-converted. */
145
+ definition?: FormDefinition | Record<string, unknown>;
53
146
  /** Callback fired when the form definition changes. */
54
147
  onChange?: (definition: FormDefinition) => void;
55
- /** Whether drag-and-drop reordering is enabled (default: true). Disable for better performance on slow devices. */
148
+ /**
149
+ * Called once after the builder mounts, providing a narrow `BuilderTools`
150
+ * facade for MCP / AI tool integrations. Not intended for general developer use —
151
+ * everything a developer needs is available through the builder's own UI and props.
152
+ */
153
+ onBuilderToolsReady?: (tools: BuilderTools) => void;
154
+ /** Whether drag-and-drop reordering is enabled (default: true). When false, field reordering is disabled entirely — no fallback UI (e.g. arrow buttons) is shown. */
56
155
  dragEnabled?: boolean;
57
156
  /** Additional CSS class name. */
58
157
  className?: string;
59
158
  /** Optional content rendered below the header (e.g. custom status/debug panels). */
60
159
  children?: default_2.ReactNode;
160
+ /**
161
+ * Enable touch-optimized mode with larger touch targets in preview mode.
162
+ * - `true`: Always enable touch mode
163
+ * - `false`: Never enable touch mode (CSS media query still applies)
164
+ * - `'auto'`: Enable based on viewport width (<980px) via JavaScript
165
+ * - `undefined`: Rely on CSS media query only (default)
166
+ */
167
+ touchMode?: boolean | 'auto';
168
+ /** Called when touch mode changes (via auto-detection or programmatic toggle). */
169
+ onTouchModeChange?: (enabled: boolean) => void;
61
170
  }
62
171
 
172
+ export declare function executeToolCall(toolName: string, args: ToolArgs, tools: BuilderTools): string | Record<string, unknown>;
173
+
63
174
  export { FieldComponentProps }
64
175
 
176
+ export { FieldDefinition }
177
+
178
+ export declare type FieldResponseMap = Record<string, FieldResponse>;
179
+
180
+ /** Summary of a single field, suitable for AI context. */
181
+ export declare interface FieldSummary {
182
+ id: string;
183
+ fieldType: string;
184
+ question: string | undefined;
185
+ required: boolean;
186
+ options: {
187
+ id: string;
188
+ value: string;
189
+ }[];
190
+ rows: {
191
+ id: string;
192
+ value: string;
193
+ }[];
194
+ columns: {
195
+ id: string;
196
+ value: string;
197
+ }[];
198
+ /** Which tool family to use: 'add_option' for option-based fields, 'add_row / add_column' for matrix fields. */
199
+ editWith: string;
200
+ /** True if this field has conditional logic rules attached. Use get_field to inspect them. */
201
+ hasRules: boolean;
202
+ /** Required value format for structured input types (date, datetime-local, month, time). Use this exact format when calling fill_field. */
203
+ valueFormat?: string;
204
+ /** True if this field already has a response value. False means it is still empty and needs to be filled. */
205
+ hasValue: boolean;
206
+ /** Section child fields (only present when fieldType === 'section'). */
207
+ children?: FieldSummary[];
208
+ }
209
+
65
210
  /**
66
211
  * FieldWrapper - Extensibility API for custom field components.
67
212
  *
@@ -83,7 +228,7 @@ export { FieldComponentProps }
83
228
  * </FieldWrapper>
84
229
  * ```
85
230
  */
86
- export declare function FieldWrapper({ fieldId, form, ui, dragHandleRef, isSelectedOverride, onSelectOverride, selectedVariant: _selectedVariant, forceExpandVersion, forceCollapseVersion, children, }: FieldWrapperProps): JSX.Element | null;
231
+ export declare function FieldWrapper({ fieldId, form, ui, dragHandleRef, isSelectedOverride, onSelectOverride, selectedVariant, forceExpandVersion, forceCollapseVersion, children, }: FieldWrapperProps): JSX.Element | null;
87
232
 
88
233
  export declare interface FieldWrapperProps {
89
234
  /** The field ID */
@@ -115,6 +260,52 @@ export declare interface FieldWrapperProps {
115
260
  */
116
261
  export declare type FieldWrapperRenderProps = FieldComponentProps;
117
262
 
263
+ export declare interface FormApi {
264
+ field: FieldNode | undefined;
265
+ response: FieldResponse | undefined;
266
+ isVisible: boolean;
267
+ isEnabled: boolean;
268
+ isRequired: boolean;
269
+ normalized: NormalizedDefinition;
270
+ responses: FieldResponseMap;
271
+ instanceId: string;
272
+ form: {
273
+ addField: (type: FieldType, opts?: AddFieldOptions) => string | null;
274
+ loadDefinition: FormStore['getState'] extends () => infer S ? S extends {
275
+ loadDefinition: infer F;
276
+ } ? F : never : never;
277
+ setFormId: (id: string) => void;
278
+ hydrateDefinition: () => ReturnType<ReturnType<FormStore['getState']>['hydrateDefinition']>;
279
+ hydrateResponse: () => ReturnType<ReturnType<FormStore['getState']>['hydrateResponse']>;
280
+ resetResponses: () => void;
281
+ };
282
+ field_: {
283
+ update: (patch: Partial<Omit<FieldDefinition, 'fields'>>) => boolean;
284
+ remove: () => boolean;
285
+ move: (toIndex: number, toParentId?: string | null) => boolean;
286
+ setResponse: (resp: FieldResponse) => void;
287
+ clearResponse: () => void;
288
+ };
289
+ option: {
290
+ add: (value?: string) => string | null;
291
+ update: (optId: string, value: string) => boolean;
292
+ remove: (optId: string) => boolean;
293
+ };
294
+ row: {
295
+ add: (value?: string) => string | null;
296
+ update: (rowId: string, value: string) => boolean;
297
+ remove: (rowId: string) => boolean;
298
+ };
299
+ column: {
300
+ add: (value?: string) => string | null;
301
+ update: (colId: string, value: string) => boolean;
302
+ remove: (colId: string) => boolean;
303
+ };
304
+ _form: FormStore;
305
+ }
306
+
307
+ export { FormDefinition }
308
+
118
309
  export { FormStoreContext }
119
310
 
120
311
  export { getFieldComponent }
@@ -125,7 +316,31 @@ export declare const InstanceIdContext: default_2.Context<string>;
125
316
 
126
317
  export { registerCustomFieldTypes }
127
318
 
128
- export { resetComponentRegistry }
319
+ declare type ToolArgs = Record<string, unknown>;
320
+
321
+ export declare interface ToolDefinition {
322
+ type: string;
323
+ function: {
324
+ name: string;
325
+ description: string;
326
+ parameters: Record<string, unknown>;
327
+ };
328
+ }
329
+
330
+ export declare interface UiApi {
331
+ mode: BuilderMode;
332
+ selectedFieldId: string | null;
333
+ selectedFieldChildId: string | null;
334
+ editTab: EditTab;
335
+ codeEditorHasError: boolean;
336
+ selectField: (id: string | null) => void;
337
+ selectFieldChild: (parentId: string, childId: string | null) => void;
338
+ setMode: (m: BuilderMode) => void;
339
+ setEditTab: (tab: EditTab) => void;
340
+ setEditModalOpen: (open: boolean) => void;
341
+ clearDragState: () => void;
342
+ _ui: UIStore;
343
+ }
129
344
 
130
345
  export { UIContext }
131
346
 
@@ -133,6 +348,47 @@ export { UIState }
133
348
 
134
349
  export { UIStore }
135
350
 
351
+ /**
352
+ * Listens for AI tool-call events on a target element and dispatches them to
353
+ * the builder's MCP tool executor. Returns the `onBuilderToolsReady` callback
354
+ * to pass to `<EsheetBuilder>`.
355
+ *
356
+ * @example – default (listens on document)
357
+ * const onBuilderToolsReady = useBuilderMcpToolHandler();
358
+ * <EsheetBuilder onBuilderToolsReady={onBuilderToolsReady} />
359
+ *
360
+ * @example – scoped to a container element
361
+ * const ref = React.useRef<HTMLDivElement>(null);
362
+ * const onBuilderToolsReady = useBuilderMcpToolHandler({ target: ref.current ?? undefined });
363
+ * <div ref={ref}><EsheetBuilder onBuilderToolsReady={onBuilderToolsReady} /></div>
364
+ *
365
+ * @example – custom event name
366
+ * const onBuilderToolsReady = useBuilderMcpToolHandler({ eventName: 'my-ai-tool-call' });
367
+ */
368
+ export declare function useBuilderMcpToolHandler(options: UseBuilderMcpToolHandlerOptions): (tools: BuilderTools) => void;
369
+
370
+ export declare interface UseBuilderMcpToolHandlerOptions {
371
+ /**
372
+ * The DOM element to listen on for tool-call events.
373
+ * Pass `document` to listen globally, or a specific element to scope it.
374
+ */
375
+ target?: EventTarget;
376
+ /**
377
+ * The event name to listen for, e.g. `'ozwell-tool-call'`.
378
+ */
379
+ eventName: string;
380
+ }
381
+
382
+ /**
383
+ * useFormApi — reactive field state + form store actions.
384
+ *
385
+ * Touches only the FormStore. For UI state (mode, selection, tabs) use
386
+ * useUiApi(). For the computed visible root IDs use useVisibleRootIds().
387
+ *
388
+ * @param fieldId - The field to bind to. Pass undefined for form-level ops only.
389
+ */
390
+ export declare function useFormApi(fieldId?: string): FormApi;
391
+
136
392
  export { useFormStore }
137
393
 
138
394
  /** Hook to access the per-instance ID for unique DOM element IDs. */
@@ -140,4 +396,22 @@ export declare function useInstanceId(): string;
140
396
 
141
397
  export { useUI }
142
398
 
399
+ /**
400
+ * useUiApi — lightweight hook for components that only need UI state/actions.
401
+ *
402
+ * Useful when you don't need field-scoped state. Requires UIContext provider.
403
+ */
404
+ export declare function useUiApi(): UiApi;
405
+
406
+ /**
407
+ * useVisibleRootIds — returns the root field IDs to render.
408
+ *
409
+ * In build/code mode: all root IDs.
410
+ * In preview mode: only IDs whose visibility rules evaluate to true.
411
+ *
412
+ * Requires both FormStoreContext and UIContext providers.
413
+ * Uses a stable-ref cache so the array reference only changes when content does.
414
+ */
415
+ export declare function useVisibleRootIds(): readonly string[];
416
+
143
417
  export { }