@clikvn/showroom-visualizer 0.4.1-dev-04 → 0.4.1-dev-05

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