@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
Maintainers
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 manuallyTable 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, successAdvanced: 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 appearanceerror- Red border for errorswarning- Orange border for warningssuccess- Green border for successborderless- No borderinline- Inline style
Button Variants
primary- Primary action buttonoutline- Outlined buttonghost- Ghost/transparent buttonlink- Link-styled buttonprimaryDestructive- Destructive primaryoutlineDestructive- Destructive outlineghostDestructive- Destructive ghost
Sizes
small- Small sizedefault- Default sizelarge- 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.
