@esheet/builder 0.0.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.
- package/README.md +119 -0
- package/dist/index.d.ts +141 -0
- package/dist/index.js +8375 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# @esheet/builder
|
|
2
|
+
|
|
3
|
+
Drag-and-drop questionnaire builder for eSheet. Provides a full editing UI for creating and modifying form schemas.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- ✅ Visual form builder with drag & drop (custom pointer-based engine)
|
|
8
|
+
- ✅ 19 built-in field types via `@esheet/fields`
|
|
9
|
+
- ✅ Section nesting with drag-into-section support
|
|
10
|
+
- ✅ Field editors (question text, options, matrix rows/columns, conditional logic)
|
|
11
|
+
- ✅ Code view with Monaco editor (JSON/YAML toggle)
|
|
12
|
+
- ✅ Live preview mode
|
|
13
|
+
- ✅ Import/Export (JSON + YAML)
|
|
14
|
+
- ✅ Custom field type registration
|
|
15
|
+
- ✅ Dark mode support
|
|
16
|
+
- ✅ Mobile responsive (bottom drawer for panels)
|
|
17
|
+
- ✅ Self-contained CSS (injected at runtime, no external stylesheet needed)
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @esheet/builder @esheet/fields @esheet/core
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Basic Example
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
import { EsheetBuilder } from '@esheet/builder';
|
|
31
|
+
import type { FormDefinition } from '@esheet/core';
|
|
32
|
+
|
|
33
|
+
function App() {
|
|
34
|
+
const handleChange = (definition: FormDefinition) => {
|
|
35
|
+
console.log('Form updated:', definition);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
return <EsheetBuilder onChange={handleChange} />;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### With Initial Schema
|
|
43
|
+
|
|
44
|
+
```tsx
|
|
45
|
+
import { EsheetBuilder } from '@esheet/builder';
|
|
46
|
+
|
|
47
|
+
const initialForm: FormDefinition = {
|
|
48
|
+
schemaType: 'mieforms-v1.0',
|
|
49
|
+
title: 'Patient Intake',
|
|
50
|
+
fields: [
|
|
51
|
+
{ id: 'name', fieldType: 'text', question: 'Full Name', required: true },
|
|
52
|
+
{ id: 'dob', fieldType: 'date', question: 'Date of Birth' },
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
<EsheetBuilder initialDefinition={initialForm} onChange={handleChange} />;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Dark Mode
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<div className="dark">
|
|
63
|
+
<EsheetBuilder onChange={handleChange} />
|
|
64
|
+
</div>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Add the `dark` class to the builder's root or any ancestor — the builder scopes all dark styles via `.ms-builder-root.dark`.
|
|
68
|
+
|
|
69
|
+
## API
|
|
70
|
+
|
|
71
|
+
### `<EsheetBuilder>`
|
|
72
|
+
|
|
73
|
+
**Props:**
|
|
74
|
+
|
|
75
|
+
| Prop | Type | Description |
|
|
76
|
+
| ------------------- | ------------------------------- | ------------------------------- |
|
|
77
|
+
| `initialDefinition` | `FormDefinition` | Pre-load a form schema |
|
|
78
|
+
| `onChange` | `(def: FormDefinition) => void` | Callback on any form change |
|
|
79
|
+
| `className` | `string` | Additional CSS classes for root |
|
|
80
|
+
|
|
81
|
+
## Custom Field Types
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { EsheetBuilder } from '@esheet/builder';
|
|
85
|
+
import { registerCustomFieldTypes } from '@esheet/fields';
|
|
86
|
+
import { registerFieldType } from '@esheet/core';
|
|
87
|
+
|
|
88
|
+
// Register the metadata
|
|
89
|
+
registerFieldType({
|
|
90
|
+
type: 'nps',
|
|
91
|
+
label: 'NPS Score',
|
|
92
|
+
category: 'scale',
|
|
93
|
+
defaultProps: { question: 'How likely are you to recommend us?' },
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// Register the component
|
|
97
|
+
registerCustomFieldTypes({
|
|
98
|
+
nps: {
|
|
99
|
+
component: NpsField,
|
|
100
|
+
meta: {
|
|
101
|
+
/* ... */
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
<EsheetBuilder onChange={handleChange} />;
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## CSS Architecture
|
|
110
|
+
|
|
111
|
+
The builder 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 `.ms-builder-root` prevents style leakage in either direction.
|
|
112
|
+
|
|
113
|
+
## Building
|
|
114
|
+
|
|
115
|
+
Run `nx build @esheet/builder` to build the library.
|
|
116
|
+
|
|
117
|
+
## Running unit tests
|
|
118
|
+
|
|
119
|
+
Run `nx test @esheet/builder` to execute the unit tests via [Vitest](https://vitest.dev/).
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { BuilderMode } from '@esheet/core';
|
|
2
|
+
import { createUIStore } from '@esheet/core';
|
|
3
|
+
import { default as default_2 } from 'react';
|
|
4
|
+
import { EditTab } from '@esheet/core';
|
|
5
|
+
import { FieldComponentProps } from '@esheet/core';
|
|
6
|
+
import { FormDefinition } from '@esheet/core';
|
|
7
|
+
import { FormStore } from '@esheet/core';
|
|
8
|
+
import { FormStoreContext } from '@esheet/fields';
|
|
9
|
+
import { getFieldComponent } from '@esheet/fields';
|
|
10
|
+
import { getRegisteredComponentKeys } from '@esheet/fields';
|
|
11
|
+
import { JSX } from 'react/jsx-runtime';
|
|
12
|
+
import { registerCustomFieldTypes } from '@esheet/fields';
|
|
13
|
+
import { resetComponentRegistry } from '@esheet/fields';
|
|
14
|
+
import { UIContext } from '@esheet/fields';
|
|
15
|
+
import { UIState } from '@esheet/core';
|
|
16
|
+
import { UIStore } from '@esheet/core';
|
|
17
|
+
import { useFormStore } from '@esheet/fields';
|
|
18
|
+
import { useUI } from '@esheet/fields';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* BuilderHeader — top bar with Build/Code/Preview mode toggle and Import/Export actions.
|
|
22
|
+
*/
|
|
23
|
+
export declare function BuilderHeader({ form, ui }: BuilderHeaderProps): JSX.Element;
|
|
24
|
+
|
|
25
|
+
export declare interface BuilderHeaderProps {
|
|
26
|
+
form: FormStore;
|
|
27
|
+
ui: UIStore;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { BuilderMode }
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* CodeView — Monaco-based JSON/YAML editor for the form definition.
|
|
34
|
+
*
|
|
35
|
+
* Serialize on mount, live-validate on edit, auto-save on unmount.
|
|
36
|
+
*/
|
|
37
|
+
export declare function CodeView({ form, ui }: CodeViewProps): JSX.Element;
|
|
38
|
+
|
|
39
|
+
export declare interface CodeViewProps {
|
|
40
|
+
form: FormStore;
|
|
41
|
+
ui: UIStore;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export { createUIStore }
|
|
45
|
+
|
|
46
|
+
export { EditTab }
|
|
47
|
+
|
|
48
|
+
export declare function EsheetBuilder({ definition, onChange, dragEnabled, className, children, }: EsheetBuilderProps): JSX.Element;
|
|
49
|
+
|
|
50
|
+
export declare interface EsheetBuilderProps {
|
|
51
|
+
/** Initial form definition to load. */
|
|
52
|
+
definition?: FormDefinition;
|
|
53
|
+
/** Callback fired when the form definition changes. */
|
|
54
|
+
onChange?: (definition: FormDefinition) => void;
|
|
55
|
+
/** Whether drag-and-drop reordering is enabled (default: true). Disable for better performance on slow devices. */
|
|
56
|
+
dragEnabled?: boolean;
|
|
57
|
+
/** Additional CSS class name. */
|
|
58
|
+
className?: string;
|
|
59
|
+
/** Optional content rendered below the header (e.g. custom status/debug panels). */
|
|
60
|
+
children?: default_2.ReactNode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export { FieldComponentProps }
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* FieldWrapper - Extensibility API for custom field components.
|
|
67
|
+
*
|
|
68
|
+
* Wraps a field with collapsible header, selection highlighting, edit/delete buttons, and drag handles.
|
|
69
|
+
* Exposes field data and tools to the render function, allowing users to create
|
|
70
|
+
* custom field types while getting all the built-in editor functionality.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* ```tsx
|
|
74
|
+
* <FieldWrapper fieldId={id} form={form} ui={ui}>
|
|
75
|
+
* {({ field, onUpdate, onRemove }) => (
|
|
76
|
+
* <div>
|
|
77
|
+
* <input
|
|
78
|
+
* value={field.question}
|
|
79
|
+
* onChange={(e) => onUpdate({ question: e.target.value })}
|
|
80
|
+
* />
|
|
81
|
+
* </div>
|
|
82
|
+
* )}
|
|
83
|
+
* </FieldWrapper>
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function FieldWrapper({ fieldId, form, ui, dragHandleRef, isSelectedOverride, onSelectOverride, selectedVariant, forceExpandVersion, children, }: FieldWrapperProps): JSX.Element | null;
|
|
87
|
+
|
|
88
|
+
export declare interface FieldWrapperProps {
|
|
89
|
+
/** The field ID */
|
|
90
|
+
fieldId: string;
|
|
91
|
+
/** The form store */
|
|
92
|
+
form: FormStore;
|
|
93
|
+
/** The UI store */
|
|
94
|
+
ui: UIStore;
|
|
95
|
+
/** Ref attached to the drag-handle element. */
|
|
96
|
+
dragHandleRef?: default_2.RefObject<HTMLDivElement | null>;
|
|
97
|
+
/** Optional override for selection state (used by nested section child interaction). */
|
|
98
|
+
isSelectedOverride?: boolean;
|
|
99
|
+
/** Optional override for click selection behavior. */
|
|
100
|
+
onSelectOverride?: (e: default_2.MouseEvent) => void;
|
|
101
|
+
/** Optional selected styling variant. */
|
|
102
|
+
selectedVariant?: 'default' | 'nested';
|
|
103
|
+
/** Optional signal used to force expand a field wrapper (used for section drop UX). */
|
|
104
|
+
forceExpandVersion?: number;
|
|
105
|
+
/** Render function that receives field data and tools */
|
|
106
|
+
children: (props: FieldWrapperRenderProps) => default_2.ReactNode;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Props exposed to the render function for custom field components.
|
|
111
|
+
* Identical to `FieldComponentProps` from core — kept as a named alias for
|
|
112
|
+
* backward-compatibility with existing builder consumers.
|
|
113
|
+
*/
|
|
114
|
+
export declare type FieldWrapperRenderProps = FieldComponentProps;
|
|
115
|
+
|
|
116
|
+
export { FormStoreContext }
|
|
117
|
+
|
|
118
|
+
export { getFieldComponent }
|
|
119
|
+
|
|
120
|
+
export { getRegisteredComponentKeys }
|
|
121
|
+
|
|
122
|
+
export declare const InstanceIdContext: default_2.Context<string>;
|
|
123
|
+
|
|
124
|
+
export { registerCustomFieldTypes }
|
|
125
|
+
|
|
126
|
+
export { resetComponentRegistry }
|
|
127
|
+
|
|
128
|
+
export { UIContext }
|
|
129
|
+
|
|
130
|
+
export { UIState }
|
|
131
|
+
|
|
132
|
+
export { UIStore }
|
|
133
|
+
|
|
134
|
+
export { useFormStore }
|
|
135
|
+
|
|
136
|
+
/** Hook to access the per-instance ID for unique DOM element IDs. */
|
|
137
|
+
export declare function useInstanceId(): string;
|
|
138
|
+
|
|
139
|
+
export { useUI }
|
|
140
|
+
|
|
141
|
+
export { }
|