@xenterprises/nuxt-x-app-formkit
v0.2.1
Published
Nuxt layer providing FormKit DX enhancements for admin dashboards — CRUD modal/slide components, custom file upload input, and dynamic FormKit Pro support.
Downloads
225
Readme
@xenterprises/nuxt-x-app-formkit
Nuxt layer providing FormKit DX enhancements for admin dashboards — CRUD modal/slide components, custom file upload input, and dynamic FormKit Pro support.
Install
npm add @xenterprises/nuxt-x-app-formkitSetup
// nuxt.config.ts
export default defineNuxtConfig({
extends: ["@xenterprises/nuxt-x-app-formkit"],
});FormKit Theme
This layer does not include a FormKit theme. You must provide your own formkit.theme.ts.
See .playground/formkit.theme.ts for an example theme. Reference it in your config:
// formkit.config.ts
import { defineFormKitConfig } from "@formkit/vue";
import { rootClasses } from "./formkit.theme";
export default defineFormKitConfig({
config: { rootClasses },
});For Tailwind CSS v4, add to your main CSS:
@source "./formkit.theme.ts";FormKit Pro (Optional)
Set the FORMKIT environment variable to enable Pro inputs:
FORMKIT=fk-your-pro-keyThe layer loads FormKit Pro automatically when the key starts with fk- and @formkit/pro is installed.
Components
XFormModal
Modal dialog with FormKit integration for CRUD operations.
<XFormModal
v-model="showModal"
endpoint="/api/users"
@success="handleSuccess"
>
<FormKit type="text" name="name" label="Name" validation="required" />
<FormKit type="email" name="email" label="Email" validation="required|email" />
</XFormModal>Props
| Name | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| modelValue | boolean | false | No | Controls modal visibility (v-model) |
| title | string | "" | No | Modal title. Auto-generated from endpoint if omitted |
| size | "sm" \| "md" \| "lg" \| "xl" \| "full" | "md" | No | Modal width |
| closable | boolean | true | No | Show close button in header |
| loading | boolean | false | No | External loading state |
| disabled | boolean | false | No | Disable form submission |
| submitText | string | "Save" | No | Submit button text. Shows "Create"/"Update" when using endpoint |
| cancelText | string | "Cancel" | No | Cancel button text |
| confirmClose | boolean | false | No | Require confirmation before closing |
| endpoint | string | — | No | API endpoint for CRUD operations |
| recordId | string \| number | — | No | Record ID for edit mode (triggers GET on open) |
| initialData | Record<string, any> | — | No | Pre-fill form data |
| method | "POST" \| "PUT" \| "PATCH" | Auto | No | HTTP method. Auto-selects POST (create) or PUT (edit) |
| idKey | string | "id" | No | Key used to identify records |
| headers | Record<string, string> \| () => Record<string, string> | — | No | Custom request headers |
| transform | (data) => data | — | No | Transform data before submission |
| showToast | boolean | true | No | Show success/error toasts |
| closeOnSuccess | boolean | true | No | Close modal on successful submission |
| resetOnClose | boolean | true | No | Reset form when modal closes |
| formId | string | Auto | No | Custom FormKit form ID |
| onSuccess | "refresh" \| "navigate" \| function | — | No | Action after successful submission |
| navigateTo | string | — | No | Route to navigate to (use with onSuccess="navigate") |
Events
| Event | Payload | Description |
|-------|---------|-------------|
| update:modelValue | boolean | Modal visibility changed |
| submit | — | Submit clicked (legacy mode, no endpoint) |
| success | (data, response) | CRUD operation succeeded |
| error | (error) | CRUD operation failed |
| loaded | (data) | Record loaded by ID |
| close | — | Close button clicked |
Slots
| Slot | Props | Description |
|------|-------|-------------|
| default | { state, disabled, data, isEdit } | Form content |
| header | — | Custom header content |
| footer | { loading, disabled } | Custom footer with action buttons |
| loading | — | Custom loading indicator |
| error | { error, retry } | Custom error state |
Exposed Methods
| Method | Description |
|--------|-------------|
| open(data?) | Open modal, optionally pre-filling data |
| close() | Close modal |
| reset() | Reset form to initial state |
| submit() | Trigger form submission |
XFormSlide
Slide-over panel with FormKit integration for CRUD operations. Same props/events as XFormModal, plus:
| Name | Type | Default | Description |
|------|------|---------|-------------|
| side | "left" \| "right" | "right" | Panel position |
| size | "sm" \| "md" \| "lg" \| "xl" | "md" | Panel width (320/400/500/600px) |
<XFormSlide
v-model="showSlide"
endpoint="/api/settings"
:initial-data="{ id: 1, key: 'theme', value: 'dark' }"
method="PATCH"
side="right"
@success="handleSuccess"
>
<FormKit type="text" name="key" label="Key" validation="required" />
<FormKit type="text" name="value" label="Value" validation="required" />
</XFormSlide>XFormFileUpload
Drag-and-drop file upload component.
<XFormFileUpload
v-model="files"
accept="image/*"
:multiple="true"
:max-size="5 * 1024 * 1024"
:max-files="3"
:upload-handler="handleUpload"
/>Props
| Name | Type | Default | Required | Description |
|------|------|---------|----------|-------------|
| modelValue | File \| File[] \| null | null | No | Selected file(s) |
| multiple | boolean | false | No | Allow multiple file selection |
| accept | string | "*" | No | Accepted file types (e.g., "image/*", ".pdf,.doc") |
| acceptLabel | string | "" | No | Human-readable label for accepted types |
| maxSize | number | — | No | Maximum file size in bytes |
| maxFiles | number | — | No | Maximum number of files (multiple mode) |
| disabled | boolean | false | No | Disable the upload |
| dropzone | boolean | true | No | Enable drag-and-drop |
| uploadHandler | (files: File[]) => Promise<void> | — | No | Custom upload handler called after file selection |
Events
| Event | Payload | Description |
|-------|---------|-------------|
| update:modelValue | File \| File[] \| null | File selection changed |
| error | string | Validation error (size, count) |
Exposed Methods
| Method | Description |
|--------|-------------|
| clear() | Clear all selected files |
| openFilePicker() | Open the native file picker |
FormKit File Upload Input
Use as a FormKit input type:
<FormKit
type="fileUpload"
name="avatar"
label="Profile Picture"
accept="image/*"
:max-size="5 * 1024 * 1024"
help="Upload a profile picture"
/>Supports all XFormFileUpload props as FormKit input props.
Composables
useFormCrud
Shared CRUD logic used internally by XFormModal and XFormSlide. Available for building custom form containers.
const crud = useFormCrud(options, callbacks, externalLoading?, externalDisabled?)Returns: { isLoading, isSubmitting, loadError, formData, formKey, isEditMode, combinedLoading, combinedDisabled, loadRecord, initializeForm, handleFormKitSubmit, resetForm, computeTitle, computeSubmitText }
Environment Variables
| Name | Required | Description |
|------|----------|-------------|
| FORMKIT | No | FormKit Pro license key. Must start with fk- to activate Pro inputs |
Error Reference
| Error | Source | Description |
|-------|--------|-------------|
| [nuxt-x-formkit] FORMKIT env var is set but does not start with 'fk-' | Startup | Invalid Pro key format |
| [nuxt-x-formkit] FORMKIT env var is set but @formkit/pro is not installed | Startup | Missing @formkit/pro package |
| Failed to load record | CRUD load | GET request to endpoint/recordId failed |
| Created successfully / Updated successfully | CRUD submit | Success toast |
| Operation failed | CRUD submit | Generic submission error |
How It Works
The layer registers @formkit/nuxt with auto-import and a shared formkit.config.ts. At startup, it checks the FORMKIT runtime config for a Pro key and dynamically imports @formkit/pro if available.
XFormModal and XFormSlide both consume the useFormCrud composable, which handles:
- Detecting create vs. edit mode (from
recordIdorinitialData) - Loading records by ID with error/retry states
- Building the correct HTTP method and URL
- Transforming payloads before submission
- Showing toast notifications
- Handling success behaviors (refresh, navigate, custom function)
The XFormFileUpload component provides a standalone drag-and-drop upload with validation. It also registers as a custom FormKit input (type="fileUpload") via the createInput API, bridging FormKit context with the Vue component.
Layer Architecture
nuxt.config.ts— Registers@formkit/nuxtmodule, points toformkit.config.ts, exposesFORMKITruntime config.formkit.config.ts— Configures FormKit with genesis icons, the customfileUploadinput, and optional Pro plugin.app/components/— Auto-imported components (XFormModal, XFormSlide, XFormFileUpload).app/composables/— Auto-imported composables (useFormCrud).app/formkit/inputs/— Custom FormKit input definitions.
Consumer apps should provide their own formkit.theme.ts and can override the formkit.config.ts via Nuxt's formkit.configFile option.
Usage with nuxt-x-app
For full admin dashboard functionality, use both layers:
export default defineNuxtConfig({
extends: [
"@xenterprises/nuxt-x-app",
"@xenterprises/nuxt-x-app-formkit",
],
});Development
npm install
npm run dev # Start playground
npm run test # Run tests
npm run dev:prepare # Prepare types