npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jupiter-dynamic-forms

v1.16.3

Published

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

Readme

Jupiter Dynamic Forms

Jupiter Dynamic Forms

Framework-agnostic dynamic form builder for XBRL entrypoints using Web Components

npm version License: MIT TypeScript

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.

✨ Key Features

  • 🎭 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

🚀 Quick Start

Installation

npm install @jupiter/dynamic-forms

Angular 18+ Integration

// 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"
      [attr.language]="language"
      [attr.periodStartDate]="periodStart"
      [attr.periodEndDate]="periodEnd"
      (formSubmit)="onFormSubmit($event)"
      (formChange)="onFormChange($event)">
    </jupiter-dynamic-form>
  `
})
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);
  }
}

📊 XBRL Data Structure

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

🚀 Features

  • 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

🔍 Smart Role Filtering (Enhanced in v1.11.0)

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
// Listen for filter changes
form.addEventListener('roles-filter-changed', (event) => {
  const { selectedRoleIds, totalRoles, visibleRoles, periodPreferences } = event.detail;
  console.log(`Showing ${visibleRoles} of ${totalRoles} roles`);
  console.log('Period preferences:', periodPreferences);
});

💾 Draft Persistence (New in v1.11.0)

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
// 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;

📦 Installation

npm install @jupiter/dynamic-forms

🎯 Quick Start

Vanilla JavaScript / HTML

<!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>

Angular

// 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>

React

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}
    />
  );
}

Vue

<template>
  <JupiterDynamicForm
    :schema="formSchema"
    :config="formConfig"
    @form-submit="handleSubmit"
  />
</template>

<script>
import { JupiterDynamicForm } from '@jupiter/dynamic-forms/vue';

export default {
  components: {
    JupiterDynamicForm
  },
  // ...
}
</script>

📋 Schema Structure

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...
          ]
        }
      ]
    }
  ]
}

🎛️ Configuration Options

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
};

🔧 Field Types

  • 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

✅ Validation Rules

  • 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

🎨 Styling

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 */
}

📚 API Reference

Properties

| 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 |

Methods

| 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 |

Events

| 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 |

🏗️ Development

# 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

🤝 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)
  5. Open a Pull Request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🔗 Links