@gymmymac/bob-widget 1.1.3 → 1.1.5
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/README.md +110 -61
- package/dist/BobProvider.d.ts +4 -1
- package/dist/components/BobWidget.d.ts +67 -0
- package/dist/components/mobile/ContainedChatDrawer.d.ts +23 -0
- package/dist/components/mobile/ContainedMobileBobLayout.d.ts +40 -0
- package/dist/components/mobile/index.d.ts +2 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +13 -13
- package/dist/index.mjs +3551 -1319
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -8,83 +8,95 @@ AI-powered automotive parts assistant widget for integration into partner websit
|
|
|
8
8
|
npm install @gymmymac/bob-widget
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
## Quick Start
|
|
11
|
+
## Quick Start (Recommended)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
15
|
-
import { BobProvider, Bob } from '@gymmymac/bob-widget';
|
|
13
|
+
The easiest way to integrate Bob - just use the `BobWidget` component:
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
```tsx
|
|
16
|
+
import { BobWidget } from '@gymmymac/bob-widget';
|
|
18
17
|
|
|
19
18
|
function App() {
|
|
20
19
|
return (
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
>
|
|
42
|
-
<YourApp />
|
|
43
|
-
<Bob variant="floating" />
|
|
44
|
-
</BobProvider>
|
|
45
|
-
</QueryClientProvider>
|
|
20
|
+
<BobWidget
|
|
21
|
+
bobConfig={{
|
|
22
|
+
supabaseUrl: 'https://gjoguxzstsihhxvdgpto.supabase.co',
|
|
23
|
+
supabaseKey: 'eyJhbGciOiJI...', // Bob's public anon key
|
|
24
|
+
}}
|
|
25
|
+
hostApiConfig={{
|
|
26
|
+
baseUrl: 'https://api.yoursite.com',
|
|
27
|
+
apiKey: process.env.API_KEY!,
|
|
28
|
+
partnerCode: 'YOUR_PARTNER_CODE',
|
|
29
|
+
}}
|
|
30
|
+
hostContext={{
|
|
31
|
+
user: { id: user?.id, email: user?.email },
|
|
32
|
+
vehicle: { selectedVehicle: currentVehicle },
|
|
33
|
+
}}
|
|
34
|
+
callbacks={{
|
|
35
|
+
onVehicleIdentified: (vehicle) => saveVehicle(vehicle),
|
|
36
|
+
onAddToCart: (item) => addToCart(item),
|
|
37
|
+
}}
|
|
38
|
+
variant="mobile"
|
|
39
|
+
/>
|
|
46
40
|
);
|
|
47
41
|
}
|
|
48
42
|
```
|
|
49
43
|
|
|
50
|
-
|
|
44
|
+
**That's it!** No `QueryClientProvider` wrapping needed - Bob handles everything internally.
|
|
51
45
|
|
|
52
|
-
|
|
46
|
+
## Alternative: BobProvider + Bob
|
|
53
47
|
|
|
54
|
-
If you
|
|
48
|
+
If you need access to Bob's context in other components:
|
|
55
49
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
npm install @tanstack/react-query
|
|
59
|
-
```
|
|
50
|
+
```tsx
|
|
51
|
+
import { BobProvider, Bob, useHostContext } from '@gymmymac/bob-widget';
|
|
60
52
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
53
|
+
function App() {
|
|
54
|
+
return (
|
|
55
|
+
<BobProvider
|
|
56
|
+
bobConfig={{
|
|
57
|
+
supabaseUrl: 'https://gjoguxzstsihhxvdgpto.supabase.co',
|
|
58
|
+
supabaseKey: 'eyJhbGciOiJI...',
|
|
59
|
+
}}
|
|
60
|
+
hostApiConfig={{
|
|
61
|
+
baseUrl: 'https://api.yoursite.com',
|
|
62
|
+
apiKey: process.env.API_KEY!,
|
|
63
|
+
partnerCode: 'YOUR_PARTNER_CODE',
|
|
64
|
+
}}
|
|
65
|
+
hostContext={{
|
|
66
|
+
user: { id: user?.id, email: user?.email },
|
|
67
|
+
}}
|
|
68
|
+
callbacks={{
|
|
69
|
+
onAddToCart: (item) => addToCart(item),
|
|
70
|
+
}}
|
|
71
|
+
>
|
|
72
|
+
<YourApp />
|
|
73
|
+
<Bob variant="mobile" />
|
|
74
|
+
</BobProvider>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
73
78
|
|
|
74
|
-
|
|
79
|
+
## Checking Bob's Version
|
|
75
80
|
|
|
76
|
-
|
|
81
|
+
Ask Bob directly: "What version are you running?"
|
|
77
82
|
|
|
78
83
|
Or programmatically:
|
|
79
84
|
```tsx
|
|
80
85
|
import { BOB_VERSION, getBobVersion } from '@gymmymac/bob-widget';
|
|
81
86
|
|
|
82
|
-
console.log(`Bob Widget Version: ${getBobVersion()}`); // e.g., "1.1.
|
|
87
|
+
console.log(`Bob Widget Version: ${getBobVersion()}`); // e.g., "1.1.4"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Check the console for startup logs:
|
|
91
|
+
```
|
|
92
|
+
[BobWidget] Package loaded - v1.1.4
|
|
93
|
+
[BobWidget] v1.1.4 initialized
|
|
94
|
+
[BobWidget] QueryClient: internal
|
|
83
95
|
```
|
|
84
96
|
|
|
85
97
|
## Configuration
|
|
86
98
|
|
|
87
|
-
### BobProvider Props
|
|
99
|
+
### BobWidget / BobProvider Props
|
|
88
100
|
|
|
89
101
|
| Prop | Type | Description |
|
|
90
102
|
|------|------|-------------|
|
|
@@ -92,6 +104,15 @@ console.log(`Bob Widget Version: ${getBobVersion()}`); // e.g., "1.1.3"
|
|
|
92
104
|
| `hostApiConfig` | `HostApiConfig` | Your API credentials for product/vehicle lookups |
|
|
93
105
|
| `hostContext` | `HostContext` | Current user, vehicle, cart, and purchase history |
|
|
94
106
|
| `callbacks` | `BobCallbacks` | Event handlers for Bob actions |
|
|
107
|
+
| `queryClient` | `QueryClient` | Optional: share your app's QueryClient |
|
|
108
|
+
|
|
109
|
+
### BobWidget Additional Props
|
|
110
|
+
|
|
111
|
+
| Prop | Type | Default | Description |
|
|
112
|
+
|------|------|---------|-------------|
|
|
113
|
+
| `variant` | `'mobile' \| 'inline' \| 'floating' \| 'fullscreen'` | `'mobile'` | Display variant |
|
|
114
|
+
| `showChat` | `boolean` | `true` | Show chat interface |
|
|
115
|
+
| `className` | `string` | `''` | Additional CSS classes |
|
|
95
116
|
|
|
96
117
|
### Host Context
|
|
97
118
|
|
|
@@ -127,22 +148,15 @@ Handle Bob's actions in your app:
|
|
|
127
148
|
|
|
128
149
|
```tsx
|
|
129
150
|
const callbacks = {
|
|
130
|
-
// Called when Bob identifies a vehicle
|
|
131
151
|
onVehicleIdentified: (vehicle) => {
|
|
132
152
|
dispatch(setCurrentVehicle(vehicle));
|
|
133
153
|
},
|
|
134
|
-
|
|
135
|
-
// Called when parts are found
|
|
136
154
|
onPartsFound: (parts) => {
|
|
137
155
|
dispatch(setParts(parts));
|
|
138
156
|
},
|
|
139
|
-
|
|
140
|
-
// Called when user wants to add to cart
|
|
141
157
|
onAddToCart: (item) => {
|
|
142
158
|
dispatch(addToCart(item));
|
|
143
159
|
},
|
|
144
|
-
|
|
145
|
-
// Called when checkout is requested
|
|
146
160
|
onCheckoutRequested: (url) => {
|
|
147
161
|
window.location.href = url;
|
|
148
162
|
},
|
|
@@ -151,7 +165,7 @@ const callbacks = {
|
|
|
151
165
|
|
|
152
166
|
## Hooks
|
|
153
167
|
|
|
154
|
-
Access Bob's context from anywhere in your app:
|
|
168
|
+
Access Bob's context from anywhere in your app (when using BobProvider):
|
|
155
169
|
|
|
156
170
|
```tsx
|
|
157
171
|
import {
|
|
@@ -170,6 +184,41 @@ function MyComponent() {
|
|
|
170
184
|
}
|
|
171
185
|
```
|
|
172
186
|
|
|
187
|
+
## Advanced: Shared QueryClient
|
|
188
|
+
|
|
189
|
+
If you want Bob to share your app's React Query cache:
|
|
190
|
+
|
|
191
|
+
```tsx
|
|
192
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
193
|
+
import { BobProvider, Bob } from '@gymmymac/bob-widget';
|
|
194
|
+
|
|
195
|
+
const queryClient = new QueryClient();
|
|
196
|
+
|
|
197
|
+
function App() {
|
|
198
|
+
return (
|
|
199
|
+
<QueryClientProvider client={queryClient}>
|
|
200
|
+
<BobProvider
|
|
201
|
+
bobConfig={...}
|
|
202
|
+
hostApiConfig={...}
|
|
203
|
+
queryClient={queryClient} // Share the cache
|
|
204
|
+
>
|
|
205
|
+
<Bob variant="mobile" />
|
|
206
|
+
</BobProvider>
|
|
207
|
+
</QueryClientProvider>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Dependencies
|
|
213
|
+
|
|
214
|
+
Bob Widget v1.1.4+ bundles its own dependencies. You only need:
|
|
215
|
+
- `react` ^18.0.0
|
|
216
|
+
- `react-dom` ^18.0.0
|
|
217
|
+
|
|
218
|
+
## Integration Guide
|
|
219
|
+
|
|
220
|
+
For detailed integration instructions, see [CARFIX-INTEGRATION.md](./CARFIX-INTEGRATION.md).
|
|
221
|
+
|
|
173
222
|
## License
|
|
174
223
|
|
|
175
224
|
MIT
|
package/dist/BobProvider.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
2
|
import { SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
import { QueryClient } from '@tanstack/react-query';
|
|
3
4
|
import { BobConfig, HostApiConfig, HostContext, BobCallbacks } from './types';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -29,6 +30,8 @@ interface BobProviderProps {
|
|
|
29
30
|
hostContext?: HostContext;
|
|
30
31
|
/** Event callbacks */
|
|
31
32
|
callbacks?: BobCallbacks;
|
|
33
|
+
/** Optional external QueryClient - if not provided, an internal one is created */
|
|
34
|
+
queryClient?: QueryClient;
|
|
32
35
|
}
|
|
33
36
|
/**
|
|
34
37
|
* BobProvider - Context provider for the Bob widget
|
|
@@ -62,7 +65,7 @@ interface BobProviderProps {
|
|
|
62
65
|
* </BobProvider>
|
|
63
66
|
* ```
|
|
64
67
|
*/
|
|
65
|
-
export declare function BobProvider({ children, bobConfig, hostApiConfig, hostContext: initialHostContext, callbacks, }: BobProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
68
|
+
export declare function BobProvider({ children, bobConfig, hostApiConfig, hostContext: initialHostContext, callbacks, queryClient: externalQueryClient, }: BobProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
66
69
|
/**
|
|
67
70
|
* Hook to access Bob context
|
|
68
71
|
* Must be used within a BobProvider
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { BobVariant } from './Bob';
|
|
3
|
+
import { BobConfig, HostApiConfig, HostContext, BobCallbacks } from '../types';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Props for the self-contained BobWidget component
|
|
7
|
+
*/
|
|
8
|
+
export interface BobWidgetProps {
|
|
9
|
+
/** Bob's Supabase configuration (for animations, TTS) */
|
|
10
|
+
bobConfig: BobConfig;
|
|
11
|
+
/** Host's API configuration for product/vehicle lookups */
|
|
12
|
+
hostApiConfig: HostApiConfig;
|
|
13
|
+
/** Current host context (user, vehicle, cart, history) */
|
|
14
|
+
hostContext?: HostContext;
|
|
15
|
+
/** Event callbacks for Bob actions */
|
|
16
|
+
callbacks?: BobCallbacks;
|
|
17
|
+
/** Display variant */
|
|
18
|
+
variant?: BobVariant;
|
|
19
|
+
/** Initial animation state */
|
|
20
|
+
initialState?: string;
|
|
21
|
+
/** Show chat interface */
|
|
22
|
+
showChat?: boolean;
|
|
23
|
+
/** Additional CSS classes */
|
|
24
|
+
className?: string;
|
|
25
|
+
/** Custom backdrop URL (overrides database) */
|
|
26
|
+
backdropUrl?: string;
|
|
27
|
+
/** Custom counter overlay URL */
|
|
28
|
+
counterOverlayUrl?: string;
|
|
29
|
+
/** Counter height as percentage */
|
|
30
|
+
counterHeightPercent?: number;
|
|
31
|
+
/** Fallback Bob image URL */
|
|
32
|
+
defaultBobImage?: string;
|
|
33
|
+
/** Vertical offset for Bob character */
|
|
34
|
+
verticalOffset?: number;
|
|
35
|
+
/** Scale percentage for Bob character */
|
|
36
|
+
scale?: number;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* BobWidget - Self-contained Bob widget component
|
|
40
|
+
*
|
|
41
|
+
* This is the easiest way to integrate Bob into your application.
|
|
42
|
+
* It handles all providers internally - no QueryClientProvider needed!
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```tsx
|
|
46
|
+
* import { BobWidget } from '@gymmymac/bob-widget';
|
|
47
|
+
*
|
|
48
|
+
* function App() {
|
|
49
|
+
* return (
|
|
50
|
+
* <BobWidget
|
|
51
|
+
* bobConfig={{
|
|
52
|
+
* supabaseUrl: 'https://gjoguxzstsihhxvdgpto.supabase.co',
|
|
53
|
+
* supabaseKey: 'eyJhbGciOiJI...',
|
|
54
|
+
* }}
|
|
55
|
+
* hostApiConfig={{
|
|
56
|
+
* baseUrl: 'https://api.yoursite.com',
|
|
57
|
+
* apiKey: process.env.API_KEY!,
|
|
58
|
+
* partnerCode: 'YOUR_CODE',
|
|
59
|
+
* }}
|
|
60
|
+
* variant="mobile"
|
|
61
|
+
* />
|
|
62
|
+
* );
|
|
63
|
+
* }
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare const BobWidget: React.FC<BobWidgetProps>;
|
|
67
|
+
export default BobWidget;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { Message } from '../../types/message';
|
|
3
|
+
|
|
4
|
+
interface ContainedChatDrawerProps {
|
|
5
|
+
messages: Message[];
|
|
6
|
+
input: string;
|
|
7
|
+
setInput: (value: string) => void;
|
|
8
|
+
isLoading: boolean;
|
|
9
|
+
onSend: () => void;
|
|
10
|
+
onKeyPress: (e: React.KeyboardEvent) => void;
|
|
11
|
+
onInputFocus: () => void;
|
|
12
|
+
onInputBlur: () => void;
|
|
13
|
+
chatEndRef: React.RefObject<HTMLDivElement>;
|
|
14
|
+
isMuted?: boolean;
|
|
15
|
+
onToggleMute?: () => void;
|
|
16
|
+
isSpeaking?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* ContainedChatDrawer - Chat drawer using absolute positioning
|
|
20
|
+
* Stays within parent container bounds instead of viewport.
|
|
21
|
+
*/
|
|
22
|
+
export declare const ContainedChatDrawer: React.FC<ContainedChatDrawerProps>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { Message, HighlightedProduct } from '../../types/message';
|
|
3
|
+
import { Product, ServicePackage } from '../../types';
|
|
4
|
+
import { Vehicle } from '../../types/vehicle';
|
|
5
|
+
|
|
6
|
+
interface ContainedMobileBobLayoutProps {
|
|
7
|
+
currentImage: string;
|
|
8
|
+
animationState: string;
|
|
9
|
+
backdropUrl?: string;
|
|
10
|
+
counterOverlayUrl?: string;
|
|
11
|
+
counterHeightPercent?: number;
|
|
12
|
+
messages: Message[];
|
|
13
|
+
input: string;
|
|
14
|
+
setInput: (value: string) => void;
|
|
15
|
+
isLoading: boolean;
|
|
16
|
+
onSend: () => void;
|
|
17
|
+
onKeyPress: (e: React.KeyboardEvent) => void;
|
|
18
|
+
onInputFocus: () => void;
|
|
19
|
+
onInputBlur: () => void;
|
|
20
|
+
chatEndRef: React.RefObject<HTMLDivElement>;
|
|
21
|
+
isMuted?: boolean;
|
|
22
|
+
onToggleMute?: () => void;
|
|
23
|
+
isSpeaking?: boolean;
|
|
24
|
+
products: Product[];
|
|
25
|
+
servicePackages: ServicePackage[];
|
|
26
|
+
highlightedPartType?: string | null;
|
|
27
|
+
highlightedProduct?: HighlightedProduct | null;
|
|
28
|
+
onProductClick?: (product: Product) => void;
|
|
29
|
+
onPackageSelect?: (pkg: ServicePackage) => void;
|
|
30
|
+
isResearching?: boolean;
|
|
31
|
+
vehicle?: Vehicle | null;
|
|
32
|
+
onChangeVehicle?: () => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* ContainedMobileBobLayout - Immersive layout that fits within a parent container
|
|
36
|
+
* Uses position: absolute instead of fixed, so it respects parent boundaries.
|
|
37
|
+
* Ideal for embedding Bob in a page with header/footer.
|
|
38
|
+
*/
|
|
39
|
+
export declare const ContainedMobileBobLayout: React.FC<ContainedMobileBobLayoutProps>;
|
|
40
|
+
export {};
|
|
@@ -2,3 +2,5 @@ export { MobileBobCharacter } from './MobileBobCharacter';
|
|
|
2
2
|
export { MobileChatDrawer } from './MobileChatDrawer';
|
|
3
3
|
export { MobileProductColumn } from './MobileProductColumn';
|
|
4
4
|
export { MobileBobLayout } from './MobileBobLayout';
|
|
5
|
+
export { ContainedMobileBobLayout } from './ContainedMobileBobLayout';
|
|
6
|
+
export { ContainedChatDrawer } from './ContainedChatDrawer';
|
package/dist/index.d.ts
CHANGED
|
@@ -2,14 +2,18 @@
|
|
|
2
2
|
* @gymmymac/bob-widget
|
|
3
3
|
*
|
|
4
4
|
* AI-powered automotive parts assistant widget - Full immersive experience
|
|
5
|
+
*
|
|
6
|
+
* v1.1.4+ - Self-contained with internal QueryClientProvider
|
|
5
7
|
*/
|
|
6
8
|
export { BOB_VERSION, getBobVersion } from './version';
|
|
7
9
|
export { BobProvider, useBobContext, useBobSupabase, useHostContext, useHostApiConfig, useBobCallbacks, } from './BobProvider';
|
|
10
|
+
export { BobWidget } from './components/BobWidget';
|
|
11
|
+
export type { BobWidgetProps } from './components/BobWidget';
|
|
8
12
|
export { Bob } from './components/Bob';
|
|
9
13
|
export type { BobVariant } from './components/Bob';
|
|
10
14
|
export { BobCharacter } from './components/BobCharacter';
|
|
11
15
|
export { ChatInterface } from './components/ChatInterface';
|
|
12
|
-
export { MobileBobCharacter, MobileChatDrawer, MobileProductColumn, MobileBobLayout } from './components/mobile';
|
|
16
|
+
export { MobileBobCharacter, MobileChatDrawer, MobileProductColumn, MobileBobLayout, ContainedMobileBobLayout, ContainedChatDrawer } from './components/mobile';
|
|
13
17
|
export { useBobChat } from './hooks/useBobChat';
|
|
14
18
|
export { useSpeechSynthesis } from './hooks/useSpeechSynthesis';
|
|
15
19
|
export { useBobAnimation } from './hooks/useBobAnimation';
|