Framework-agnostic dynamic form builder for XBRL entrypoints using Web Components. Supports Angular 14+, React, Vue, and vanilla HTML.
npm install jupiter-dynamic-forms> Framework-agnostic dynamic form builder for XBRL entrypoints using Web Components



Jupiter Dynamic Forms is a powerful, framework-agnostic form builder specifically designed for XBRL (eXtensible Business Reporting Language) data. It automatically generates interactive forms with accordion sections from XBRL taxonomy data, supporting Angular 18+, React, Vue, and vanilla HTML applications.
- 🎭 XBRL Integration: Direct consumption of XBRL taxonomy JSON files
- 📱 Framework Agnostic: Works with Angular 18+, React, Vue, or vanilla HTML
- 🎨 Accordion UI: Automatic accordion sections for each presentation role
- 🔍 Role Filtering: Smart filtering for complex forms with 10+ sections
- 💾 Draft Persistence: Automatic localStorage draft saving with full state preservation
- 🔄 Period Preferences: Show/hide concepts by period type (duration/instant) with persistence
- 📅 Previous Year Column: Optional previous year comparison columns per role
- 🏗️ Hierarchical Display: Nested concept trees with proper indentation
- 🔧 Smart Field Types: Automatic mapping from XBRL types to form controls
- 🌐 Multi-language: Intelligent label selection from XBRL labels
- 📊 TypeScript: Full type safety with comprehensive interfaces
- ⚡ Web Components: Built with Lit Element for maximum compatibility
``bash`
npm install @jupiter/dynamic-forms
`typescript
// app.module.ts
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@jupiter/dynamic-forms';
@NgModule({
// ... other config
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule { }
`
`typescript
// your-component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-form',
template:
[attr.config]="formConfig"
[attr.language]="language"
[attr.periodStartDate]="periodStart"
[attr.periodEndDate]="periodEnd"
(formSubmit)="onFormSubmit($event)"
(formChange)="onFormChange($event)">
`
})
export class FormComponent {
language = 'nl'; // Dutch labels
periodStart = '2024-01-01';
periodEnd = '2024-12-31';
xbrlData = {
presentation: [/ your XBRL data /]
};
formConfig = {
showValidationSummary: true,
collapsibleSections: true
};
onFormSubmit(event: CustomEvent) {
console.log('Form submitted:', event.detail);
}
onFormChange(event: CustomEvent) {
console.log('Form changed:', event.detail);
}
}
Jupiter Dynamic Forms expects XBRL data in JSON format. Each presentation role automatically becomes an accordion section:
- [000001] Filing Information → Company details and registration
- [000101] Profit or Loss Statement → Income statement data
- [000201] Comprehensive Income → Comprehensive income items
- [000301] Financial Position → Balance sheet structure
- [000401] Changes in Equity → Equity movements
- [000501] Cash Flows → Cash flow analysis
- Framework Agnostic: Works with Angular, React, Vue, and vanilla JavaScript
- JSON Schema Driven: Define complex forms using simple JSON schemas
- XBRL Optimized: Built specifically for XBRL entrypoint data collection
- Accordion Sections: Collapsible sections for better organization
- Nested Concept Trees: Hierarchical data organization with expandable/collapsible nodes
- Tabular Layout: Clean table-based layout with concept trees and input columns
- Dynamic Columns: Add/remove dimension columns on the fly
- Rich Field Types: Support for text, number, date, currency, boolean, select, and more
- Built-in Validation: Comprehensive validation with customizable rules
- TypeScript Support: Full TypeScript definitions included
- Themeable: CSS custom properties for easy styling customization
For complex XBRL taxonomies with many presentation roles, Jupiter Dynamic Forms provides intelligent filtering:
- Always Available: Filter button always visible for complete user control
- Interactive Dialog: Easy-to-use modal for selecting which roles to display
- Period Preferences: Show/hide duration and instant concepts per role
- Previous Year Column: Optional previous year comparison column per role
- Bulk Actions: "Select All", "Select None", and "Reset" options
- Live Updates: Form sections update immediately when filter is applied
- Role Count Badge: Visual indicator showing selected vs. total roles (e.g., "8/15")
- Preference Persistence: All selections saved automatically to localStorage
`javascriptShowing ${visibleRoles} of ${totalRoles} roles
// Listen for filter changes
form.addEventListener('roles-filter-changed', (event) => {
const { selectedRoleIds, totalRoles, visibleRoles, periodPreferences } = event.detail;
console.log();`
console.log('Period preferences:', periodPreferences);
});
Automatic draft saving ensures no data loss:
- Automatic Saving: Draft saved to localStorage whenever form data changes
- Full State Preservation: Saves form data, period preferences, selected roles, and custom columns
- Seamless Restoration: Automatically restores draft on page reload
- Smart Validation: Validates draft compatibility with current period dates
- External Storage Support: Supports external draft storage via dynaformsFacts and dynaformsMetadata properties
- Manual Save: "Save Draft" button for explicit save operations
`javascript
// Listen for draft save
form.addEventListener('form-save-draft', (event) => {
const { draftData, metadata, saved } = event.detail;
console.log('Draft saved:', saved);
// Optionally save to external storage
await saveToServer(event.detail.dynaformsFacts, event.detail.dynaformsMetadata);
});
// Listen for draft load
form.addEventListener('form-draft-loaded', (event) => {
const { draft, compatible, warnings } = event.detail;
console.log('Draft loaded:', compatible);
if (warnings.length > 0) {
console.warn('Draft compatibility warnings:', warnings);
}
});
// Provide external draft data
form.dynaformsFacts = loadedFactsFromServer;
form.dynaformsMetadata = loadedMetadataFromServer;
`
`bash`
npm install @jupiter/dynamic-forms
`html`
`typescript
// app.module.ts
import { JupiterDynamicFormModule } from '@jupiter/dynamic-forms/angular';
@NgModule({
imports: [JupiterDynamicFormModule],
// ...
})
export class AppModule { }
`
`html`
[config]="formConfig"
(formSubmit)="onFormSubmit($event)"
>
`tsx
import { JupiterDynamicForm } from '@jupiter/dynamic-forms/react';
function MyComponent() {
const handleSubmit = (data) => {
console.log('Form data:', data);
};
return (
config={formConfig}
onFormSubmit={handleSubmit}
/>
);
}
`
`vue
:config="formConfig"
@form-submit="handleSubmit"
/>
`
The form is driven by a JSON schema that defines sections, concepts, and fields:
`json`
{
"version": "1.0",
"formId": "financial-statement",
"title": "Financial Statement Form",
"description": "XBRL financial data entry",
"sections": [
{
"id": "balance-sheet",
"title": "Balance Sheet",
"expanded": true,
"concepts": [
{
"id": "assets",
"name": "Assets",
"label": "Total Assets",
"level": 0,
"fields": [
{
"id": "assets-base",
"conceptId": "assets",
"columnId": "base",
"type": "currency",
"label": "Assets",
"required": true,
"validation": [
{
"type": "required",
"message": "Assets value is required"
}
]
}
],
"children": [
// Nested concepts...
]
}
]
}
]
}
`typescript`
const config = {
theme: 'light' | 'dark' | 'auto',
locale: 'en-US',
dateFormat: 'YYYY-MM-DD',
currencyCode: 'USD',
showValidationSummary: true,
collapsibleSections: true,
collapsibleConcepts: true,
enableColumnManagement: true,
maxColumns: 10,
autoSave: false,
autoSaveInterval: 30000
};
- text - Single line text inputtextarea
- - Multi-line text inputnumber
- - Numeric inputdecimal
- - Decimal number with formattingcurrency
- - Currency input with formattingpercentage
- - Percentage inputdate
- - Date pickerdatetime
- - Date and time pickerboolean
- - Checkboxselect
- - Dropdown selectionmultiselect
- - Multiple selectionemail
- - Email input with validationurl
- - URL input with validationtel
- - Telephone number input
- required - Field must have a valuemin
- / max - Numeric range validationminLength
- / maxLength - String length validationpattern
- - Regular expression validationemail
- - Email format validationurl
- - URL format validationcustom
- - Custom validation functions
The component uses CSS custom properties for theming:
`css`
:root {
--jupiter-primary-color: #1976d2;
--jupiter-background: #ffffff;
--jupiter-text-primary: #333333;
--jupiter-border-color: #dddddd;
--jupiter-error-color: #d32f2f;
/ ... more variables /
}
| Property | Type | Description |
|----------|------|-------------|
| schema | XBRLFormSchema | The form schema definition |xbrlInput
| | XBRLFormInput | XBRL taxonomy data for automatic schema generation |config
| | ComponentConfig | Configuration options |initialData
| | FormData | Initial form data |disabled
| | boolean | Disable the entire form |readonly
| | boolean | Make form read-only |periodStartDate
| | string | Start date for reporting period (default: '2026-01-01') |periodEndDate
| | string | End date for reporting period (default: '2026-12-31') |language
| | string | ISO language code for XBRL labels (default: 'en', supports 'nl', 'de', etc.) |dynaformsFacts
| | SubmissionData | External draft facts data for restoration |dynaformsMetadata
| | DraftMetadata | External draft metadata for restoration |mode
| | 'input' \| 'admin' | Form mode: 'input' for data entry, 'admin' for role configuration |display
| | 'accordion' \| 'sidePanel' | Layout mode: accordion or side panel with role list |
| Method | Returns | Description |
|--------|---------|-------------|
| getData() | FormData | Get current form data |setData(data)
| | void | Set form data |validate()
| | boolean | Validate form and return result |reset()
| | void | Reset form to initial state |getState()
| | FormState | Get complete form state |
| Event | Detail | Description |
|-------|--------|-------------|
| field-change | {fieldId, conceptId, columnId, value, oldValue} | Field value changed |section-expand
| | {sectionId, expanded} | Section expanded/collapsed |concept-expand
| | {conceptId, expanded} | Concept expanded/collapsed |column-add
| | {column} | Column added |column-remove
| | {columnId, sectionId} | Column removed |form-submit
| | {data, submissionData, valid, errors} | Form submitted |form-save-draft
| | {draftData, metadata, saved, dynaformsFacts, dynaformsMetadata} | Draft saved |form-draft-loaded
| | {draft, compatible, warnings, source} | Draft loaded from storage |roles-filter-changed
| | {selectedRoleIds, totalRoles, visibleRoles, periodPreferences} | Role filter applied |form-reset
| | {} | Form reset |
`bashInstall dependencies
npm install
🤝 Contributing
1. Fork the repository
2. Create your feature branch (
git checkout -b feature/amazing-feature)
3. Commit your changes (git commit -m 'Add some amazing feature')
4. Push to the branch (git push origin feature/amazing-feature`)This project is licensed under the MIT License - see the LICENSE file for details.