@wix/ai-assistant-avatar 0.39.0
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 +343 -0
- package/dist/cjs/Astro/Astro.js +200 -0
- package/dist/cjs/Astro/Astro.js.map +1 -0
- package/dist/cjs/Astro/Astro.module.scss +46 -0
- package/dist/cjs/Astro/components/DotTrail.js +47 -0
- package/dist/cjs/Astro/components/DotTrail.js.map +1 -0
- package/dist/cjs/Astro/config/animation.js +35 -0
- package/dist/cjs/Astro/config/animation.js.map +1 -0
- package/dist/cjs/Astro/config/index.js +16 -0
- package/dist/cjs/Astro/config/index.js.map +1 -0
- package/dist/cjs/Astro/config/size.js +9 -0
- package/dist/cjs/Astro/config/size.js.map +1 -0
- package/dist/cjs/Astro/hooks/index.js +22 -0
- package/dist/cjs/Astro/hooks/index.js.map +1 -0
- package/dist/cjs/Astro/hooks/useAvatarSetup.js +49 -0
- package/dist/cjs/Astro/hooks/useAvatarSetup.js.map +1 -0
- package/dist/cjs/Astro/hooks/useDotAnimation.js +148 -0
- package/dist/cjs/Astro/hooks/useDotAnimation.js.map +1 -0
- package/dist/cjs/Astro/hooks/useMovement.js +25 -0
- package/dist/cjs/Astro/hooks/useMovement.js.map +1 -0
- package/dist/cjs/Astro/types/index.js +4 -0
- package/dist/cjs/Astro/types/index.js.map +1 -0
- package/dist/cjs/Astro/utils/helpers.js +29 -0
- package/dist/cjs/Astro/utils/helpers.js.map +1 -0
- package/dist/cjs/Astro/utils/index.js +22 -0
- package/dist/cjs/Astro/utils/index.js.map +1 -0
- package/dist/cjs/Astro/utils/logs.js +6 -0
- package/dist/cjs/Astro/utils/logs.js.map +1 -0
- package/dist/cjs/Astro/utils/pathGeneration.js +36 -0
- package/dist/cjs/Astro/utils/pathGeneration.js.map +1 -0
- package/dist/cjs/Astro/utils/positioning.js +15 -0
- package/dist/cjs/Astro/utils/positioning.js.map +1 -0
- package/dist/cjs/__tests__/spec-setup.js +14 -0
- package/dist/cjs/__tests__/spec-setup.js.map +1 -0
- package/dist/cjs/external-types.d.js +2 -0
- package/dist/cjs/external-types.d.js.map +1 -0
- package/dist/cjs/index.js +38 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/test-types.d.js +2 -0
- package/dist/cjs/test-types.d.js.map +1 -0
- package/dist/esm/Astro/Astro.js +163 -0
- package/dist/esm/Astro/Astro.js.map +1 -0
- package/dist/esm/Astro/Astro.module.scss +46 -0
- package/dist/esm/Astro/components/DotTrail.js +29 -0
- package/dist/esm/Astro/components/DotTrail.js.map +1 -0
- package/dist/esm/Astro/config/animation.js +31 -0
- package/dist/esm/Astro/config/animation.js.map +1 -0
- package/dist/esm/Astro/config/index.js +3 -0
- package/dist/esm/Astro/config/index.js.map +1 -0
- package/dist/esm/Astro/config/size.js +5 -0
- package/dist/esm/Astro/config/size.js.map +1 -0
- package/dist/esm/Astro/hooks/index.js +4 -0
- package/dist/esm/Astro/hooks/index.js.map +1 -0
- package/dist/esm/Astro/hooks/useAvatarSetup.js +48 -0
- package/dist/esm/Astro/hooks/useAvatarSetup.js.map +1 -0
- package/dist/esm/Astro/hooks/useDotAnimation.js +152 -0
- package/dist/esm/Astro/hooks/useDotAnimation.js.map +1 -0
- package/dist/esm/Astro/hooks/useMovement.js +22 -0
- package/dist/esm/Astro/hooks/useMovement.js.map +1 -0
- package/dist/esm/Astro/types/index.js +2 -0
- package/dist/esm/Astro/types/index.js.map +1 -0
- package/dist/esm/Astro/utils/helpers.js +25 -0
- package/dist/esm/Astro/utils/helpers.js.map +1 -0
- package/dist/esm/Astro/utils/index.js +4 -0
- package/dist/esm/Astro/utils/index.js.map +1 -0
- package/dist/esm/Astro/utils/logs.js +2 -0
- package/dist/esm/Astro/utils/logs.js.map +1 -0
- package/dist/esm/Astro/utils/pathGeneration.js +27 -0
- package/dist/esm/Astro/utils/pathGeneration.js.map +1 -0
- package/dist/esm/Astro/utils/positioning.js +16 -0
- package/dist/esm/Astro/utils/positioning.js.map +1 -0
- package/dist/esm/__tests__/spec-setup.js +12 -0
- package/dist/esm/__tests__/spec-setup.js.map +1 -0
- package/dist/esm/external-types.d.js +2 -0
- package/dist/esm/external-types.d.js.map +1 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/test-types.d.js +2 -0
- package/dist/esm/test-types.d.js.map +1 -0
- package/dist/types/Astro/Astro.d.ts +4 -0
- package/dist/types/Astro/Astro.d.ts.map +1 -0
- package/dist/types/Astro/components/DotTrail.d.ts +8 -0
- package/dist/types/Astro/components/DotTrail.d.ts.map +1 -0
- package/dist/types/Astro/config/animation.d.ts +4 -0
- package/dist/types/Astro/config/animation.d.ts.map +1 -0
- package/dist/types/Astro/config/index.d.ts +3 -0
- package/dist/types/Astro/config/index.d.ts.map +1 -0
- package/dist/types/Astro/config/size.d.ts +3 -0
- package/dist/types/Astro/config/size.d.ts.map +1 -0
- package/dist/types/Astro/hooks/index.d.ts +4 -0
- package/dist/types/Astro/hooks/index.d.ts.map +1 -0
- package/dist/types/Astro/hooks/useAvatarSetup.d.ts +20 -0
- package/dist/types/Astro/hooks/useAvatarSetup.d.ts.map +1 -0
- package/dist/types/Astro/hooks/useDotAnimation.d.ts +10 -0
- package/dist/types/Astro/hooks/useDotAnimation.d.ts.map +1 -0
- package/dist/types/Astro/hooks/useMovement.d.ts +6 -0
- package/dist/types/Astro/hooks/useMovement.d.ts.map +1 -0
- package/dist/types/Astro/types/index.d.ts +79 -0
- package/dist/types/Astro/types/index.d.ts.map +1 -0
- package/dist/types/Astro/utils/helpers.d.ts +7 -0
- package/dist/types/Astro/utils/helpers.d.ts.map +1 -0
- package/dist/types/Astro/utils/index.d.ts +4 -0
- package/dist/types/Astro/utils/index.d.ts.map +1 -0
- package/dist/types/Astro/utils/logs.d.ts +2 -0
- package/dist/types/Astro/utils/logs.d.ts.map +1 -0
- package/dist/types/Astro/utils/pathGeneration.d.ts +7 -0
- package/dist/types/Astro/utils/pathGeneration.d.ts.map +1 -0
- package/dist/types/Astro/utils/positioning.d.ts +3 -0
- package/dist/types/Astro/utils/positioning.d.ts.map +1 -0
- package/dist/types/__tests__/spec-setup.d.ts +2 -0
- package/dist/types/__tests__/spec-setup.d.ts.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/package.json +87 -0
package/README.md
ADDED
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
# @wix/ai-assistant-avatar Usage Guide <img width="34" height="34" alt="Avatar (1)" src="https://github.com/user-attachments/assets/3f667860-eaa6-4cc4-bb9a-1d9d6e493c3a" />
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
`@wix/ai-assistant-avatar` is a React component library that provides an animated avatar (Astro) for AI assistant interfaces. The avatar uses `@wix/aria-ai-avatar` to provide smooth, interactive animations including eye tracking, state transitions, and movement animations.
|
|
6
|
+
|
|
7
|
+
### Key Features
|
|
8
|
+
|
|
9
|
+
- **Animated Avatar Component**: Animated character with multiple states powered by `@wix/aria-ai-avatar`
|
|
10
|
+
- **Eye Tracking**: Automatic eye movement following mouse cursor or typing position
|
|
11
|
+
- **State Management**: Multiple animation states (idle, loading, thinking, etc.)
|
|
12
|
+
- **Smooth Transitions**: Coordinated animations for moving between UI positions
|
|
13
|
+
- **Imperative API**: Full control via ref methods for programmatic animation control
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
yarn add @wix/ai-assistant-avatar
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Peer Dependencies
|
|
22
|
+
|
|
23
|
+
- `react`: `^16.8.0` or higher
|
|
24
|
+
- `react-dom`: `^16.8.0` or higher
|
|
25
|
+
|
|
26
|
+
### Runtime Dependencies
|
|
27
|
+
|
|
28
|
+
The package includes these dependencies (automatically installed):
|
|
29
|
+
- `@wix/aria-ai-avatar`: Avatar animation runtime
|
|
30
|
+
- `classnames`: CSS class name utilities
|
|
31
|
+
|
|
32
|
+
## Basic Usage
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
import React, { useRef } from 'react';
|
|
36
|
+
import { AiAssistantAvatar, AstroRef } from '@wix/ai-assistant-avatar';
|
|
37
|
+
|
|
38
|
+
function MyComponent() {
|
|
39
|
+
const avatarRef = useRef<AstroRef>(null);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div>
|
|
43
|
+
<AiAssistantAvatar ref={avatarRef} />
|
|
44
|
+
<button onClick={() => avatarRef.current?.trigger.idle()}>
|
|
45
|
+
Reset to Idle
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## API Reference
|
|
53
|
+
|
|
54
|
+
### Component Props (`AstroProps`)
|
|
55
|
+
|
|
56
|
+
| Prop | Type | Default | Description |
|
|
57
|
+
|------|------|---------|-------------|
|
|
58
|
+
| `mode` | `'light' \| 'dark'` | lib default | Color mode of the avatar |
|
|
59
|
+
| `variant` | `'2d' \| '3d'` | lib default | Visual variant of the avatar |
|
|
60
|
+
|
|
61
|
+
The avatar uses fixed dimensions of 94x94 pixels (defined in `ASTRO_SIZE`).
|
|
62
|
+
|
|
63
|
+
### Ref API (`AstroRef`)
|
|
64
|
+
|
|
65
|
+
The component exposes an imperative handle via ref:
|
|
66
|
+
|
|
67
|
+
#### Animation Triggers
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
trigger: {
|
|
71
|
+
idle: () => Promise<void>; // Switch to idle state
|
|
72
|
+
undo: () => Promise<void>; // Undo event animation
|
|
73
|
+
ideaSpark: () => Promise<void>; // Idea spark event animation
|
|
74
|
+
boredom: () => Promise<void>; // Toggle between SLEEPING and IDLE states
|
|
75
|
+
bigLoader: () => Promise<void>; // Toggle between BIG_LOADER and IDLE states
|
|
76
|
+
smallLoader: () => Promise<void>; // Toggle to SMALL_LOADER (from SMALL state)
|
|
77
|
+
shrink: () => Promise<void>; // Toggle between SMALL and IDLE states
|
|
78
|
+
publish: () => Promise<void>; // Publish event animation
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### Visibility & Interaction
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
hide: () => void; // Hide the avatar
|
|
86
|
+
show: () => void; // Show the avatar
|
|
87
|
+
onMouseMove: (clientX: number, clientY: number) => void; // Track mouse for eye movement
|
|
88
|
+
onUserTyping: (caretX: number, caretY: number) => void; // Track typing position
|
|
89
|
+
onTravelHomeFrom: (x: number, y: number, options: MoveOptions) => Promise<void>; // Animate from offset TO home position
|
|
90
|
+
onTravelAwayTo: (x: number, y: number, options: MoveOptions) => Promise<void>; // Animate from home TO offset position
|
|
91
|
+
changeAstroColor: (color: string) => void; // Change avatar color using any valid CSS color string (e.g. '#ff0000', 'rgb(255,0,0)')
|
|
92
|
+
toggleAvatarBackground: () => void; // Toggle avatar background visibility
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### State Properties
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
avatarHidden: boolean; // Whether the avatar is hidden
|
|
99
|
+
getState: () => AvatarState; // Get current animation state
|
|
100
|
+
wrapper: HTMLDivElement | null; // DOM wrapper element
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Examples
|
|
104
|
+
|
|
105
|
+
### Example 1: State-Based Chat Avatar
|
|
106
|
+
|
|
107
|
+
Complete example showing how to control avatar animations based on chat state, with mouse tracking:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import React, { useRef, useEffect } from 'react';
|
|
111
|
+
import { AiAssistantAvatar, AstroRef } from '@wix/ai-assistant-avatar';
|
|
112
|
+
|
|
113
|
+
function ChatAvatar({
|
|
114
|
+
isLoading,
|
|
115
|
+
hasNewMessage
|
|
116
|
+
}: {
|
|
117
|
+
isLoading: boolean;
|
|
118
|
+
hasNewMessage: boolean;
|
|
119
|
+
}) {
|
|
120
|
+
const avatarRef = useRef<AstroRef>(null);
|
|
121
|
+
|
|
122
|
+
// Update avatar state based on chat status
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
if (isLoading) {
|
|
125
|
+
avatarRef.current?.trigger.bigLoader();
|
|
126
|
+
} else if (hasNewMessage) {
|
|
127
|
+
avatarRef.current?.trigger.ideaSpark();
|
|
128
|
+
setTimeout(() => avatarRef.current?.trigger.idle(), 1000);
|
|
129
|
+
} else {
|
|
130
|
+
avatarRef.current?.trigger.idle();
|
|
131
|
+
}
|
|
132
|
+
}, [isLoading, hasNewMessage]);
|
|
133
|
+
|
|
134
|
+
// Enable eye tracking with mouse movement
|
|
135
|
+
useEffect(() => {
|
|
136
|
+
const handleMouseMove = (e: MouseEvent) => {
|
|
137
|
+
avatarRef.current?.onMouseMove(e.clientX, e.clientY);
|
|
138
|
+
};
|
|
139
|
+
window.addEventListener('mousemove', handleMouseMove);
|
|
140
|
+
return () => window.removeEventListener('mousemove', handleMouseMove);
|
|
141
|
+
}, []);
|
|
142
|
+
|
|
143
|
+
return <AiAssistantAvatar ref={avatarRef} />;
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### Example 2: Single Instance with Portal Pattern
|
|
148
|
+
|
|
149
|
+
For complex UIs where the avatar moves between positions (input box, messages, welcome screen), use a single avatar instance with React portals:
|
|
150
|
+
|
|
151
|
+
```tsx
|
|
152
|
+
import React, { useRef, useState, useCallback, useEffect } from 'react';
|
|
153
|
+
import { createPortal } from 'react-dom';
|
|
154
|
+
import { AiAssistantAvatar, AstroRef, AvatarState } from '@wix/ai-assistant-avatar';
|
|
155
|
+
|
|
156
|
+
function AvatarManager() {
|
|
157
|
+
const avatarRef = useRef<AstroRef>(null);
|
|
158
|
+
const inputSlotRef = useRef<HTMLDivElement>(null);
|
|
159
|
+
const messageSlotRef = useRef<HTMLDivElement>(null);
|
|
160
|
+
|
|
161
|
+
const [activeSlot, setActiveSlot] = useState<HTMLDivElement | null>(null);
|
|
162
|
+
const [previousPosition, setPreviousPosition] = useState<DOMRect | null>(null);
|
|
163
|
+
const [moveOptions, setMoveOptions] = useState({ endState: AvatarState.IDLE });
|
|
164
|
+
|
|
165
|
+
// Animate when slot changes
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
if (!avatarRef.current || !activeSlot) return;
|
|
168
|
+
|
|
169
|
+
const currentRect = avatarRef.current.wrapper?.getBoundingClientRect();
|
|
170
|
+
if (currentRect) {
|
|
171
|
+
const deltaX = previousPosition ? previousPosition.x - currentRect.x : 0;
|
|
172
|
+
const deltaY = previousPosition ? previousPosition.y - currentRect.y : 0;
|
|
173
|
+
|
|
174
|
+
avatarRef.current.onTravelHomeFrom(deltaX, deltaY, moveOptions).then(() => {
|
|
175
|
+
setPreviousPosition(currentRect);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}, [activeSlot]);
|
|
179
|
+
|
|
180
|
+
const moveToMessage = useCallback(() => {
|
|
181
|
+
if (!messageSlotRef.current) return;
|
|
182
|
+
|
|
183
|
+
// Capture current position before moving
|
|
184
|
+
const currentRect = avatarRef.current?.wrapper?.getBoundingClientRect();
|
|
185
|
+
if (currentRect) setPreviousPosition(currentRect);
|
|
186
|
+
|
|
187
|
+
setMoveOptions({ endState: AvatarState.SMALL_LOADER });
|
|
188
|
+
setActiveSlot(messageSlotRef.current);
|
|
189
|
+
}, []);
|
|
190
|
+
|
|
191
|
+
const moveToInput = useCallback(() => {
|
|
192
|
+
if (!inputSlotRef.current) return;
|
|
193
|
+
|
|
194
|
+
const currentRect = avatarRef.current?.wrapper?.getBoundingClientRect();
|
|
195
|
+
if (currentRect) setPreviousPosition(currentRect);
|
|
196
|
+
|
|
197
|
+
setMoveOptions({ endState: AvatarState.IDLE });
|
|
198
|
+
setActiveSlot(inputSlotRef.current);
|
|
199
|
+
}, []);
|
|
200
|
+
|
|
201
|
+
return (
|
|
202
|
+
<>
|
|
203
|
+
{/* Slot placeholders - avatar will portal into the active one */}
|
|
204
|
+
<div ref={inputSlotRef} />
|
|
205
|
+
<div ref={messageSlotRef} />
|
|
206
|
+
|
|
207
|
+
{/* Single avatar instance rendered via portal */}
|
|
208
|
+
{activeSlot && createPortal(
|
|
209
|
+
<AiAssistantAvatar ref={avatarRef} />,
|
|
210
|
+
activeSlot
|
|
211
|
+
)}
|
|
212
|
+
|
|
213
|
+
<button onClick={moveToMessage}>Move to Message</button>
|
|
214
|
+
<button onClick={moveToInput}>Move to Input</button>
|
|
215
|
+
</>
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Example 3: Typing Position Tracking
|
|
221
|
+
|
|
222
|
+
Track user's typing position so avatar eyes follow the caret:
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
function InputWithAvatar() {
|
|
226
|
+
const avatarRef = useRef<AstroRef>(null);
|
|
227
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
228
|
+
|
|
229
|
+
const handleInputChange = () => {
|
|
230
|
+
const input = inputRef.current;
|
|
231
|
+
if (!input || !avatarRef.current) return;
|
|
232
|
+
|
|
233
|
+
// Get caret position
|
|
234
|
+
const selectionStart = input.selectionStart || 0;
|
|
235
|
+
const rect = input.getBoundingClientRect();
|
|
236
|
+
|
|
237
|
+
// Calculate approximate caret position
|
|
238
|
+
const textBeforeCaret = input.value.substring(0, selectionStart);
|
|
239
|
+
const canvas = document.createElement('canvas');
|
|
240
|
+
const context = canvas.getContext('2d');
|
|
241
|
+
|
|
242
|
+
if (context) {
|
|
243
|
+
context.font = getComputedStyle(input).font;
|
|
244
|
+
const textWidth = context.measureText(textBeforeCaret).width;
|
|
245
|
+
const caretX = rect.left + textWidth;
|
|
246
|
+
const caretY = rect.top + rect.height / 2;
|
|
247
|
+
|
|
248
|
+
// Avatar eyes will follow the caret
|
|
249
|
+
avatarRef.current.onUserTyping(caretX, caretY);
|
|
250
|
+
}
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<div>
|
|
255
|
+
<input ref={inputRef} onChange={handleInputChange} />
|
|
256
|
+
<AiAssistantAvatar ref={avatarRef} />
|
|
257
|
+
</div>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Configuration Constants
|
|
263
|
+
|
|
264
|
+
### Animation States (`AvatarState`)
|
|
265
|
+
|
|
266
|
+
The `AvatarState` enum is exported from `@wix/ai-assistant-avatar`:
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import { AvatarState } from '@wix/ai-assistant-avatar';
|
|
270
|
+
|
|
271
|
+
AvatarState.IDLE // Default idle state
|
|
272
|
+
AvatarState.SMALL // Shrunk/minimized state
|
|
273
|
+
AvatarState.SMALL_LOADER // Small loading indicator
|
|
274
|
+
AvatarState.BIG_LOADER // Large loading indicator
|
|
275
|
+
AvatarState.SLEEPING // Boredom/sleeping state
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Size Constants (`ASTRO_SIZE`)
|
|
279
|
+
|
|
280
|
+
```typescript
|
|
281
|
+
ASTRO_SIZE = {
|
|
282
|
+
WIDTH: 94,
|
|
283
|
+
HEIGHT: 94,
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Advanced Patterns
|
|
288
|
+
|
|
289
|
+
### Visibility Control
|
|
290
|
+
|
|
291
|
+
Control avatar visibility programmatically:
|
|
292
|
+
|
|
293
|
+
```tsx
|
|
294
|
+
// Hide/show avatar
|
|
295
|
+
avatarRef.current?.hide();
|
|
296
|
+
avatarRef.current?.show();
|
|
297
|
+
|
|
298
|
+
// Check if hidden
|
|
299
|
+
const isHidden = avatarRef.current?.avatarHidden;
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Background Toggle
|
|
303
|
+
|
|
304
|
+
Toggle avatar background visibility:
|
|
305
|
+
|
|
306
|
+
```tsx
|
|
307
|
+
avatarRef.current?.toggleAvatarBackground();
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## Best Practices
|
|
311
|
+
|
|
312
|
+
1. **Single Instance with Portals**: Use a single avatar instance with `createPortal` for moving between UI positions
|
|
313
|
+
2. **Animation Coordination**: Use the appropriate travel method based on direction:
|
|
314
|
+
- `onTravelHomeFrom(x, y)` - Avatar arriving: animates FROM offset TO home position
|
|
315
|
+
- `onTravelAwayTo(x, y)` - Avatar departing: animates FROM home TO offset position
|
|
316
|
+
3. **Performance**: Control visibility with `hide()`/`show()` methods
|
|
317
|
+
4. **State Management**: Use `AvatarState` enum instead of magic strings
|
|
318
|
+
5. **Error Handling**: Wrap animation calls in try-catch blocks
|
|
319
|
+
|
|
320
|
+
## Troubleshooting
|
|
321
|
+
|
|
322
|
+
**Avatar not appearing**: Ensure ref is initialized and the portal target element exists in the DOM
|
|
323
|
+
|
|
324
|
+
**Animations not triggering**: Verify ref is attached and methods are called after mount
|
|
325
|
+
|
|
326
|
+
**Eye tracking not working**: Ensure `onMouseMove` receives viewport coordinates (`clientX`, `clientY`)
|
|
327
|
+
|
|
328
|
+
**Position transitions not smooth**: Check that `onTravelHomeFrom` delta coordinates are calculated correctly (previous position minus current position)
|
|
329
|
+
|
|
330
|
+
**Portal not rendering**: Ensure `activeSlot` state is set to a valid DOM element before rendering the portal
|
|
331
|
+
|
|
332
|
+
## TypeScript Support
|
|
333
|
+
|
|
334
|
+
The package includes full TypeScript definitions:
|
|
335
|
+
|
|
336
|
+
```typescript
|
|
337
|
+
import type { AstroRef, AstroProps, Position, MoveOptions } from '@wix/ai-assistant-avatar';
|
|
338
|
+
import { AvatarState } from '@wix/ai-assistant-avatar';
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
## Additional Resources
|
|
342
|
+
|
|
343
|
+
- Example Implementation: See `packages/ai-assistant-chat-ui` for a complete integration example with the portal pattern
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
exports.__esModule = true;
|
|
5
|
+
exports.AiAssistantAvatar = void 0;
|
|
6
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
7
|
+
var _AstroModule = _interopRequireDefault(require("./Astro.module.scss"));
|
|
8
|
+
var _config = require("./config");
|
|
9
|
+
var _hooks = require("./hooks");
|
|
10
|
+
var _DotTrail = require("./components/DotTrail");
|
|
11
|
+
var _ariaAiAvatar = require("@wix/aria-ai-avatar");
|
|
12
|
+
var _jsxFileName = "/home/builduser/work/4baef6c1cf3e5e6a/packages/ai-assistant-avatar/dist/cjs/Astro/Astro.tsx";
|
|
13
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
14
|
+
const AiAssistantAvatar = exports.AiAssistantAvatar = /*#__PURE__*/(0, _react.forwardRef)(({
|
|
15
|
+
mode,
|
|
16
|
+
variant
|
|
17
|
+
}, ref) => {
|
|
18
|
+
const wrapperRef = (0, _react.useRef)(null);
|
|
19
|
+
const typingTimeout = (0, _react.useRef)(null);
|
|
20
|
+
const [isTyping, setIsTyping] = (0, _react.useState)(false);
|
|
21
|
+
const [showBg, setShowBg] = (0, _react.useState)(false);
|
|
22
|
+
const {
|
|
23
|
+
AriaAvatar,
|
|
24
|
+
avatarHidden,
|
|
25
|
+
setAvatarHidden
|
|
26
|
+
} = (0, _hooks.useAvatarSetup)({
|
|
27
|
+
mode,
|
|
28
|
+
variant
|
|
29
|
+
});
|
|
30
|
+
const {
|
|
31
|
+
setCenter
|
|
32
|
+
} = (0, _hooks.useMovement)(wrapperRef, _config.ASTRO_SIZE.WIDTH, _config.ASTRO_SIZE.HEIGHT);
|
|
33
|
+
const {
|
|
34
|
+
leadDotRef,
|
|
35
|
+
trailRefs,
|
|
36
|
+
hideDots,
|
|
37
|
+
moveFromOffsetWithDots,
|
|
38
|
+
moveToOffsetWithDots
|
|
39
|
+
} = (0, _hooks.useDotAnimation)(setCenter, setAvatarHidden, AriaAvatar.setState);
|
|
40
|
+
const onTravelHomeFrom = async (x, y, options) => {
|
|
41
|
+
const pos = {
|
|
42
|
+
x,
|
|
43
|
+
y
|
|
44
|
+
};
|
|
45
|
+
await moveFromOffsetWithDots(pos, options);
|
|
46
|
+
};
|
|
47
|
+
const onTravelAwayTo = async (x, y, options) => {
|
|
48
|
+
const pos = {
|
|
49
|
+
x,
|
|
50
|
+
y
|
|
51
|
+
};
|
|
52
|
+
await moveToOffsetWithDots(pos, options);
|
|
53
|
+
};
|
|
54
|
+
const onMouseMove = (clientX, clientY) => {
|
|
55
|
+
if (isTyping) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
AriaAvatar.lookAt(clientX, clientY);
|
|
59
|
+
};
|
|
60
|
+
const onUserTyping = (caretX, caretY) => {
|
|
61
|
+
try {
|
|
62
|
+
setIsTyping(true);
|
|
63
|
+
AriaAvatar.lookAt(caretX, caretY);
|
|
64
|
+
if (typingTimeout.current) {
|
|
65
|
+
clearTimeout(typingTimeout.current);
|
|
66
|
+
}
|
|
67
|
+
typingTimeout.current = setTimeout(() => {
|
|
68
|
+
setIsTyping(false);
|
|
69
|
+
}, 500);
|
|
70
|
+
} catch (err) {
|
|
71
|
+
console.error('[Astro] Error tracking typing:', err);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
(0, _react.useEffect)(() => {
|
|
75
|
+
return () => {
|
|
76
|
+
if (typingTimeout.current) {
|
|
77
|
+
clearTimeout(typingTimeout.current);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}, []);
|
|
81
|
+
const hideAvatar = ({
|
|
82
|
+
withDots = false
|
|
83
|
+
} = {}) => {
|
|
84
|
+
setAvatarHidden(true);
|
|
85
|
+
if (withDots) {
|
|
86
|
+
hideDots();
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
const showAvatar = () => {
|
|
90
|
+
setAvatarHidden(false);
|
|
91
|
+
};
|
|
92
|
+
(0, _react.useImperativeHandle)(ref, () => ({
|
|
93
|
+
trigger: {
|
|
94
|
+
shrink: () => {
|
|
95
|
+
if (AriaAvatar.getState() === _ariaAiAvatar.AvatarState.SMALL) {
|
|
96
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.IDLE);
|
|
97
|
+
}
|
|
98
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.SMALL);
|
|
99
|
+
},
|
|
100
|
+
smallLoader: () => {
|
|
101
|
+
if (AriaAvatar.getState() === _ariaAiAvatar.AvatarState.SMALL) {
|
|
102
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.SMALL_LOADER);
|
|
103
|
+
}
|
|
104
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.SMALL);
|
|
105
|
+
},
|
|
106
|
+
pulse: () => Promise.resolve(),
|
|
107
|
+
idle: async () => {
|
|
108
|
+
if (AriaAvatar.getState() === _ariaAiAvatar.AvatarState.SMALL_LOADER) {
|
|
109
|
+
await AriaAvatar.setState(_ariaAiAvatar.AvatarState.SMALL);
|
|
110
|
+
}
|
|
111
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.IDLE);
|
|
112
|
+
},
|
|
113
|
+
undo: () => AriaAvatar.fireEvent(_ariaAiAvatar.AvatarEvent.UNDO_EVENT),
|
|
114
|
+
boredom: () => {
|
|
115
|
+
if (AriaAvatar.getState() === _ariaAiAvatar.AvatarState.SLEEPING) {
|
|
116
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.IDLE);
|
|
117
|
+
}
|
|
118
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.SLEEPING);
|
|
119
|
+
},
|
|
120
|
+
bigLoader: () => {
|
|
121
|
+
if (AriaAvatar.getState() === _ariaAiAvatar.AvatarState.BIG_LOADER) {
|
|
122
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.IDLE);
|
|
123
|
+
}
|
|
124
|
+
return AriaAvatar.setState(_ariaAiAvatar.AvatarState.BIG_LOADER);
|
|
125
|
+
},
|
|
126
|
+
ideaSpark: () => AriaAvatar.fireEvent(_ariaAiAvatar.AvatarEvent.IDEA_SPARK),
|
|
127
|
+
publish: () => AriaAvatar.fireEvent(_ariaAiAvatar.AvatarEvent.PUBLISH_EVENT)
|
|
128
|
+
},
|
|
129
|
+
avatarHidden,
|
|
130
|
+
wrapper: wrapperRef.current,
|
|
131
|
+
getState: AriaAvatar.getState,
|
|
132
|
+
onMouseMove,
|
|
133
|
+
onUserTyping,
|
|
134
|
+
onTravelHomeFrom,
|
|
135
|
+
onTravelAwayTo,
|
|
136
|
+
changeAstroColor: color => {
|
|
137
|
+
AriaAvatar.setAvatarColor(color);
|
|
138
|
+
},
|
|
139
|
+
toggleAvatarBackground: () => {
|
|
140
|
+
if (showBg) {
|
|
141
|
+
setShowBg(false);
|
|
142
|
+
AriaAvatar.hideBg();
|
|
143
|
+
} else {
|
|
144
|
+
setShowBg(true);
|
|
145
|
+
AriaAvatar.showBg();
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
hide: hideAvatar,
|
|
149
|
+
show: showAvatar
|
|
150
|
+
}));
|
|
151
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
152
|
+
className: _AstroModule.default.avatar,
|
|
153
|
+
__self: void 0,
|
|
154
|
+
__source: {
|
|
155
|
+
fileName: _jsxFileName,
|
|
156
|
+
lineNumber: 172,
|
|
157
|
+
columnNumber: 7
|
|
158
|
+
}
|
|
159
|
+
}, /*#__PURE__*/_react.default.createElement(_DotTrail.DotTrail, {
|
|
160
|
+
leadDotRef: leadDotRef,
|
|
161
|
+
trailRefs: trailRefs,
|
|
162
|
+
__self: void 0,
|
|
163
|
+
__source: {
|
|
164
|
+
fileName: _jsxFileName,
|
|
165
|
+
lineNumber: 173,
|
|
166
|
+
columnNumber: 9
|
|
167
|
+
}
|
|
168
|
+
}), /*#__PURE__*/_react.default.createElement("div", {
|
|
169
|
+
ref: wrapperRef,
|
|
170
|
+
className: _AstroModule.default.astro,
|
|
171
|
+
style: {
|
|
172
|
+
opacity: avatarHidden ? 0 : 1
|
|
173
|
+
},
|
|
174
|
+
__self: void 0,
|
|
175
|
+
__source: {
|
|
176
|
+
fileName: _jsxFileName,
|
|
177
|
+
lineNumber: 175,
|
|
178
|
+
columnNumber: 9
|
|
179
|
+
}
|
|
180
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
181
|
+
style: {
|
|
182
|
+
width: _config.ASTRO_SIZE.WIDTH,
|
|
183
|
+
height: _config.ASTRO_SIZE.HEIGHT
|
|
184
|
+
},
|
|
185
|
+
__self: void 0,
|
|
186
|
+
__source: {
|
|
187
|
+
fileName: _jsxFileName,
|
|
188
|
+
lineNumber: 182,
|
|
189
|
+
columnNumber: 11
|
|
190
|
+
}
|
|
191
|
+
}, /*#__PURE__*/_react.default.createElement(AriaAvatar.AriaAvatar, {
|
|
192
|
+
__self: void 0,
|
|
193
|
+
__source: {
|
|
194
|
+
fileName: _jsxFileName,
|
|
195
|
+
lineNumber: 183,
|
|
196
|
+
columnNumber: 13
|
|
197
|
+
}
|
|
198
|
+
}))));
|
|
199
|
+
});
|
|
200
|
+
//# sourceMappingURL=Astro.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireWildcard","require","_AstroModule","_interopRequireDefault","_config","_hooks","_DotTrail","_ariaAiAvatar","_jsxFileName","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","AiAssistantAvatar","exports","forwardRef","mode","variant","ref","wrapperRef","useRef","typingTimeout","isTyping","setIsTyping","useState","showBg","setShowBg","AriaAvatar","avatarHidden","setAvatarHidden","useAvatarSetup","setCenter","useMovement","ASTRO_SIZE","WIDTH","HEIGHT","leadDotRef","trailRefs","hideDots","moveFromOffsetWithDots","moveToOffsetWithDots","useDotAnimation","setState","onTravelHomeFrom","x","y","options","pos","onTravelAwayTo","onMouseMove","clientX","clientY","lookAt","onUserTyping","caretX","caretY","current","clearTimeout","setTimeout","err","console","error","useEffect","hideAvatar","withDots","showAvatar","useImperativeHandle","trigger","shrink","getState","AvatarState","SMALL","IDLE","smallLoader","SMALL_LOADER","pulse","Promise","resolve","idle","undo","fireEvent","AvatarEvent","UNDO_EVENT","boredom","SLEEPING","bigLoader","BIG_LOADER","ideaSpark","IDEA_SPARK","publish","PUBLISH_EVENT","wrapper","changeAstroColor","color","setAvatarColor","toggleAvatarBackground","hideBg","hide","show","createElement","className","s","avatar","__self","__source","fileName","lineNumber","columnNumber","DotTrail","astro","style","opacity","width","height"],"sources":["../../../src/Astro/Astro.tsx"],"sourcesContent":["import React, {\n forwardRef,\n Ref,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from 'react';\nimport s from './Astro.module.scss';\nimport type { AstroRef, AstroProps, MoveOptions } from './types';\nimport { ASTRO_SIZE } from './config';\nimport { useAvatarSetup, useMovement, useDotAnimation } from './hooks';\nimport { DotTrail } from './components/DotTrail';\nimport { AvatarEvent, AvatarState } from '@wix/aria-ai-avatar';\n\nexport const AiAssistantAvatar = forwardRef<AstroRef, AstroProps>(\n ({ mode, variant }, ref: Ref<AstroRef> | null) => {\n const wrapperRef = useRef<HTMLDivElement | null>(null);\n const typingTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const [isTyping, setIsTyping] = useState(false);\n\n const [showBg, setShowBg] = useState(false);\n\n const { AriaAvatar, avatarHidden, setAvatarHidden } = useAvatarSetup({\n mode,\n variant,\n });\n\n const { setCenter } = useMovement(\n wrapperRef,\n ASTRO_SIZE.WIDTH,\n ASTRO_SIZE.HEIGHT,\n );\n\n const {\n leadDotRef,\n trailRefs,\n hideDots,\n moveFromOffsetWithDots,\n moveToOffsetWithDots,\n } = useDotAnimation(setCenter, setAvatarHidden, AriaAvatar.setState);\n\n const onTravelHomeFrom = async (\n x: number,\n y: number,\n options?: MoveOptions,\n ) => {\n const pos = { x, y };\n await moveFromOffsetWithDots(pos, options);\n };\n\n const onTravelAwayTo = async (\n x: number,\n y: number,\n options?: MoveOptions,\n ) => {\n const pos = { x, y };\n await moveToOffsetWithDots(pos, options);\n };\n\n const onMouseMove = (clientX: number, clientY: number) => {\n if (isTyping) {\n return;\n }\n\n AriaAvatar.lookAt(clientX, clientY);\n };\n\n const onUserTyping = (caretX: number, caretY: number) => {\n try {\n setIsTyping(true);\n AriaAvatar.lookAt(caretX, caretY);\n\n if (typingTimeout.current) {\n clearTimeout(typingTimeout.current);\n }\n\n typingTimeout.current = setTimeout(() => {\n setIsTyping(false);\n }, 500);\n } catch (err) {\n console.error('[Astro] Error tracking typing:', err);\n }\n };\n\n useEffect(() => {\n return () => {\n if (typingTimeout.current) {\n clearTimeout(typingTimeout.current);\n }\n };\n }, []);\n\n const hideAvatar = ({ withDots = false }: { withDots?: boolean } = {}) => {\n setAvatarHidden(true);\n\n if (withDots) {\n hideDots();\n }\n };\n\n const showAvatar = () => {\n setAvatarHidden(false);\n };\n\n useImperativeHandle(ref, () => ({\n trigger: {\n shrink: () => {\n if (AriaAvatar.getState() === AvatarState.SMALL) {\n return AriaAvatar.setState(AvatarState.IDLE);\n }\n return AriaAvatar.setState(AvatarState.SMALL);\n },\n smallLoader: () => {\n if (AriaAvatar.getState() === AvatarState.SMALL) {\n return AriaAvatar.setState(AvatarState.SMALL_LOADER);\n }\n return AriaAvatar.setState(AvatarState.SMALL);\n },\n pulse: () => Promise.resolve(),\n idle: async () => {\n if (AriaAvatar.getState() === AvatarState.SMALL_LOADER) {\n await AriaAvatar.setState(AvatarState.SMALL);\n }\n return AriaAvatar.setState(AvatarState.IDLE);\n },\n undo: () => AriaAvatar.fireEvent(AvatarEvent.UNDO_EVENT),\n boredom: () => {\n if (AriaAvatar.getState() === AvatarState.SLEEPING) {\n return AriaAvatar.setState(AvatarState.IDLE);\n }\n return AriaAvatar.setState(AvatarState.SLEEPING);\n },\n bigLoader: () => {\n if (AriaAvatar.getState() === AvatarState.BIG_LOADER) {\n return AriaAvatar.setState(AvatarState.IDLE);\n }\n return AriaAvatar.setState(AvatarState.BIG_LOADER);\n },\n ideaSpark: () => AriaAvatar.fireEvent(AvatarEvent.IDEA_SPARK),\n publish: () => AriaAvatar.fireEvent(AvatarEvent.PUBLISH_EVENT),\n },\n avatarHidden,\n wrapper: wrapperRef.current,\n getState: AriaAvatar.getState,\n\n onMouseMove,\n onUserTyping,\n onTravelHomeFrom,\n onTravelAwayTo,\n\n changeAstroColor: (color: string) => {\n AriaAvatar.setAvatarColor(color);\n },\n\n toggleAvatarBackground: () => {\n if (showBg) {\n setShowBg(false);\n AriaAvatar.hideBg();\n } else {\n setShowBg(true);\n AriaAvatar.showBg();\n }\n },\n\n hide: hideAvatar,\n show: showAvatar,\n }));\n\n return (\n <div className={s.avatar}>\n <DotTrail leadDotRef={leadDotRef} trailRefs={trailRefs} />\n\n <div\n ref={wrapperRef}\n className={s.astro}\n style={{\n opacity: avatarHidden ? 0 : 1,\n }}\n >\n <div style={{ width: ASTRO_SIZE.WIDTH, height: ASTRO_SIZE.HEIGHT }}>\n <AriaAvatar.AriaAvatar />\n </div>\n </div>\n </div>\n );\n },\n);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
@mixin position {
|
|
2
|
+
opacity: 0;
|
|
3
|
+
margin: 16px;
|
|
4
|
+
border-radius: 50%;
|
|
5
|
+
position: absolute;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
$astroZIndex: 3;
|
|
9
|
+
|
|
10
|
+
.avatar {
|
|
11
|
+
width: 32px;
|
|
12
|
+
height: 32px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.astro {
|
|
16
|
+
@include position;
|
|
17
|
+
z-index: $astroZIndex;
|
|
18
|
+
transition: opacity 80ms linear;
|
|
19
|
+
transform: translate3d(0, 0, 0);
|
|
20
|
+
|
|
21
|
+
clip-path: inset(23px 23px 23px 23px); // cut off the edges to stop hijacking mouse events. maybe we need to reduce canvas size itself instead of this.
|
|
22
|
+
|
|
23
|
+
@starting-style {
|
|
24
|
+
opacity: 0;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.leadDot {
|
|
29
|
+
@include position;
|
|
30
|
+
z-index: $astroZIndex - 1;
|
|
31
|
+
transition: opacity 150ms ease-in-out;
|
|
32
|
+
|
|
33
|
+
@starting-style {
|
|
34
|
+
opacity: 0;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.trailDot {
|
|
39
|
+
@include position;
|
|
40
|
+
z-index: $astroZIndex - 2;
|
|
41
|
+
transition: opacity 150ms ease-in-out;
|
|
42
|
+
|
|
43
|
+
@starting-style {
|
|
44
|
+
opacity: 0;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
exports.__esModule = true;
|
|
5
|
+
exports.DotTrail = void 0;
|
|
6
|
+
var _react = _interopRequireDefault(require("react"));
|
|
7
|
+
var _config = require("../config");
|
|
8
|
+
var _AstroModule = _interopRequireDefault(require("../Astro.module.scss"));
|
|
9
|
+
var _jsxFileName = "/home/builduser/work/4baef6c1cf3e5e6a/packages/ai-assistant-avatar/dist/cjs/Astro/components/DotTrail.tsx";
|
|
10
|
+
const DotTrail = ({
|
|
11
|
+
leadDotRef,
|
|
12
|
+
trailRefs
|
|
13
|
+
}) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
14
|
+
ref: leadDotRef,
|
|
15
|
+
className: _AstroModule.default.leadDot,
|
|
16
|
+
style: {
|
|
17
|
+
width: _config.ANIMATION_CONFIG.DOT_SIZE,
|
|
18
|
+
height: _config.ANIMATION_CONFIG.DOT_SIZE,
|
|
19
|
+
background: _config.ANIMATION_CONFIG.DOT_COLOR
|
|
20
|
+
},
|
|
21
|
+
__self: void 0,
|
|
22
|
+
__source: {
|
|
23
|
+
fileName: _jsxFileName,
|
|
24
|
+
lineNumber: 12,
|
|
25
|
+
columnNumber: 5
|
|
26
|
+
}
|
|
27
|
+
}), Array.from({
|
|
28
|
+
length: _config.ANIMATION_CONFIG.TRAIL_COUNT
|
|
29
|
+
}).map((_, i) => /*#__PURE__*/_react.default.createElement("div", {
|
|
30
|
+
key: i,
|
|
31
|
+
ref: el => trailRefs.current[i] = el,
|
|
32
|
+
className: _AstroModule.default.trailDot,
|
|
33
|
+
style: {
|
|
34
|
+
width: _config.ANIMATION_CONFIG.DOT_SIZE,
|
|
35
|
+
height: _config.ANIMATION_CONFIG.DOT_SIZE,
|
|
36
|
+
background: _config.ANIMATION_CONFIG.DOT_COLOR,
|
|
37
|
+
filter: _config.ANIMATION_CONFIG.TRAIL_BLUR ? `blur(${_config.ANIMATION_CONFIG.TRAIL_BLUR}px)` : 'none'
|
|
38
|
+
},
|
|
39
|
+
__self: void 0,
|
|
40
|
+
__source: {
|
|
41
|
+
fileName: _jsxFileName,
|
|
42
|
+
lineNumber: 23,
|
|
43
|
+
columnNumber: 7
|
|
44
|
+
}
|
|
45
|
+
})));
|
|
46
|
+
exports.DotTrail = DotTrail;
|
|
47
|
+
//# sourceMappingURL=DotTrail.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_react","_interopRequireDefault","require","_config","_AstroModule","_jsxFileName","DotTrail","leadDotRef","trailRefs","default","createElement","Fragment","ref","className","s","leadDot","style","width","ANIMATION_CONFIG","DOT_SIZE","height","background","DOT_COLOR","__self","__source","fileName","lineNumber","columnNumber","Array","from","length","TRAIL_COUNT","map","_","i","key","el","current","trailDot","filter","TRAIL_BLUR","exports"],"sources":["../../../../src/Astro/components/DotTrail.tsx"],"sourcesContent":["import React, { MutableRefObject } from 'react';\nimport { ANIMATION_CONFIG } from '../config';\nimport s from '../Astro.module.scss';\n\ntype DotTrailProps = {\n leadDotRef: MutableRefObject<HTMLDivElement | null>;\n trailRefs: MutableRefObject<(HTMLDivElement | null)[]>;\n};\n\nexport const DotTrail = ({ leadDotRef, trailRefs }: DotTrailProps) => (\n <>\n <div\n ref={leadDotRef}\n className={s.leadDot}\n style={{\n width: ANIMATION_CONFIG.DOT_SIZE,\n height: ANIMATION_CONFIG.DOT_SIZE,\n background: ANIMATION_CONFIG.DOT_COLOR,\n }}\n />\n\n {Array.from({ length: ANIMATION_CONFIG.TRAIL_COUNT }).map((_, i) => (\n <div\n key={i}\n ref={(el) => (trailRefs.current[i] = el)}\n className={s.trailDot}\n style={{\n width: ANIMATION_CONFIG.DOT_SIZE,\n height: ANIMATION_CONFIG.DOT_SIZE,\n background: ANIMATION_CONFIG.DOT_COLOR,\n filter: ANIMATION_CONFIG.TRAIL_BLUR\n ? `blur(${ANIMATION_CONFIG.TRAIL_BLUR}px)`\n : 'none',\n }}\n />\n ))}\n </>\n);\n"],"mappings":";;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,OAAA,GAAAD,OAAA;AACA,IAAAE,YAAA,GAAAH,sBAAA,CAAAC,OAAA;AAAqC,IAAAG,YAAA;AAO9B,MAAMC,QAAQ,GAAGA,CAAC;EAAEC,UAAU;EAAEC;AAAyB,CAAC,kBAC/DR,MAAA,CAAAS,OAAA,CAAAC,aAAA,CAAAV,MAAA,CAAAS,OAAA,CAAAE,QAAA,qBACEX,MAAA,CAAAS,OAAA,CAAAC,aAAA;EACEE,GAAG,EAAEL,UAAW;EAChBM,SAAS,EAAEC,oBAAC,CAACC,OAAQ;EACrBC,KAAK,EAAE;IACLC,KAAK,EAAEC,wBAAgB,CAACC,QAAQ;IAChCC,MAAM,EAAEF,wBAAgB,CAACC,QAAQ;IACjCE,UAAU,EAAEH,wBAAgB,CAACI;EAC/B,CAAE;EAAAC,MAAA;EAAAC,QAAA;IAAAC,QAAA,EAAApB,YAAA;IAAAqB,UAAA;IAAAC,YAAA;EAAA;AAAA,CACH,CAAC,EAEDC,KAAK,CAACC,IAAI,CAAC;EAAEC,MAAM,EAAEZ,wBAAgB,CAACa;AAAY,CAAC,CAAC,CAACC,GAAG,CAAC,CAACC,CAAC,EAAEC,CAAC,kBAC7DlC,MAAA,CAAAS,OAAA,CAAAC,aAAA;EACEyB,GAAG,EAAED,CAAE;EACPtB,GAAG,EAAGwB,EAAE,IAAM5B,SAAS,CAAC6B,OAAO,CAACH,CAAC,CAAC,GAAGE,EAAI;EACzCvB,SAAS,EAAEC,oBAAC,CAACwB,QAAS;EACtBtB,KAAK,EAAE;IACLC,KAAK,EAAEC,wBAAgB,CAACC,QAAQ;IAChCC,MAAM,EAAEF,wBAAgB,CAACC,QAAQ;IACjCE,UAAU,EAAEH,wBAAgB,CAACI,SAAS;IACtCiB,MAAM,EAAErB,wBAAgB,CAACsB,UAAU,GAC/B,QAAQtB,wBAAgB,CAACsB,UAAU,KAAK,GACxC;EACN,CAAE;EAAAjB,MAAA;EAAAC,QAAA;IAAAC,QAAA,EAAApB,YAAA;IAAAqB,UAAA;IAAAC,YAAA;EAAA;AAAA,CACH,CACF,CACD,CACH;AAACc,OAAA,CAAAnC,QAAA,GAAAA,QAAA","ignoreList":[]}
|