# @iblai/web-containers

A comprehensive React component library for IBL AI applications, built with shadcn/ui, Radix UI, and Tailwind CSS.

## Installation

```bash
pnpm add @iblai/web-containers
```

## Package Structure

The package is organized into multiple entry points:

- **`@iblai/web-containers`** - Framework-agnostic components (works with any React app)
- **`@iblai/web-containers/next`** - Next.js-specific components (requires Next.js)
- **`@iblai/web-containers/sso`** - SSO utilities for handling authentication callbacks

### Import Examples

```tsx
// Framework-agnostic components (any React app)
import { Button, Card, LoginButton, SignupButton } from '@iblai/web-containers';

// Next.js-specific components (requires Next.js)
import { SsoLogin, ErrorPage, UserProfileDropdown } from '@iblai/web-containers/next';

// SSO utilities for custom implementations
import { handleSsoCallback, parseSsoData } from '@iblai/web-containers/sso';
```

## Overview

The web-containers package provides:
- **Pre-built UI components** following IBL AI design system
- **Chat interfaces** for AI mentor interactions
- **Authentication components** (LoginButton, SignupButton)
- **Profile management** components
- **Subscription** and billing components
- **Form components** with validation
- **Notification** system
- **shadcn/ui** components with IBL AI theming

## Getting Started

### Basic Setup

```tsx
import { Button, Card, Input } from '@iblai/web-containers';

function MyComponent() {
  return (
    <Card>
      <h2>Hello World</h2>
      <Input placeholder="Enter text..." />
      <Button>Submit</Button>
    </Card>
  );
}
```

### With Theming

```tsx
import { ThemeProvider } from 'next-themes';

function App() {
  return (
    <ThemeProvider attribute="class" defaultTheme="light">
      <YourApp />
    </ThemeProvider>
  );
}
```

## Authentication Components

### Login Button

Redirect users to the auth SPA for login:

```tsx
import { LoginButton } from '@iblai/web-containers';

function NavBar() {
  return (
    <nav>
      <LoginButton
        authUrl="https://auth.example.com"
        appName="mentor"
        platformKey="my-tenant"
        label="Log In"
        variant="default"
      />
    </nav>
  );
}
```

### Signup Button

Redirect users to signup/join flow:

```tsx
import { SignupButton } from '@iblai/web-containers';

function LandingPage() {
  return (
    <div>
      <h1>Join IBL AI</h1>
      <SignupButton
        authUrl="https://auth.example.com"
        tenantKey="my-tenant"
        label="Sign Up for Free"
        variant="outline"
      />
    </div>
  );
}
```

### Combined Auth Buttons

```tsx
import { LoginButton, SignupButton } from '@iblai/web-containers';
import { isLoggedIn } from '@iblai/web-utils';

function Header() {
  if (isLoggedIn()) {
    return <UserMenu />;
  }

  return (
    <div className="flex gap-x-2">
      <LoginButton
        authUrl="https://auth.example.com"
        appName="mentor"
        label="Log In"
      />
      <SignupButton
        authUrl="https://auth.example.com"
        label="Sign Up"
        variant="outline"
      />
    </div>
  );
}
```

### SSO Login Component (Next.js)

> **Note:** This component requires Next.js. Import from `@iblai/web-containers/next`.

Handle SSO callbacks in your Next.js app:

```tsx
// app/sso-login/page.tsx
import { SsoLogin } from '@iblai/web-containers/next';

const LOCAL_STORAGE_KEYS = {
  CURRENT_TENANT: 'IBL_CURRENT_TENANT',
  USER_DATA: 'IBL_USER_DATA',
  TENANTS: 'IBL_TENANTS',
};

export default function SsoLoginPage() {
  return (
    <SsoLogin
      localStorageKeys={LOCAL_STORAGE_KEYS}
      defaultRedirectPath="/"
      onLoginSuccess={(data) => {
        console.log('Login successful:', data);
      }}
    />
  );
}
```

### SSO Utilities (Framework-agnostic)

For non-Next.js React applications, use the SSO utilities directly:

```tsx
import {
  handleSsoCallback,
  parseSsoData,
  DEFAULT_SSO_STORAGE_KEYS,
} from '@iblai/web-containers/sso';

// In your SSO callback handler
function handleCallback() {
  const urlParams = new URLSearchParams(window.location.search);
  const encodedData = urlParams.get('data');

  if (encodedData) {
    const result = handleSsoCallback({
      encodedData,
      localStorageKeys: DEFAULT_SSO_STORAGE_KEYS,
      redirectPathKey: 'redirect-to',
      defaultRedirectPath: '/',
    });

    if (result.success) {
      window.location.href = result.redirectPath;
    }
  }
}
```

## UI Components

### Buttons

```tsx
import { Button } from '@iblai/web-containers';

<Button variant="default">Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button disabled>Disabled</Button>
```

### Cards

```tsx
import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
} from '@iblai/web-containers';

<Card>
  <CardHeader>
    <CardTitle>Card Title</CardTitle>
    <CardDescription>Card description goes here</CardDescription>
  </CardHeader>
  <CardContent>
    <p>Card content</p>
  </CardContent>
  <CardFooter>
    <Button>Action</Button>
  </CardFooter>
</Card>
```

### Forms

```tsx
import {
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl,
  FormMessage,
  Input,
  Button,
} from '@iblai/web-containers';
import { useForm } from '@tanstack/react-form';

function LoginForm() {
  const form = useForm({
    defaultValues: {
      email: '',
      password: '',
    },
    onSubmit: async ({ value }) => {
      await login(value);
    },
  });

  return (
    <form onSubmit={form.handleSubmit}>
      <FormField name="email">
        {(field) => (
          <FormItem>
            <FormLabel>Email</FormLabel>
            <FormControl>
              <Input
                type="email"
                value={field.state.value}
                onChange={(e) => field.handleChange(e.target.value)}
              />
            </FormControl>
            <FormMessage />
          </FormItem>
        )}
      </FormField>
      <Button type="submit">Sign In</Button>
    </form>
  );
}
```

### Dialogs

```tsx
import {
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogDescription,
  DialogFooter,
  Button,
} from '@iblai/web-containers';

<Dialog>
  <DialogTrigger asChild>
    <Button>Open Dialog</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Are you sure?</DialogTitle>
      <DialogDescription>
        This action cannot be undone.
      </DialogDescription>
    </DialogHeader>
    <DialogFooter>
      <Button variant="outline">Cancel</Button>
      <Button>Confirm</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>
```

### Dropdowns

```tsx
import {
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuSeparator,
  Button,
} from '@iblai/web-containers';

<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="outline">Open Menu</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuItem>Profile</DropdownMenuItem>
    <DropdownMenuItem>Settings</DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem>Logout</DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>
```

## Chat Components

### Chat Container

Full-featured chat interface for AI mentors:

```tsx
import { ChatContainer } from '@iblai/web-containers';

function MentorChat() {
  return (
    <ChatContainer
      mentorId="mentor-123"
      tenantKey="my-tenant"
      wsUrl="wss://api.example.com/chat"
      wsToken="your-token"
      onSessionCreate={(sessionId) => {
        console.log('Session created:', sessionId);
      }}
    />
  );
}
```

### Chat Message

Display individual chat messages:

```tsx
import { ChatMessage } from '@iblai/web-containers';

<ChatMessage
  message={{
    id: '1',
    content: 'Hello! How can I help you?',
    role: 'assistant',
    timestamp: new Date(),
  }}
  isStreaming={false}
/>
```

### Chat Input

Input field for sending messages:

```tsx
import { ChatInput } from '@iblai/web-containers';

<ChatInput
  onSend={(message) => {
    console.log('Sending:', message);
  }}
  placeholder="Type your message..."
  disabled={false}
/>
```

## Profile Components

### User Profile Dropdown (Next.js)

> **Note:** This component requires Next.js. Import from `@iblai/web-containers/next`.

```tsx
import { UserProfileDropdown } from '@iblai/web-containers/next';

<UserProfileDropdown
  user={{
    name: 'John Doe',
    email: 'john@example.com',
    avatar: 'https://example.com/avatar.jpg',
  }}
  onLogout={() => handleLogout()}
  onProfileClick={() => navigate('/profile')}
/>
```

### Profile Settings

```tsx
import { ProfileSettings } from '@iblai/web-containers';

<ProfileSettings
  user={{
    name: 'John Doe',
    email: 'john@example.com',
    bio: 'Software developer',
  }}
  onUpdate={(data) => {
    console.log('Updated:', data);
  }}
/>
```

## Notification Components

### Toast Notifications

```tsx
import { useToast } from '@iblai/web-containers';

function MyComponent() {
  const { toast } = useToast();

  const showNotification = () => {
    toast({
      title: 'Success',
      description: 'Your changes have been saved.',
      variant: 'default',
    });
  };

  return <Button onClick={showNotification}>Save</Button>;
}
```

### Notification Center

```tsx
import { NotificationCenter } from '@iblai/web-containers';

<NotificationCenter
  notifications={[
    {
      id: '1',
      title: 'New message',
      description: 'You have a new message from AI Mentor',
      timestamp: new Date(),
      read: false,
    },
  ]}
  onMarkAsRead={(id) => console.log('Mark as read:', id)}
  onClearAll={() => console.log('Clear all')}
/>
```

## Subscription Components

### Subscription Badge

```tsx
import { SubscriptionBadge } from '@iblai/web-containers';

<SubscriptionBadge
  plan="pro"
  status="active"
/>
```

### Pricing Cards

```tsx
import { PricingCard } from '@iblai/web-containers';

<PricingCard
  title="Pro Plan"
  price="$29"
  period="month"
  features={[
    'Unlimited AI chats',
    'Priority support',
    'Advanced analytics',
  ]}
  onSubscribe={() => handleSubscribe('pro')}
/>
```

## Advanced Components

### Date Picker

```tsx
import { Calendar } from '@iblai/web-containers';
import { useState } from 'react';

function DateSelector() {
  const [date, setDate] = useState<Date | undefined>(new Date());

  return (
    <Calendar
      mode="single"
      selected={date}
      onSelect={setDate}
    />
  );
}
```

### Select

```tsx
import {
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem,
} from '@iblai/web-containers';

<Select onValueChange={(value) => console.log(value)}>
  <SelectTrigger>
    <SelectValue placeholder="Select option" />
  </SelectTrigger>
  <SelectContent>
    <SelectItem value="option1">Option 1</SelectItem>
    <SelectItem value="option2">Option 2</SelectItem>
    <SelectItem value="option3">Option 3</SelectItem>
  </SelectContent>
</Select>
```

### Tabs

```tsx
import {
  Tabs,
  TabsList,
  TabsTrigger,
  TabsContent,
} from '@iblai/web-containers';

<Tabs defaultValue="tab1">
  <TabsList>
    <TabsTrigger value="tab1">Tab 1</TabsTrigger>
    <TabsTrigger value="tab2">Tab 2</TabsTrigger>
  </TabsList>
  <TabsContent value="tab1">Content 1</TabsContent>
  <TabsContent value="tab2">Content 2</TabsContent>
</Tabs>
```

### Accordion

```tsx
import {
  Accordion,
  AccordionItem,
  AccordionTrigger,
  AccordionContent,
} from '@iblai/web-containers';

<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger>Question 1</AccordionTrigger>
    <AccordionContent>Answer 1</AccordionContent>
  </AccordionItem>
  <AccordionItem value="item-2">
    <AccordionTrigger>Question 2</AccordionTrigger>
    <AccordionContent>Answer 2</AccordionContent>
  </AccordionItem>
</Accordion>
```

## Styling

All components use Tailwind CSS and support custom className props:

```tsx
<Button className="bg-blue-500 hover:bg-blue-600">
  Custom Styled Button
</Button>

<Card className="shadow-lg border-2">
  Custom Card
</Card>
```

### Theme Customization

Customize the theme in your `tailwind.config.js`:

```js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          DEFAULT: 'hsl(var(--primary))',
          foreground: 'hsl(var(--primary-foreground))',
        },
      },
    },
  },
}
```

## TypeScript Support

All components are fully typed:

```tsx
import type {
  ButtonProps,
  CardProps,
  ChatMessageProps,
  UserProfileProps,
} from '@iblai/web-containers';

const buttonProps: ButtonProps = {
  variant: 'default',
  size: 'md',
  disabled: false,
};
```

## Accessibility

All components follow WAI-ARIA guidelines and support:
- Keyboard navigation
- Screen reader support
- Focus management
- ARIA labels and descriptions

## Contributing

We welcome contributions! Please read our [contributing guidelines](CONTRIBUTING.md).

## Development

### Building

```bash
pnpm build
```

### Testing

```bash
pnpm test
```

### Storybook

```bash
pnpm storybook
```

## License

ISC
