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

@superleapai/flow-ui

v2.3.5

Published

A reusable design system for building multi-step forms with comprehensive UI components. Single file, clean globals, SDK included. Only FlowUI and SuperLeap exposed.

Downloads

1,354

Readme

@superleapai/flow-ui

A comprehensive, reusable design system for building multi-step forms and UI components with vanilla JavaScript and Tailwind CSS.

✨ Clean Architecture: Only FlowUI and SuperLeap are exposed to global scope. All components are internal.

📦 Installation

npm install @superleapai/flow-ui

🚀 Quick Start

Browser Usage (Single Script Tag)

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@superleapai/flow-ui@latest/dist/output.css">
</head>
<body>
  <div id="app"></div>
  
  <!-- Single script tag - includes SuperLeap SDK and all components -->
  <script src="https://cdn.jsdelivr.net/npm/@superleapai/flow-ui@latest/index.js"></script>
  
  <script>
    // Wait for library to be ready
    document.addEventListener('superleap-flow:ready', function() {
      // Initialize SuperLeap SDK (optional, for Record Select)
      SuperLeap.init({
        // apiKey: 'YOUR_API_KEY'
      });
      
      // Initialize state
      FlowUI.initState({ name: '', email: '' });
      
      // Create UI
      const app = document.getElementById('app');
      const screen = FlowUI.createScreen('Welcome', 'Please enter your details');
      const grid = FlowUI.createGrid();
      
      grid.appendChild(FlowUI.createInput({
        label: 'Name',
        fieldId: 'name',
        placeholder: 'Enter your name',
        required: true
      }));
      
      grid.appendChild(FlowUI.createInput({
        label: 'Email',
        fieldId: 'email',
        type: 'email',
        required: true
      }));
      
      const submitBtn = FlowUI.createButton({
        variant: 'primary',
        text: 'Submit',
        onClick: () => {
          const data = FlowUI.getState();
          console.log(data);
          FlowUI.showToast('Form submitted!', 'success');
        }
      });
      
      screen.appendChild(grid);
      screen.appendChild(submitBtn);
      app.appendChild(screen);
    });
  </script>
</body>
</html>

🔌 CRM Embedded Usage (Inside iframes)

When your flow is embedded in the SuperLeap CRM as an iframe, use SuperLeap.connect() to establish a secure connection. This automatically provides credentials and context without requiring hardcoded API keys.

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@superleapai/flow-ui@latest/dist/output.css">
</head>
<body>
  <div id="app"></div>

  <script src="https://cdn.jsdelivr.net/npm/@superleapai/flow-ui@latest/index.js"></script>

  <script>
    document.addEventListener('superleap-flow:ready', async function() {
      try {
        // Connect to CRM - SDK is auto-initialized with credentials
        // flowId must match the custom_id of your iframe component in the CRM
        const { context, config } = await SuperLeap.connect({
          flowId: 'my-onboarding-flow' // Use the custom_id from your iframe component
        });

        // Access CRM context (orgId, userId, recordId, etc.)
        console.log('Organization:', context.orgId);
        console.log('Current User:', context.userId);
        console.log('Record ID:', context.recordId); // if in record context

        // Initialize your form state
        FlowUI.initState({
          name: '',
          email: '',
          // Pre-fill with context data if needed
          accountId: context.recordId
        });

        // Build your UI
        const app = document.getElementById('app');
        const screen = FlowUI.createScreen('Onboarding', 'Complete your profile');
        const grid = FlowUI.createGrid();

        grid.appendChild(FlowUI.createInput({
          label: 'Name',
          fieldId: 'name',
          required: true
        }));

        grid.appendChild(FlowUI.createInput({
          label: 'Email',
          fieldId: 'email',
          type: 'email',
          required: true
        }));

        const submitBtn = FlowUI.createButton({
          variant: 'primary',
          text: 'Submit',
          onClick: async () => {
            const data = FlowUI.getState();

            // Show loading in CRM
            SuperLeap.setLoading(true);

            try {
              // Your business logic here
              const sdk = SuperLeap.getSdk();
              await sdk.records.create('contacts', data);

              // Show success notification in CRM
              SuperLeap.toast('Profile created successfully!', 'success');

              // Close the form/modal
              SuperLeap.closeForm();
            } catch (error) {
              SuperLeap.toast('Failed to create profile', 'error');
            } finally {
              SuperLeap.setLoading(false);
            }
          }
        });

        screen.appendChild(grid);
        screen.appendChild(submitBtn);
        app.appendChild(screen);

      } catch (error) {
        console.error('Failed to connect to CRM:', error);
      }
    });
  </script>
</body>
</html>

CRM Bridge API

Connect to CRM:

const { context, config } = await SuperLeap.connect({
  flowId: 'my-flow',         // Required: the custom_id of your iframe component in CRM
  crmOrigin: 'https://...',  // Optional: validate CRM origin
  autoInit: true,            // Optional: auto-initialize SDK (default: true)
  timeout: 5000              // Optional: connection timeout in ms (default: 5000)
});

Access CRM Context:

const context = SuperLeap.getContext();
// {
//   orgId: string,
//   userId: string,
//   recordId?: string,        // Present if iframe is in a record view
//   objectSlug?: string,      // e.g., 'accounts', 'contacts'
//   formId?: string,
//   componentId?: string
// }

CRM Actions:

// Show/hide loading overlay in CRM
SuperLeap.setLoading(true);
SuperLeap.setLoading(false);

// Close the current form/modal in CRM
SuperLeap.closeForm();

// Show toast notification in CRM
SuperLeap.toast('Success!', 'success', 3000);
SuperLeap.toast('Error occurred', 'error');
SuperLeap.toast('Warning message', 'warning');
SuperLeap.toast('Info message', 'info');

// Navigate to a path in CRM
SuperLeap.navigate('/records/contacts/123');

Custom Events (CRM ↔ Iframe Communication):

// Send custom event to CRM
SuperLeap.send('form-submitted', { values: {...} });
SuperLeap.send('validation-failed', { errors: [...] });

// Listen for custom events from CRM
const unsubscribe = SuperLeap.on('prefill-data', (data) => {
  FlowUI.setState(data);
});

// Remove listener
SuperLeap.off('prefill-data', callbackFunction);

// Or use unsubscribe function
unsubscribe();

Check Connection Status:

if (SuperLeap.isConnected()) {
  // Connected to CRM
}

Disconnect:

SuperLeap.disconnect();

React Native WebView Support

The bridge automatically detects and supports React Native WebView environments. No configuration changes needed - use the same API as shown above.

🎯 What's Exposed

// Only 2 objects in global scope
window.FlowUI    // ✅ UI Framework with all components
window.SuperLeap // ✅ SDK Client for API integration

// All components are internal (not global)
window.Toast     // ❌ Not available
window.Button    // ❌ Not available
window.Alert     // ❌ Not available
// ... 20+ components kept internal

✨ Features

  • 🎨 Complete Design System - Pre-built components matching modern UI standards
  • 📝 Form Components - Input, Select, Textarea, Checkbox, Radio, and more
  • 📅 Date & Time - Date picker, time picker, and date-time picker
  • 💰 Specialized Inputs - Currency, phone number, file upload
  • 🔄 State Management - Built-in reactive state management
  • 🎯 Multi-step Forms - Stepper component for wizard-style forms
  • 📊 Data Tables - Sortable, searchable tables
  • 🎨 Customizable - Tailwind CSS for easy styling
  • 📱 Responsive - Mobile-first design
  • Clean Architecture - Only FlowUI and SuperLeap exposed globally
  • 📦 Single Script - One file includes everything (SDK + components)
  • 🚀 Zero Dependencies - Pure vanilla JavaScript

📚 API Reference

FlowUI API

State Management

// Initialize state
FlowUI.initState(initialState, onChangeCallback)

// Get entire state
const state = FlowUI.getState()

// Update state
FlowUI.setState({ name: 'John' })

// Get single value
const name = FlowUI.get('name')

// Set single value
FlowUI.set('name', 'John')

Layout Components

// Create screen wrapper
FlowUI.createScreen(title, description)

// Create form grid
FlowUI.createGrid()

// Create field wrapper
FlowUI.createFieldWrapper(label, required, helpText)

Form Components

// Text input
FlowUI.createInput({
  label: 'Name',
  fieldId: 'name',
  placeholder: 'Enter name',
  required: true,
  type: 'text', // text, email, password, number, tel, url
  variant: 'default', // default, error, warning, success, borderless, inline
  inputSize: 'default', // default, large, small
  disabled: false,
  helpText: 'Your full name'
})

// Textarea
FlowUI.createTextarea({
  label: 'Comments',
  fieldId: 'comments',
  placeholder: 'Enter comments',
  required: false
})

// Select dropdown
FlowUI.createSelect({
  label: 'Role',
  fieldId: 'role',
  options: [
    { value: 'admin', label: 'Administrator' },
    { value: 'user', label: 'User' }
  ],
  required: true,
  onChange: (value) => console.log(value)
})

// Multi-select
FlowUI.createMultiSelect({
  label: 'Tags',
  fieldId: 'tags',
  options: [...],
  placeholder: 'Select tags',
  type: 'default', // default (count) or tags (show tags)
  onChange: (values) => console.log(values)
})

// Radio group
FlowUI.createRadioGroup({
  label: 'Plan',
  fieldId: 'plan',
  options: [...],
  onChange: (value) => console.log(value)
})

// Checkbox
FlowUI.createCheckbox({
  label: 'I accept terms',
  fieldId: 'acceptTerms',
  size: 'default', // default, small, large
  align: 'left', // left, right
  onChange: (checked) => console.log(checked)
})

// Time picker
FlowUI.createTimePicker({
  label: 'Time',
  fieldId: 'time',
  use24Hour: false, // false = 12-hour AM/PM, true = 24-hour
  onChange: (value) => console.log(value)
})

// Date-time picker
FlowUI.createDateTimePicker({
  label: 'Date & Time',
  fieldId: 'datetime',
  granularity: 'minute', // day, hour, minute, second
  hourCycle: 12, // 12 or 24
  onChange: (date) => console.log(date)
})

// Currency input
FlowUI.createCurrency({
  label: 'Amount',
  fieldId: 'amount',
  column: {
    properties: {
      currency: { currency: 'USD' }
    }
  },
  onChange: (value) => console.log(value)
})

// Phone input
FlowUI.createPhoneInput({
  label: 'Phone',
  fieldId: 'phone',
  defaultCountryCode: 'IN',
  onChange: (fullValue, country) => console.log(fullValue, country)
})

// File upload
FlowUI.createFileUpload({
  label: 'Attachments',
  fieldId: 'files',
  multiple: true,
  accept: '.pdf,.jpg,.png'
})

// Record select (requires SuperLeap SDK)
FlowUI.createRecordSelect({
  label: 'Account',
  fieldId: 'account',
  objectSlug: 'account',
  placeholder: 'Select account',
  onChange: (value, record) => console.log(value, record)
})

UI Components

// Button
FlowUI.createButton({
  variant: 'primary', // primary, outline, ghost, link, etc.
  size: 'default', // small, default, large
  text: 'Submit',
  icon: '<svg>...</svg>',
  iconPosition: 'left', // left, right
  loading: false,
  disabled: false,
  onClick: (event) => console.log('Clicked')
})

// Toast notification
FlowUI.showToast(message, type, duration)
// type: success, error, warning, info, loading
// duration: milliseconds (0 for persistent)

// Example:
FlowUI.showToast('Success!', 'success', 3000)
const loadingToast = FlowUI.showToast('Loading...', 'loading', 0)
loadingToast.close() // Close manually

Table Components

// Data table
FlowUI.createDataTable({
  columns: [
    { key: 'name', label: 'Name' },
    { key: 'email', label: 'Email' }
  ],
  data: [...],
  fieldId: 'selectedRow',
  idKey: 'id',
  onSelect: (row) => console.log(row)
})

// Search input
FlowUI.createSearchInput({
  placeholder: 'Search...',
  fieldId: 'search',
  onSearch: (query) => console.log(query)
})

Stepper

FlowUI.renderStepper(
  container,
  [
    { id: 'step1', label: 'Step 1' },
    { id: 'step2', label: 'Step 2' },
    { id: 'step3', label: 'Step 3' }
  ],
  'step1' // current step
)

Summary

FlowUI.createSummaryRow(label, value)

Alerts

FlowUI.showToast(message, type)
// type: error, info, success

Advanced: Direct Component Access

// Get internal component reference (advanced use)
const Toast = FlowUI._getComponent('Toast')
const Button = FlowUI._getComponent('Button')

// Use directly
Toast.success('Hello!')
Button.create({ text: 'Click me' })

SuperLeap API

// Initialize SDK
SuperLeap.init({
  apiKey: 'YOUR_API_KEY',
  baseUrl: 'https://app.superleap.com/api/v1'
})

// Get SDK instance
const sdk = SuperLeap.getSdk()

// Check availability
if (SuperLeap.isAvailable()) {
  // SDK is ready
}

// Get default config
const config = SuperLeap.getDefaultConfig()

🎨 Component Variants

Input/Select Variants

  • default - Standard appearance
  • error - Red border for errors
  • warning - Orange border for warnings
  • success - Green border for success
  • borderless - No border
  • inline - Inline style

Button Variants

  • primary - Primary action button
  • outline - Outlined button
  • ghost - Ghost/transparent button
  • link - Link-styled button
  • primaryDestructive - Destructive primary
  • outlineDestructive - Destructive outline
  • ghostDestructive - Destructive ghost

Sizes

  • small - Small size
  • default - Default size
  • large - Large size

📖 Examples

See example.html for a comprehensive demonstration of all components.

🔧 TypeScript Support

Full TypeScript definitions included:

import { FlowUI, SuperLeap, SuperLeapConfig } from '@superleapai/flow-ui';

const config: SuperLeapConfig = {
  apiKey: 'YOUR_KEY'
};

SuperLeap.init(config);
FlowUI.initState({ name: '' });

📄 License

MIT

🤝 Contributing

See CONTRIBUTING.md for contribution guidelines.

📝 Changelog

See CHANGELOG.md for version history.