@einhasad-vue/form-builder-vue
v0.3.0
Published
Vue 3 form builder library — drag-and-drop form creation, no jQuery dependency
Downloads
579
Maintainers
Readme
Vue 3 Form Builder
Drag-and-drop form builder and renderer for Vue 3 — TypeScript-first, zero jQuery, zero runtime dependencies.
Size
Measured against @einhasad-vue/[email protected] on a clean install. vue is a peer dependency — the numbers below are the delta you pay on top of an existing Vue app; Vue's own runtime (~11 KB gzip) is not counted because your app already has it. CSS is required for the builder's drag preview; the renderer works without it.
What actually reaches the browser
| Import | Raw (min) | gzip | brotli |
|---|---:|---:|---:|
| FormBuilder + FormRenderer (everything) | 45 KB | ~12 KB | ~11 KB |
| FormRenderer only (tree-shaken) | 22 KB | ~6 KB | ~5 KB |
| form-builder-vue.css (required for builder UI) | 20 KB | ~3.5 KB | ~3 KB |
Measured by bundling a consumer with esbuild --bundle --minify and vue marked external.
What npm puts on disk
| | Size |
|---|---:|
| Tarball downloaded from the registry | ~38 KB |
| node_modules/@einhasad-vue/form-builder-vue/ (ESM + UMD + CSS + .d.ts) | ~172 KB |
Zero runtime dependencies — nothing transitive gets pulled in. Library is ESM, so modern bundlers tree-shake unused exports.
Features
- Drag-and-drop form builder with live preview
- 16 built-in field types (text, select, checkbox-group, radio-group, date, file, header, paragraph, etc.)
- Form renderer for displaying saved forms and collecting user input
- v-model support on both builder and renderer
- Fully typed with TypeScript
- Customizable via options (disable fields, custom attrs, i18n, action buttons)
- Scoped styles, no global CSS pollution
- Zero jQuery dependency
Installation
npm install @einhasad-vue/form-builder-vueRequires Vue 3.5+ as a peer dependency.
Usage
Form Builder
<script setup lang="ts">
import { ref } from 'vue'
import { FormBuilder } from '@einhasad-vue/form-builder-vue'
import type { FormDataField } from '@einhasad-vue/form-builder-vue'
const formData = ref<FormDataField[]>([])
</script>
<template>
<FormBuilder v-model="formData" />
</template>Form Renderer
<script setup lang="ts">
import { ref } from 'vue'
import { FormRenderer } from '@einhasad-vue/form-builder-vue'
import type { FormDataField, UserDataMap } from '@einhasad-vue/form-builder-vue'
const formData = ref<FormDataField[]>([/* saved form data */])
const userData = ref<UserDataMap>({})
</script>
<template>
<FormRenderer
:form-data="formData"
v-model="userData"
/>
</template>API
FormBuilder Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| modelValue | FormDataField[] | [] | Form fields (v-model) |
| options | Partial<BuilderOptions> | {} | Configuration overrides |
FormBuilder Events
| Event | Payload | Description |
|-------|---------|-------------|
| update:modelValue | FormDataField[] | Fields changed |
| field-added | { fieldId, field } | Field added |
| field-removed | { fieldId, field } | Field removed |
| field-updated | { fieldId, field } | Field updated |
| field-moved | { fieldId, fromIndex, toIndex } | Field reordered |
| field-selected | { fieldId } | Field selected for editing |
| save | { formData } | Save button clicked |
| clear | — | Clear button clicked |
| loaded | — | Builder mounted |
FormBuilder Exposed Methods
| Method | Description |
|--------|-------------|
| getData() | Get current form data array |
| setData(fields) | Set form data |
| addField(field) | Add a new field |
| removeField(id) | Remove field by id |
| clearFields() | Remove all fields |
| save() | Returns current form data |
FormRenderer Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| formData | FormDataField[] | [] | Field definitions to render |
| modelValue | UserDataMap | {} | User answers (v-model) |
| options | Partial<RendererOptions> | {} | Configuration overrides |
| disabled | boolean | false | Disable all inputs |
BuilderOptions
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| controlPosition | 'left' \| 'right' | 'left' | Control panel side |
| disableFields | FieldType[] | [] | Field types to hide |
| showActionButtons | boolean | true | Show Save/Clear buttons |
| disabledAttrs | string[] | [] | Attributes to disable in edit panel |
| editOnAdd | boolean | false | Open edit panel on field add |
| fieldRemoveWarn | boolean | false | Warn before removing fields |
Field Types
text, number, date, select, checkbox-group, radio-group, textarea, file, autocomplete, button, header, paragraph, hidden, checkbox
Composables
All internal composables are exported for advanced usage:
import {
useFormBuilder,
useFormRenderer,
useFieldRegistry,
useDragDrop,
useI18n,
} from '@einhasad-vue/form-builder-vue'Provide / inject helpers
The library shares configuration, state, field registry, and i18n with
descendant components through provide/inject. The injection keys are
module-private — consumers interact with them through paired helper
functions. Use these when mounting child pieces (e.g. BuilderStage) inside
custom wrappers, or when reading context from your own composables:
import {
provideBuilderOptions, useBuilderOptions,
provideBuilderState, useBuilderState,
provideBuilderRegistry, useBuilderRegistry,
provideBuilderI18n, useBuilderI18n,
type BuilderRegistryContext,
type BuilderI18nContext,
} from '@einhasad-vue/form-builder-vue'Each use*() returns undefined if nothing was provided upstream, so
consumers can fall back cleanly.
Theming
Scoped styles read their colors from CSS custom properties. Redefine them
on .form-builder (or any ancestor) to retheme without overriding
individual selectors. Key variables:
| Variable | Purpose | Default |
| --- | --- | --- |
| --accent | Primary accent — action buttons, focus rings | #ffc833 |
| --fb-control-accent | accent-color for checkbox/radio inputs and .toggle :checked background | var(--accent, #ffc833) |
| --surface, --surface-sunk | Panel / stage backgrounds | #fff, #f3f0e8 |
| --ink, --ink-2, --ink-3 | Primary / secondary / muted text | #111, #3a3a3a, #6e6a63 |
| --line, --line-2 | Subtle / medium borders | #e8e4db, #d3cec1 |
Development
npm run build # Build library
npm run test # Run tests
npm run test:coverage # Run tests with 100% coverage thresholds
npm run typecheck # TypeScript type checking
npm run lint # ESLintLicense
MIT
