@thisispamela/react 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import React, { createContext, useContext, useState, useEffect } from 'react';
1
+ import React, { createContext, useMemo, useContext, useState, useRef, useEffect } from 'react';
2
2
  import { PamelaClient } from '@thisispamela/sdk';
3
3
 
4
4
  function styleInject(css, ref) {
@@ -28,15 +28,15 @@ function styleInject(css, ref) {
28
28
  }
29
29
  }
30
30
 
31
- var css_248z = "/**\n * Pamela B2B React Component Library - Default Styles\n * \n * These styles match the Pamela B2C design system:\n * - Colors: Orange (#FA931C), Beige (#e7ab84), Blue (#4b4bea)\n * - Fonts: Poppins, Inter\n * - Dark mode support\n */\n\n/* Pulse animation for status indicators */\n@keyframes pamela-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n\n/* Call Button - matches your gradient style */\n.pamela-call-button {\n font-family: 'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;\n background: linear-gradient(to right, #FA931C, #fd8b74);\n color: white;\n border: none;\n border-radius: 0.5rem;\n font-weight: 600;\n transition: opacity 0.2s;\n box-shadow: 0 2px 4px rgba(250, 147, 28, 0.2);\n}\n\n.pamela-call-button:hover:not(:disabled) {\n opacity: 0.9;\n}\n\n.pamela-call-button:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n background: linear-gradient(to right, #ccc, #aaa);\n}\n\n/* Call Status - matches your card style */\n.pamela-call-status {\n font-family: 'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n}\n\n/* Transcript Viewer - matches your message bubble style */\n.pamela-transcript-viewer {\n font-family: 'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n}\n\n/* Dark mode support */\n@media (prefers-color-scheme: dark) {\n .pamela-call-status {\n color: #ffffff;\n }\n \n .pamela-transcript-viewer {\n color: #ffffff;\n }\n}\n\n";
31
+ var css_248z = "/**\n * Pamela Enterprise React Component Library - Default Styles\n *\n * These styles align with the Pamela app design schema.\n * If the host app already defines these CSS variables, its values will win.\n */\n\n:root {\n --accent: #F27A1A;\n --accent-2: #F06C4F;\n --accent-3: #F3A84C;\n --accent-gradient: linear-gradient(90deg, var(--accent), var(--accent-2));\n --bg-gradient: linear-gradient(135deg, #F5F0E8 0%, #F3EEE8 45%, #EFE8DF 100%);\n --bg-glow: radial-gradient(1200px circle at 10% 20%, rgba(250, 147, 28, 0.1), transparent 58%),\n radial-gradient(900px circle at 80% 10%, rgba(253, 139, 116, 0.1), transparent 62%),\n radial-gradient(800px circle at 70% 80%, rgba(251, 193, 107, 0.08), transparent 60%);\n --surface: rgba(255, 255, 255, 0.5);\n --surface-strong: rgba(255, 255, 255, 0.78);\n --surface-border: rgba(231, 171, 132, 0.24);\n --surface-border-strong: rgba(255, 255, 255, 0.75);\n --surface-highlight: rgba(255, 255, 255, 0.68);\n --surface-liquid: linear-gradient(135deg, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.38));\n --surface-liquid-strong: linear-gradient(140deg, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.5));\n --liquid-highlight: linear-gradient(120deg, rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0) 45%);\n --liquid-shadow: 0 18px 42px rgba(28, 25, 17, 0.14);\n --liquid-glow: 0 0 32px rgba(250, 147, 28, 0.2);\n --shadow-soft: 0 12px 26px rgba(28, 25, 17, 0.1);\n --shadow-hover: 0 24px 44px rgba(28, 25, 17, 0.18);\n --shadow-inset: inset 0 1px 0 rgba(255, 255, 255, 0.7);\n --cta-bg: linear-gradient(120deg, rgba(255, 255, 255, 0.7), rgba(250, 147, 28, 0.32));\n --cta-border: 1px solid rgba(250, 147, 28, 0.4);\n --cta-glow: 0 0 18px rgba(250, 147, 28, 0.28);\n --cta-glow-hover: 0 0 22px rgba(250, 147, 28, 0.36);\n --danger-bg: linear-gradient(120deg, rgba(255, 255, 255, 0.6), rgba(239, 68, 68, 0.3));\n --danger-border: 1px solid rgba(239, 68, 68, 0.45);\n --danger-glow: 0 0 16px rgba(239, 68, 68, 0.3);\n --danger-glow-hover: 0 0 20px rgba(239, 68, 68, 0.4);\n --badge-bg: linear-gradient(120deg, rgba(255, 255, 255, 0.7), rgba(250, 147, 28, 0.28));\n --badge-border: 1px solid rgba(250, 147, 28, 0.4);\n --badge-glow: 0 0 14px rgba(250, 147, 28, 0.24);\n --avatar-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.6), rgba(250, 147, 28, 0.38), rgba(253, 139, 116, 0.32));\n --avatar-border: 1px solid rgba(250, 147, 28, 0.35);\n --avatar-glow: 0 0 20px rgba(250, 147, 28, 0.28);\n --glass-blur: 24px;\n --glass-blur-strong: 32px;\n --noise-opacity: 0.05;\n --focus-ring: 0 0 0 3px rgba(250, 147, 28, 0.28);\n --radius-sm: 0.5rem;\n --radius-md: 0.75rem;\n --radius-lg: 1rem;\n --radius-xl: 1.5rem;\n --text-primary: #1C1917;\n --text-secondary: rgba(28, 25, 17, 0.78);\n --text-muted: rgba(28, 25, 17, 0.55);\n --status-success: #10b981;\n --status-warning: #eab308;\n --status-muted: #d1d5db;\n --status-error: #ef4444;\n --bubble-user: #FA931C;\n --bubble-pamela: #ffffff;\n --bubble-recipient: #4b4bea;\n --bubble-border: rgba(231, 171, 132, 0.3);\n}\n\n.dark {\n --bg-gradient: linear-gradient(135deg, #171513 0%, #14110f 45%, #0f0d0b 100%);\n --bg-glow: radial-gradient(1100px circle at 20% 10%, rgba(250, 147, 28, 0.18), transparent 60%),\n radial-gradient(900px circle at 80% 20%, rgba(253, 139, 116, 0.16), transparent 60%),\n radial-gradient(700px circle at 60% 80%, rgba(251, 193, 107, 0.12), transparent 55%);\n --surface: rgba(255, 255, 255, 0.08);\n --surface-strong: rgba(255, 255, 255, 0.16);\n --surface-border: rgba(255, 255, 255, 0.18);\n --surface-border-strong: rgba(255, 255, 255, 0.36);\n --surface-highlight: rgba(255, 255, 255, 0.2);\n --surface-liquid: linear-gradient(150deg, rgba(255, 255, 255, 0.16), rgba(255, 255, 255, 0.05));\n --surface-liquid-strong: linear-gradient(150deg, rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.08));\n --liquid-highlight: linear-gradient(120deg, rgba(255, 255, 255, 0.24), rgba(255, 255, 255, 0) 45%);\n --liquid-shadow: 0 22px 48px rgba(0, 0, 0, 0.55);\n --liquid-glow: 0 0 30px rgba(250, 147, 28, 0.24);\n --shadow-soft: 0 16px 32px rgba(0, 0, 0, 0.5);\n --shadow-hover: 0 26px 44px rgba(0, 0, 0, 0.7);\n --shadow-inset: inset 0 1px 0 rgba(255, 255, 255, 0.12);\n --cta-bg: linear-gradient(120deg, rgba(255, 255, 255, 0.22), rgba(250, 147, 28, 0.34));\n --cta-border: 1px solid rgba(250, 147, 28, 0.5);\n --cta-glow: 0 0 16px rgba(250, 147, 28, 0.26);\n --cta-glow-hover: 0 0 20px rgba(250, 147, 28, 0.32);\n --danger-bg: linear-gradient(120deg, rgba(255, 255, 255, 0.18), rgba(239, 68, 68, 0.32));\n --danger-border: 1px solid rgba(248, 113, 113, 0.55);\n --danger-glow: 0 0 18px rgba(239, 68, 68, 0.32);\n --danger-glow-hover: 0 0 22px rgba(239, 68, 68, 0.4);\n --badge-bg: linear-gradient(120deg, rgba(255, 255, 255, 0.2), rgba(250, 147, 28, 0.32));\n --badge-border: 1px solid rgba(250, 147, 28, 0.5);\n --badge-glow: 0 0 14px rgba(250, 147, 28, 0.22);\n --avatar-bg: linear-gradient(135deg, rgba(255, 255, 255, 0.22), rgba(250, 147, 28, 0.26), rgba(253, 139, 116, 0.24));\n --avatar-border: 1px solid rgba(255, 255, 255, 0.18);\n --avatar-glow: 0 0 18px rgba(250, 147, 28, 0.22);\n --glass-blur: 24px;\n --glass-blur-strong: 32px;\n --noise-opacity: 0.08;\n --focus-ring: 0 0 0 3px rgba(250, 147, 28, 0.35);\n --text-primary: rgba(255, 255, 255, 0.95);\n --text-secondary: rgba(255, 255, 255, 0.72);\n --text-muted: rgba(255, 255, 255, 0.5);\n --bubble-pamela: rgba(255, 255, 255, 0.12);\n --bubble-border: rgba(255, 255, 255, 0.2);\n}\n\n/* Pulse animation for status indicators */\n@keyframes pamela-pulse {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.5;\n }\n}\n\n/* VoiceOrb animations */\n@keyframes shimmer {\n 0% {\n transform: translateX(-100%) translateY(-100%) rotate(45deg);\n }\n 100% {\n transform: translateX(100%) translateY(100%) rotate(45deg);\n }\n}\n\n@keyframes ripple {\n 0% {\n transform: scale(1);\n opacity: 0.6;\n }\n 50% {\n transform: scale(2);\n opacity: 0;\n }\n 100% {\n transform: scale(1);\n opacity: 0.6;\n }\n}\n\n@keyframes float {\n 0%, 100% {\n transform: translateY(0px);\n }\n 50% {\n transform: translateY(-10px);\n }\n}\n\n/* Call Button - matches your gradient style */\n.pamela-call-button {\n font-family: 'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;\n background: var(--accent-gradient);\n color: var(--text-primary);\n border: var(--cta-border);\n border-radius: var(--radius-md);\n font-weight: 600;\n transition: opacity 0.2s;\n box-shadow: var(--shadow-soft), var(--cta-glow);\n padding: 10px 20px;\n font-size: 16px;\n cursor: pointer;\n}\n\n.pamela-call-button--primary {\n background: var(--accent-gradient);\n}\n\n.pamela-call-button--secondary {\n background: var(--surface-liquid);\n border: 1px solid var(--surface-border-strong);\n box-shadow: var(--shadow-soft), var(--liquid-glow);\n}\n\n.pamela-call-button--danger {\n background: var(--danger-bg);\n border: var(--danger-border);\n color: #b91c1c;\n box-shadow: var(--shadow-soft), var(--danger-glow);\n}\n\n.pamela-call-button--sm {\n padding: 6px 12px;\n font-size: 14px;\n}\n\n.pamela-call-button--md {\n padding: 10px 20px;\n font-size: 16px;\n}\n\n.pamela-call-button--lg {\n padding: 12px 24px;\n font-size: 18px;\n}\n\n.pamela-call-button:hover:not(:disabled) {\n opacity: 0.9;\n}\n\n.pamela-call-button:disabled {\n opacity: 0.7;\n cursor: not-allowed;\n background: linear-gradient(to right, #cfcfcf, #b6b6b6);\n border: 1px solid rgba(0, 0, 0, 0.08);\n box-shadow: none;\n}\n\n/* Call Status - matches your card style */\n.pamela-call-status {\n font-family: 'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n}\n\n/* Transcript Viewer - matches your message bubble style */\n.pamela-transcript-viewer {\n font-family: 'Poppins', 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n}\n\n.pamela-card {\n background: var(--surface-liquid-strong);\n border: 1px solid var(--surface-border-strong);\n border-radius: var(--radius-lg);\n box-shadow: var(--shadow-soft), var(--liquid-glow);\n}\n\n.pamela-panel {\n background: var(--surface-liquid);\n border: 1px solid var(--surface-border-strong);\n border-radius: var(--radius-xl);\n box-shadow: var(--liquid-shadow), var(--liquid-glow);\n}\n\n.pamela-chip {\n background: var(--surface-liquid);\n border: 1px solid var(--surface-border-strong);\n border-radius: 999px;\n padding: 0.25rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--text-secondary);\n box-shadow: var(--shadow-inset);\n}\n\n.pamela-transcript-container {\n background: var(--surface);\n border-radius: var(--radius-md);\n padding: 16px;\n}\n\n.pamela-transcript-bubble {\n border-radius: var(--radius-md);\n padding: 12px 16px;\n}\n\n.pamela-transcript-bubble--pamela {\n background: var(--bubble-pamela);\n border: 1px solid var(--bubble-border);\n color: var(--text-primary);\n}\n\n.pamela-transcript-bubble--user {\n background: var(--bubble-user);\n color: #ffffff;\n}\n\n.pamela-transcript-bubble--recipient {\n background: var(--bubble-recipient);\n color: #ffffff;\n}\n\n/* Utility classes aligned with Pamela app design */\n.app-gradient {\n background: var(--bg-glow), var(--bg-gradient);\n}\n\n.surface-card {\n background: var(--surface-strong);\n border: 1px solid var(--surface-border);\n box-shadow: var(--shadow-soft);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n.surface-card-hover {\n transition: box-shadow 180ms ease, transform 180ms ease;\n}\n\n.surface-card-hover:hover {\n box-shadow: var(--shadow-hover);\n}\n\n.accent-card {\n background: linear-gradient(90deg, rgba(250, 147, 28, 0.12), rgba(253, 139, 116, 0.12));\n border: 1px solid rgba(250, 147, 28, 0.3);\n box-shadow: var(--shadow-soft);\n}\n\n.dark .accent-card {\n background: linear-gradient(90deg, rgba(250, 147, 28, 0.22), rgba(253, 139, 116, 0.22));\n border-color: rgba(250, 147, 28, 0.35);\n}\n\n.send-button-idle {\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.78), rgba(255, 255, 255, 0.4));\n border: 1px solid rgba(231, 171, 132, 0.45);\n color: rgba(28, 25, 17, 0.5);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.7), 0 0 14px rgba(250, 147, 28, 0.18);\n}\n\n.dark .send-button-idle {\n background: linear-gradient(135deg, rgba(255, 255, 255, 0.14), rgba(255, 255, 255, 0.04));\n border-color: rgba(255, 255, 255, 0.22);\n color: rgba(255, 255, 255, 0.6);\n box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), 0 0 16px rgba(250, 147, 28, 0.22);\n}\n\n.send-button-gradient {\n background: linear-gradient(120deg, rgba(250, 147, 28, 0.9), rgba(253, 139, 116, 0.9));\n border: 1px solid rgba(255, 255, 255, 0.45);\n box-shadow: 0 0 16px rgba(250, 147, 28, 0.32);\n}\n\n.send-button-gradient:hover,\n.send-button-gradient:focus-visible {\n box-shadow: 0 0 18px rgba(250, 147, 28, 0.36);\n}\n\n.transcript-bubble {\n box-shadow: 0 6px 14px rgba(15, 23, 42, 0.12), 0 0 10px rgba(250, 147, 28, 0.14);\n transition: box-shadow 180ms ease;\n}\n\n.transcript-bubble:hover,\n.transcript-bubble:focus-visible {\n box-shadow: 0 6px 14px rgba(15, 23, 42, 0.12), 0 0 10px rgba(250, 147, 28, 0.14);\n}\n\n.btn-primary {\n background: var(--cta-bg);\n border: var(--cta-border);\n color: var(--text-primary);\n font-weight: 600;\n border-radius: var(--radius-md);\n box-shadow: var(--shadow-soft), var(--cta-glow);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n transition: transform 150ms ease, box-shadow 150ms ease, opacity 150ms ease;\n}\n\n.btn-primary:hover {\n box-shadow: var(--shadow-hover), var(--cta-glow-hover);\n opacity: 0.96;\n}\n\n.btn-primary:active {\n transform: scale(0.98);\n}\n\n.btn-danger {\n background: var(--danger-bg);\n border: var(--danger-border);\n color: #b91c1c;\n box-shadow: var(--shadow-soft), var(--danger-glow);\n backdrop-filter: blur(10px);\n -webkit-backdrop-filter: blur(10px);\n transition: box-shadow 180ms ease, transform 180ms ease, opacity 180ms ease;\n}\n\n.dark .btn-danger {\n color: #fca5a5;\n}\n\n.btn-danger:hover {\n box-shadow: var(--danger-glow-hover);\n}\n\n.badge-pill {\n background: var(--badge-bg);\n border: var(--badge-border);\n border-radius: 999px;\n padding: 0.25rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--text-secondary);\n box-shadow: var(--shadow-inset), var(--badge-glow);\n}\n\n.badge-accent {\n background: rgba(250, 147, 28, 0.15);\n color: rgba(250, 147, 28, 0.95);\n}\n\n.dark .badge-accent {\n background: rgba(250, 147, 28, 0.25);\n color: rgba(253, 139, 116, 0.95);\n}\n\n.h1 {\n font-size: 1.875rem;\n line-height: 2.25rem;\n font-weight: 700;\n}\n\n.h2 {\n font-size: 1.5rem;\n line-height: 2rem;\n font-weight: 600;\n}\n\n.h3 {\n font-size: 1.125rem;\n line-height: 1.75rem;\n font-weight: 600;\n}\n\n.body {\n font-size: 0.95rem;\n line-height: 1.5rem;\n}\n\n.meta {\n font-size: 0.75rem;\n line-height: 1.125rem;\n color: rgba(28, 25, 17, 0.6);\n}\n\n.dark .meta {\n color: rgba(255, 255, 255, 0.6);\n}\n\n.input-base {\n background: rgba(255, 255, 255, 0.86);\n border: 1px solid rgba(231, 171, 132, 0.28);\n border-radius: var(--radius-lg);\n padding: 0.75rem 1rem;\n color: #1C1917;\n transition: box-shadow 150ms ease, border-color 150ms ease;\n}\n\n.dark .input-base {\n background: rgba(255, 255, 255, 0.1);\n color: #ffffff;\n}\n\n.input-base:focus {\n outline: none;\n border-color: rgba(250, 147, 28, 0.6);\n box-shadow: var(--focus-ring);\n}\n\n.panel {\n position: relative;\n background: var(--surface-liquid);\n border: 1px solid var(--surface-border-strong);\n border-radius: var(--radius-xl);\n box-shadow: var(--liquid-shadow), var(--liquid-glow);\n backdrop-filter: blur(var(--glass-blur-strong));\n -webkit-backdrop-filter: blur(var(--glass-blur-strong));\n overflow: hidden;\n}\n\n.card {\n position: relative;\n background: var(--surface-liquid-strong);\n border: 1px solid var(--surface-border-strong);\n border-radius: var(--radius-lg);\n box-shadow: var(--shadow-soft), var(--liquid-glow);\n backdrop-filter: blur(var(--glass-blur));\n -webkit-backdrop-filter: blur(var(--glass-blur));\n overflow: hidden;\n}\n\n.card-hover {\n transition: box-shadow 180ms ease, transform 180ms ease;\n}\n\n.card-hover:hover {\n box-shadow: var(--shadow-hover), var(--liquid-glow);\n transform: translateY(-2px);\n}\n\n.chip {\n background: var(--surface-liquid);\n border: 1px solid var(--surface-border-strong);\n border-radius: 999px;\n padding: 0.25rem 0.6rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--text-secondary);\n box-shadow: var(--shadow-inset);\n}\n\n.input-field {\n position: relative;\n background: var(--surface-liquid-strong);\n border: 1px solid var(--surface-border-strong);\n border-radius: var(--radius-lg);\n padding: 0.75rem 1rem;\n color: var(--text-primary);\n box-shadow: var(--shadow-inset), var(--liquid-glow);\n transition: box-shadow 150ms ease, border-color 150ms ease, transform 150ms ease;\n}\n\n.input-field:focus {\n outline: none;\n border-color: rgba(250, 147, 28, 0.6);\n box-shadow: var(--focus-ring), var(--liquid-glow);\n transform: translateY(-1px);\n}\n\n.btn-secondary {\n border-radius: var(--radius-md);\n border: 1px solid var(--surface-border-strong);\n background: var(--surface-liquid);\n color: var(--text-primary);\n box-shadow: var(--shadow-soft), var(--liquid-glow);\n transition: transform 150ms ease, box-shadow 150ms ease, opacity 150ms ease;\n}\n\n.btn-secondary:hover {\n box-shadow: var(--shadow-hover), var(--liquid-glow);\n}\n\n.btn-secondary:active {\n transform: scale(0.98);\n}\n\n.tooltip-panel {\n background: var(--surface-liquid-strong);\n border: 1px solid var(--surface-border-strong);\n color: var(--text-primary);\n box-shadow: var(--shadow-soft), 0 12px 24px rgba(28, 25, 17, 0.16);\n backdrop-filter: blur(calc(var(--glass-blur) * 0.9));\n -webkit-backdrop-filter: blur(calc(var(--glass-blur) * 0.9));\n}\n\n.tooltip-arrow {\n background: var(--surface-liquid-strong);\n border: 1px solid var(--surface-border-strong);\n}\n\n::where(.panel, .card) {\n isolation: isolate;\n}\n\n::where(.panel, .card) > * {\n position: relative;\n z-index: 1;\n}\n\n::where(.panel, .card)::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background: var(--liquid-highlight);\n opacity: 0.6;\n pointer-events: none;\n z-index: 0;\n}\n\n::where(.panel, .card)::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background-image: radial-gradient(rgba(255, 255, 255, 0.16) 0.5px, transparent 0.5px);\n background-size: 4px 4px;\n opacity: var(--noise-opacity);\n pointer-events: none;\n z-index: 0;\n}\n\n.avatar {\n background: var(--avatar-bg);\n border: var(--avatar-border);\n box-shadow: var(--shadow-soft), var(--avatar-glow);\n backdrop-filter: blur(12px);\n -webkit-backdrop-filter: blur(12px);\n}\n\n.conversations-scroll::-webkit-scrollbar,\n.chat-scroll::-webkit-scrollbar {\n width: 6px;\n}\n\n.conversations-scroll::-webkit-scrollbar-track,\n.chat-scroll::-webkit-scrollbar-track {\n background: transparent;\n}\n\n.conversations-scroll::-webkit-scrollbar-thumb,\n.chat-scroll::-webkit-scrollbar-thumb {\n background: rgba(230, 171, 132, 0.3);\n border-radius: 3px;\n}\n\n.conversations-scroll::-webkit-scrollbar-thumb:hover,\n.chat-scroll::-webkit-scrollbar-thumb:hover {\n background: rgba(230, 171, 132, 0.5);\n}\n\n.conversations-scroll,\n.chat-scroll {\n scrollbar-width: thin;\n scrollbar-color: rgba(230, 171, 132, 0.3) transparent;\n}\n\n.touch-manipulation {\n touch-action: manipulation;\n}\n\n/* Dark mode support */\n@media (prefers-color-scheme: dark) {\n .pamela-call-status {\n color: #ffffff;\n }\n \n .pamela-transcript-viewer {\n color: #ffffff;\n }\n}\n\n";
32
32
  styleInject(css_248z);
33
33
 
34
34
  const PamelaContext = createContext(null);
35
35
  function PamelaProvider({ config, children }) {
36
- const client = new PamelaClient({
36
+ const client = useMemo(() => new PamelaClient({
37
37
  apiKey: config.apiKey,
38
38
  baseUrl: config.baseUrl,
39
- });
39
+ }), [config.apiKey, config.baseUrl]);
40
40
  return (React.createElement(PamelaContext.Provider, { value: { client } }, children));
41
41
  }
42
42
  function usePamela() {
@@ -47,13 +47,37 @@ function usePamela() {
47
47
  return context;
48
48
  }
49
49
 
50
- function CallButton({ to, task, country, locale, instructions, end_user_id, metadata, onCallStart, onCallComplete, onError, disabled = false, className = '', children, }) {
50
+ function CallButton({ to, task, country, locale, instructions, end_user_id, metadata, tools, webhooks, onCallStart, onCallComplete, onError, variant = 'primary', size = 'md', pollInterval = 2000, pollTimeout = 5 * 60 * 1000, disabled = false, className = '', children, }) {
51
51
  const { client } = usePamela();
52
52
  const [loading, setLoading] = useState(false);
53
53
  const [callId, setCallId] = useState(null);
54
+ const pollIntervalRef = useRef(null);
55
+ const timeoutRef = useRef(null);
56
+ // Cleanup on unmount
57
+ useEffect(() => {
58
+ return () => {
59
+ if (pollIntervalRef.current) {
60
+ clearInterval(pollIntervalRef.current);
61
+ pollIntervalRef.current = null;
62
+ }
63
+ if (timeoutRef.current) {
64
+ clearTimeout(timeoutRef.current);
65
+ timeoutRef.current = null;
66
+ }
67
+ };
68
+ }, []);
54
69
  const handleClick = async () => {
55
70
  if (loading || disabled)
56
71
  return;
72
+ // Clear any existing intervals/timeouts
73
+ if (pollIntervalRef.current) {
74
+ clearInterval(pollIntervalRef.current);
75
+ pollIntervalRef.current = null;
76
+ }
77
+ if (timeoutRef.current) {
78
+ clearTimeout(timeoutRef.current);
79
+ timeoutRef.current = null;
80
+ }
57
81
  setLoading(true);
58
82
  try {
59
83
  const call = await client.createCall({
@@ -64,78 +88,101 @@ function CallButton({ to, task, country, locale, instructions, end_user_id, meta
64
88
  instructions,
65
89
  end_user_id,
66
90
  metadata,
91
+ tools,
92
+ webhooks,
67
93
  });
68
94
  setCallId(call.id);
69
95
  onCallStart?.(call.id);
70
96
  // Poll for call completion
71
- const pollInterval = setInterval(async () => {
97
+ pollIntervalRef.current = setInterval(async () => {
72
98
  try {
73
99
  const status = await client.getCall(call.id);
74
100
  if (status.status === 'completed' || status.status === 'failed' || status.status === 'cancelled') {
75
- clearInterval(pollInterval);
101
+ if (pollIntervalRef.current) {
102
+ clearInterval(pollIntervalRef.current);
103
+ pollIntervalRef.current = null;
104
+ }
105
+ if (timeoutRef.current) {
106
+ clearTimeout(timeoutRef.current);
107
+ timeoutRef.current = null;
108
+ }
76
109
  setLoading(false);
77
110
  onCallComplete?.(status);
78
111
  }
79
112
  }
80
113
  catch (error) {
81
- clearInterval(pollInterval);
114
+ if (pollIntervalRef.current) {
115
+ clearInterval(pollIntervalRef.current);
116
+ pollIntervalRef.current = null;
117
+ }
118
+ if (timeoutRef.current) {
119
+ clearTimeout(timeoutRef.current);
120
+ timeoutRef.current = null;
121
+ }
82
122
  setLoading(false);
83
123
  onError?.(error);
84
124
  }
85
- }, 2000);
125
+ }, pollInterval);
86
126
  // Timeout after 5 minutes
87
- setTimeout(() => {
88
- clearInterval(pollInterval);
127
+ timeoutRef.current = setTimeout(() => {
128
+ if (pollIntervalRef.current) {
129
+ clearInterval(pollIntervalRef.current);
130
+ pollIntervalRef.current = null;
131
+ }
89
132
  setLoading(false);
90
- }, 5 * 60 * 1000);
133
+ }, pollTimeout);
91
134
  }
92
135
  catch (error) {
93
136
  setLoading(false);
94
137
  onError?.(error);
95
138
  }
96
139
  };
97
- return (React.createElement("button", { onClick: handleClick, disabled: loading || disabled, className: `pamela-call-button ${className}`, style: {
98
- padding: '10px 20px',
99
- background: loading
100
- ? 'linear-gradient(to right, #ccc, #aaa)'
101
- : 'linear-gradient(to right, #FA931C, #fd8b74)',
102
- color: 'white',
103
- border: 'none',
104
- borderRadius: '0.5rem',
105
- cursor: loading || disabled ? 'not-allowed' : 'pointer',
106
- fontSize: '16px',
107
- fontWeight: '600',
108
- fontFamily: 'Poppins, Inter, -apple-system, BlinkMacSystemFont, sans-serif',
109
- transition: 'opacity 0.2s',
110
- opacity: loading || disabled ? 0.7 : 1,
111
- boxShadow: loading || disabled ? 'none' : '0 2px 4px rgba(250, 147, 28, 0.2)',
112
- } }, loading ? 'Calling...' : children || 'Call Now'));
140
+ const variantClass = variant === 'secondary'
141
+ ? 'pamela-call-button--secondary'
142
+ : variant === 'danger'
143
+ ? 'pamela-call-button--danger'
144
+ : 'pamela-call-button--primary';
145
+ const sizeClass = size === 'sm'
146
+ ? 'pamela-call-button--sm'
147
+ : size === 'lg'
148
+ ? 'pamela-call-button--lg'
149
+ : 'pamela-call-button--md';
150
+ return (React.createElement("button", { onClick: handleClick, disabled: loading || disabled, className: `pamela-call-button ${variantClass} ${sizeClass} ${className}` }, loading ? 'Calling...' : children || 'Call Now'));
113
151
  }
114
152
 
115
- function TranscriptViewer({ transcript, className = '' }) {
153
+ function TranscriptViewer({ transcript, maxHeight = 400, autoScroll = true, className = '', }) {
154
+ const containerRef = useRef(null);
155
+ useEffect(() => {
156
+ if (!autoScroll || !containerRef.current)
157
+ return;
158
+ containerRef.current.scrollTop = containerRef.current.scrollHeight;
159
+ }, [autoScroll, transcript]);
116
160
  const getMessageStyle = (speaker) => {
117
161
  if (speaker === 'pamela' || speaker === 'agent') {
118
162
  // Pamela messages: white background with beige border
119
163
  return {
120
- backgroundColor: '#ffffff',
121
- border: '1px solid rgba(231, 171, 132, 0.3)',
122
- color: '#1f2937',
164
+ backgroundColor: 'var(--bubble-pamela, #ffffff)',
165
+ border: '1px solid var(--bubble-border, rgba(231, 171, 132, 0.3))',
166
+ color: 'var(--text-primary, #1f2937)',
167
+ className: 'pamela-transcript-bubble pamela-transcript-bubble--pamela',
123
168
  };
124
169
  }
125
170
  else if (speaker === 'user' || speaker === 'caller') {
126
171
  // User messages: orange background
127
172
  return {
128
- backgroundColor: '#FA931C',
173
+ backgroundColor: 'var(--bubble-user, #FA931C)',
129
174
  border: 'none',
130
175
  color: '#ffffff',
176
+ className: 'pamela-transcript-bubble pamela-transcript-bubble--user',
131
177
  };
132
178
  }
133
179
  else {
134
180
  // Call recipient: blue background
135
181
  return {
136
- backgroundColor: '#4b4bea',
182
+ backgroundColor: 'var(--bubble-recipient, #4b4bea)',
137
183
  border: 'none',
138
184
  color: '#ffffff',
185
+ className: 'pamela-transcript-bubble pamela-transcript-bubble--recipient',
139
186
  };
140
187
  }
141
188
  };
@@ -146,21 +193,21 @@ function TranscriptViewer({ transcript, className = '' }) {
146
193
  marginBottom: '16px',
147
194
  fontSize: '18px',
148
195
  fontWeight: '600',
149
- color: '#1f2937',
196
+ color: 'var(--text-primary, #1f2937)',
150
197
  } }, "Transcript"),
151
- React.createElement("div", { style: {
152
- maxHeight: '400px',
198
+ React.createElement("div", { className: "pamela-transcript-container", style: {
199
+ maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight,
153
200
  overflowY: 'auto',
154
- borderRadius: '0.5rem',
201
+ borderRadius: 'var(--radius-sm, 0.5rem)',
155
202
  padding: '16px',
156
- backgroundColor: '#F7F4ED',
157
- } }, transcript.map((entry, index) => {
203
+ background: 'var(--surface, #F7F4ED)',
204
+ }, ref: containerRef }, transcript.map((entry, index) => {
158
205
  const style = getMessageStyle(entry.speaker);
159
- return (React.createElement("div", { key: index, style: {
206
+ const { className: bubbleClassName, ...bubbleStyle } = style;
207
+ return (React.createElement("div", { key: index, className: bubbleClassName, style: {
160
208
  marginBottom: '12px',
161
- padding: '12px 16px',
162
- ...style,
163
- borderRadius: '0.75rem',
209
+ ...bubbleStyle,
210
+ borderRadius: 'var(--radius-md, 0.75rem)',
164
211
  maxWidth: '75%',
165
212
  marginLeft: entry.speaker === 'pamela' || entry.speaker === 'agent' ? '0' : 'auto',
166
213
  marginRight: entry.speaker === 'pamela' || entry.speaker === 'agent' ? 'auto' : '0',
@@ -168,7 +215,7 @@ function TranscriptViewer({ transcript, className = '' }) {
168
215
  React.createElement("div", { style: {
169
216
  fontSize: '12px',
170
217
  fontWeight: '600',
171
- color: style.color === '#ffffff' ? 'rgba(255, 255, 255, 0.9)' : '#6b7280',
218
+ color: style.color === '#ffffff' ? 'rgba(255, 255, 255, 0.9)' : 'var(--text-muted, #6b7280)',
172
219
  marginBottom: '6px',
173
220
  textTransform: 'capitalize',
174
221
  } }, entry.speaker === 'pamela' || entry.speaker === 'agent'
@@ -185,7 +232,7 @@ function TranscriptViewer({ transcript, className = '' }) {
185
232
  } }, entry.text),
186
233
  entry.timestamp && (React.createElement("div", { style: {
187
234
  fontSize: '11px',
188
- color: style.color === '#ffffff' ? 'rgba(255, 255, 255, 0.7)' : '#9ca3af',
235
+ color: style.color === '#ffffff' ? 'rgba(255, 255, 255, 0.7)' : 'var(--text-muted, #9ca3af)',
189
236
  marginTop: '6px',
190
237
  } }, new Date(entry.timestamp).toLocaleTimeString()))));
191
238
  }))));
@@ -195,45 +242,63 @@ function TranscriptViewer({ transcript, className = '' }) {
195
242
  function StatusIndicator({ status }) {
196
243
  const getStatusConfig = () => {
197
244
  switch (status) {
245
+ case 'queued':
246
+ case 'initiating':
247
+ return {
248
+ dots: [
249
+ { color: 'var(--status-warning, #eab308)', pulse: true },
250
+ { color: 'var(--status-muted, #d1d5db)', pulse: false },
251
+ { color: 'var(--status-muted, #d1d5db)', pulse: false },
252
+ { color: 'var(--status-muted, #d1d5db)', pulse: false },
253
+ ],
254
+ text: 'Queued...',
255
+ textColor: 'var(--status-warning, #eab308)',
256
+ };
198
257
  case 'ringing':
199
258
  return {
200
259
  dots: [
201
- { color: '#10b981', pulse: true }, // green-500 (first dot)
202
- { color: '#eab308', pulse: true }, // yellow-500 (second dot)
203
- { color: '#d1d5db', pulse: false }, // gray-300 (third dot)
204
- { color: '#d1d5db', pulse: false }, // gray-300 (fourth dot)
260
+ { color: 'var(--status-success, #10b981)', pulse: true },
261
+ { color: 'var(--status-warning, #eab308)', pulse: true },
262
+ { color: 'var(--status-muted, #d1d5db)', pulse: false },
263
+ { color: 'var(--status-muted, #d1d5db)', pulse: false },
205
264
  ],
206
265
  text: 'Ringing...',
207
- textColor: '#eab308', // yellow-600
266
+ textColor: 'var(--status-warning, #eab308)',
208
267
  };
209
268
  case 'in_progress':
210
269
  case 'in-progress':
211
270
  return {
212
271
  dots: [
213
- { color: '#10b981', pulse: false }, // green-500
214
- { color: '#10b981', pulse: false },
215
- { color: '#10b981', pulse: true }, // third dot pulses
216
- { color: '#d1d5db', pulse: false }, // gray-300
272
+ { color: 'var(--status-success, #10b981)', pulse: false },
273
+ { color: 'var(--status-success, #10b981)', pulse: false },
274
+ { color: 'var(--status-success, #10b981)', pulse: true },
275
+ { color: 'var(--status-muted, #d1d5db)', pulse: false },
217
276
  ],
218
277
  text: 'In progress',
219
- textColor: '#10b981', // green-600
278
+ textColor: 'var(--status-success, #10b981)',
220
279
  };
221
280
  case 'completed':
222
281
  return {
223
282
  dots: [
224
- { color: '#10b981', pulse: false },
225
- { color: '#10b981', pulse: false },
226
- { color: '#10b981', pulse: false },
227
- { color: '#10b981', pulse: false, icon: true },
283
+ { color: 'var(--status-success, #10b981)', pulse: false },
284
+ { color: 'var(--status-success, #10b981)', pulse: false },
285
+ { color: 'var(--status-success, #10b981)', pulse: false },
286
+ { color: 'var(--status-success, #10b981)', pulse: false, icon: true },
228
287
  ],
229
288
  text: 'Completed',
230
- textColor: '#10b981',
289
+ textColor: 'var(--status-success, #10b981)',
231
290
  };
232
291
  case 'failed':
233
292
  return {
234
293
  dots: [],
235
294
  text: 'Failed',
236
- textColor: '#ef4444', // red-500
295
+ textColor: 'var(--status-error, #ef4444)',
296
+ };
297
+ case 'cancelled':
298
+ return {
299
+ dots: [],
300
+ text: 'Cancelled',
301
+ textColor: 'var(--status-error, #ef4444)',
237
302
  };
238
303
  default:
239
304
  return {
@@ -251,16 +316,17 @@ function StatusIndicator({ status }) {
251
316
  height: '8px',
252
317
  borderRadius: '50%',
253
318
  backgroundColor: dot.color,
254
- animation: dot.pulse ? 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite' : 'none',
319
+ animation: dot.pulse ? 'pamela-pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite' : 'none',
255
320
  } }))))))),
256
321
  React.createElement("span", { style: {
257
322
  fontSize: '12px',
258
323
  fontWeight: '500',
259
324
  color: config.textColor,
325
+ fontStyle: 'italic',
260
326
  fontFamily: 'Poppins, Inter, sans-serif',
261
327
  } }, config.text)));
262
328
  }
263
- function CallStatus({ callId, pollInterval = 5000, onStatusChange, showTranscript = true, className = '', }) {
329
+ function CallStatus({ callId, pollInterval = 5000, onStatusChange, showTranscript = true, showSummary = true, compact = false, className = '', }) {
264
330
  const { client } = usePamela();
265
331
  const [status, setStatus] = useState(null);
266
332
  const [loading, setLoading] = useState(true);
@@ -286,74 +352,64 @@ function CallStatus({ callId, pollInterval = 5000, onStatusChange, showTranscrip
286
352
  }, [callId, pollInterval, client, onStatusChange]);
287
353
  if (loading) {
288
354
  return (React.createElement("div", { className: `pamela-call-status ${className}` },
289
- React.createElement("div", { style: { color: '#6b7280', fontFamily: 'Poppins, Inter, sans-serif' } }, "Loading call status...")));
355
+ React.createElement("div", { style: { color: 'var(--text-muted, #6b7280)', fontFamily: 'Poppins, Inter, sans-serif' } }, "Loading call status...")));
290
356
  }
291
357
  if (error) {
292
358
  return (React.createElement("div", { className: `pamela-call-status ${className}` },
293
- React.createElement("div", { style: { color: '#ef4444', fontFamily: 'Poppins, Inter, sans-serif' } },
359
+ React.createElement("div", { style: { color: 'var(--status-error, #ef4444)', fontFamily: 'Poppins, Inter, sans-serif' } },
294
360
  "Error: ",
295
361
  error.message)));
296
362
  }
297
363
  if (!status) {
298
364
  return (React.createElement("div", { className: `pamela-call-status ${className}` },
299
- React.createElement("div", { style: { color: '#6b7280', fontFamily: 'Poppins, Inter, sans-serif' } }, "Call not found")));
365
+ React.createElement("div", { style: { color: 'var(--text-muted, #6b7280)', fontFamily: 'Poppins, Inter, sans-serif' } }, "Call not found")));
300
366
  }
301
367
  return (React.createElement("div", { className: `pamela-call-status ${className}`, style: {
302
368
  fontFamily: 'Poppins, Inter, -apple-system, BlinkMacSystemFont, sans-serif',
303
369
  } },
304
370
  React.createElement("div", { style: {
305
- marginBottom: '16px',
306
- padding: '16px',
307
- backgroundColor: '#ffffff',
308
- borderRadius: '0.75rem',
309
- border: '1px solid rgba(231, 171, 132, 0.3)',
310
- boxShadow: '0 1px 3px 0 rgba(0, 0, 0, 0.1)',
371
+ marginBottom: compact ? '8px' : '16px',
372
+ padding: compact ? '12px' : '16px',
373
+ background: 'var(--surface-liquid-strong, #ffffff)',
374
+ borderRadius: 'var(--radius-md, 0.75rem)',
375
+ border: '1px solid var(--surface-border-strong, rgba(231, 171, 132, 0.3))',
376
+ boxShadow: 'var(--shadow-soft, 0 1px 3px rgba(0, 0, 0, 0.1))',
311
377
  } },
312
378
  React.createElement("div", { style: { marginBottom: '12px' } },
313
379
  React.createElement(StatusIndicator, { status: status.status })),
314
- React.createElement("div", { style: { fontSize: '14px', color: '#1f2937', lineHeight: '1.6' } },
315
- React.createElement("div", { style: { marginBottom: '8px' } },
316
- React.createElement("span", { style: { fontWeight: '600', color: '#6b7280' } }, "To:"),
380
+ React.createElement("div", { style: { fontSize: compact ? '12px' : '14px', color: 'var(--text-primary, #1f2937)', lineHeight: '1.6' } },
381
+ React.createElement("div", { style: { marginBottom: compact ? '6px' : '8px' } },
382
+ React.createElement("span", { style: { fontWeight: '600', color: 'var(--text-secondary, #6b7280)' } }, "To:"),
317
383
  ' ',
318
- React.createElement("span", { style: { color: '#1f2937' } }, status.to)),
319
- React.createElement("div", { style: { marginBottom: '8px' } },
320
- React.createElement("span", { style: { fontWeight: '600', color: '#6b7280' } }, "From:"),
384
+ React.createElement("span", { style: { color: 'var(--text-primary, #1f2937)' } }, status.to)),
385
+ React.createElement("div", { style: { marginBottom: compact ? '6px' : '8px' } },
386
+ React.createElement("span", { style: { fontWeight: '600', color: 'var(--text-secondary, #6b7280)' } }, "From:"),
321
387
  ' ',
322
- React.createElement("span", { style: { color: '#1f2937' } }, status.from_)),
323
- status.duration_seconds && (React.createElement("div", { style: { marginBottom: '8px' } },
324
- React.createElement("span", { style: { fontWeight: '600', color: '#6b7280' } }, "Duration:"),
388
+ React.createElement("span", { style: { color: 'var(--text-primary, #1f2937)' } }, status.from_)),
389
+ status.duration_seconds && !compact && (React.createElement("div", { style: { marginBottom: '8px' } },
390
+ React.createElement("span", { style: { fontWeight: '600', color: 'var(--text-secondary, #6b7280)' } }, "Duration:"),
325
391
  ' ',
326
- React.createElement("span", { style: { color: '#1f2937' } },
392
+ React.createElement("span", { style: { color: 'var(--text-primary, #1f2937)' } },
327
393
  status.duration_seconds,
328
394
  "s")))),
329
- status.summary && (React.createElement("div", { style: {
330
- marginTop: '16px',
331
- padding: '16px',
332
- background: 'linear-gradient(to right, rgba(250, 147, 28, 0.1), rgba(253, 139, 116, 0.1))',
333
- border: '1px solid rgba(250, 147, 28, 0.3)',
334
- borderRadius: '0.75rem',
395
+ showSummary && status.summary && (React.createElement("div", { style: {
396
+ marginTop: compact ? '12px' : '16px',
397
+ padding: compact ? '12px' : '16px',
398
+ background: 'var(--cta-bg, linear-gradient(to right, rgba(250, 147, 28, 0.1), rgba(253, 139, 116, 0.1)))',
399
+ border: 'var(--cta-border, 1px solid rgba(250, 147, 28, 0.3))',
400
+ borderRadius: 'var(--radius-md, 0.75rem)',
335
401
  } },
336
402
  React.createElement("div", { style: {
337
403
  display: 'flex',
338
404
  alignItems: 'center',
339
405
  gap: '8px',
340
- marginBottom: '8px',
406
+ marginBottom: compact ? '6px' : '8px',
341
407
  } },
342
- React.createElement("svg", { style: { width: '20px', height: '20px', color: '#FA931C' }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" },
408
+ React.createElement("svg", { style: { width: '20px', height: '20px', color: 'var(--accent, #FA931C)' }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24" },
343
409
  React.createElement("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" })),
344
- React.createElement("h4", { style: { fontWeight: '600', color: '#1f2937', fontSize: '14px' } }, "Call Summary")),
345
- React.createElement("p", { style: { fontSize: '14px', color: '#1f2937', lineHeight: '1.6' } }, status.summary)))),
346
- showTranscript && status.transcript && status.transcript.length > 0 && (React.createElement(TranscriptViewer, { transcript: status.transcript })),
347
- React.createElement("style", null, `
348
- @keyframes pulse {
349
- 0%, 100% {
350
- opacity: 1;
351
- }
352
- 50% {
353
- opacity: 0.5;
354
- }
355
- }
356
- `)));
410
+ React.createElement("h4", { style: { fontWeight: '600', color: 'var(--text-primary, #1f2937)', fontSize: compact ? '12px' : '14px' } }, "Call Summary")),
411
+ React.createElement("p", { style: { fontSize: compact ? '12px' : '14px', color: 'var(--text-primary, #1f2937)', lineHeight: '1.6' } }, status.summary)))),
412
+ showTranscript && status.transcript && status.transcript.length > 0 && (React.createElement(TranscriptViewer, { transcript: status.transcript }))));
357
413
  }
358
414
 
359
415
  function CallHistory({ limit = 10, onCallSelect, className = '', }) {
@@ -361,19 +417,37 @@ function CallHistory({ limit = 10, onCallSelect, className = '', }) {
361
417
  const [calls, setCalls] = useState([]);
362
418
  const [loading, setLoading] = useState(true);
363
419
  const [error, setError] = useState(null);
364
- // Note: This requires a list endpoint in the API
365
- // For now, this is a placeholder that shows the structure
366
420
  useEffect(() => {
367
- // TODO: Implement when /api/b2b/v1/calls list endpoint is available
368
- setLoading(false);
369
- }, [client]);
421
+ let isMounted = true;
422
+ const fetchCalls = async () => {
423
+ try {
424
+ const response = await client.listCalls({ limit });
425
+ if (!isMounted) {
426
+ return;
427
+ }
428
+ setCalls(response.items || []);
429
+ setLoading(false);
430
+ }
431
+ catch (err) {
432
+ if (!isMounted) {
433
+ return;
434
+ }
435
+ setError(err);
436
+ setLoading(false);
437
+ }
438
+ };
439
+ fetchCalls();
440
+ return () => {
441
+ isMounted = false;
442
+ };
443
+ }, [client, limit]);
370
444
  if (loading) {
371
445
  return (React.createElement("div", { className: `pamela-call-history ${className}` },
372
- React.createElement("div", { style: { color: '#6b7280', fontFamily: 'Poppins, Inter, sans-serif' } }, "Loading call history...")));
446
+ React.createElement("div", { style: { color: 'var(--text-muted, #6b7280)', fontFamily: 'Poppins, Inter, sans-serif' } }, "Loading call history...")));
373
447
  }
374
448
  if (error) {
375
449
  return (React.createElement("div", { className: `pamela-call-history ${className}` },
376
- React.createElement("div", { style: { color: '#ef4444', fontFamily: 'Poppins, Inter, sans-serif' } },
450
+ React.createElement("div", { style: { color: 'var(--status-error, #ef4444)', fontFamily: 'Poppins, Inter, sans-serif' } },
377
451
  "Error: ",
378
452
  error.message)));
379
453
  }
@@ -384,34 +458,238 @@ function CallHistory({ limit = 10, onCallSelect, className = '', }) {
384
458
  marginBottom: '16px',
385
459
  fontSize: '18px',
386
460
  fontWeight: '600',
387
- color: '#1f2937',
461
+ color: 'var(--text-primary, #1f2937)',
388
462
  } }, "Call History"),
389
- calls.length === 0 ? (React.createElement("div", { style: { color: '#6b7280', fontSize: '14px' } }, "No calls yet")) : (React.createElement("div", null, calls.map((call) => (React.createElement("div", { key: call.id, onClick: () => onCallSelect?.(call.id), style: {
463
+ calls.length === 0 ? (React.createElement("div", { style: { color: 'var(--text-muted, #6b7280)', fontSize: '14px' } }, "No calls yet")) : (React.createElement("div", null, calls.map((call) => (React.createElement("div", { key: call.id, onClick: () => onCallSelect?.(call.id), style: {
390
464
  padding: '12px',
391
465
  marginBottom: '8px',
392
- border: '1px solid rgba(231, 171, 132, 0.3)',
393
- borderRadius: '0.5rem',
466
+ border: '1px solid var(--surface-border-strong, rgba(231, 171, 132, 0.3))',
467
+ borderRadius: 'var(--radius-sm, 0.5rem)',
394
468
  cursor: onCallSelect ? 'pointer' : 'default',
395
- backgroundColor: '#ffffff',
469
+ background: 'var(--surface-liquid-strong, #ffffff)',
396
470
  transition: 'background-color 0.2s',
397
471
  ...(onCallSelect && {
398
472
  ':hover': {
399
- backgroundColor: '#F7F4ED',
473
+ backgroundColor: 'var(--surface, #F7F4ED)',
400
474
  },
401
475
  }),
402
476
  }, onMouseEnter: (e) => {
403
477
  if (onCallSelect) {
404
- e.currentTarget.style.backgroundColor = '#F7F4ED';
478
+ e.currentTarget.style.backgroundColor = 'var(--surface, #F7F4ED)';
405
479
  }
406
480
  }, onMouseLeave: (e) => {
407
- e.currentTarget.style.backgroundColor = '#ffffff';
481
+ e.currentTarget.style.backgroundColor = 'var(--surface-liquid-strong, #ffffff)';
408
482
  } },
409
- React.createElement("div", { style: { fontWeight: '600', color: '#1f2937', marginBottom: '4px' } }, call.to),
410
- React.createElement("div", { style: { fontSize: '14px', color: '#6b7280' } },
483
+ React.createElement("div", { style: { fontWeight: '600', color: 'var(--text-primary, #1f2937)', marginBottom: '4px' } }, call.to),
484
+ React.createElement("div", { style: { fontSize: '14px', color: 'var(--text-secondary, #6b7280)' } },
411
485
  call.status,
412
486
  " \u2022 ",
413
487
  new Date(call.created_at).toLocaleString()))))))));
414
488
  }
415
489
 
416
- export { CallButton, CallHistory, CallStatus, PamelaProvider, TranscriptViewer, usePamela };
490
+ const sizeMap = {
491
+ small: 'var(--pamela-orb-size-small, 96px)',
492
+ medium: 'var(--pamela-orb-size-medium, 128px)',
493
+ large: 'var(--pamela-orb-size-large, 192px)',
494
+ };
495
+ function VoiceOrb({ isActive = false, size = 'large', className = '' }) {
496
+ const [pulsePhase, setPulsePhase] = useState(0);
497
+ const [idlePhase, setIdlePhase] = useState(Math.floor(Math.random() * 720)); // Random initial phase to avoid sync
498
+ // Continuous animation for idle mode - runs once on mount
499
+ // Remove modulo to allow continuous rotation (can go beyond 360 degrees for seamless loop)
500
+ useEffect(() => {
501
+ const interval = setInterval(() => {
502
+ setIdlePhase(prev => prev + 1); // Continuous growth - no reset for fluid animation
503
+ }, 16); // ~60fps
504
+ return () => clearInterval(interval);
505
+ }, []); // Empty deps - only run once
506
+ // Fast animation for active mode
507
+ useEffect(() => {
508
+ if (!isActive)
509
+ return;
510
+ const interval = setInterval(() => {
511
+ setPulsePhase(prev => (prev + 1) % 360);
512
+ }, 16); // ~60fps
513
+ return () => clearInterval(interval);
514
+ }, [isActive]);
515
+ const orbSize = sizeMap[size];
516
+ // Multiple breathing layers for idle mode (more organic) - reduced by 10%
517
+ const baseTime = idlePhase * 0.05;
518
+ const idleBreath1 = Math.sin(baseTime) * 0.072; // 7.2% primary breath (was 8%)
519
+ const idleBreath2 = Math.sin(baseTime * 1.3) * 0.045; // 4.5% secondary breath (was 5%)
520
+ const idleBreath3 = Math.sin(baseTime * 0.7) * 0.027; // 2.7% tertiary breath (was 3%)
521
+ // Calculate pulse scale - multi-layer breathing when idle, faster pulse when active - reduced by 10%
522
+ const pulseScale = isActive
523
+ ? 1 + Math.sin((pulsePhase * Math.PI) / 180) * 0.135 // 13.5% pulse variation (was 15%)
524
+ : 1 + idleBreath1 + idleBreath2 + idleBreath3; // Layered breathing when idle
525
+ // Floating/levitation effect (idle only) - reduced by 10%
526
+ const floatY = isActive ? 0 : Math.sin(baseTime * 0.4) * 7.2; // 7.2px float movement (was 8px)
527
+ // Continuous gradient rotation - slower when idle, faster when active
528
+ const gradientRotation = isActive
529
+ ? pulsePhase * 0.5
530
+ : idlePhase * 0.15; // Slow, continuous rotation when idle
531
+ // Subtle color shift for idle mode - reduced by 10%
532
+ const colorShift = isActive ? 0 : Math.sin(baseTime * 0.3) * 9; // 9deg color shift (was 10deg)
533
+ const orbSizeStyle = {
534
+ width: orbSize,
535
+ height: orbSize,
536
+ };
537
+ return (React.createElement("div", { className: className, style: {
538
+ position: 'relative',
539
+ display: 'flex',
540
+ alignItems: 'center',
541
+ justifyContent: 'center',
542
+ transform: `translateY(${floatY}px)`,
543
+ transition: isActive ? 'transform 0.3s ease-out' : 'none',
544
+ } },
545
+ React.createElement("div", { style: {
546
+ ...orbSizeStyle,
547
+ position: 'absolute',
548
+ borderRadius: '50%',
549
+ filter: 'blur(24px)', // blur-xl
550
+ background: `radial-gradient(circle,
551
+ hsla(${25 + colorShift}, 75%, 55%, 0.54),
552
+ hsla(${11 + colorShift}, 97%, 72%, 0.54))`,
553
+ transform: `scale(${pulseScale * 1.125})`,
554
+ opacity: isActive ? 0.315 : 0.225,
555
+ transition: 'opacity 0.3s ease-out',
556
+ } }),
557
+ React.createElement("div", { style: {
558
+ ...orbSizeStyle,
559
+ position: 'absolute',
560
+ borderRadius: '50%',
561
+ filter: 'blur(16px)', // blur-lg
562
+ background: `radial-gradient(circle,
563
+ hsla(${25 + colorShift * 0.7}, 75%, 55%, 0.45),
564
+ hsla(${11 + colorShift * 0.7}, 97%, 72%, 0.45))`,
565
+ transform: `scale(${pulseScale * 1.035}) rotate(${gradientRotation * 0.3}deg)`,
566
+ opacity: isActive ? 0.405 : 0.315,
567
+ transition: 'opacity 0.3s ease-out',
568
+ } }),
569
+ !isActive && (React.createElement("div", { style: {
570
+ ...orbSizeStyle,
571
+ position: 'absolute',
572
+ borderRadius: '50%',
573
+ filter: 'blur(40px)', // blur-2xl
574
+ background: `radial-gradient(circle,
575
+ hsla(${25 + colorShift * 0.5}, 70%, 50%, 0.27),
576
+ hsla(${11 + colorShift * 0.5}, 97%, 72%, 0.27))`,
577
+ transform: `scale(${(1 + idleBreath1) * 1.26})`,
578
+ opacity: 0.18,
579
+ } })),
580
+ React.createElement("div", { style: {
581
+ ...orbSizeStyle,
582
+ position: 'relative',
583
+ borderRadius: '50%',
584
+ background: `linear-gradient(${gradientRotation + colorShift}deg,
585
+ hsl(${25 + colorShift}, 75%, 55%),
586
+ hsl(${11 + colorShift}, 97%, 72%),
587
+ hsl(${25 + colorShift}, 75%, 55%))`,
588
+ backgroundSize: '200% 200%',
589
+ transform: `scale(${pulseScale}) rotate(${gradientRotation * 0.1}deg)`,
590
+ boxShadow: isActive
591
+ ? '0 0 54px rgba(250,147,28,0.45), 0 0 90px rgba(253,139,116,0.27), inset 0 0 36px rgba(255,255,255,0.09)'
592
+ : `0 0 72px hsla(${25 + colorShift}, 60%, 50%, 0.36),
593
+ 0 0 108px hsla(${11 + colorShift}, 97%, 72%, 0.225),
594
+ inset 0 0 45px rgba(255,255,255,0.135)`,
595
+ transition: 'box-shadow 0.3s ease-out',
596
+ } },
597
+ React.createElement("div", { style: {
598
+ position: 'absolute',
599
+ inset: 0,
600
+ borderRadius: '50%',
601
+ background: `radial-gradient(circle at ${30 + Math.sin(baseTime * 0.2) * 5}% ${30 + Math.cos(baseTime * 0.2) * 5}%,
602
+ rgba(255,255,255,${isActive ? 0.36 : 0.315}), transparent 60%)`,
603
+ opacity: isActive ? 0.54 : 0.63,
604
+ transition: 'opacity 0.3s ease-out',
605
+ } }),
606
+ React.createElement("div", { style: {
607
+ position: 'absolute',
608
+ inset: 0,
609
+ borderRadius: '50%',
610
+ background: `linear-gradient(${45 + gradientRotation * 0.2}deg,
611
+ transparent 30%,
612
+ rgba(255,255,255,${isActive ? 0.45 : 0.225}) 50%,
613
+ transparent 70%)`,
614
+ animation: isActive ? 'shimmer 3s infinite' : 'shimmer 6s infinite',
615
+ opacity: isActive ? 0.27 : 0.18,
616
+ transition: 'opacity 0.3s ease-out',
617
+ } }),
618
+ !isActive && (React.createElement(React.Fragment, null,
619
+ React.createElement("div", { style: {
620
+ position: 'absolute',
621
+ borderRadius: '50%',
622
+ backgroundColor: 'white',
623
+ width: '8px',
624
+ height: '8px',
625
+ top: `${25 + Math.sin(baseTime * 0.5) * 15}%`,
626
+ left: `${35 + Math.cos(baseTime * 0.5) * 15}%`,
627
+ opacity: 0.36 + Math.sin(baseTime * 0.8) * 0.18,
628
+ filter: 'blur(2px)',
629
+ transform: `scale(${0.8 + Math.sin(baseTime * 1.2) * 0.36})`,
630
+ } }),
631
+ React.createElement("div", { style: {
632
+ position: 'absolute',
633
+ borderRadius: '50%',
634
+ backgroundColor: 'white',
635
+ width: '6px',
636
+ height: '6px',
637
+ top: `${60 + Math.sin(baseTime * 0.7 + 2) * 12}%`,
638
+ left: `${65 + Math.cos(baseTime * 0.7 + 2) * 12}%`,
639
+ opacity: 0.27 + Math.sin(baseTime * 0.9) * 0.135,
640
+ filter: 'blur(1.5px)',
641
+ transform: `scale(${0.7 + Math.sin(baseTime * 1.4) * 0.27})`,
642
+ } })))),
643
+ isActive && (React.createElement(React.Fragment, null,
644
+ React.createElement("div", { style: {
645
+ ...orbSizeStyle,
646
+ position: 'absolute',
647
+ borderRadius: '50%',
648
+ border: '2px solid #FA931C',
649
+ opacity: 0,
650
+ animation: 'ripple 2s infinite ease-in-out',
651
+ animationDelay: '0s',
652
+ } }),
653
+ React.createElement("div", { style: {
654
+ ...orbSizeStyle,
655
+ position: 'absolute',
656
+ borderRadius: '50%',
657
+ border: '2px solid #fd8b74',
658
+ opacity: 0,
659
+ animation: 'ripple 2s infinite ease-in-out',
660
+ animationDelay: '0.7s',
661
+ } }),
662
+ React.createElement("div", { style: {
663
+ ...orbSizeStyle,
664
+ position: 'absolute',
665
+ borderRadius: '50%',
666
+ border: '2px solid #FA931C',
667
+ opacity: 0,
668
+ animation: 'ripple 2s infinite ease-in-out',
669
+ animationDelay: '1.4s',
670
+ } }))),
671
+ !isActive && (React.createElement(React.Fragment, null,
672
+ React.createElement("div", { style: {
673
+ ...orbSizeStyle,
674
+ position: 'absolute',
675
+ borderRadius: '50%',
676
+ border: '1px solid #FA931C',
677
+ opacity: 0.135 + Math.sin(baseTime * 0.25) * 0.045,
678
+ transform: `scale(${1 + Math.sin(baseTime * 0.25) * 0.27})`,
679
+ animation: 'ripple 8s infinite ease-in-out',
680
+ animationDelay: '0s',
681
+ } }),
682
+ React.createElement("div", { style: {
683
+ ...orbSizeStyle,
684
+ position: 'absolute',
685
+ borderRadius: '50%',
686
+ border: '1px solid #fd8b74',
687
+ opacity: 0.09 + Math.sin(baseTime * 0.25 + 3) * 0.027,
688
+ transform: `scale(${1 + Math.sin(baseTime * 0.25 + 3) * 0.225})`,
689
+ animation: 'ripple 8s infinite ease-in-out',
690
+ animationDelay: '2.5s',
691
+ } })))));
692
+ }
693
+
694
+ export { CallButton, CallHistory, CallStatus, PamelaProvider, TranscriptViewer, VoiceOrb, usePamela };
417
695
  //# sourceMappingURL=index.esm.js.map