diff --git a/packages/contact-center/cc-widgets/ai-docs/AGENTS.md b/packages/contact-center/cc-widgets/ai-docs/AGENTS.md new file mode 100644 index 000000000..b4c2a0ce6 --- /dev/null +++ b/packages/contact-center/cc-widgets/ai-docs/AGENTS.md @@ -0,0 +1,341 @@ +# CC Widgets - Widget Aggregator & Web Components + +## Overview + +CC Widgets is an aggregator package that bundles all contact center widgets and exports them in two formats: React components for React applications, and Web Components for framework-agnostic use. It uses the r2wc library to convert React widgets into standards-compliant Web Components that can be used in any web application. + +**Package:** `@webex/cc-widgets` + +**Version:** See [package.json](../package.json) + +--- + +## Why and What is This Package Used For? + +### Purpose + +CC Widgets serves as the main entry point for contact center widgets. It: + +- **Single package, no dependency sprawl** - Install one package (`@webex/cc-widgets`) instead of multiple widget packages; no need to track versions, peer dependencies, or compatibility across `@webex/cc-station-login`, `@webex/cc-user-state`, `@webex/cc-task`, etc. +- **Provides complete widget suite** - All widgets (StationLogin, UserState, TaskList, CallControl, OutdialCall, etc.) are bundled and ready to use +- **Delivers production-ready bundles** - Pre-built, optimized webpack bundles with all dependencies included +- **Reduces integration effort** - One installation, one import, immediate access to all widgets + +### Key Capabilities + +- **Dual Export System**: + + - Import as React components for React applications + - Use as Web Components (``) for framework-agnostic integration + - Both formats available from the same package + +- **Automatic Web Component Registration**: + + - Web Components auto-register in the browser when bundle is loaded + - No manual `customElements.define()` required + - Ready to use immediately in HTML + +- **Single Package Management**: + + - All widgets bundled in one npm package + - Guaranteed compatibility between widgets + - Simplified version management and updates + +- **Production Optimized**: + + - Webpack-bundled with code splitting + - React and dependencies included in Web Component bundle + - Minimal bundle size for React component exports (re-exports only) + +- **Event System**: + + - React components use standard props and callbacks + - Web Components emit CustomEvents for framework-agnostic communication + - Consistent event handling across both formats + +- **Shared Store Access**: + - Global MobX store accessible from both React and Web Components + - Single source of truth for agent state, tasks, and SDK interactions + - No store duplication or synchronization needed + +--- + +## Dependencies + +**Note:** For exact versions, see [package.json](../package.json) + +### Runtime Dependencies + +| Package | Purpose | +| ------------------------------ | -------------------------------------------------------- | +| `@r2wc/react-to-web-component` | React to Web Component conversion | +| `@webex/cc-station-login` | Station Login widget | +| `@webex/cc-user-state` | User State widget | +| `@webex/cc-task` | Task widgets (TaskList, IncomingTask, CallControl, etc.) | +| `@webex/cc-store` | MobX singleton store | + +### Peer Dependencies + +| Package | Purpose | +| ---------------------------------- | -------------------------------------------- | +| `@momentum-ui/react-collaboration` | Momentum UI components (required by widgets) | + +### Note on React Dependencies + +React and ReactDOM are **not** listed as dependencies because: + +- React components expect the host app to provide React +- Web Components bundle includes React internally +- This prevents duplicate React instances + +--- + +## Available Widgets + +### React Component Exports + +```typescript +import { + StationLogin, // Agent station login + UserState, // Agent state management + IncomingTask, // Incoming task notifications + TaskList, // Active tasks list + CallControl, // Call control buttons + CallControlCAD, // CAD-enabled call control + OutdialCall, // Outbound dialing + store, // MobX store singleton +} from '@webex/cc-widgets'; +``` + +--- + +## Examples and Use Cases + +### Getting Started + +#### React Component Usage + +```typescript +import { StationLogin, UserState, TaskList } from '@webex/cc-widgets'; +import store from '@webex/cc-widgets'; +import React from 'react'; + +function MyApp() { + return ( +
+ console.log('Logged in')} + profileMode={false} + /> + console.log('State:', state)} + /> + console.log('Task:', id)} + /> +
+ ); +} +``` + +#### Web Component Usage (HTML) + +```html + + + + Contact Center Widgets + + + + + + + + + + + + + + + +``` + +### Common Use Cases + +#### 1. Embedding in Non-React Applications + +```html + + + + +
+ + + +
+ + + + + +``` + +#### 3. Micro-Frontend Architecture + +```typescript +// Host application +import { StationLogin, UserState } from '@webex/cc-widgets'; +import store from '@webex/cc-widgets'; + +// Initialize the store before using it and before sharing across micro-frontends +store.init({ + access_token: '', + // Add any other necessary configuration here +}); + +// Share store across micro-frontends +window.ccStore = store; + +function HostApp() { + return ( +
+ + {/* Other micro-frontends can access window.ccStore */} +
+ ); +} +``` + +### Integration Patterns + +#### Initializing Store Before Widget Use + +```typescript +import {store} from '@webex/cc-widgets'; + +async function initialize() { + await store.init({ + webexConfig, + access_token: , + }); + + // 4. Now widgets are ready to use + renderWidgets(); +} +``` + +#### Event Handling with Web Components + +Web Components use **property assignment** for event handlers (not `addEventListener`). Assign callback functions directly to event properties: + +```javascript +// Create or get references to Web Components +const ccStationLogin = document.createElement('widget-cc-station-login'); +const ccUserState = document.createElement('widget-cc-user-state'); +const ccIncomingTask = document.createElement('widget-cc-incoming-task'); +const ccTaskList = document.createElement('widget-cc-task-list'); +const ccCallControl = document.createElement('widget-cc-call-control'); +const ccOutdial = document.createElement('widget-cc-outdial-call'); + +// Assign event handler callbacks directly to properties +ccStationLogin.onLogin = () => { + console.log('Login successful'); + showAgentDashboard(); +}; + +ccStationLogin.onLogout = () => { + console.log('Logout successful'); + showLoginScreen(); +}; + +ccUserState.onStateChange = (status) => { + console.log('Agent state changed:', status); + updateStatusIndicator(status); +}; + +ccIncomingTask.onAccepted = () => { + console.log('Task accepted'); +}; + +ccIncomingTask.onDeclined = () => { + console.log('Task declined'); +}; + +ccTaskList.onTaskAccepted = () => { + console.log('Task accepted from task list'); +}; + +ccTaskList.onTaskDeclined = () => { + console.log('Task declined from task list'); +}; + +ccCallControl.onHoldResume = () => { + console.log('Hold/Resume toggled'); +}; + +ccCallControl.onEnd = () => { + console.log('Call ended'); +}; + +ccCallControl.onWrapUp = (params) => { + console.log('Wrap-up completed', params); +}; + +// Append widgets to DOM after assigning event handlers +document.body.appendChild(ccStationLogin); +document.body.appendChild(ccUserState); +document.body.appendChild(ccTaskList); +document.body.appendChild(ccCallControl); +``` + +--- + +## Installation + +```bash +# Install the widgets bundle +yarn add @webex/cc-widgets + +``` + +--- + +## Build Outputs + +The package produces two bundles: + +### 1. React Bundle (`dist/index.js`) + +Used with: import { StationLogin } from '@webex/cc-widgets'. Contains: Re-exports of React widgets + store. Size: Small (just re-exports, no bundled code) + +### 2. Web Components Bundle (`dist/wc.js`) + +Used with: . Contains: All widgets + React + dependencies bundled.Size: Large (self-contained bundle).Includes: r2wc wrappers + custom element registration + +--- + +## Additional Resources + +For detailed architecture, r2wc integration patterns, and troubleshooting, see [architecture.md](./architecture.md). + +--- + +_Last Updated: 2025-11-26_ diff --git a/packages/contact-center/cc-widgets/ai-docs/ARCHITECTURE.md b/packages/contact-center/cc-widgets/ai-docs/ARCHITECTURE.md new file mode 100644 index 000000000..1af94a500 --- /dev/null +++ b/packages/contact-center/cc-widgets/ai-docs/ARCHITECTURE.md @@ -0,0 +1,455 @@ +# CC Widgets - Architecture + +## Component Overview + +### File Structure + +CC Widgets is an aggregator package that provides dual exports: React components for React applications and Web Components for framework-agnostic use. It uses r2wc (React to Web Component) to convert React widgets into custom elements. + +``` +cc-widgets/ +├── src/ +│ ├── index.ts # React exports (re-export widgets + store) +│ └── wc.ts # Web Component wrappers + registration +├── dist/ +│ ├── index.js # React bundle (small) +│ ├── wc.js # Web Components bundle (large, self-contained) +│ └── types/ +│ ├── index.d.ts # Type definitions for React exports +│ └── wc.d.ts # Type definitions for WC exports +├── package.json +├── tsconfig.json +└── webpack.config.js +``` + +--- + +### Package Structure + +| Export | File | Purpose | Output | Consumer | +| ------------------ | -------------- | ---------------------------- | --------------- | -------------------------------- | +| **React Bundle** | `src/index.ts` | Re-exports React widgets | `dist/index.js` | React applications | +| **Web Components** | `src/wc.ts` | r2wc wrappers + registration | `dist/wc.js` | HTML/vanilla JS/other frameworks | + +### Widget Mapping + +| Widget Package | React Export | Web Component Tag | Props Mapped | +| --------------------------------- | ---------------- | ---------------------------- | -------------------------------------------------------- | +| `@webex/cc-station-login` | `StationLogin` | `widget-cc-station-login` | `onLogin`, `onLogout` | +| `@webex/cc-user-state` | `UserState` | `widget-cc-user-state` | `onStateChange` | +| `@webex/cc-task` → IncomingTask | `IncomingTask` | `widget-cc-incoming-task` | `incomingTask`, `onAccepted`, `onRejected` | +| `@webex/cc-task` → TaskList | `TaskList` | `widget-cc-task-list` | `onTaskAccepted`, `onTaskDeclined`, `onTaskSelected` | +| `@webex/cc-task` → CallControl | `CallControl` | `widget-cc-call-control` | `onHoldResume`, `onEnd`, `onWrapUp`, `onRecordingToggle` | +| `@webex/cc-task` → CallControlCAD | `CallControlCAD` | `widget-cc-call-control-cad` | `onHoldResume`, `onEnd`, `onWrapUp`, `onRecordingToggle` | +| `@webex/cc-task` → OutdialCall | `OutdialCall` | `widget-cc-outdial-call` | None (uses store) | + +--- + +## Data Flows + +### React Export Flow + +```mermaid +graph LR + subgraph "Widget Packages" + SL["@webex/cc-station-login"] + US["@webex/cc-user-state"] + Task["@webex/cc-task"] + end + + subgraph "CC Widgets (index.ts)" + Index[Re-export widgets
+ store] + end + + subgraph "Consumer App" + ReactApp[React Application] + end + + SL -->|StationLogin| Index + US -->|UserState| Index + Task -->|Task widgets| Index + Index -->|Named exports| ReactApp + + style Index fill:#e1f5ff + style ReactApp fill:#fff4e1 +``` + +### Web Component Flow + +```mermaid +graph TB + subgraph "Widget Packages" + SL[StationLogin
React Component] + US[UserState
React Component] + TL[TaskList
React Component] + end + + subgraph "CC Widgets (wc.ts)" + R2WC[r2wc Wrapper] + Registry[Custom Elements
Registry] + end + + subgraph "Browser" + DOM[DOM with
Custom Elements] + end + + SL -->|React component| R2WC + US -->|React component| R2WC + TL -->|React component| R2WC + + R2WC -->|WebUserState| Registry + R2WC -->|WebStationLogin| Registry + R2WC -->|WebTaskList| Registry + + Registry -->|customElements.define| DOM + + style R2WC fill:#e1f5ff + style Registry fill:#ffe1e1 + style DOM fill:#f0e1ff +``` + +--- + +## Web Component Registration + +### Registration Flow + +The `wc.ts` file automatically registers all Web Components when loaded: + +```mermaid +sequenceDiagram + participant Browser + participant wcBundle as wc.js Bundle + participant r2wc as r2wc Library + participant Registry as Custom Elements Registry + + Browser->>wcBundle: Load script + activate wcBundle + + wcBundle->>r2wc: Wrap StationLogin + r2wc-->>wcBundle: WebStationLogin class + + wcBundle->>Registry: Check if 'widget-cc-station-login' exists + alt Not registered + wcBundle->>Registry: customElements.define('widget-cc-station-login', WebStationLogin) + Registry-->>wcBundle: Registered + else Already registered + wcBundle->>wcBundle: Skip (avoid error) + end + + Note over wcBundle,Registry: Repeat for each widget + + wcBundle-->>Browser: All widgets registered + deactivate wcBundle + + Browser->>Registry: + Registry->>wcBundle: Create instance + wcBundle-->>Browser: Rendered widget +``` + +--- + +## r2wc Integration Pattern + +### Props Mapping Configuration + +```typescript +// wc.ts structure +import r2wc from '@r2wc/react-to-web-component'; +import {StationLogin} from '@webex/cc-station-login'; + +const WebStationLogin = r2wc(StationLogin, { + props: { + onLogin: 'function', // Function callbacks + onLogout: 'function', // Function callbacks + profileMode: 'boolean', // Boolean attributes (implied) + teamId: 'string', // String attributes (implied) + }, +}); +``` + +### Type Mapping Rules + +| React Prop Type | Web Component Type | HTML Attribute | JavaScript Property | +| --------------- | ------------------ | ----------------- | ----------------------- | +| `() => void` | `'function'` | N/A | Via property assignment | +| `string` | Implicit | `team-id="value"` | `.teamId = 'value'` | +| `boolean` | Implicit | `profile-mode` | `.profileMode = true` | +| `object` | `'json'` | N/A | `.incomingTask = {}` | + +### Custom Element Definition + +```typescript +const components = [ + {name: 'widget-cc-user-state', component: WebUserState}, + {name: 'widget-cc-station-login', component: WebStationLogin}, + {name: 'widget-cc-incoming-task', component: WebIncomingTask}, + {name: 'widget-cc-task-list', component: WebTaskList}, + {name: 'widget-cc-call-control', component: WebCallControl}, + {name: 'widget-cc-outdial-call', component: WebOutdialCall}, + {name: 'widget-cc-call-control-cad', component: WebCallControlCAD}, +]; + +components.forEach(({name, component}) => { + if (!customElements.get(name)) { + customElements.define(name, component); + } +}); +``` + +**Key Pattern:** + +- Check if element already registered (avoids errors on re-import) +- Use consistent naming: `widget-cc-{widget-name}` +- Register all components in single loop + +--- + +## Bundle Architecture + +### React Bundle (index.js) + +**Size**: ~10-20 KB (gzipped) + +**Contains:** + +- Re-export statements only +- No actual widget code (expects widgets installed separately) + +**Usage:** + +```typescript +import {StationLogin, UserState} from '@webex/cc-widgets'; +// Host app's bundler will include actual widget code from node_modules +``` + +**Advantages:** + +- Small bundle size +- Tree-shakeable +- Uses host app's React instance + +### Web Components Bundle (wc.js) + +**Size**: ~500 KB - 1 MB (gzipped) + +**Contains:** + +- All widget code bundled +- React + ReactDOM bundled +- r2wc library +- Store and dependencies +- Momentum UI styles (referenced, not bundled) + +**Usage:** + +```html + + +``` + +**Advantages:** + +- Framework agnostic +- No build step required +- Single file deployment + +**Trade-offs:** + +- Larger bundle size +- Includes own React instance + +--- + +## Troubleshooting Guide + +### Common Issues + +#### 1. Web Components Not Rendering + +**Symptoms:** + +- Custom elements show as undefined +- Elements appear as empty tags + +**Possible Causes:** + +- wc.js not loaded +- Script loaded after DOM parsing +- Custom elements not supported + +**Solutions:** + +```html + + + + + + + + +``` + +#### 2. Props Not Updating in Web Components + +**Symptoms:** + +- Changing attributes doesn't update widget +- Callbacks not firing + +**Possible Causes:** + +- Using attributes instead of properties for complex types +- Incorrect attribute names (camelCase vs kebab-case) + +**Solutions:** + +```javascript +// For functions and objects, use properties (not attributes) +const widget = document.querySelector('widget-cc-task-list'); + +// ❌ Wrong - functions can't be set via attributes +widget.setAttribute('onTaskSelected', myFunction); + +// ✅ Correct - use property assignment +widget.onTaskSelected = myFunction; + +// ❌ Wrong - objects can't be string attributes +widget.setAttribute('incoming-task', JSON.stringify(task)); + +// ✅ Correct - use property assignment +widget.incomingTask = task; +``` + +#### 3. Multiple React Instances Conflict + +**Symptoms:** + +- "Invalid hook call" errors +- React context not working +- Duplicate React warning + +**Possible Causes:** + +- Both React bundle and WC bundle loaded +- Multiple React versions in node_modules + +**Solutions:** + +```typescript +// Choose ONE approach: + +// Option 1: React components only (use React bundle) +import { StationLogin } from '@webex/cc-widgets'; +// Don't load wc.js + +// Option 2: Web Components only (use WC bundle) + +// Don't import '@webex/cc-widgets' in React + +// Check for duplicate React +npx npm-check-updates +yarn why react +``` + +#### 4. Store Not Initialized + +**Symptoms:** + +- Widgets render but show no data +- Console warnings about missing store.cc + +**Possible Causes:** + +- Store not configured before widget use +- SDK not initialized + +**Solutions:** + +```typescript +import {store} from '@webex/cc-widgets'; +import {ContactCenter} from '@webex/contact-center'; + +// Initialize BEFORE rendering widgets +async function setup() { + const cc = await ContactCenter.init({token, region}); + store.setCC(cc); + + // Verify initialization + console.log('Store initialized:', store.cc !== undefined); + + // Now render widgets +} +``` + +#### 5. Styles Not Loading + +**Symptoms:** + +- Components render but look unstyled +- Missing icons or layout + +**Possible Causes:** + +- Momentum UI CSS not imported +- Webpack not configured for CSS + +**Solutions:** + +```typescript +// In your app entry point +import '@momentum-ui/core/css/momentum-ui.min.css'; + +// Or via HTML + +``` + +#### 6. Web Component Events Not Firing + +**Symptoms:** + +- addEventListener doesn't work +- No callbacks triggered + +**Possible Causes:** + +- Wrong event name +- Event listeners added before element defined +- Using React prop names instead of event names + +**Solutions:** + +```javascript +// Wait for element to be defined +customElements.whenDefined('widget-cc-station-login').then(() => { + const widget = document.querySelector('widget-cc-station-login'); + + // ✅ Correct event name (lowercase) + widget.addEventListener('login', () => { + console.log('Login event fired'); + }); + + // ❌ Wrong - this is the prop name, not event name + // widget.addEventListener('onLogin', ...); +}); +``` + +--- + +## Related Documentation + +- [Agent Documentation](./agent.md) - Usage examples and exports +- [Web Component Patterns](../../../../ai-docs/patterns/web-component-patterns.md) - r2wc patterns +- [Station Login Widget](../../station-login/ai-docs/agent.md) - Individual widget docs +- [User State Widget](../../user-state/ai-docs/agent.md) - Individual widget docs +- [CC Components Library](../../cc-components/ai-docs/agent.md) - Component library + +--- + +_Last Updated: 2025-11-26_