@clikvn/showroom-visualizer
v0.5.1-dev-01
Published
Showroom Visualizer
Readme
Showroom Visualizer
A powerful, flexible 360° virtual tour visualizer với Headless Architecture support.
✨ Features
- 🎨 Flexible UI: Sử dụng default UI hoặc build custom UI hoàn toàn
- 🔧 Headless Hooks: Full control với React hooks
- 📦 Component Library: Reusable components để compose custom layouts
- 🎯 Type-safe: Full TypeScript support
- ⚡ Performance: Optimized với React best practices
- 🔄 Backwards Compatible: Code cũ vẫn hoạt động bình thường
📖 Documentation
- Headless API Documentation - Chi tiết về API và hooks
- Examples - 9+ examples từ basic đến advanced
🚀 Quick Start
1. Sử dụng Default UI
import { ShowroomVisualizer } from 'showroom-visualizer';
function App() {
return (
<ShowroomVisualizer
config={{ tourCode: 'my-tour' }}
mobile={false}
apiHost="https://api.clik.vn/vt360"
/>
);
}2. Custom UI với Headless Hooks
import { ShowroomVisualizer, useShowroomControls } from 'showroom-visualizer';
function CustomUI() {
const controls = useShowroomControls();
return (
<div>
<h1>{controls.activeScene?.name}</h1>
<button onClick={controls.goToNextScene}>Next →</button>
<button onClick={controls.toggleFloorplan}>Toggle Map</button>
</div>
);
}
function App() {
return (
<ShowroomVisualizer
config={{ tourCode: 'my-tour' }}
customLayout={<CustomUI />}
/>
);
}3. Headless Mode (No UI)
import { ShowroomVisualizer, useShowroomControls } from 'showroom-visualizer';
function ExternalControls() {
const controls = useShowroomControls();
return <div>Build your UI here...</div>;
}
function App() {
return (
<>
<ExternalControls />
<ShowroomVisualizer
config={{ tourCode: 'my-tour' }}
disableDefaultUI={true}
/>
</>
);
}📚 API Reference
Headless Hooks
useShowroomControls()- Main hook với tất cả controlsuseTourCore()- Tour engine state (read-only)useSceneNavigation()- Scene navigation controlsuseFloorplanControl()- Floorplan/minimap controlsuseScenarioControl()- Scenario auto-play controlsusePOIInteraction()- POI interaction controlsuseViewportControl()- Viewport/camera controls
Exported Components
DefaultLayout- Default UI layoutPinActions,Floorplan,SceneCategoriesPlayBar,GalleryFullScreen,ModalPopupPoi- ...và nhiều components khác
Xem HEADLESS_API.md để biết chi tiết.
🎓 Examples
Xem EXAMPLES.md để xem 9+ examples:
- Simple Custom Header
- Scene Grid Selector
- Sidebar Navigation
- External Dashboard
- Auto-play Controls
- POI Explorer
- Complete Custom UI
- Mobile-first UI
- ...và nhiều hơn nữa!
🔧 Development
# Install dependencies
yarn install
# Run development server
yarn dev
# Build for production
yarn build
# Serve built files
serve dist --cors 📝 License
MIT
Installation
npm install @clikvn/showroom-visualizer
# or
yarn add @clikvn/showroom-visualizerBasic Usage
<!-- public/index.html -->
<script type="module">
import ShowroomVisualizer from 'http://localhost:3000/web.js';
ShowroomVisualizer.initVisualizer({
apiHost: 'https://ci-api.clik.vn/vt360',
config: {
tourCode: 'TOUR_FXYCEN7ZZVW6',
language: 'EN',
},
onLoaded: (tool) => {
window.tool = tool;
},
mobile: false,
});
</script>
<div style="width: 100vw; height: 100vh">
<showroom-visualizer></showroom-visualizer>
</div>Features
- 🌐 360° Virtual Tours - Interactive panoramic experiences powered by Krpano
- 🎯 Points of Interest (POI) - Multiple POI types: Gallery, Video, Sound, Navigation, Texture, Promotions
- 🎬 Automated Scenarios - Guided tour playback with camera movements and narration
- 🗺️ Floorplan/Minimap - Interactive navigation with radar positioning
- 📱 Mobile Optimized - Touch controls and responsive layout for mobile devices
- 🌍 Multi-language - Support for EN, CN, JP, KR, VI
- 🎨 Customizable UI - Theme support and configurable components
- 📊 Comprehensive Analytics - 35+ tracking actions covering all user interactions (see below)
Comprehensive Analytics & Tracking
The library includes a powerful tracking middleware system with 35+ actions covering all user interactions:
import ShowroomVisualizer from '@clikvn/showroom-visualizer';
ShowroomVisualizer.initVisualizer({
apiHost: 'https://api.clik.vn',
config: { tourCode: 'TOUR_123' },
// Add tracking middleware
middleware: (event) => {
// Event structure:
// {
// actionName: 'onCardItemClick',
// payload: { itemCode, itemTitle, itemType, sceneCode, ... },
// timestamp: '2025-01-15T10:00:00.000Z',
// metadata: { tourCode, sceneCode, categoryCode }
// }
// Send to your analytics service
analytics.track(event.actionName, event.payload);
},
});What's Tracked (35+ Actions)
Search & Discovery (6 actions)
- Panel open/close, search queries
- Category header clicks (Products, Features, Locations, etc.)
- Promotion actions (show more, auto play)
- Individual scenario clicks
Individual Items (1 universal action covering all types)
- Product clicks
- POI clicks (Information, Features, Brands, Locations, Facilities, Multimedia)
- Feature clicks
- Promotion item clicks
POI Detail Panel (5 actions)
- Open/close, audio playback
- Action buttons (AI Assistant, Save, Audio, Share)
- Tab switching (Gallery, AR, Web Rotate, Info, Specification)
- Gallery item clicks
Scenario Playback (8 actions)
- Scenario start, play/pause
- Skip (next/previous), loop toggle
- Sound toggle, playlist toggle
- Playbar close
Navigation (6 actions)
- Scene group selection
- Floorplan changes
- Minimap expand/minimize
- View scenes button
UI Components (1+ actions)
- Guide open/close
- Other UI interactions
Key Features
✅ Deep-level tracking - Not just categories, but individual items within each category ✅ Rich payloads - Codes, names, types, and contextual data for every action ✅ User journey mapping - Complete visibility from discovery to engagement ✅ Zero overhead - No performance impact when middleware not configured ✅ Fire-and-forget - Non-blocking, error-safe pattern ✅ Analytics-ready - Easy integration with GA4, Mixpanel, or custom backends
Complete List of Tracked Events (35+ Actions)
Search & Discovery (6 events)
| Event Name | Trigger | Payload |
| ----------------------------------- | --------------------------- | ---------------------------------- |
| onSearchAndDiscoveryClose | Panel closed | {} |
| onSearchAndDiscoverySearch | User types in search | { searchQuery } |
| onSearchAndDiscoveryItemClick | Category header clicked | { itemKey, itemTitle, itemType } |
| onSearchAndDiscoveryScenarioClick | Scenario clicked from panel | { scenarioCode, scenarioName } |
| onPromotionShowMore | Show more button clicked | { totalPromotions } |
| onPromotionAutoPlay | Auto play button clicked | { totalPromotions } |
Categories tracked: HOME, AMENITIES, SCENE, PROMOTION, FEATURES, PRODUCT_LIST, INFORMATION, BRAND, LOCATION, FACILITY, MULTIMEDIA, SWAP_ELEMENT, SCENARIO, PLAYLIST, DISPLAY_HOTSPOT, DETAIL
Individual Items - Universal (1 event covering ALL types)
| Event Name | Trigger | Payload |
| ----------------- | ---------------------------------------------- | -------------------------------------------------------------------- |
| onCardItemClick | Any item clicked (product, POI, feature, etc.) | { itemCode, itemTitle, itemType, sceneCode, hotspotCode, isVideo } |
Item types covered: Products, Information POIs, Features, Brands, Locations, Facilities, Multimedia, Swap Elements, Promotions
POI Detail Panel (5 events)
| Event Name | Trigger | Payload |
| ------------------------- | ------------------------- | ----------------------------------------------------------- |
| onPoiDetailClose | Detail panel closed | { poiCode, poiName, poiType } |
| onPoiDetailAudioPlay | Audio play button clicked | { poiCode, poiName, poiType } |
| onPoiDetailGalleryClick | Gallery item clicked | { poiCode, poiName, poiType, galleryItemId, galleryType } |
| onPoiDetailActionClick | Action button clicked | { actionKey, productCode, productName, productType } |
| onPoiDetailTabChange | Tab switched | { tabKey, productCode, productName, galleryType } |
Action keys: ai_assistant, save, audio, share
Tab keys: gallery, ar, webRotate, info, specification
Scenario Playback (8 events)
| Event Name | Trigger | Payload |
| ---------------------- | -------------------------- | ----------------------------- |
| onStartScenario | Scenario started from list | scenarioCode (string) |
| onPlayBarClose | Playbar closed | { scenarioCode } |
| onPlayListToggle | Playlist toggled | { show } |
| onPlayBarPlayClick | Play button clicked | { scenarioCode } |
| onPlayBarPauseClick | Pause button clicked | { scenarioCode } |
| onPlayBarLoopToggle | Loop toggled | { loop, scenarioCode } |
| onPlayBarSoundToggle | Sound toggled | { playing } |
| onPlayBarSkip | Skip button clicked | { direction, scenarioCode } |
Direction values: 'previous' or 'next'
Navigation (6 events)
| Event Name | Trigger | Payload |
| ------------------------- | -------------------------- | ------------------------------------------ |
| onSceneGroupSelected | Scene group selected | { sceneGroupCode, sceneGroupName } |
| onSubSceneGroupSelected | Sub scene group selected | { subSceneGroupCode, subSceneGroupName } |
| onFloorplanViewScenes | View scenes button clicked | {} |
| onFloorplanChange | Floorplan changed | { floorplanCode, floorplanName } |
| onMinimapExpand | Minimap expanded | {} |
| onMinimapMinimize | Minimap minimized | {} |
UI Components (1+ events)
| Event Name | Trigger | Payload |
| -------------- | -------------------- | ------- |
| onGuideClose | Guide overlay closed | {} |
Analytics Integration Examples
Google Analytics 4:
middleware: (event) => {
gtag('event', event.actionName, {
event_category: 'showroom',
tour_code: event.metadata?.tourCode,
...event.payload,
});
};Mixpanel:
middleware: (event) => {
mixpanel.track(event.actionName, {
tour_code: event.metadata?.tourCode,
...event.payload,
});
};Custom Backend:
middleware: async (event) => {
await fetch('/api/analytics', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(event),
});
};📚 Detailed Documentation: For complete examples, user journey scenarios, and implementation patterns, see Complete Tracking Guide
Available Listeners
The library provides 21+ event listeners for custom app logic:
| Listener | Description | Payload |
| ----------------------- | --------------------- | ------------------------- |
| POI Events |
| onPoiClicked | POI clicked | POI object |
| onPoiOver | Mouse over POI | POI object |
| onPoiHover | Mouse hovering POI | POI object |
| onPoiOut | Mouse left POI | - |
| onPoiInCenter | POI nearest to center | POI object |
| Scene Events |
| onSceneCompleted | Scene loaded | sceneCode, categoryCode |
| onSceneChanged | Scene navigated | Scene object |
| Scenario Events |
| onStartScenario | Scenario started | scenarioCode |
| onScenarioPaused | Scenario paused | scenarioCode |
| onScenarioEnded | Scenario ended | scenarioCode |
| UI Events |
| onToggleSlideIn | Slide-in toggled | { open, offset } |
| onPlaybarOpen | Playbar opened | - |
| onPlaybarClosed | Playbar closed | - |
| onPinActionClicked | Pin button clicked | Button key string |
| Tour Lifecycle |
| onStartLoadingTour | Tour load started | tourCode |
| onFinishedLoadingTour | Tour load finished | tourCode |
| onLoaded | Tool ready | Tool object |
| onDataLoaded | Tour data loaded | tour, tourData |
| Product Events |
| onAIProductClicked | AI product clicked | Product code |
| onShareProductClicked | Share product clicked | Product code |
| Other Events |
| onChanged | Config changed | Config object |
| onTourSwitchLoaded | Tour switch ready | TourSwitch object |
| onStateChanged | State changed | State values |
Key Differences: Listeners vs Middleware
| Feature | Listeners | Middleware (Tracked Actions) | | -------------- | ------------------ | ------------------------------ | | Purpose | Custom app logic | Analytics & tracking | | When fires | Only if configured | Always (if middleware set) | | Count | 21+ events | 35+ actions | | Use case | App functionality | User behavior insights | | Blocking | Can be blocking | Non-blocking (fire-and-forget) |
Example:
- Use listeners to trigger custom UI updates when a scene changes
- Use middleware to track that scene change in your analytics platform
Both can be used together - listeners for app logic, middleware for analytics!
Configuration Options
ShowroomVisualizer.initVisualizer({
// Required
apiHost: string; // API endpoint URL
config: {
tourCode: string; // Tour identifier
language?: string; // 'EN' | 'CN' | 'JP' | 'KR' | 'VI'
};
// Optional
mobile?: boolean; // Mobile mode
onLoaded?: (tool) => void; // Callback when loaded
middleware?: (event) => void; // Analytics tracking
listeners?: { // Event listeners (see table above)
onPoiClicked?: (poi) => void;
onSceneChanged?: (scene) => void;
onStartScenario?: (scenarioCode) => void;
onPinActionClicked?: (key) => void;
onSceneCompleted?: (sceneCode, categoryCode) => void;
// ... 16+ more listeners available
};
});Development
# Development with hot reload
yarn dev
# Production build
yarn build
# Linting
yarn lint
yarn lint:fix
# Code formatting
yarn prettier
# Serve built files locally
serve dist --corsDocumentation
Core Documentation
- CLAUDE.md - Complete architecture overview and development guide
- README.md - This file - Quick start and API reference
Analytics & Tracking
- 📚 Complete Tracking Guide - Full reference for all 35+ tracking actions
- 📖 Quick Reference Card - Handy cheat sheet for developers
- 📝 Middleware Architecture - Core middleware system documentation
- 📋 Changes Summary - Implementation details and file list
Planning & Specifications
- Planning/ - Feature planning and specifications
- TEMPLATE.md - Template for new feature planning
License
Proprietary - Clik Vietnam
