@clikvn/showroom-visualizer 0.3.4-dev-07 → 0.3.4-dev-09

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.
Files changed (41) hide show
  1. package/CLAUDE.md +145 -145
  2. package/DEVELOPMENT.md +120 -120
  3. package/EXAMPLES.md +967 -967
  4. package/README.md +489 -489
  5. package/SETUP_COMPLETE.md +149 -149
  6. package/base.json +21 -21
  7. package/dist/commons/SkinLayer/components/CardItemGroup/index.d.ts.map +1 -1
  8. package/dist/components/SkinLayer/Drawer/PoiHeader/index.d.ts +16 -0
  9. package/dist/components/SkinLayer/Drawer/PoiHeader/index.d.ts.map +1 -0
  10. package/dist/components/SkinLayer/Drawer/index.d.ts +29 -0
  11. package/dist/components/SkinLayer/Drawer/index.d.ts.map +1 -0
  12. package/dist/components/SkinLayer/Floorplan/Minimap/index.d.ts.map +1 -1
  13. package/dist/components/SkinLayer/PlayAll/index.d.ts +8 -0
  14. package/dist/components/SkinLayer/PlayAll/index.d.ts.map +1 -0
  15. package/dist/features/VirtualTourVisualizer/index.d.ts +20 -0
  16. package/dist/features/VirtualTourVisualizer/index.d.ts.map +1 -0
  17. package/dist/features/VirtualTourVisualizerUI/index.d.ts +17 -0
  18. package/dist/features/VirtualTourVisualizerUI/index.d.ts.map +1 -0
  19. package/dist/fonts/icomoon.svg +633 -633
  20. package/dist/index.html +32 -0
  21. package/dist/index.js +1 -1
  22. package/dist/web.d.ts.map +1 -1
  23. package/dist/web.js +1 -1
  24. package/example/CSS_HANDLING.md +141 -141
  25. package/example/FIXES_SUMMARY.md +121 -121
  26. package/example/PATH_ALIASES.md +103 -103
  27. package/example/README.md +64 -64
  28. package/example/index.html +13 -13
  29. package/example/package.json +25 -25
  30. package/example/postcss.config.cjs +5 -5
  31. package/example/tailwind.config.cjs +12 -12
  32. package/example/tsconfig.node.json +12 -12
  33. package/example/vite.config.ts +142 -142
  34. package/package.json +132 -132
  35. package/rollup.config.js +400 -400
  36. package/tailwind.config.cjs +151 -151
  37. package/.claude/settings.local.json +0 -19
  38. package/dist/components/SkinLayer/Floorplan/Minimap/test01.d.ts +0 -15
  39. package/dist/components/SkinLayer/Floorplan/Minimap/test01.d.ts.map +0 -1
  40. /package/dist/features/ShowroomVisualizer/{CssStyles.d.ts → cssStyles.d.ts} +0 -0
  41. /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