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
- 🏗️ 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
npm install @jupiter/dynamic-forms
// 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 { }
// your-component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-form',
template: `
<jupiter-dynamic-form
[attr.xbrlInput]="xbrlData"
[attr.config]="formConfig"
(formSubmit)="onFormSubmit($event)"
(formChange)="onFormChange($event)">
</jupiter-dynamic-form>
`
})
export class FormComponent {
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
npm install @jupiter/dynamic-forms
<!DOCTYPE html>
<html>
<head>
<script type="module">
import '@jupiter/dynamic-forms';
</script>
</head>
<body>
<jupiter-dynamic-form id="my-form"></jupiter-dynamic-form>
<script>
const form = document.getElementById('my-form');
form.schema = {
version: '1.0',
formId: 'example',
title: 'My XBRL Form',
sections: [
// Your schema here
]
};
</script>
</body>
</html>
// app.module.ts
import { JupiterDynamicFormModule } from '@jupiter/dynamic-forms/angular';
@NgModule({
imports: [JupiterDynamicFormModule],
// ...
})
export class AppModule { }
<!-- component.html -->
<jupiter-dynamic-form-ng
[schema]="formSchema"
[config]="formConfig"
(formSubmit)="onFormSubmit($event)"
></jupiter-dynamic-form-ng>
import { JupiterDynamicForm } from '@jupiter/dynamic-forms/react';
function MyComponent() {
const handleSubmit = (data) => {
console.log('Form data:', data);
};
return (
<JupiterDynamicForm
schema={formSchema}
config={formConfig}
onFormSubmit={handleSubmit}
/>
);
}
<template>
<JupiterDynamicForm
:schema="formSchema"
:config="formConfig"
@form-submit="handleSubmit"
/>
</template>
<script>
import { JupiterDynamicForm } from '@jupiter/dynamic-forms/vue';
export default {
components: {
JupiterDynamicForm
},
// ...
}
</script>
The form is driven by a JSON schema that defines sections, concepts, and fields:
{
"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...
]
}
]
}
]
}
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 input -
textarea
- Multi-line text input -
number
- Numeric input -
decimal
- Decimal number with formatting -
currency
- Currency input with formatting -
percentage
- Percentage input -
date
- Date picker -
datetime
- Date and time picker -
boolean
- Checkbox -
select
- Dropdown selection -
multiselect
- Multiple selection -
email
- Email input with validation -
url
- URL input with validation -
tel
- Telephone number input
-
required
- Field must have a value -
min
/max
- Numeric range validation -
minLength
/maxLength
- String length validation -
pattern
- Regular expression validation -
email
- Email format validation -
url
- URL format validation -
custom
- Custom validation functions
The component uses CSS custom properties for theming:
: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 |
config |
ComponentConfig |
Configuration options |
initialData |
FormData |
Initial form data |
disabled |
boolean |
Disable the entire form |
readonly |
boolean |
Make form read-only |
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} |
Column removed |
form-submit |
{data, valid, errors} |
Form submitted |
form-reset |
{} |
Form reset |
# Install dependencies
npm install
# Start development server
npm run dev
# Build the library
npm run build
# Run tests
npm test
# Lint code
npm run lint
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.