@esheet/builder 0.0.3 → 0.0.4-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 (83) hide show
  1. package/README.md +1 -1
  2. package/dist/index.d.ts +16 -143
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +11252 -6751
  5. package/dist/lib/EsheetBuilder.d.ts +46 -0
  6. package/dist/lib/EsheetBuilder.d.ts.map +1 -0
  7. package/dist/lib/EsheetBuilder.js +111 -0
  8. package/dist/lib/builder-tools.d.ts +107 -0
  9. package/dist/lib/builder-tools.d.ts.map +1 -0
  10. package/dist/lib/builder-tools.js +321 -0
  11. package/dist/lib/components/BuilderHeader.d.ts +7 -0
  12. package/dist/lib/components/BuilderHeader.d.ts.map +1 -0
  13. package/dist/lib/components/BuilderHeader.js +390 -0
  14. package/dist/lib/components/Canvas.d.ts +12 -0
  15. package/dist/lib/components/Canvas.d.ts.map +1 -0
  16. package/dist/lib/components/Canvas.js +288 -0
  17. package/dist/lib/components/CodeView.d.ts +12 -0
  18. package/dist/lib/components/CodeView.d.ts.map +1 -0
  19. package/dist/lib/components/CodeView.js +197 -0
  20. package/dist/lib/components/FeedbackModal.d.ts +23 -0
  21. package/dist/lib/components/FeedbackModal.d.ts.map +1 -0
  22. package/dist/lib/components/FeedbackModal.js +22 -0
  23. package/dist/lib/components/FieldWrapper.d.ts +53 -0
  24. package/dist/lib/components/FieldWrapper.d.ts.map +1 -0
  25. package/dist/lib/components/FieldWrapper.js +152 -0
  26. package/dist/lib/components/MobileBottomDrawer.d.ts +9 -0
  27. package/dist/lib/components/MobileBottomDrawer.d.ts.map +1 -0
  28. package/dist/lib/components/MobileBottomDrawer.js +6 -0
  29. package/dist/lib/components/ToolPanel.d.ts +11 -0
  30. package/dist/lib/components/ToolPanel.d.ts.map +1 -0
  31. package/dist/lib/components/ToolPanel.js +117 -0
  32. package/dist/lib/components/edit-panel/CommonEditor.d.ts +16 -0
  33. package/dist/lib/components/edit-panel/CommonEditor.d.ts.map +1 -0
  34. package/dist/lib/components/edit-panel/CommonEditor.js +16 -0
  35. package/dist/lib/components/edit-panel/DraftIdEditor.d.ts +16 -0
  36. package/dist/lib/components/edit-panel/DraftIdEditor.d.ts.map +1 -0
  37. package/dist/lib/components/edit-panel/DraftIdEditor.js +32 -0
  38. package/dist/lib/components/edit-panel/EditPanel.d.ts +10 -0
  39. package/dist/lib/components/edit-panel/EditPanel.d.ts.map +1 -0
  40. package/dist/lib/components/edit-panel/EditPanel.js +156 -0
  41. package/dist/lib/components/edit-panel/InputTypeEditor.d.ts +16 -0
  42. package/dist/lib/components/edit-panel/InputTypeEditor.d.ts.map +1 -0
  43. package/dist/lib/components/edit-panel/InputTypeEditor.js +32 -0
  44. package/dist/lib/components/edit-panel/LogicEditor.d.ts +15 -0
  45. package/dist/lib/components/edit-panel/LogicEditor.d.ts.map +1 -0
  46. package/dist/lib/components/edit-panel/LogicEditor.js +392 -0
  47. package/dist/lib/components/edit-panel/MatrixEditor.d.ts +12 -0
  48. package/dist/lib/components/edit-panel/MatrixEditor.d.ts.map +1 -0
  49. package/dist/lib/components/edit-panel/MatrixEditor.js +32 -0
  50. package/dist/lib/components/edit-panel/OptionListEditor.d.ts +14 -0
  51. package/dist/lib/components/edit-panel/OptionListEditor.d.ts.map +1 -0
  52. package/dist/lib/components/edit-panel/OptionListEditor.js +27 -0
  53. package/dist/lib/hooks/useFormApi.d.ts +55 -0
  54. package/dist/lib/hooks/useFormApi.d.ts.map +1 -0
  55. package/dist/lib/hooks/useFormApi.js +80 -0
  56. package/dist/lib/hooks/useUiApi.d.ts +22 -0
  57. package/dist/lib/hooks/useUiApi.d.ts.map +1 -0
  58. package/dist/lib/hooks/useUiApi.js +37 -0
  59. package/dist/lib/hooks/useVisibleRootIds.d.ts +11 -0
  60. package/dist/lib/hooks/useVisibleRootIds.d.ts.map +1 -0
  61. package/dist/lib/hooks/useVisibleRootIds.js +32 -0
  62. package/dist/lib/icons.d.ts +31 -0
  63. package/dist/lib/icons.d.ts.map +1 -0
  64. package/dist/lib/icons.js +47 -0
  65. package/dist/lib/mcp/index.d.ts +7 -0
  66. package/dist/lib/mcp/index.d.ts.map +1 -0
  67. package/dist/lib/mcp/index.js +4 -0
  68. package/dist/lib/mcp/system-prompt.d.ts +2 -0
  69. package/dist/lib/mcp/system-prompt.d.ts.map +1 -0
  70. package/dist/lib/mcp/system-prompt.js +9 -0
  71. package/dist/lib/mcp/tool-definitions.d.ts +10 -0
  72. package/dist/lib/mcp/tool-definitions.d.ts.map +1 -0
  73. package/dist/lib/mcp/tool-definitions.js +436 -0
  74. package/dist/lib/mcp/tool-executor.d.ts +5 -0
  75. package/dist/lib/mcp/tool-executor.d.ts.map +1 -0
  76. package/dist/lib/mcp/tool-executor.js +482 -0
  77. package/dist/lib/mcp/useBuilderToolBridge.d.ts +31 -0
  78. package/dist/lib/mcp/useBuilderToolBridge.d.ts.map +1 -0
  79. package/dist/lib/mcp/useBuilderToolBridge.js +56 -0
  80. package/dist/lib/register-defaults.d.ts +2 -0
  81. package/dist/lib/register-defaults.d.ts.map +1 -0
  82. package/dist/lib/register-defaults.js +37 -0
  83. package/package.json +7 -5
@@ -0,0 +1,46 @@
1
+ import React from 'react';
2
+ import { type FormDefinition } from '@esheet/core';
3
+ import { type BuilderTools, type FieldSummary } from './builder-tools.js';
4
+ export { FormStoreContext, UIContext, useFormStore, useUI, } from '@esheet/fields';
5
+ export declare const InstanceIdContext: React.Context<string>;
6
+ /** Hook to access the per-instance ID for unique DOM element IDs. */
7
+ export declare function useInstanceId(): string;
8
+ export type { BuilderTools, FieldSummary };
9
+ export interface EsheetBuilderProps {
10
+ /** Initial form definition to load. Also accepts SurveyJS, MCP elicitation, or FHIR Questionnaire schemas, which are auto-converted. */
11
+ definition?: FormDefinition | Record<string, unknown>;
12
+ /** Callback fired when the form definition changes. */
13
+ onChange?: (definition: FormDefinition) => void;
14
+ /**
15
+ * Called once after the builder mounts, providing a narrow `BuilderTools`
16
+ * facade for MCP / AI tool integrations. Not intended for general developer use —
17
+ * everything a developer needs is available through the builder's own UI and props.
18
+ */
19
+ onBuilderToolsReady?: (tools: BuilderTools) => void;
20
+ /** 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. */
21
+ dragEnabled?: boolean;
22
+ /** Additional CSS class name. */
23
+ className?: string;
24
+ /** Optional content rendered below the header (e.g. custom status/debug panels). */
25
+ children?: React.ReactNode;
26
+ /**
27
+ * Enable touch-optimized mode with larger touch targets in preview mode.
28
+ * - `true`: Always enable touch mode
29
+ * - `false`: Never enable touch mode (CSS media query still applies)
30
+ * - `'auto'`: Enable based on viewport width (<980px) via JavaScript
31
+ * - `undefined`: Rely on CSS media query only (default)
32
+ */
33
+ touchMode?: boolean | 'auto';
34
+ /** Called when touch mode changes (via auto-detection or programmatic toggle). */
35
+ onTouchModeChange?: (enabled: boolean) => void;
36
+ }
37
+ export interface EsheetBuilderHandle {
38
+ /** Returns true if touch mode is currently enabled */
39
+ isTouchModeEnabled: () => boolean;
40
+ /** Toggle touch mode on/off. Only works when touchMode prop is 'auto' or undefined. */
41
+ setTouchMode: (enabled: boolean) => void;
42
+ /** Reset to auto-detection mode (clears manual override). Only works when touchMode='auto'. */
43
+ resetTouchMode: () => void;
44
+ }
45
+ export declare const EsheetBuilder: React.ForwardRefExoticComponent<EsheetBuilderProps & React.RefAttributes<EsheetBuilderHandle>>;
46
+ //# sourceMappingURL=EsheetBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EsheetBuilder.d.ts","sourceRoot":"","sources":["../../src/lib/EsheetBuilder.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAGL,KAAK,cAAc,EAGpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAEL,KAAK,YAAY,EACjB,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AA2B5B,OAAO,EACL,gBAAgB,EAChB,SAAS,EACT,YAAY,EACZ,KAAK,GACN,MAAM,gBAAgB,CAAC;AACxB,eAAO,MAAM,iBAAiB,uBAAkC,CAAC;AAEjE,qEAAqE;AACrE,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAGD,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAM3C,MAAM,WAAW,kBAAkB;IACjC,wIAAwI;IACxI,UAAU,CAAC,EAAE,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtD,uDAAuD;IACvD,QAAQ,CAAC,EAAE,CAAC,UAAU,EAAE,cAAc,KAAK,IAAI,CAAC;IAChD;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACpD,qKAAqK;IACrK,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC7B,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAChD;AAED,MAAM,WAAW,mBAAmB;IAClC,sDAAsD;IACtD,kBAAkB,EAAE,MAAM,OAAO,CAAC;IAClC,uFAAuF;IACvF,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,+FAA+F;IAC/F,cAAc,EAAE,MAAM,IAAI,CAAC;CAC5B;AAMD,eAAO,MAAM,aAAa,gGAuMxB,CAAC"}
@@ -0,0 +1,111 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import { useSyncExternalStore } from 'react';
4
+ import { createFormStore, createUIStore, } from '@esheet/core';
5
+ import { createBuilderTools, } from './builder-tools.js';
6
+ import { FormStoreContext, UIContext, useTouchMode } from '@esheet/fields';
7
+ import { convertSurveyJS, isSurveyJSSchema, importFromMcp, isMcpElicitationRequest, importFromFhir, isFhirQuestionnaire, } from '@esheet/adapters';
8
+ import { Canvas } from './components/Canvas.js';
9
+ import { ToolPanel } from './components/ToolPanel.js';
10
+ import { EditPanel } from './components/edit-panel/EditPanel.js';
11
+ import { BuilderHeader } from './components/BuilderHeader.js';
12
+ import { CodeView } from './components/CodeView.js';
13
+ import { PlusIcon } from './icons.js';
14
+ import { ensureDefaultFieldComponentsRegistered } from './register-defaults.js';
15
+ import { MobileBottomDrawer } from './components/MobileBottomDrawer.js';
16
+ import { Switch } from '@mieweb/ui';
17
+ // ---------------------------------------------------------------------------
18
+ // Contexts
19
+ // ---------------------------------------------------------------------------
20
+ export { FormStoreContext, UIContext, useFormStore, useUI, } from '@esheet/fields';
21
+ export const InstanceIdContext = React.createContext('');
22
+ /** Hook to access the per-instance ID for unique DOM element IDs. */
23
+ export function useInstanceId() {
24
+ return React.useContext(InstanceIdContext);
25
+ }
26
+ // ---------------------------------------------------------------------------
27
+ // Component
28
+ // ---------------------------------------------------------------------------
29
+ export const EsheetBuilder = React.forwardRef(function EsheetBuilder({ definition, onChange, onBuilderToolsReady, dragEnabled = true, className = '', children, touchMode: touchModeProp, onTouchModeChange, }, ref) {
30
+ ensureDefaultFieldComponentsRegistered();
31
+ const formRef = React.useRef(null);
32
+ const uiRef = React.useRef(null);
33
+ if (!formRef.current) {
34
+ let resolved;
35
+ if (isFhirQuestionnaire(definition)) {
36
+ resolved = importFromFhir(definition);
37
+ }
38
+ else if (isSurveyJSSchema(definition)) {
39
+ resolved = convertSurveyJS(definition);
40
+ }
41
+ else if (isMcpElicitationRequest(definition)) {
42
+ const mcpReq = definition;
43
+ if (mcpReq.params.mode !== 'url') {
44
+ resolved = importFromMcp(mcpReq.params.requestedSchema, { mcpId: mcpReq.id, mcpMessage: mcpReq.params.message });
45
+ }
46
+ }
47
+ else {
48
+ resolved = definition;
49
+ }
50
+ formRef.current = createFormStore(resolved);
51
+ }
52
+ if (!uiRef.current) {
53
+ uiRef.current = createUIStore();
54
+ }
55
+ const form = formRef.current;
56
+ const ui = uiRef.current;
57
+ // Stable per-instance ID for unique DOM element IDs
58
+ const instanceId = React.useId();
59
+ // Subscribe to mode for conditional rendering
60
+ const mode = useSyncExternalStore((cb) => ui.subscribe(cb), () => ui.getState().mode, () => ui.getState().mode);
61
+ const selectedFieldId = useSyncExternalStore((cb) => ui.subscribe(cb), () => ui.getState().selectedFieldId, () => ui.getState().selectedFieldId);
62
+ const editModalOpen = useSyncExternalStore((cb) => ui.subscribe(cb), () => ui.getState().editModalOpen, () => ui.getState().editModalOpen);
63
+ const [toolsModalOpen, setToolsModalOpen] = React.useState(false);
64
+ // Touch mode state using shared hook
65
+ const { isTouchEnabled, isManualOverride, setTouchMode, resetTouchMode } = useTouchMode({ mode: touchModeProp, onChange: onTouchModeChange });
66
+ // Expose ref API for touch mode
67
+ React.useImperativeHandle(ref, () => ({
68
+ isTouchModeEnabled: () => isTouchEnabled,
69
+ setTouchMode,
70
+ resetTouchMode,
71
+ }), [isTouchEnabled, setTouchMode, resetTouchMode]);
72
+ React.useEffect(() => {
73
+ if (mode !== 'build') {
74
+ setToolsModalOpen(false);
75
+ ui.getState().setEditModalOpen(false);
76
+ }
77
+ }, [mode, ui]);
78
+ React.useEffect(() => {
79
+ if (!selectedFieldId && editModalOpen) {
80
+ ui.getState().setEditModalOpen(false);
81
+ }
82
+ }, [selectedFieldId, editModalOpen, ui]);
83
+ // Subscribe to form changes and forward to onChange.
84
+ React.useEffect(() => {
85
+ if (!onChange)
86
+ return;
87
+ return form.subscribe(() => {
88
+ onChange(form.getState().hydrateDefinition());
89
+ });
90
+ }, [form, onChange]);
91
+ // Expose a narrow BuilderTools facade to MCP / AI tool callers once on mount.
92
+ React.useEffect(() => {
93
+ if (onBuilderToolsReady)
94
+ onBuilderToolsReady(createBuilderTools(form));
95
+ // eslint-disable-next-line react-hooks/exhaustive-deps
96
+ }, [form]);
97
+ // Apply disabled class when user explicitly disabled touch mode (prevents CSS media query)
98
+ const applyTouchDisabledClass = isManualOverride && !isTouchEnabled;
99
+ // Build root class string
100
+ const rootClasses = [
101
+ 'ms-builder-root',
102
+ isTouchEnabled && 'esheet-touch-active',
103
+ applyTouchDisabledClass && 'touch-mode-disabled',
104
+ 'ms:flex ms:h-full ms:flex-1 ms:min-h-0 ms:max-h-full ms:w-full ms:min-w-0 ms:max-w-[1440px] ms:mx-auto ms:flex-col ms:gap-2',
105
+ 'ms:overflow-x-hidden ms:bg-msbackground ms:text-mstext',
106
+ className,
107
+ ]
108
+ .filter(Boolean)
109
+ .join(' ');
110
+ return (_jsx(FormStoreContext.Provider, { value: form, children: _jsx(UIContext.Provider, { value: ui, children: _jsx(InstanceIdContext.Provider, { value: instanceId, children: _jsxs("div", { className: rootClasses, children: [_jsx("div", { className: "ms:sticky ms:top-0 ms:z-40 ms:bg-msbackground", children: _jsx(BuilderHeader, {}) }), children, mode === 'build' && (_jsxs("div", { className: "builder-layout ms:grid ms:min-w-0 ms:grid-cols-1 ms:lg:grid-cols-[18rem_minmax(0,1fr)_340px] ms:gap-3", children: [_jsx("aside", { className: "panel-tools-wrap panel-tools ms:hidden ms:lg:flex ms:self-start ms:min-h-0 ms:max-h-[calc(100dvh-12.5rem)] ms:overflow-y-auto ms:flex-col ms:rounded-lg ms:border ms:border-msborder ms:bg-mssurface", children: _jsx(ToolPanel, {}) }), _jsxs("main", { className: "panel-canvas ms:min-w-0 ms:self-start ms:max-h-[calc(100dvh-12.5rem)] ms:overflow-hidden ms:flex ms:flex-col ms:rounded-lg ms:border ms:border-msborder ms:bg-mssurface", children: [_jsx(Canvas, { form: form, ui: ui, dragEnabled: dragEnabled }), _jsx("div", { className: "ms:lg:hidden ms:sticky ms:bottom-0 ms:z-20 ms:pt-2 ms:pb-3 ms:flex ms:justify-center ms:pointer-events-none", children: _jsxs("button", { type: "button", onClick: () => setToolsModalOpen(true), className: "ms:pointer-events-auto ms:inline-flex ms:items-center ms:gap-1.5 ms:px-3.5 ms:py-2 ms:rounded-full ms:bg-mssurface/95 ms:backdrop-blur-sm ms:text-mstext ms:text-sm ms:font-semibold ms:border ms:border-msprimary/35 ms:shadow-lg ms:shadow-msprimary/10 ms:outline-none ms:focus:outline-none ms:hover:bg-mssurface ms:hover:border-msprimary/50 ms:hover:shadow-xl ms:hover:shadow-msprimary/15 ms:transition-all", "aria-label": "Open add field tools", children: [_jsx(PlusIcon, { className: "ms:w-3.5 ms:h-3.5 ms:text-msprimary" }), _jsx("span", { children: "Add field" })] }) })] }), _jsx("aside", { className: "panel-editor-wrap panel-editor ms:hidden ms:lg:flex ms:self-start ms:min-h-0 ms:max-h-[calc(100dvh-12.5rem)] ms:overflow-y-auto ms:flex-col ms:rounded-lg ms:border ms:border-msborder ms:bg-mssurface", children: _jsx(EditPanel, {}) }), _jsx(MobileBottomDrawer, { title: "Add Field", open: toolsModalOpen, onClose: () => setToolsModalOpen(false), children: _jsx(ToolPanel, {}) }), _jsx(MobileBottomDrawer, { title: "Edit Field", open: editModalOpen && !!selectedFieldId, onClose: () => ui.getState().setEditModalOpen(false), children: _jsx(EditPanel, {}) })] })), mode === 'code' && (_jsx("div", { className: "code-layout ms:flex ms:h-[calc(100dvh-12.5rem)] ms:min-h-0 ms:min-w-0 ms:overflow-hidden ms:rounded-lg ms:border ms:border-msborder ms:bg-mssurface", children: _jsx(CodeView, { form: form, ui: ui }) })), mode === 'preview' && (_jsxs("div", { className: "preview-layout ms:flex-1 ms:min-h-0 ms:min-w-0 ms:w-full ms:max-w-2xl ms:mx-auto ms:p-4 ms:max-h-[calc(100dvh-12.5rem)] ms:overflow-y-auto", children: [_jsx("div", { className: "ms:flex ms:items-center ms:justify-end ms:mb-3", children: _jsx(Switch, { size: "sm", checked: isTouchEnabled, onCheckedChange: setTouchMode, label: "Touch Mode" }) }), _jsx(Canvas, { form: form, ui: ui, dragEnabled: false })] }))] }) }) }) }));
111
+ });
@@ -0,0 +1,107 @@
1
+ import type { AddFieldOptions, FieldType, FieldTypeMeta, FormStore } from '@esheet/core';
2
+ /** Summary of a single field, suitable for AI context. */
3
+ export interface FieldSummary {
4
+ id: string;
5
+ fieldType: string;
6
+ question: string | undefined;
7
+ required: boolean;
8
+ options: {
9
+ id: string;
10
+ value: string;
11
+ }[];
12
+ rows: {
13
+ id: string;
14
+ value: string;
15
+ }[];
16
+ columns: {
17
+ id: string;
18
+ value: string;
19
+ }[];
20
+ /** Which tool family to use: 'add_option' for option-based fields, 'add_row / add_column' for matrix fields. */
21
+ editWith: string;
22
+ /** True if this field has conditional logic rules attached. Use get_field to inspect them. */
23
+ hasRules: boolean;
24
+ /** Required value format for structured input types (date, datetime-local, month, time). Use this exact format when calling fill_field. */
25
+ valueFormat?: string;
26
+ /** True if this field already has a response value. False means it is still empty and needs to be filled. */
27
+ hasValue: boolean;
28
+ /** Section child fields (only present when fieldType === 'section'). */
29
+ children?: FieldSummary[];
30
+ }
31
+ /**
32
+ * Narrow interface exposed to MCP / AI tools via `onBuilderToolsReady`.
33
+ * Only the operations an external AI agent needs — no raw store internals.
34
+ */
35
+ export interface BuilderTools {
36
+ /** Add a new field. Returns the generated ID, or null for unknown type. */
37
+ addField: (fieldType: FieldType, opts?: AddFieldOptions) => string | null;
38
+ /** Patch a field's properties. Returns false if the field was not found. */
39
+ updateField: (fieldId: string, patch: Record<string, unknown>) => boolean;
40
+ /** Remove a field. Returns false if not found. */
41
+ removeField: (fieldId: string) => boolean;
42
+ /** Find a field ID by exact ID or partial question match. */
43
+ resolveFieldId: (fieldId?: string, fieldQuestion?: string) => string | undefined;
44
+ /** Replace the entire form with a new definition. */
45
+ resetForm: (definition: {
46
+ id?: string;
47
+ fields: Record<string, unknown>[];
48
+ }) => void;
49
+ /** Generate a form from a list of plain question descriptors. */
50
+ generateForm: (questions: {
51
+ question: string;
52
+ fieldType?: string;
53
+ required?: boolean;
54
+ inputType?: string;
55
+ options?: string[];
56
+ }[]) => string;
57
+ /** Snapshot of the current form suitable for AI context. */
58
+ getFormSummary: () => {
59
+ formId: string;
60
+ fieldCount: number;
61
+ fields: FieldSummary[];
62
+ };
63
+ /** 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. */
64
+ fillField: (fieldId: string, value: unknown) => boolean | string;
65
+ /** Clear all responses. */
66
+ clearResponses: () => void;
67
+ /** Get current responses keyed by field ID. */
68
+ getResponses: () => Record<string, unknown>;
69
+ /** Granular option mutations (radio, check, dropdown, etc.). */
70
+ option: {
71
+ add: (fieldId: string, value?: string) => string | null;
72
+ update: (fieldId: string, optionId: string, value: string) => boolean;
73
+ remove: (fieldId: string, optionId: string) => boolean;
74
+ };
75
+ /** Granular row mutations (matrix fields). */
76
+ row: {
77
+ add: (fieldId: string, value?: string) => string | null;
78
+ update: (fieldId: string, rowId: string, value: string) => boolean;
79
+ remove: (fieldId: string, rowId: string) => boolean;
80
+ };
81
+ /** Granular column mutations (matrix fields). */
82
+ column: {
83
+ add: (fieldId: string, value?: string) => string | null;
84
+ update: (fieldId: string, columnId: string, value: string) => boolean;
85
+ remove: (fieldId: string, columnId: string) => boolean;
86
+ };
87
+ /** Move a field to a new index. */
88
+ moveField: (fieldId: string, toIndex: number, toParentId?: string | null) => boolean;
89
+ /** Get a single field node by ID. */
90
+ getField: (fieldId: string) => import('@esheet/core').FieldNode | undefined;
91
+ /** List all registered field type keys and their labels. */
92
+ getFieldTypes: () => {
93
+ key: string;
94
+ label: string;
95
+ category: string;
96
+ hasOptions: boolean;
97
+ hasMatrix: boolean;
98
+ }[];
99
+ /** Get full spec for a single field type (properties, capabilities, defaults). */
100
+ getFieldSpec: (fieldType: string) => FieldTypeMeta | undefined;
101
+ /** Export the full form definition tree (inverse of loadDefinition). */
102
+ getDefinition: () => import('@esheet/core').FormDefinition;
103
+ /** Update the form's top-level ID without replacing fields. */
104
+ setFormId: (id: string) => void;
105
+ }
106
+ export declare function createBuilderTools(form: FormStore): BuilderTools;
107
+ //# sourceMappingURL=builder-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builder-tools.d.ts","sourceRoot":"","sources":["../../src/lib/builder-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,321 @@
1
+ // ---------------------------------------------------------------------------
2
+ // BuilderTools — narrow facade for MCP / AI tool callers only.
3
+ // Normal developers interact with the builder entirely through its props/UI.
4
+ // ---------------------------------------------------------------------------
5
+ import { getFieldTypeMeta, getRegisteredFieldTypes, hydrateDefinition, } from '@esheet/core';
6
+ export function createBuilderTools(form) {
7
+ function resolveFieldId(fieldId, fieldQuestion) {
8
+ if (fieldId)
9
+ return fieldId;
10
+ if (fieldQuestion) {
11
+ const q = fieldQuestion.toLowerCase();
12
+ const { normalized } = form.getState();
13
+ for (const id of Object.keys(normalized.byId)) {
14
+ const question = normalized.byId[id].definition.question;
15
+ if (question?.toLowerCase().includes(q))
16
+ return id;
17
+ }
18
+ }
19
+ return undefined;
20
+ }
21
+ return {
22
+ resetForm: (definition) => form.getState().loadDefinition(definition),
23
+ generateForm: (questions) => {
24
+ const fields = questions.map((q, i) => ({
25
+ id: `f${i + 1}`,
26
+ fieldType: q.fieldType ?? 'text',
27
+ question: q.question,
28
+ ...(q.required !== undefined && { required: q.required }),
29
+ ...(q.inputType && { inputType: q.inputType }),
30
+ ...(q.options && {
31
+ options: q.options.map((v, j) => ({ id: `o${j + 1}`, value: v })),
32
+ }),
33
+ }));
34
+ form.getState().loadDefinition({
35
+ id: form.getState().formId,
36
+ fields: [],
37
+ });
38
+ form.getState().loadDefinition({
39
+ id: form.getState().formId,
40
+ fields,
41
+ });
42
+ const summary = fields
43
+ .map((f, i) => `${i + 1}. ${f.question} (${f.fieldType})`)
44
+ .join(', ');
45
+ return `Form generated with ${fields.length} field(s): ${summary}`;
46
+ },
47
+ addField: (fieldType, opts) => form.getState().addField(fieldType, opts),
48
+ updateField: (fieldId, patch) => form.getState().updateField(fieldId, patch),
49
+ removeField: (fieldId) => form.getState().removeField(fieldId),
50
+ resolveFieldId,
51
+ fillField: (fieldId, value) => {
52
+ const { normalized } = form.getState();
53
+ const node = normalized.byId[fieldId];
54
+ if (!node)
55
+ return false;
56
+ const def = node.definition;
57
+ function normalizeTextValue(v, inputType) {
58
+ if (!v)
59
+ return v;
60
+ switch (inputType) {
61
+ case 'date':
62
+ if (/^\d{4}-\d{2}-\d{2}$/.test(v))
63
+ return v;
64
+ if (/^\d{4}-\d{2}$/.test(v))
65
+ return `${v}-01`;
66
+ if (/^\d{4}$/.test(v))
67
+ return `${v}-01-01`;
68
+ return null;
69
+ case 'month':
70
+ if (/^\d{4}-\d{2}$/.test(v))
71
+ return v;
72
+ if (/^\d{4}-\d{2}-\d{2}$/.test(v))
73
+ return v.slice(0, 7);
74
+ return null;
75
+ case 'datetime-local': {
76
+ const n = v.replace(' ', 'T');
77
+ if (/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}$/.test(n))
78
+ return n;
79
+ if (/^\d{4}-\d{2}-\d{2}$/.test(n))
80
+ return `${n}T00:00`;
81
+ return null;
82
+ }
83
+ case 'time': {
84
+ if (/^\d{2}:\d{2}$/.test(v))
85
+ return v;
86
+ const m = v.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)$/i);
87
+ if (m) {
88
+ let h = parseInt(m[1], 10);
89
+ if (m[3].toUpperCase() === 'AM' && h === 12)
90
+ h = 0;
91
+ if (m[3].toUpperCase() === 'PM' && h !== 12)
92
+ h += 12;
93
+ return `${String(h).padStart(2, '0')}:${m[2]}`;
94
+ }
95
+ return null;
96
+ }
97
+ default:
98
+ return v;
99
+ }
100
+ }
101
+ let response;
102
+ if (def.fieldType === 'singlematrix' &&
103
+ value !== null &&
104
+ typeof value === 'object') {
105
+ const rows = def.rows ?? [];
106
+ const columns = def.columns ?? [];
107
+ const existing = (form.getState().responses[fieldId]?.selected ??
108
+ {});
109
+ const selected = {
110
+ ...existing,
111
+ };
112
+ const entries = Array.isArray(value)
113
+ ? value.map((v, i) => [rows[i]?.value ?? String(i), v])
114
+ : Object.entries(value);
115
+ for (const [rowKey, colVal] of entries) {
116
+ const row = rows.find((r) => r.value.toLowerCase() === rowKey.toLowerCase() || r.id === rowKey);
117
+ if (!row)
118
+ continue;
119
+ const colStr = String(colVal);
120
+ const col = columns.find((c) => c.value.toLowerCase() === colStr.toLowerCase() ||
121
+ c.id === colStr) ?? columns[parseInt(colStr, 10)];
122
+ if (col)
123
+ selected[row.id] = { id: col.id, value: col.value };
124
+ }
125
+ response = { selected };
126
+ }
127
+ else if (def.fieldType === 'multimatrix' &&
128
+ value !== null &&
129
+ typeof value === 'object') {
130
+ const rows = def.rows ?? [];
131
+ const columns = def.columns ?? [];
132
+ const existing = (form.getState().responses[fieldId]?.selected ??
133
+ {});
134
+ const selected = {
135
+ ...existing,
136
+ };
137
+ const entries = Array.isArray(value)
138
+ ? value.map((v, i) => [rows[i]?.value ?? String(i), v])
139
+ : Object.entries(value);
140
+ for (const [rowKey, colVals] of entries) {
141
+ const row = rows.find((r) => r.value.toLowerCase() === rowKey.toLowerCase() || r.id === rowKey);
142
+ if (!row)
143
+ continue;
144
+ const colValArr = Array.isArray(colVals)
145
+ ? colVals
146
+ : [colVals];
147
+ const matched = colValArr
148
+ .map((v) => {
149
+ const s = String(v);
150
+ return columns.find((c) => c.value.toLowerCase() === s.toLowerCase() || c.id === s);
151
+ })
152
+ .filter((c) => c != null);
153
+ if (matched.length > 0)
154
+ selected[row.id] = matched;
155
+ }
156
+ response = { selected };
157
+ }
158
+ else if (['radio', 'dropdown', 'boolean', 'rating', 'slider'].includes(def.fieldType)) {
159
+ const opts = def.options ?? [];
160
+ const match = opts.find((o) => o.value.toLowerCase() === String(value).toLowerCase() ||
161
+ o.id === value);
162
+ const numVal = Number(value);
163
+ const numMatch = !match && !isNaN(numVal)
164
+ ? opts[numVal - 1] ?? opts[numVal]
165
+ : undefined;
166
+ const resolved = match ?? numMatch;
167
+ response = resolved
168
+ ? { selected: { id: resolved.id, value: resolved.value } }
169
+ : { selected: undefined };
170
+ }
171
+ else if (def.fieldType === 'check' ||
172
+ def.fieldType === 'multiselectdropdown') {
173
+ const opts = def.options ?? [];
174
+ const vals = Array.isArray(value) ? value : [value];
175
+ const matches = opts.filter((o) => vals.some((v) => o.value.toLowerCase() === String(v).toLowerCase() || o.id === v));
176
+ response = {
177
+ selected: matches.map((o) => ({ id: o.id, value: o.value })),
178
+ };
179
+ }
180
+ else if (def.fieldType === 'ranking') {
181
+ const opts = def.options ?? [];
182
+ const vals = Array.isArray(value) ? value : [value];
183
+ const ordered = vals
184
+ .map((v) => opts.find((o) => o.value.toLowerCase() === String(v).toLowerCase() || o.id === v))
185
+ .filter((o) => o != null);
186
+ const mentioned = new Set(ordered.map((o) => o.id));
187
+ const remaining = opts.filter((o) => !mentioned.has(o.id));
188
+ response = { selected: [...ordered, ...remaining] };
189
+ }
190
+ else if (def.fieldType === 'multitext') {
191
+ const opts = def.options ?? [];
192
+ const vals = Array.isArray(value)
193
+ ? value
194
+ : typeof value === 'object' && value !== null
195
+ ? Object.values(value)
196
+ : [value];
197
+ const multitextAnswers = {};
198
+ opts.forEach((opt, i) => {
199
+ if (vals[i] != null)
200
+ multitextAnswers[opt.id] = String(vals[i]);
201
+ });
202
+ response = { multitextAnswers };
203
+ }
204
+ else {
205
+ if (value == null) {
206
+ response = { answer: undefined };
207
+ }
208
+ else {
209
+ const normalized = normalizeTextValue(String(value), def.inputType);
210
+ if (normalized === null) {
211
+ const fmt = {
212
+ date: 'YYYY-MM-DD',
213
+ 'datetime-local': 'YYYY-MM-DDTHH:mm',
214
+ month: 'YYYY-MM',
215
+ time: 'HH:mm',
216
+ };
217
+ const expected = fmt[def.inputType ?? ''];
218
+ return expected
219
+ ? `Error: invalid value for inputType "${def.inputType}" — expected format ${expected}`
220
+ : `Error: invalid value for field`;
221
+ }
222
+ response = { answer: normalized };
223
+ }
224
+ }
225
+ form
226
+ .getState()
227
+ .setResponse(fieldId, { ...response, _ai: true });
228
+ return true;
229
+ },
230
+ clearResponses: () => form.getState().resetResponses(),
231
+ getResponses: () => form.getState().responses,
232
+ option: {
233
+ add: (fieldId, value) => form.getState().addOption(fieldId, value),
234
+ update: (fieldId, optionId, value) => form.getState().updateOption(fieldId, optionId, value),
235
+ remove: (fieldId, optionId) => form.getState().removeOption(fieldId, optionId),
236
+ },
237
+ row: {
238
+ add: (fieldId, value) => form.getState().addRow(fieldId, value),
239
+ update: (fieldId, rowId, value) => form.getState().updateRow(fieldId, rowId, value),
240
+ remove: (fieldId, rowId) => form.getState().removeRow(fieldId, rowId),
241
+ },
242
+ column: {
243
+ add: (fieldId, value) => form.getState().addColumn(fieldId, value),
244
+ update: (fieldId, columnId, value) => form.getState().updateColumn(fieldId, columnId, value),
245
+ remove: (fieldId, columnId) => form.getState().removeColumn(fieldId, columnId),
246
+ },
247
+ moveField: (fieldId, toIndex, toParentId) => form.getState().moveField(fieldId, toIndex, toParentId),
248
+ getField: (fieldId) => form.getState().getField(fieldId),
249
+ getFieldTypes: () => getRegisteredFieldTypes().map((key) => {
250
+ const meta = getFieldTypeMeta(key);
251
+ return {
252
+ key,
253
+ label: meta.label,
254
+ category: meta.category,
255
+ hasOptions: meta.hasOptions,
256
+ hasMatrix: meta.hasMatrix,
257
+ };
258
+ }),
259
+ getFieldSpec: (fieldType) => getFieldTypeMeta(fieldType),
260
+ getDefinition: () => {
261
+ const { normalized, formId } = form.getState();
262
+ return {
263
+ id: formId,
264
+ fields: hydrateDefinition(normalized),
265
+ };
266
+ },
267
+ setFormId: (id) => form.getState().setFormId(id),
268
+ getFormSummary: () => {
269
+ const { normalized, formId } = form.getState();
270
+ const INPUT_TYPE_FORMAT = {
271
+ date: 'YYYY-MM-DD',
272
+ 'datetime-local': 'YYYY-MM-DDTHH:mm',
273
+ month: 'YYYY-MM',
274
+ time: 'HH:mm',
275
+ };
276
+ function summarizeField(id) {
277
+ const node = normalized.byId[id];
278
+ const def = node.definition;
279
+ const isMatrix = def.fieldType === 'singlematrix' || def.fieldType === 'multimatrix';
280
+ const isSection = def.fieldType === 'section';
281
+ const base = {
282
+ id,
283
+ fieldType: def.fieldType,
284
+ question: isSection
285
+ ? def.title
286
+ : def.question,
287
+ required: def.required ?? false,
288
+ options: def.options ?? [],
289
+ rows: def.rows ?? [],
290
+ columns: def.columns ?? [],
291
+ editWith: isMatrix
292
+ ? 'add_row / add_column (NOT add_option)'
293
+ : 'add_option',
294
+ hasRules: (def.rules?.length ?? 0) > 0,
295
+ hasValue: (() => {
296
+ const r = form.getState().responses[id];
297
+ return (r != null &&
298
+ Object.values(r).some((v) => v != null &&
299
+ v !== '' &&
300
+ !(Array.isArray(v) && v.length === 0) &&
301
+ !(typeof v === 'object' &&
302
+ !Array.isArray(v) &&
303
+ Object.keys(v).length === 0)));
304
+ })(),
305
+ ...(def.inputType && INPUT_TYPE_FORMAT[def.inputType]
306
+ ? { valueFormat: INPUT_TYPE_FORMAT[def.inputType] }
307
+ : {}),
308
+ };
309
+ if (isSection && node.childIds.length > 0) {
310
+ return { ...base, children: node.childIds.map(summarizeField) };
311
+ }
312
+ return base;
313
+ }
314
+ return {
315
+ formId,
316
+ fieldCount: Object.keys(normalized.byId).length,
317
+ fields: normalized.rootIds.map(summarizeField),
318
+ };
319
+ },
320
+ };
321
+ }
@@ -0,0 +1,7 @@
1
+ export interface BuilderHeaderProps {
2
+ }
3
+ /**
4
+ * BuilderHeader — top bar with Build/Code/Preview mode toggle and Import/Export actions.
5
+ */
6
+ export declare function BuilderHeader(_props: BuilderHeaderProps): import("react/jsx-runtime").JSX.Element;
7
+ //# sourceMappingURL=BuilderHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BuilderHeader.d.ts","sourceRoot":"","sources":["../../../src/lib/components/BuilderHeader.tsx"],"names":[],"mappings":"AAuCA,MAAM,WAAW,kBAAkB;CAAG;AAmLtC;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,kBAAkB,2CAgnBvD"}