@clikvn/showroom-visualizer 0.4.1-dev-11 → 0.4.1-dev-13
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/.claude/settings.local.json +19 -0
- package/CLAUDE.md +145 -145
- package/DEVELOPMENT.md +120 -120
- package/EXAMPLES.md +967 -967
- package/README.md +489 -489
- package/SETUP_COMPLETE.md +149 -149
- package/base.json +21 -21
- package/dist/components/SkinLayer/Floorplan/Minimap/test01.d.ts +15 -0
- package/dist/components/SkinLayer/Floorplan/Minimap/test01.d.ts.map +1 -0
- package/dist/components/SkinLayer/PoiDetailSlideIn/Detail.d.ts +1 -1
- package/dist/components/SkinLayer/PoiDetailSlideIn/Detail.d.ts.map +1 -1
- package/dist/components/SkinLayer/PoiDetailSlideIn/GroupActionButton.d.ts +1 -0
- package/dist/components/SkinLayer/PoiDetailSlideIn/GroupActionButton.d.ts.map +1 -1
- package/dist/fonts/icomoon.svg +633 -633
- package/dist/index.js +1 -1
- package/dist/web.d.ts.map +1 -1
- package/dist/web.js +1 -1
- package/example/CSS_HANDLING.md +141 -141
- package/example/FIXES_SUMMARY.md +131 -121
- package/example/PATH_ALIASES.md +102 -103
- package/example/README.md +63 -64
- package/example/index.html +12 -13
- package/example/package.json +25 -25
- package/example/postcss.config.cjs +6 -6
- package/example/tailwind.config.cjs +12 -12
- package/example/tsconfig.node.json +11 -12
- package/example/vite.config.ts +142 -142
- package/package.json +133 -133
- package/rollup.config.js +400 -400
- package/tailwind.config.cjs +151 -151
- package/dist/components/SkinLayer/Drawer/PoiHeader/index.d.ts +0 -16
- package/dist/components/SkinLayer/Drawer/PoiHeader/index.d.ts.map +0 -1
- package/dist/components/SkinLayer/Drawer/index.d.ts +0 -29
- package/dist/components/SkinLayer/Drawer/index.d.ts.map +0 -1
- package/dist/components/SkinLayer/PlayAll/index.d.ts +0 -8
- package/dist/components/SkinLayer/PlayAll/index.d.ts.map +0 -1
- package/dist/features/VirtualTourVisualizer/index.d.ts +0 -20
- package/dist/features/VirtualTourVisualizer/index.d.ts.map +0 -1
- package/dist/features/VirtualTourVisualizerUI/index.d.ts +0 -17
- package/dist/features/VirtualTourVisualizerUI/index.d.ts.map +0 -1
- package/dist/index.html +0 -36
- /package/dist/features/ShowroomVisualizer/{cssStyles.d.ts → CssStyles.d.ts} +0 -0
- /package/dist/features/ShowroomVisualizer/{cssStyles.d.ts.map → CssStyles.d.ts.map} +0 -0
package/README.md
CHANGED
|
@@ -1,489 +1,489 @@
|
|
|
1
|
-
# Showroom Visualizer
|
|
2
|
-
|
|
3
|
-
A powerful, flexible 360° virtual tour visualizer với **Headless Architecture** support.
|
|
4
|
-
|
|
5
|
-
## ✨ Features
|
|
6
|
-
|
|
7
|
-
- 🎨 **Flexible UI**: Sử dụng default UI hoặc build custom UI hoàn toàn
|
|
8
|
-
- 🔧 **Headless Hooks**: Full control với React hooks
|
|
9
|
-
- 📦 **Component Library**: Reusable components để compose custom layouts
|
|
10
|
-
- 🎯 **Type-safe**: Full TypeScript support
|
|
11
|
-
- ⚡ **Performance**: Optimized với React best practices
|
|
12
|
-
- 🔄 **Backwards Compatible**: Code cũ vẫn hoạt động bình thường
|
|
13
|
-
|
|
14
|
-
## 📖 Documentation
|
|
15
|
-
|
|
16
|
-
- [Headless API Documentation](./HEADLESS_API.md) - Chi tiết về API và hooks
|
|
17
|
-
- [Examples](./EXAMPLES.md) - 9+ examples từ basic đến advanced
|
|
18
|
-
|
|
19
|
-
## 🚀 Quick Start
|
|
20
|
-
|
|
21
|
-
### 1. Sử dụng Default UI
|
|
22
|
-
|
|
23
|
-
```tsx
|
|
24
|
-
import { ShowroomVisualizer } from 'showroom-visualizer';
|
|
25
|
-
|
|
26
|
-
function App() {
|
|
27
|
-
return (
|
|
28
|
-
<ShowroomVisualizer
|
|
29
|
-
config={{ tourCode: 'my-tour' }}
|
|
30
|
-
mobile={false}
|
|
31
|
-
apiHost="https://api.clik.vn/vt360"
|
|
32
|
-
/>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### 2. Custom UI với Headless Hooks
|
|
38
|
-
|
|
39
|
-
```tsx
|
|
40
|
-
import { ShowroomVisualizer, useShowroomControls } from 'showroom-visualizer';
|
|
41
|
-
|
|
42
|
-
function CustomUI() {
|
|
43
|
-
const controls = useShowroomControls();
|
|
44
|
-
|
|
45
|
-
return (
|
|
46
|
-
<div>
|
|
47
|
-
<h1>{controls.activeScene?.name}</h1>
|
|
48
|
-
<button onClick={controls.goToNextScene}>Next →</button>
|
|
49
|
-
<button onClick={controls.toggleFloorplan}>Toggle Map</button>
|
|
50
|
-
</div>
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function App() {
|
|
55
|
-
return (
|
|
56
|
-
<ShowroomVisualizer
|
|
57
|
-
config={{ tourCode: 'my-tour' }}
|
|
58
|
-
customLayout={<CustomUI />}
|
|
59
|
-
/>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### 3. Headless Mode (No UI)
|
|
65
|
-
|
|
66
|
-
```tsx
|
|
67
|
-
import { ShowroomVisualizer, useShowroomControls } from 'showroom-visualizer';
|
|
68
|
-
|
|
69
|
-
function ExternalControls() {
|
|
70
|
-
const controls = useShowroomControls();
|
|
71
|
-
return <div>Build your UI here...</div>;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function App() {
|
|
75
|
-
return (
|
|
76
|
-
<>
|
|
77
|
-
<ExternalControls />
|
|
78
|
-
<ShowroomVisualizer
|
|
79
|
-
config={{ tourCode: 'my-tour' }}
|
|
80
|
-
disableDefaultUI={true}
|
|
81
|
-
/>
|
|
82
|
-
</>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
## 📚 API Reference
|
|
88
|
-
|
|
89
|
-
### Headless Hooks
|
|
90
|
-
|
|
91
|
-
- `useShowroomControls()` - Main hook với tất cả controls
|
|
92
|
-
- `useTourCore()` - Tour engine state (read-only)
|
|
93
|
-
- `useSceneNavigation()` - Scene navigation controls
|
|
94
|
-
- `useFloorplanControl()` - Floorplan/minimap controls
|
|
95
|
-
- `useScenarioControl()` - Scenario auto-play controls
|
|
96
|
-
- `usePOIInteraction()` - POI interaction controls
|
|
97
|
-
- `useViewportControl()` - Viewport/camera controls
|
|
98
|
-
|
|
99
|
-
### Exported Components
|
|
100
|
-
|
|
101
|
-
- `DefaultLayout` - Default UI layout
|
|
102
|
-
- `PinActions`, `Floorplan`, `SceneCategories`
|
|
103
|
-
- `PlayBar`, `GalleryFullScreen`, `ModalPopupPoi`
|
|
104
|
-
- ...và nhiều components khác
|
|
105
|
-
|
|
106
|
-
Xem [HEADLESS_API.md](./HEADLESS_API.md) để biết chi tiết.
|
|
107
|
-
|
|
108
|
-
## 🎓 Examples
|
|
109
|
-
|
|
110
|
-
Xem [EXAMPLES.md](./EXAMPLES.md) để xem 9+ examples:
|
|
111
|
-
- Simple Custom Header
|
|
112
|
-
- Scene Grid Selector
|
|
113
|
-
- Sidebar Navigation
|
|
114
|
-
- External Dashboard
|
|
115
|
-
- Auto-play Controls
|
|
116
|
-
- POI Explorer
|
|
117
|
-
- Complete Custom UI
|
|
118
|
-
- Mobile-first UI
|
|
119
|
-
- ...và nhiều hơn nữa!
|
|
120
|
-
|
|
121
|
-
## 🔧 Development
|
|
122
|
-
|
|
123
|
-
```bash
|
|
124
|
-
# Install dependencies
|
|
125
|
-
yarn install
|
|
126
|
-
|
|
127
|
-
# Run development server
|
|
128
|
-
yarn dev
|
|
129
|
-
|
|
130
|
-
# Build for production
|
|
131
|
-
yarn build
|
|
132
|
-
|
|
133
|
-
# Serve built files
|
|
134
|
-
serve dist --cors
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## 📝 License
|
|
138
|
-
|
|
139
|
-
MIT
|
|
140
|
-
=======
|
|
141
|
-
## Installation
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
npm install @clikvn/showroom-visualizer
|
|
145
|
-
# or
|
|
146
|
-
yarn add @clikvn/showroom-visualizer
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
## Basic Usage
|
|
150
|
-
|
|
151
|
-
```html
|
|
152
|
-
<!-- public/index.html -->
|
|
153
|
-
<script type="module">
|
|
154
|
-
import ShowroomVisualizer from 'http://localhost:3000/web.js';
|
|
155
|
-
ShowroomVisualizer.initVisualizer({
|
|
156
|
-
apiHost: 'https://ci-api.clik.vn/vt360',
|
|
157
|
-
config: {
|
|
158
|
-
tourCode: 'TOUR_FXYCEN7ZZVW6',
|
|
159
|
-
language: 'EN',
|
|
160
|
-
},
|
|
161
|
-
onLoaded: (tool) => {
|
|
162
|
-
window.tool = tool;
|
|
163
|
-
},
|
|
164
|
-
mobile: false,
|
|
165
|
-
});
|
|
166
|
-
</script>
|
|
167
|
-
<div style="width: 100vw; height: 100vh">
|
|
168
|
-
<showroom-visualizer></showroom-visualizer>
|
|
169
|
-
</div>
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
## Features
|
|
173
|
-
|
|
174
|
-
- 🌐 **360° Virtual Tours** - Interactive panoramic experiences powered by Krpano
|
|
175
|
-
- 🎯 **Points of Interest (POI)** - Multiple POI types: Gallery, Video, Sound, Navigation, Texture, Promotions
|
|
176
|
-
- 🎬 **Automated Scenarios** - Guided tour playback with camera movements and narration
|
|
177
|
-
- 🗺️ **Floorplan/Minimap** - Interactive navigation with radar positioning
|
|
178
|
-
- 📱 **Mobile Optimized** - Touch controls and responsive layout for mobile devices
|
|
179
|
-
- 🌍 **Multi-language** - Support for EN, CN, JP, KR, VI
|
|
180
|
-
- 🎨 **Customizable UI** - Theme support and configurable components
|
|
181
|
-
- 📊 **Comprehensive Analytics** - **35+ tracking actions** covering all user interactions (see below)
|
|
182
|
-
|
|
183
|
-
## Comprehensive Analytics & Tracking
|
|
184
|
-
|
|
185
|
-
The library includes a powerful **tracking middleware** system with **35+ actions** covering all user interactions:
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
import ShowroomVisualizer from '@clikvn/showroom-visualizer';
|
|
189
|
-
|
|
190
|
-
ShowroomVisualizer.initVisualizer({
|
|
191
|
-
apiHost: 'https://api.clik.vn',
|
|
192
|
-
config: { tourCode: 'TOUR_123' },
|
|
193
|
-
|
|
194
|
-
// Add tracking middleware
|
|
195
|
-
middleware: (event) => {
|
|
196
|
-
// Event structure:
|
|
197
|
-
// {
|
|
198
|
-
// actionName: 'onCardItemClick',
|
|
199
|
-
// payload: { itemCode, itemTitle, itemType, sceneCode, ... },
|
|
200
|
-
// timestamp: '2025-01-15T10:00:00.000Z',
|
|
201
|
-
// metadata: { tourCode, sceneCode, categoryCode }
|
|
202
|
-
// }
|
|
203
|
-
|
|
204
|
-
// Send to your analytics service
|
|
205
|
-
analytics.track(event.actionName, event.payload);
|
|
206
|
-
},
|
|
207
|
-
});
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### What's Tracked (35+ Actions)
|
|
211
|
-
|
|
212
|
-
**Search & Discovery (6 actions)**
|
|
213
|
-
|
|
214
|
-
- Panel open/close, search queries
|
|
215
|
-
- Category header clicks (Products, Features, Locations, etc.)
|
|
216
|
-
- Promotion actions (show more, auto play)
|
|
217
|
-
- Individual scenario clicks
|
|
218
|
-
|
|
219
|
-
**Individual Items (1 universal action covering all types)**
|
|
220
|
-
|
|
221
|
-
- Product clicks
|
|
222
|
-
- POI clicks (Information, Features, Brands, Locations, Facilities, Multimedia)
|
|
223
|
-
- Feature clicks
|
|
224
|
-
- Promotion item clicks
|
|
225
|
-
|
|
226
|
-
**POI Detail Panel (5 actions)**
|
|
227
|
-
|
|
228
|
-
- Open/close, audio playback
|
|
229
|
-
- Action buttons (AI Assistant, Save, Audio, Share)
|
|
230
|
-
- Tab switching (Gallery, AR, Web Rotate, Info, Specification)
|
|
231
|
-
- Gallery item clicks
|
|
232
|
-
|
|
233
|
-
**Scenario Playback (8 actions)**
|
|
234
|
-
|
|
235
|
-
- Scenario start, play/pause
|
|
236
|
-
- Skip (next/previous), loop toggle
|
|
237
|
-
- Sound toggle, playlist toggle
|
|
238
|
-
- Playbar close
|
|
239
|
-
|
|
240
|
-
**Navigation (6 actions)**
|
|
241
|
-
|
|
242
|
-
- Scene group selection
|
|
243
|
-
- Floorplan changes
|
|
244
|
-
- Minimap expand/minimize
|
|
245
|
-
- View scenes button
|
|
246
|
-
|
|
247
|
-
**UI Components (1+ actions)**
|
|
248
|
-
|
|
249
|
-
- Guide open/close
|
|
250
|
-
- Other UI interactions
|
|
251
|
-
|
|
252
|
-
### Key Features
|
|
253
|
-
|
|
254
|
-
✅ **Deep-level tracking** - Not just categories, but individual items within each category
|
|
255
|
-
✅ **Rich payloads** - Codes, names, types, and contextual data for every action
|
|
256
|
-
✅ **User journey mapping** - Complete visibility from discovery to engagement
|
|
257
|
-
✅ **Zero overhead** - No performance impact when middleware not configured
|
|
258
|
-
✅ **Fire-and-forget** - Non-blocking, error-safe pattern
|
|
259
|
-
✅ **Analytics-ready** - Easy integration with GA4, Mixpanel, or custom backends
|
|
260
|
-
|
|
261
|
-
### Complete List of Tracked Events (35+ Actions)
|
|
262
|
-
|
|
263
|
-
#### Search & Discovery (6 events)
|
|
264
|
-
|
|
265
|
-
| Event Name | Trigger | Payload |
|
|
266
|
-
| ----------------------------------- | --------------------------- | ---------------------------------- |
|
|
267
|
-
| `onSearchAndDiscoveryClose` | Panel closed | `{}` |
|
|
268
|
-
| `onSearchAndDiscoverySearch` | User types in search | `{ searchQuery }` |
|
|
269
|
-
| `onSearchAndDiscoveryItemClick` | Category header clicked | `{ itemKey, itemTitle, itemType }` |
|
|
270
|
-
| `onSearchAndDiscoveryScenarioClick` | Scenario clicked from panel | `{ scenarioCode, scenarioName }` |
|
|
271
|
-
| `onPromotionShowMore` | Show more button clicked | `{ totalPromotions }` |
|
|
272
|
-
| `onPromotionAutoPlay` | Auto play button clicked | `{ totalPromotions }` |
|
|
273
|
-
|
|
274
|
-
**Categories tracked:** HOME, AMENITIES, SCENE, PROMOTION, FEATURES, PRODUCT_LIST, INFORMATION, BRAND, LOCATION, FACILITY, MULTIMEDIA, SWAP_ELEMENT, SCENARIO, PLAYLIST, DISPLAY_HOTSPOT, DETAIL
|
|
275
|
-
|
|
276
|
-
#### Individual Items - Universal (1 event covering ALL types)
|
|
277
|
-
|
|
278
|
-
| Event Name | Trigger | Payload |
|
|
279
|
-
| ----------------- | ---------------------------------------------- | -------------------------------------------------------------------- |
|
|
280
|
-
| `onCardItemClick` | Any item clicked (product, POI, feature, etc.) | `{ itemCode, itemTitle, itemType, sceneCode, hotspotCode, isVideo }` |
|
|
281
|
-
|
|
282
|
-
**Item types covered:** Products, Information POIs, Features, Brands, Locations, Facilities, Multimedia, Swap Elements, Promotions
|
|
283
|
-
|
|
284
|
-
#### POI Detail Panel (5 events)
|
|
285
|
-
|
|
286
|
-
| Event Name | Trigger | Payload |
|
|
287
|
-
| ------------------------- | ------------------------- | ----------------------------------------------------------- |
|
|
288
|
-
| `onPoiDetailClose` | Detail panel closed | `{ poiCode, poiName, poiType }` |
|
|
289
|
-
| `onPoiDetailAudioPlay` | Audio play button clicked | `{ poiCode, poiName, poiType }` |
|
|
290
|
-
| `onPoiDetailGalleryClick` | Gallery item clicked | `{ poiCode, poiName, poiType, galleryItemId, galleryType }` |
|
|
291
|
-
| `onPoiDetailActionClick` | Action button clicked | `{ actionKey, productCode, productName, productType }` |
|
|
292
|
-
| `onPoiDetailTabChange` | Tab switched | `{ tabKey, productCode, productName, galleryType }` |
|
|
293
|
-
|
|
294
|
-
**Action keys:** `ai_assistant`, `save`, `audio`, `share`
|
|
295
|
-
**Tab keys:** `gallery`, `ar`, `webRotate`, `info`, `specification`
|
|
296
|
-
|
|
297
|
-
#### Scenario Playback (8 events)
|
|
298
|
-
|
|
299
|
-
| Event Name | Trigger | Payload |
|
|
300
|
-
| ---------------------- | -------------------------- | ----------------------------- |
|
|
301
|
-
| `onStartScenario` | Scenario started from list | `scenarioCode` (string) |
|
|
302
|
-
| `onPlayBarClose` | Playbar closed | `{ scenarioCode }` |
|
|
303
|
-
| `onPlayListToggle` | Playlist toggled | `{ show }` |
|
|
304
|
-
| `onPlayBarPlayClick` | Play button clicked | `{ scenarioCode }` |
|
|
305
|
-
| `onPlayBarPauseClick` | Pause button clicked | `{ scenarioCode }` |
|
|
306
|
-
| `onPlayBarLoopToggle` | Loop toggled | `{ loop, scenarioCode }` |
|
|
307
|
-
| `onPlayBarSoundToggle` | Sound toggled | `{ playing }` |
|
|
308
|
-
| `onPlayBarSkip` | Skip button clicked | `{ direction, scenarioCode }` |
|
|
309
|
-
|
|
310
|
-
**Direction values:** `'previous'` or `'next'`
|
|
311
|
-
|
|
312
|
-
#### Navigation (6 events)
|
|
313
|
-
|
|
314
|
-
| Event Name | Trigger | Payload |
|
|
315
|
-
| ------------------------- | -------------------------- | ------------------------------------------ |
|
|
316
|
-
| `onSceneGroupSelected` | Scene group selected | `{ sceneGroupCode, sceneGroupName }` |
|
|
317
|
-
| `onSubSceneGroupSelected` | Sub scene group selected | `{ subSceneGroupCode, subSceneGroupName }` |
|
|
318
|
-
| `onFloorplanViewScenes` | View scenes button clicked | `{}` |
|
|
319
|
-
| `onFloorplanChange` | Floorplan changed | `{ floorplanCode, floorplanName }` |
|
|
320
|
-
| `onMinimapExpand` | Minimap expanded | `{}` |
|
|
321
|
-
| `onMinimapMinimize` | Minimap minimized | `{}` |
|
|
322
|
-
|
|
323
|
-
#### UI Components (1+ events)
|
|
324
|
-
|
|
325
|
-
| Event Name | Trigger | Payload |
|
|
326
|
-
| -------------- | -------------------- | ------- |
|
|
327
|
-
| `onGuideClose` | Guide overlay closed | `{}` |
|
|
328
|
-
|
|
329
|
-
### Analytics Integration Examples
|
|
330
|
-
|
|
331
|
-
**Google Analytics 4:**
|
|
332
|
-
|
|
333
|
-
```typescript
|
|
334
|
-
middleware: (event) => {
|
|
335
|
-
gtag('event', event.actionName, {
|
|
336
|
-
event_category: 'showroom',
|
|
337
|
-
tour_code: event.metadata?.tourCode,
|
|
338
|
-
...event.payload,
|
|
339
|
-
});
|
|
340
|
-
};
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
**Mixpanel:**
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
middleware: (event) => {
|
|
347
|
-
mixpanel.track(event.actionName, {
|
|
348
|
-
tour_code: event.metadata?.tourCode,
|
|
349
|
-
...event.payload,
|
|
350
|
-
});
|
|
351
|
-
};
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
**Custom Backend:**
|
|
355
|
-
|
|
356
|
-
```typescript
|
|
357
|
-
middleware: async (event) => {
|
|
358
|
-
await fetch('/api/analytics', {
|
|
359
|
-
method: 'POST',
|
|
360
|
-
headers: { 'Content-Type': 'application/json' },
|
|
361
|
-
body: JSON.stringify(event),
|
|
362
|
-
});
|
|
363
|
-
};
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
> **📚 Detailed Documentation:** For complete examples, user journey scenarios, and implementation patterns, see [Complete Tracking Guide](./Planning/README-tracking-complete.md)
|
|
367
|
-
|
|
368
|
-
## Available Listeners
|
|
369
|
-
|
|
370
|
-
The library provides **21+ event listeners** for custom app logic:
|
|
371
|
-
|
|
372
|
-
| Listener | Description | Payload |
|
|
373
|
-
| ----------------------- | --------------------- | ------------------------- |
|
|
374
|
-
| **POI Events** |
|
|
375
|
-
| `onPoiClicked` | POI clicked | POI object |
|
|
376
|
-
| `onPoiOver` | Mouse over POI | POI object |
|
|
377
|
-
| `onPoiHover` | Mouse hovering POI | POI object |
|
|
378
|
-
| `onPoiOut` | Mouse left POI | - |
|
|
379
|
-
| `onPoiInCenter` | POI nearest to center | POI object |
|
|
380
|
-
| **Scene Events** |
|
|
381
|
-
| `onSceneCompleted` | Scene loaded | `sceneCode, categoryCode` |
|
|
382
|
-
| `onSceneChanged` | Scene navigated | Scene object |
|
|
383
|
-
| **Scenario Events** |
|
|
384
|
-
| `onStartScenario` | Scenario started | `scenarioCode` |
|
|
385
|
-
| `onScenarioPaused` | Scenario paused | `scenarioCode` |
|
|
386
|
-
| `onScenarioEnded` | Scenario ended | `scenarioCode` |
|
|
387
|
-
| **UI Events** |
|
|
388
|
-
| `onToggleSlideIn` | Slide-in toggled | `{ open, offset }` |
|
|
389
|
-
| `onPlaybarOpen` | Playbar opened | - |
|
|
390
|
-
| `onPlaybarClosed` | Playbar closed | - |
|
|
391
|
-
| `onPinActionClicked` | Pin button clicked | Button key string |
|
|
392
|
-
| **Tour Lifecycle** |
|
|
393
|
-
| `onStartLoadingTour` | Tour load started | `tourCode` |
|
|
394
|
-
| `onFinishedLoadingTour` | Tour load finished | `tourCode` |
|
|
395
|
-
| `onLoaded` | Tool ready | Tool object |
|
|
396
|
-
| `onDataLoaded` | Tour data loaded | `tour, tourData` |
|
|
397
|
-
| **Product Events** |
|
|
398
|
-
| `onAIProductClicked` | AI product clicked | Product code |
|
|
399
|
-
| `onShareProductClicked` | Share product clicked | Product code |
|
|
400
|
-
| **Other Events** |
|
|
401
|
-
| `onChanged` | Config changed | Config object |
|
|
402
|
-
| `onTourSwitchLoaded` | Tour switch ready | TourSwitch object |
|
|
403
|
-
| `onStateChanged` | State changed | State values |
|
|
404
|
-
|
|
405
|
-
## Key Differences: Listeners vs Middleware
|
|
406
|
-
|
|
407
|
-
| Feature | Listeners | Middleware (Tracked Actions) |
|
|
408
|
-
| -------------- | ------------------ | ------------------------------ |
|
|
409
|
-
| **Purpose** | Custom app logic | Analytics & tracking |
|
|
410
|
-
| **When fires** | Only if configured | Always (if middleware set) |
|
|
411
|
-
| **Count** | 21+ events | 35+ actions |
|
|
412
|
-
| **Use case** | App functionality | User behavior insights |
|
|
413
|
-
| **Blocking** | Can be blocking | Non-blocking (fire-and-forget) |
|
|
414
|
-
|
|
415
|
-
**Example:**
|
|
416
|
-
|
|
417
|
-
- Use **listeners** to trigger custom UI updates when a scene changes
|
|
418
|
-
- Use **middleware** to track that scene change in your analytics platform
|
|
419
|
-
|
|
420
|
-
Both can be used together - listeners for app logic, middleware for analytics!
|
|
421
|
-
|
|
422
|
-
## Configuration Options
|
|
423
|
-
|
|
424
|
-
```typescript
|
|
425
|
-
ShowroomVisualizer.initVisualizer({
|
|
426
|
-
// Required
|
|
427
|
-
apiHost: string; // API endpoint URL
|
|
428
|
-
config: {
|
|
429
|
-
tourCode: string; // Tour identifier
|
|
430
|
-
language?: string; // 'EN' | 'CN' | 'JP' | 'KR' | 'VI'
|
|
431
|
-
};
|
|
432
|
-
|
|
433
|
-
// Optional
|
|
434
|
-
mobile?: boolean; // Mobile mode
|
|
435
|
-
onLoaded?: (tool) => void; // Callback when loaded
|
|
436
|
-
middleware?: (event) => void; // Analytics tracking
|
|
437
|
-
listeners?: { // Event listeners (see table above)
|
|
438
|
-
onPoiClicked?: (poi) => void;
|
|
439
|
-
onSceneChanged?: (scene) => void;
|
|
440
|
-
onStartScenario?: (scenarioCode) => void;
|
|
441
|
-
onPinActionClicked?: (key) => void;
|
|
442
|
-
onSceneCompleted?: (sceneCode, categoryCode) => void;
|
|
443
|
-
// ... 16+ more listeners available
|
|
444
|
-
};
|
|
445
|
-
});
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
## Development
|
|
449
|
-
|
|
450
|
-
```bash
|
|
451
|
-
# Development with hot reload
|
|
452
|
-
yarn dev
|
|
453
|
-
|
|
454
|
-
# Production build
|
|
455
|
-
yarn build
|
|
456
|
-
|
|
457
|
-
# Linting
|
|
458
|
-
yarn lint
|
|
459
|
-
yarn lint:fix
|
|
460
|
-
|
|
461
|
-
# Code formatting
|
|
462
|
-
yarn prettier
|
|
463
|
-
|
|
464
|
-
# Serve built files locally
|
|
465
|
-
serve dist --cors
|
|
466
|
-
```
|
|
467
|
-
|
|
468
|
-
## Documentation
|
|
469
|
-
|
|
470
|
-
### Core Documentation
|
|
471
|
-
|
|
472
|
-
- **[CLAUDE.md](./CLAUDE.md)** - Complete architecture overview and development guide
|
|
473
|
-
- **[README.md](./README.md)** - This file - Quick start and API reference
|
|
474
|
-
|
|
475
|
-
### Analytics & Tracking
|
|
476
|
-
|
|
477
|
-
- 📚 **[Complete Tracking Guide](./Planning/README-tracking-complete.md)** - Full reference for all 35+ tracking actions
|
|
478
|
-
- 📖 **[Quick Reference Card](./Planning/TRACKING-QUICK-REFERENCE.md)** - Handy cheat sheet for developers
|
|
479
|
-
- 📝 **[Middleware Architecture](./Planning/README-middleware.md)** - Core middleware system documentation
|
|
480
|
-
- 📋 **[Changes Summary](./Planning/TRACKING-CHANGES-SUMMARY.md)** - Implementation details and file list
|
|
481
|
-
|
|
482
|
-
### Planning & Specifications
|
|
483
|
-
|
|
484
|
-
- **[Planning/](./Planning/)** - Feature planning and specifications
|
|
485
|
-
- [TEMPLATE.md](./Planning/TEMPLATE.md) - Template for new feature planning
|
|
486
|
-
|
|
487
|
-
## License
|
|
488
|
-
|
|
489
|
-
Proprietary - Clik Vietnam
|
|
1
|
+
# Showroom Visualizer
|
|
2
|
+
|
|
3
|
+
A powerful, flexible 360° virtual tour visualizer với **Headless Architecture** support.
|
|
4
|
+
|
|
5
|
+
## ✨ Features
|
|
6
|
+
|
|
7
|
+
- 🎨 **Flexible UI**: Sử dụng default UI hoặc build custom UI hoàn toàn
|
|
8
|
+
- 🔧 **Headless Hooks**: Full control với React hooks
|
|
9
|
+
- 📦 **Component Library**: Reusable components để compose custom layouts
|
|
10
|
+
- 🎯 **Type-safe**: Full TypeScript support
|
|
11
|
+
- ⚡ **Performance**: Optimized với React best practices
|
|
12
|
+
- 🔄 **Backwards Compatible**: Code cũ vẫn hoạt động bình thường
|
|
13
|
+
|
|
14
|
+
## 📖 Documentation
|
|
15
|
+
|
|
16
|
+
- [Headless API Documentation](./HEADLESS_API.md) - Chi tiết về API và hooks
|
|
17
|
+
- [Examples](./EXAMPLES.md) - 9+ examples từ basic đến advanced
|
|
18
|
+
|
|
19
|
+
## 🚀 Quick Start
|
|
20
|
+
|
|
21
|
+
### 1. Sử dụng Default UI
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
import { ShowroomVisualizer } from 'showroom-visualizer';
|
|
25
|
+
|
|
26
|
+
function App() {
|
|
27
|
+
return (
|
|
28
|
+
<ShowroomVisualizer
|
|
29
|
+
config={{ tourCode: 'my-tour' }}
|
|
30
|
+
mobile={false}
|
|
31
|
+
apiHost="https://api.clik.vn/vt360"
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### 2. Custom UI với Headless Hooks
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { ShowroomVisualizer, useShowroomControls } from 'showroom-visualizer';
|
|
41
|
+
|
|
42
|
+
function CustomUI() {
|
|
43
|
+
const controls = useShowroomControls();
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<div>
|
|
47
|
+
<h1>{controls.activeScene?.name}</h1>
|
|
48
|
+
<button onClick={controls.goToNextScene}>Next →</button>
|
|
49
|
+
<button onClick={controls.toggleFloorplan}>Toggle Map</button>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function App() {
|
|
55
|
+
return (
|
|
56
|
+
<ShowroomVisualizer
|
|
57
|
+
config={{ tourCode: 'my-tour' }}
|
|
58
|
+
customLayout={<CustomUI />}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 3. Headless Mode (No UI)
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
import { ShowroomVisualizer, useShowroomControls } from 'showroom-visualizer';
|
|
68
|
+
|
|
69
|
+
function ExternalControls() {
|
|
70
|
+
const controls = useShowroomControls();
|
|
71
|
+
return <div>Build your UI here...</div>;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function App() {
|
|
75
|
+
return (
|
|
76
|
+
<>
|
|
77
|
+
<ExternalControls />
|
|
78
|
+
<ShowroomVisualizer
|
|
79
|
+
config={{ tourCode: 'my-tour' }}
|
|
80
|
+
disableDefaultUI={true}
|
|
81
|
+
/>
|
|
82
|
+
</>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 📚 API Reference
|
|
88
|
+
|
|
89
|
+
### Headless Hooks
|
|
90
|
+
|
|
91
|
+
- `useShowroomControls()` - Main hook với tất cả controls
|
|
92
|
+
- `useTourCore()` - Tour engine state (read-only)
|
|
93
|
+
- `useSceneNavigation()` - Scene navigation controls
|
|
94
|
+
- `useFloorplanControl()` - Floorplan/minimap controls
|
|
95
|
+
- `useScenarioControl()` - Scenario auto-play controls
|
|
96
|
+
- `usePOIInteraction()` - POI interaction controls
|
|
97
|
+
- `useViewportControl()` - Viewport/camera controls
|
|
98
|
+
|
|
99
|
+
### Exported Components
|
|
100
|
+
|
|
101
|
+
- `DefaultLayout` - Default UI layout
|
|
102
|
+
- `PinActions`, `Floorplan`, `SceneCategories`
|
|
103
|
+
- `PlayBar`, `GalleryFullScreen`, `ModalPopupPoi`
|
|
104
|
+
- ...và nhiều components khác
|
|
105
|
+
|
|
106
|
+
Xem [HEADLESS_API.md](./HEADLESS_API.md) để biết chi tiết.
|
|
107
|
+
|
|
108
|
+
## 🎓 Examples
|
|
109
|
+
|
|
110
|
+
Xem [EXAMPLES.md](./EXAMPLES.md) để xem 9+ examples:
|
|
111
|
+
- Simple Custom Header
|
|
112
|
+
- Scene Grid Selector
|
|
113
|
+
- Sidebar Navigation
|
|
114
|
+
- External Dashboard
|
|
115
|
+
- Auto-play Controls
|
|
116
|
+
- POI Explorer
|
|
117
|
+
- Complete Custom UI
|
|
118
|
+
- Mobile-first UI
|
|
119
|
+
- ...và nhiều hơn nữa!
|
|
120
|
+
|
|
121
|
+
## 🔧 Development
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Install dependencies
|
|
125
|
+
yarn install
|
|
126
|
+
|
|
127
|
+
# Run development server
|
|
128
|
+
yarn dev
|
|
129
|
+
|
|
130
|
+
# Build for production
|
|
131
|
+
yarn build
|
|
132
|
+
|
|
133
|
+
# Serve built files
|
|
134
|
+
serve dist --cors
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## 📝 License
|
|
138
|
+
|
|
139
|
+
MIT
|
|
140
|
+
=======
|
|
141
|
+
## Installation
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
npm install @clikvn/showroom-visualizer
|
|
145
|
+
# or
|
|
146
|
+
yarn add @clikvn/showroom-visualizer
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Basic Usage
|
|
150
|
+
|
|
151
|
+
```html
|
|
152
|
+
<!-- public/index.html -->
|
|
153
|
+
<script type="module">
|
|
154
|
+
import ShowroomVisualizer from 'http://localhost:3000/web.js';
|
|
155
|
+
ShowroomVisualizer.initVisualizer({
|
|
156
|
+
apiHost: 'https://ci-api.clik.vn/vt360',
|
|
157
|
+
config: {
|
|
158
|
+
tourCode: 'TOUR_FXYCEN7ZZVW6',
|
|
159
|
+
language: 'EN',
|
|
160
|
+
},
|
|
161
|
+
onLoaded: (tool) => {
|
|
162
|
+
window.tool = tool;
|
|
163
|
+
},
|
|
164
|
+
mobile: false,
|
|
165
|
+
});
|
|
166
|
+
</script>
|
|
167
|
+
<div style="width: 100vw; height: 100vh">
|
|
168
|
+
<showroom-visualizer></showroom-visualizer>
|
|
169
|
+
</div>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Features
|
|
173
|
+
|
|
174
|
+
- 🌐 **360° Virtual Tours** - Interactive panoramic experiences powered by Krpano
|
|
175
|
+
- 🎯 **Points of Interest (POI)** - Multiple POI types: Gallery, Video, Sound, Navigation, Texture, Promotions
|
|
176
|
+
- 🎬 **Automated Scenarios** - Guided tour playback with camera movements and narration
|
|
177
|
+
- 🗺️ **Floorplan/Minimap** - Interactive navigation with radar positioning
|
|
178
|
+
- 📱 **Mobile Optimized** - Touch controls and responsive layout for mobile devices
|
|
179
|
+
- 🌍 **Multi-language** - Support for EN, CN, JP, KR, VI
|
|
180
|
+
- 🎨 **Customizable UI** - Theme support and configurable components
|
|
181
|
+
- 📊 **Comprehensive Analytics** - **35+ tracking actions** covering all user interactions (see below)
|
|
182
|
+
|
|
183
|
+
## Comprehensive Analytics & Tracking
|
|
184
|
+
|
|
185
|
+
The library includes a powerful **tracking middleware** system with **35+ actions** covering all user interactions:
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
import ShowroomVisualizer from '@clikvn/showroom-visualizer';
|
|
189
|
+
|
|
190
|
+
ShowroomVisualizer.initVisualizer({
|
|
191
|
+
apiHost: 'https://api.clik.vn',
|
|
192
|
+
config: { tourCode: 'TOUR_123' },
|
|
193
|
+
|
|
194
|
+
// Add tracking middleware
|
|
195
|
+
middleware: (event) => {
|
|
196
|
+
// Event structure:
|
|
197
|
+
// {
|
|
198
|
+
// actionName: 'onCardItemClick',
|
|
199
|
+
// payload: { itemCode, itemTitle, itemType, sceneCode, ... },
|
|
200
|
+
// timestamp: '2025-01-15T10:00:00.000Z',
|
|
201
|
+
// metadata: { tourCode, sceneCode, categoryCode }
|
|
202
|
+
// }
|
|
203
|
+
|
|
204
|
+
// Send to your analytics service
|
|
205
|
+
analytics.track(event.actionName, event.payload);
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### What's Tracked (35+ Actions)
|
|
211
|
+
|
|
212
|
+
**Search & Discovery (6 actions)**
|
|
213
|
+
|
|
214
|
+
- Panel open/close, search queries
|
|
215
|
+
- Category header clicks (Products, Features, Locations, etc.)
|
|
216
|
+
- Promotion actions (show more, auto play)
|
|
217
|
+
- Individual scenario clicks
|
|
218
|
+
|
|
219
|
+
**Individual Items (1 universal action covering all types)**
|
|
220
|
+
|
|
221
|
+
- Product clicks
|
|
222
|
+
- POI clicks (Information, Features, Brands, Locations, Facilities, Multimedia)
|
|
223
|
+
- Feature clicks
|
|
224
|
+
- Promotion item clicks
|
|
225
|
+
|
|
226
|
+
**POI Detail Panel (5 actions)**
|
|
227
|
+
|
|
228
|
+
- Open/close, audio playback
|
|
229
|
+
- Action buttons (AI Assistant, Save, Audio, Share)
|
|
230
|
+
- Tab switching (Gallery, AR, Web Rotate, Info, Specification)
|
|
231
|
+
- Gallery item clicks
|
|
232
|
+
|
|
233
|
+
**Scenario Playback (8 actions)**
|
|
234
|
+
|
|
235
|
+
- Scenario start, play/pause
|
|
236
|
+
- Skip (next/previous), loop toggle
|
|
237
|
+
- Sound toggle, playlist toggle
|
|
238
|
+
- Playbar close
|
|
239
|
+
|
|
240
|
+
**Navigation (6 actions)**
|
|
241
|
+
|
|
242
|
+
- Scene group selection
|
|
243
|
+
- Floorplan changes
|
|
244
|
+
- Minimap expand/minimize
|
|
245
|
+
- View scenes button
|
|
246
|
+
|
|
247
|
+
**UI Components (1+ actions)**
|
|
248
|
+
|
|
249
|
+
- Guide open/close
|
|
250
|
+
- Other UI interactions
|
|
251
|
+
|
|
252
|
+
### Key Features
|
|
253
|
+
|
|
254
|
+
✅ **Deep-level tracking** - Not just categories, but individual items within each category
|
|
255
|
+
✅ **Rich payloads** - Codes, names, types, and contextual data for every action
|
|
256
|
+
✅ **User journey mapping** - Complete visibility from discovery to engagement
|
|
257
|
+
✅ **Zero overhead** - No performance impact when middleware not configured
|
|
258
|
+
✅ **Fire-and-forget** - Non-blocking, error-safe pattern
|
|
259
|
+
✅ **Analytics-ready** - Easy integration with GA4, Mixpanel, or custom backends
|
|
260
|
+
|
|
261
|
+
### Complete List of Tracked Events (35+ Actions)
|
|
262
|
+
|
|
263
|
+
#### Search & Discovery (6 events)
|
|
264
|
+
|
|
265
|
+
| Event Name | Trigger | Payload |
|
|
266
|
+
| ----------------------------------- | --------------------------- | ---------------------------------- |
|
|
267
|
+
| `onSearchAndDiscoveryClose` | Panel closed | `{}` |
|
|
268
|
+
| `onSearchAndDiscoverySearch` | User types in search | `{ searchQuery }` |
|
|
269
|
+
| `onSearchAndDiscoveryItemClick` | Category header clicked | `{ itemKey, itemTitle, itemType }` |
|
|
270
|
+
| `onSearchAndDiscoveryScenarioClick` | Scenario clicked from panel | `{ scenarioCode, scenarioName }` |
|
|
271
|
+
| `onPromotionShowMore` | Show more button clicked | `{ totalPromotions }` |
|
|
272
|
+
| `onPromotionAutoPlay` | Auto play button clicked | `{ totalPromotions }` |
|
|
273
|
+
|
|
274
|
+
**Categories tracked:** HOME, AMENITIES, SCENE, PROMOTION, FEATURES, PRODUCT_LIST, INFORMATION, BRAND, LOCATION, FACILITY, MULTIMEDIA, SWAP_ELEMENT, SCENARIO, PLAYLIST, DISPLAY_HOTSPOT, DETAIL
|
|
275
|
+
|
|
276
|
+
#### Individual Items - Universal (1 event covering ALL types)
|
|
277
|
+
|
|
278
|
+
| Event Name | Trigger | Payload |
|
|
279
|
+
| ----------------- | ---------------------------------------------- | -------------------------------------------------------------------- |
|
|
280
|
+
| `onCardItemClick` | Any item clicked (product, POI, feature, etc.) | `{ itemCode, itemTitle, itemType, sceneCode, hotspotCode, isVideo }` |
|
|
281
|
+
|
|
282
|
+
**Item types covered:** Products, Information POIs, Features, Brands, Locations, Facilities, Multimedia, Swap Elements, Promotions
|
|
283
|
+
|
|
284
|
+
#### POI Detail Panel (5 events)
|
|
285
|
+
|
|
286
|
+
| Event Name | Trigger | Payload |
|
|
287
|
+
| ------------------------- | ------------------------- | ----------------------------------------------------------- |
|
|
288
|
+
| `onPoiDetailClose` | Detail panel closed | `{ poiCode, poiName, poiType }` |
|
|
289
|
+
| `onPoiDetailAudioPlay` | Audio play button clicked | `{ poiCode, poiName, poiType }` |
|
|
290
|
+
| `onPoiDetailGalleryClick` | Gallery item clicked | `{ poiCode, poiName, poiType, galleryItemId, galleryType }` |
|
|
291
|
+
| `onPoiDetailActionClick` | Action button clicked | `{ actionKey, productCode, productName, productType }` |
|
|
292
|
+
| `onPoiDetailTabChange` | Tab switched | `{ tabKey, productCode, productName, galleryType }` |
|
|
293
|
+
|
|
294
|
+
**Action keys:** `ai_assistant`, `save`, `audio`, `share`
|
|
295
|
+
**Tab keys:** `gallery`, `ar`, `webRotate`, `info`, `specification`
|
|
296
|
+
|
|
297
|
+
#### Scenario Playback (8 events)
|
|
298
|
+
|
|
299
|
+
| Event Name | Trigger | Payload |
|
|
300
|
+
| ---------------------- | -------------------------- | ----------------------------- |
|
|
301
|
+
| `onStartScenario` | Scenario started from list | `scenarioCode` (string) |
|
|
302
|
+
| `onPlayBarClose` | Playbar closed | `{ scenarioCode }` |
|
|
303
|
+
| `onPlayListToggle` | Playlist toggled | `{ show }` |
|
|
304
|
+
| `onPlayBarPlayClick` | Play button clicked | `{ scenarioCode }` |
|
|
305
|
+
| `onPlayBarPauseClick` | Pause button clicked | `{ scenarioCode }` |
|
|
306
|
+
| `onPlayBarLoopToggle` | Loop toggled | `{ loop, scenarioCode }` |
|
|
307
|
+
| `onPlayBarSoundToggle` | Sound toggled | `{ playing }` |
|
|
308
|
+
| `onPlayBarSkip` | Skip button clicked | `{ direction, scenarioCode }` |
|
|
309
|
+
|
|
310
|
+
**Direction values:** `'previous'` or `'next'`
|
|
311
|
+
|
|
312
|
+
#### Navigation (6 events)
|
|
313
|
+
|
|
314
|
+
| Event Name | Trigger | Payload |
|
|
315
|
+
| ------------------------- | -------------------------- | ------------------------------------------ |
|
|
316
|
+
| `onSceneGroupSelected` | Scene group selected | `{ sceneGroupCode, sceneGroupName }` |
|
|
317
|
+
| `onSubSceneGroupSelected` | Sub scene group selected | `{ subSceneGroupCode, subSceneGroupName }` |
|
|
318
|
+
| `onFloorplanViewScenes` | View scenes button clicked | `{}` |
|
|
319
|
+
| `onFloorplanChange` | Floorplan changed | `{ floorplanCode, floorplanName }` |
|
|
320
|
+
| `onMinimapExpand` | Minimap expanded | `{}` |
|
|
321
|
+
| `onMinimapMinimize` | Minimap minimized | `{}` |
|
|
322
|
+
|
|
323
|
+
#### UI Components (1+ events)
|
|
324
|
+
|
|
325
|
+
| Event Name | Trigger | Payload |
|
|
326
|
+
| -------------- | -------------------- | ------- |
|
|
327
|
+
| `onGuideClose` | Guide overlay closed | `{}` |
|
|
328
|
+
|
|
329
|
+
### Analytics Integration Examples
|
|
330
|
+
|
|
331
|
+
**Google Analytics 4:**
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
middleware: (event) => {
|
|
335
|
+
gtag('event', event.actionName, {
|
|
336
|
+
event_category: 'showroom',
|
|
337
|
+
tour_code: event.metadata?.tourCode,
|
|
338
|
+
...event.payload,
|
|
339
|
+
});
|
|
340
|
+
};
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
**Mixpanel:**
|
|
344
|
+
|
|
345
|
+
```typescript
|
|
346
|
+
middleware: (event) => {
|
|
347
|
+
mixpanel.track(event.actionName, {
|
|
348
|
+
tour_code: event.metadata?.tourCode,
|
|
349
|
+
...event.payload,
|
|
350
|
+
});
|
|
351
|
+
};
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Custom Backend:**
|
|
355
|
+
|
|
356
|
+
```typescript
|
|
357
|
+
middleware: async (event) => {
|
|
358
|
+
await fetch('/api/analytics', {
|
|
359
|
+
method: 'POST',
|
|
360
|
+
headers: { 'Content-Type': 'application/json' },
|
|
361
|
+
body: JSON.stringify(event),
|
|
362
|
+
});
|
|
363
|
+
};
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
> **📚 Detailed Documentation:** For complete examples, user journey scenarios, and implementation patterns, see [Complete Tracking Guide](./Planning/README-tracking-complete.md)
|
|
367
|
+
|
|
368
|
+
## Available Listeners
|
|
369
|
+
|
|
370
|
+
The library provides **21+ event listeners** for custom app logic:
|
|
371
|
+
|
|
372
|
+
| Listener | Description | Payload |
|
|
373
|
+
| ----------------------- | --------------------- | ------------------------- |
|
|
374
|
+
| **POI Events** |
|
|
375
|
+
| `onPoiClicked` | POI clicked | POI object |
|
|
376
|
+
| `onPoiOver` | Mouse over POI | POI object |
|
|
377
|
+
| `onPoiHover` | Mouse hovering POI | POI object |
|
|
378
|
+
| `onPoiOut` | Mouse left POI | - |
|
|
379
|
+
| `onPoiInCenter` | POI nearest to center | POI object |
|
|
380
|
+
| **Scene Events** |
|
|
381
|
+
| `onSceneCompleted` | Scene loaded | `sceneCode, categoryCode` |
|
|
382
|
+
| `onSceneChanged` | Scene navigated | Scene object |
|
|
383
|
+
| **Scenario Events** |
|
|
384
|
+
| `onStartScenario` | Scenario started | `scenarioCode` |
|
|
385
|
+
| `onScenarioPaused` | Scenario paused | `scenarioCode` |
|
|
386
|
+
| `onScenarioEnded` | Scenario ended | `scenarioCode` |
|
|
387
|
+
| **UI Events** |
|
|
388
|
+
| `onToggleSlideIn` | Slide-in toggled | `{ open, offset }` |
|
|
389
|
+
| `onPlaybarOpen` | Playbar opened | - |
|
|
390
|
+
| `onPlaybarClosed` | Playbar closed | - |
|
|
391
|
+
| `onPinActionClicked` | Pin button clicked | Button key string |
|
|
392
|
+
| **Tour Lifecycle** |
|
|
393
|
+
| `onStartLoadingTour` | Tour load started | `tourCode` |
|
|
394
|
+
| `onFinishedLoadingTour` | Tour load finished | `tourCode` |
|
|
395
|
+
| `onLoaded` | Tool ready | Tool object |
|
|
396
|
+
| `onDataLoaded` | Tour data loaded | `tour, tourData` |
|
|
397
|
+
| **Product Events** |
|
|
398
|
+
| `onAIProductClicked` | AI product clicked | Product code |
|
|
399
|
+
| `onShareProductClicked` | Share product clicked | Product code |
|
|
400
|
+
| **Other Events** |
|
|
401
|
+
| `onChanged` | Config changed | Config object |
|
|
402
|
+
| `onTourSwitchLoaded` | Tour switch ready | TourSwitch object |
|
|
403
|
+
| `onStateChanged` | State changed | State values |
|
|
404
|
+
|
|
405
|
+
## Key Differences: Listeners vs Middleware
|
|
406
|
+
|
|
407
|
+
| Feature | Listeners | Middleware (Tracked Actions) |
|
|
408
|
+
| -------------- | ------------------ | ------------------------------ |
|
|
409
|
+
| **Purpose** | Custom app logic | Analytics & tracking |
|
|
410
|
+
| **When fires** | Only if configured | Always (if middleware set) |
|
|
411
|
+
| **Count** | 21+ events | 35+ actions |
|
|
412
|
+
| **Use case** | App functionality | User behavior insights |
|
|
413
|
+
| **Blocking** | Can be blocking | Non-blocking (fire-and-forget) |
|
|
414
|
+
|
|
415
|
+
**Example:**
|
|
416
|
+
|
|
417
|
+
- Use **listeners** to trigger custom UI updates when a scene changes
|
|
418
|
+
- Use **middleware** to track that scene change in your analytics platform
|
|
419
|
+
|
|
420
|
+
Both can be used together - listeners for app logic, middleware for analytics!
|
|
421
|
+
|
|
422
|
+
## Configuration Options
|
|
423
|
+
|
|
424
|
+
```typescript
|
|
425
|
+
ShowroomVisualizer.initVisualizer({
|
|
426
|
+
// Required
|
|
427
|
+
apiHost: string; // API endpoint URL
|
|
428
|
+
config: {
|
|
429
|
+
tourCode: string; // Tour identifier
|
|
430
|
+
language?: string; // 'EN' | 'CN' | 'JP' | 'KR' | 'VI'
|
|
431
|
+
};
|
|
432
|
+
|
|
433
|
+
// Optional
|
|
434
|
+
mobile?: boolean; // Mobile mode
|
|
435
|
+
onLoaded?: (tool) => void; // Callback when loaded
|
|
436
|
+
middleware?: (event) => void; // Analytics tracking
|
|
437
|
+
listeners?: { // Event listeners (see table above)
|
|
438
|
+
onPoiClicked?: (poi) => void;
|
|
439
|
+
onSceneChanged?: (scene) => void;
|
|
440
|
+
onStartScenario?: (scenarioCode) => void;
|
|
441
|
+
onPinActionClicked?: (key) => void;
|
|
442
|
+
onSceneCompleted?: (sceneCode, categoryCode) => void;
|
|
443
|
+
// ... 16+ more listeners available
|
|
444
|
+
};
|
|
445
|
+
});
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
## Development
|
|
449
|
+
|
|
450
|
+
```bash
|
|
451
|
+
# Development with hot reload
|
|
452
|
+
yarn dev
|
|
453
|
+
|
|
454
|
+
# Production build
|
|
455
|
+
yarn build
|
|
456
|
+
|
|
457
|
+
# Linting
|
|
458
|
+
yarn lint
|
|
459
|
+
yarn lint:fix
|
|
460
|
+
|
|
461
|
+
# Code formatting
|
|
462
|
+
yarn prettier
|
|
463
|
+
|
|
464
|
+
# Serve built files locally
|
|
465
|
+
serve dist --cors
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
## Documentation
|
|
469
|
+
|
|
470
|
+
### Core Documentation
|
|
471
|
+
|
|
472
|
+
- **[CLAUDE.md](./CLAUDE.md)** - Complete architecture overview and development guide
|
|
473
|
+
- **[README.md](./README.md)** - This file - Quick start and API reference
|
|
474
|
+
|
|
475
|
+
### Analytics & Tracking
|
|
476
|
+
|
|
477
|
+
- 📚 **[Complete Tracking Guide](./Planning/README-tracking-complete.md)** - Full reference for all 35+ tracking actions
|
|
478
|
+
- 📖 **[Quick Reference Card](./Planning/TRACKING-QUICK-REFERENCE.md)** - Handy cheat sheet for developers
|
|
479
|
+
- 📝 **[Middleware Architecture](./Planning/README-middleware.md)** - Core middleware system documentation
|
|
480
|
+
- 📋 **[Changes Summary](./Planning/TRACKING-CHANGES-SUMMARY.md)** - Implementation details and file list
|
|
481
|
+
|
|
482
|
+
### Planning & Specifications
|
|
483
|
+
|
|
484
|
+
- **[Planning/](./Planning/)** - Feature planning and specifications
|
|
485
|
+
- [TEMPLATE.md](./Planning/TEMPLATE.md) - Template for new feature planning
|
|
486
|
+
|
|
487
|
+
## License
|
|
488
|
+
|
|
489
|
+
Proprietary - Clik Vietnam
|