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

```bash
npm install @superleapai/flow-ui
```

## 🚀 Quick Start

### Browser Usage (Single Script Tag)

```html
<!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.

```html
<!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:**
```javascript
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:**
```javascript
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:**
```javascript
// 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):**
```javascript
// 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:**
```javascript
if (SuperLeap.isConnected()) {
  // Connected to CRM
}
```

**Disconnect:**
```javascript
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

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

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

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

// Create form grid
FlowUI.createGrid()

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

#### Form Components

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

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

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

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

#### Summary

```javascript
FlowUI.createSummaryRow(label, value)
```

#### Alerts

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

#### Advanced: Direct Component Access

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

```javascript
// 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:

```typescript
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.
