@clikvn/showroom-visualizer 0.5.0 → 0.5.1-dev-02

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 (121) 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/dist/components/SkinLayer/DefaultLayout/index.d.ts.map +1 -1
  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/GalleryFullScreen/Content/ARViewer.d.ts +30 -0
  12. package/dist/components/SkinLayer/GalleryFullScreen/Content/ARViewer.d.ts.map +1 -0
  13. package/dist/components/SkinLayer/HotspotOverview/index.d.ts.map +1 -1
  14. package/dist/components/SkinLayer/Layout/index.d.ts.map +1 -1
  15. package/dist/components/SkinLayer/ModalItemInfo/Description.d.ts +10 -0
  16. package/dist/components/SkinLayer/ModalItemInfo/Description.d.ts.map +1 -0
  17. package/dist/components/SkinLayer/ModalItemInfo/Intro.d.ts +9 -0
  18. package/dist/components/SkinLayer/ModalItemInfo/Intro.d.ts.map +1 -0
  19. package/dist/components/SkinLayer/ModalItemInfo/Media.d.ts +13 -0
  20. package/dist/components/SkinLayer/ModalItemInfo/Media.d.ts.map +1 -0
  21. package/dist/components/SkinLayer/ModalItemInfo/index.d.ts +10 -0
  22. package/dist/components/SkinLayer/ModalItemInfo/index.d.ts.map +1 -0
  23. package/dist/components/SkinLayer/PlayAll/index.d.ts +8 -0
  24. package/dist/components/SkinLayer/PlayAll/index.d.ts.map +1 -0
  25. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/HorizontalMenu.d.ts +14 -0
  26. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/HorizontalMenu.d.ts.map +1 -0
  27. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/ListMovingMenuItem.d.ts +14 -0
  28. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/ListMovingMenuItem.d.ts.map +1 -0
  29. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/SemicircleMenu.d.ts +14 -0
  30. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/SemicircleMenu.d.ts.map +1 -0
  31. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/VerticalMenu.d.ts +14 -0
  32. package/dist/components/SkinLayer/PoiListMovingOptions/Menu/VerticalMenu.d.ts.map +1 -0
  33. package/dist/components/SkinLayer/PoiListMovingOptions/index.d.ts +4 -0
  34. package/dist/components/SkinLayer/PoiListMovingOptions/index.d.ts.map +1 -0
  35. package/dist/components/SkinLayer/PoiTextureOptions/HorizontalMenu/index.d.ts +13 -0
  36. package/dist/components/SkinLayer/PoiTextureOptions/HorizontalMenu/index.d.ts.map +1 -0
  37. package/dist/components/SkinLayer/PoiTextureOptions/SemicircleMenu/index.d.ts +13 -0
  38. package/dist/components/SkinLayer/PoiTextureOptions/SemicircleMenu/index.d.ts.map +1 -0
  39. package/dist/components/SkinLayer/PoiTextureOptions/TextureMenuItem/index.d.ts +15 -0
  40. package/dist/components/SkinLayer/PoiTextureOptions/TextureMenuItem/index.d.ts.map +1 -0
  41. package/dist/components/SkinLayer/PoiTextureOptions/VerticalMenu/index.d.ts +13 -0
  42. package/dist/components/SkinLayer/PoiTextureOptions/VerticalMenu/index.d.ts.map +1 -0
  43. package/dist/components/SkinLayer/index.d.ts +1 -0
  44. package/dist/components/SkinLayer/index.d.ts.map +1 -1
  45. package/dist/constants/Visualizer/index.d.ts +1 -0
  46. package/dist/constants/Visualizer/index.d.ts.map +1 -1
  47. package/dist/constants/Visualizer/poi.d.ts +1 -0
  48. package/dist/constants/Visualizer/poi.d.ts.map +1 -1
  49. package/dist/context/StoreContext.d.ts +5 -0
  50. package/dist/context/StoreContext.d.ts.map +1 -0
  51. package/dist/features/ShowroomVisualizer/Scripts.d.ts +4 -0
  52. package/dist/features/ShowroomVisualizer/Scripts.d.ts.map +1 -0
  53. package/dist/features/ShowroomVisualizer/TourContainer.d.ts +9 -0
  54. package/dist/features/ShowroomVisualizer/TourContainer.d.ts.map +1 -0
  55. package/dist/features/ShowroomVisualizer/Tours.d.ts +3 -0
  56. package/dist/features/ShowroomVisualizer/Tours.d.ts.map +1 -0
  57. package/dist/features/ShowroomVisualizer/{CssStyles.d.ts.map → cssStyles.d.ts.map} +1 -1
  58. package/dist/features/ShowroomVisualizer/index.d.ts +1 -0
  59. package/dist/features/ShowroomVisualizer/index.d.ts.map +1 -1
  60. package/dist/features/VirtualTourVisualizer/index.d.ts +20 -0
  61. package/dist/features/VirtualTourVisualizer/index.d.ts.map +1 -0
  62. package/dist/features/VirtualTourVisualizerUI/index.d.ts +17 -0
  63. package/dist/features/VirtualTourVisualizerUI/index.d.ts.map +1 -0
  64. package/dist/hooks/SkinLayer/useAutoPlayer.d.ts.map +1 -1
  65. package/dist/hooks/Visualizer/reducer.d.ts +116 -0
  66. package/dist/hooks/Visualizer/reducer.d.ts.map +1 -0
  67. package/dist/hooks/Visualizer/useTourVisualizer.d.ts.map +1 -1
  68. package/dist/hooks/useStore.d.ts.map +1 -1
  69. package/dist/index.d.ts +1 -1
  70. package/dist/index.d.ts.map +1 -1
  71. package/dist/index.html +110 -0
  72. package/dist/index.js +1 -1
  73. package/dist/models/Visualizer/Poi/PoiListMoving.d.ts +39 -0
  74. package/dist/models/Visualizer/Poi/PoiListMoving.d.ts.map +1 -0
  75. package/dist/models/Visualizer/Scene.d.ts.map +1 -1
  76. package/dist/models/Visualizer/Tour.d.ts +3 -0
  77. package/dist/models/Visualizer/Tour.d.ts.map +1 -1
  78. package/dist/models/Visualizer/TourScenario/TourScenarioPlayer.d.ts +1 -0
  79. package/dist/models/Visualizer/TourScenario/TourScenarioPlayer.d.ts.map +1 -1
  80. package/dist/models/Visualizer/TourScenario/actions/RotationAction.d.ts.map +1 -1
  81. package/dist/types/SkinLayer/store.type.d.ts +7 -0
  82. package/dist/types/SkinLayer/store.type.d.ts.map +1 -1
  83. package/dist/types/Visualizer/poi.type.d.ts +17 -0
  84. package/dist/types/Visualizer/poi.type.d.ts.map +1 -1
  85. package/dist/types/Visualizer/signal.type.d.ts +3 -0
  86. package/dist/types/Visualizer/signal.type.d.ts.map +1 -1
  87. package/dist/utils/Visualizer/index.d.ts +1 -0
  88. package/dist/utils/Visualizer/index.d.ts.map +1 -1
  89. package/dist/utils/Visualizer/scene.utils.d.ts +5 -0
  90. package/dist/utils/Visualizer/scene.utils.d.ts.map +1 -0
  91. package/dist/web.js +1 -1
  92. package/example/CSS_HANDLING.md +141 -141
  93. package/example/FIXES_SUMMARY.md +121 -121
  94. package/example/PATH_ALIASES.md +103 -103
  95. package/example/README.md +64 -64
  96. package/example/index.html +13 -13
  97. package/example/package.json +25 -25
  98. package/example/postcss.config.cjs +5 -5
  99. package/example/src/App.tsx +195 -0
  100. package/example/src/components/ControlPanel.tsx +736 -0
  101. package/example/src/components/CustomComponents/FloorplanComponents.tsx +37 -0
  102. package/example/src/components/CustomComponents/HotspotCategoryComponents.tsx +106 -0
  103. package/example/src/components/CustomComponents/PinActionsComponents.tsx +45 -0
  104. package/example/src/components/CustomComponents/PlayBarComponents.tsx +41 -0
  105. package/example/src/components/CustomComponents/PoiDetailComponents.tsx +296 -0
  106. package/example/src/components/CustomComponents/SearchAndDiscoveryComponents.tsx +207 -0
  107. package/example/src/components/CustomComponents/index.tsx +7 -0
  108. package/example/src/css-modules.d.ts +4 -0
  109. package/example/src/hooks/useCustomLayout.ts +328 -0
  110. package/example/src/index.css +31 -0
  111. package/example/src/main.tsx +11 -0
  112. package/example/tailwind.config.cjs +12 -12
  113. package/example/tsconfig.node.json +12 -12
  114. package/example/vite.config.ts +142 -142
  115. package/package.json +133 -133
  116. package/rollup.config.js +400 -400
  117. package/yarn-error.log +12200 -0
  118. package/.claude/settings.local.json +0 -19
  119. package/dist/components/SkinLayer/Floorplan/Minimap/test01.d.ts +0 -15
  120. package/dist/components/SkinLayer/Floorplan/Minimap/test01.d.ts.map +0 -1
  121. /package/dist/features/ShowroomVisualizer/{CssStyles.d.ts → cssStyles.d.ts} +0 -0
@@ -0,0 +1,37 @@
1
+ import { MiniMapMarkerDefault } from '@clikvn/showroom-visualizer';
2
+
3
+ // 🎨 Custom Marker Component
4
+ export const CustomMarker = (props: any) => {
5
+ return (
6
+ <div className="custom-minimap-marker ">
7
+ <MiniMapMarkerDefault
8
+ marker={props.marker}
9
+ active={props.active}
10
+ scaleOffset={props.scaleOffset}
11
+ color={props.color}
12
+ size={props.size}
13
+ onClick={props.onClick}
14
+ />
15
+ </div>
16
+ );
17
+ };
18
+
19
+ export const FloorplanMinimapDefault = (props: any) => {
20
+ return (
21
+ <div className="custom-hotspot-overview">
22
+ <div
23
+ style={{
24
+ width: '100%',
25
+ height: '100%',
26
+ display: 'flex',
27
+ alignItems: 'center',
28
+ justifyContent: 'center',
29
+ }}
30
+ >
31
+ <span style={{ fontSize: '12px', color: 'white' }}>
32
+ 🏠 custom mini map
33
+ </span>
34
+ </div>
35
+ </div>
36
+ );
37
+ };
@@ -0,0 +1,106 @@
1
+ import {
2
+ HotspotCategorySlideIn as HotspotCategorySlideInDefault,
3
+ ScenarioSlideIn as ScenarioSlideInDefault,
4
+ SpaceAndSceneSlideIn as SpaceAndSceneSlideInDefault,
5
+ FeatureSlideIn as FeatureSlideInDefault,
6
+ ProductSlideIn as ProductSlideInDefault,
7
+ PoiSlideIn as PoiSlideInDefault,
8
+ } from '@clikvn/showroom-visualizer';
9
+
10
+ // 🏠 Custom HotspotCategorySlideIn Component
11
+ export const CustomHotspotCategorySlideIn = (props: any) => {
12
+ return <HotspotCategorySlideInDefault {...props} />;
13
+ };
14
+
15
+ // đŸŽŦ Custom ScenarioSlideIn
16
+ export const CustomScenarioSlideIn = (props: any) => {
17
+ return (
18
+ <div
19
+ style={{
20
+ background: 'linear-gradient(135deg, #6b46c1 0%, #2d3748 100%)',
21
+ padding: '20px',
22
+ height: '100%',
23
+ overflow: 'auto',
24
+ }}
25
+ >
26
+ <h3 style={{ color: 'white', marginBottom: '20px' }}>
27
+ đŸŽŦ Custom Scenarios
28
+ </h3>
29
+ <ScenarioSlideInDefault {...props} />
30
+ </div>
31
+ );
32
+ };
33
+
34
+ // đŸ›ī¸ Custom SpaceAndSceneSlideIn
35
+ export const CustomSpaceAndSceneSlideIn = (props: any) => {
36
+ return (
37
+ <div
38
+ style={{
39
+ background: 'linear-gradient(135deg, #4299e1 0%, #2b6cb0 100%)',
40
+ padding: '20px',
41
+ height: '100%',
42
+ overflow: 'auto',
43
+ }}
44
+ >
45
+ <h3 style={{ color: 'white', marginBottom: '20px' }}>
46
+ đŸ›ī¸ Custom Spaces & Scenes
47
+ </h3>
48
+ <SpaceAndSceneSlideInDefault {...props} />
49
+ </div>
50
+ );
51
+ };
52
+
53
+ // ⭐ Custom FeatureSlideIn
54
+ export const CustomFeatureSlideIn = (props: any) => {
55
+ return (
56
+ <div
57
+ style={{
58
+ background: 'linear-gradient(135deg, #ed8936 0%, #c05621 100%)',
59
+ padding: '20px',
60
+ height: '100%',
61
+ overflow: 'auto',
62
+ }}
63
+ >
64
+ <h3 style={{ color: 'white', marginBottom: '20px' }}>
65
+ ⭐ Custom Features
66
+ </h3>
67
+ <FeatureSlideInDefault {...props} />
68
+ </div>
69
+ );
70
+ };
71
+
72
+ // đŸ›ī¸ Custom ProductSlideIn
73
+ export const CustomProductSlideIn = (props: any) => {
74
+ return (
75
+ <div
76
+ style={{
77
+ background: 'linear-gradient(135deg, #48bb78 0%, #2f855a 100%)',
78
+ padding: '20px',
79
+ height: '100%',
80
+ overflow: 'auto',
81
+ }}
82
+ >
83
+ <h3 style={{ color: 'white', marginBottom: '20px' }}>
84
+ đŸ›ī¸ Custom Products
85
+ </h3>
86
+ <ProductSlideInDefault {...props} />
87
+ </div>
88
+ );
89
+ };
90
+
91
+ // 📍 Custom PoiSlideIn
92
+ export const CustomPoiSlideIn = (props: any) => {
93
+ return (
94
+ <div
95
+ style={{
96
+ background: 'linear-gradient(135deg, #e53e3e 0%, #c53030 100%)',
97
+ padding: '20px',
98
+ height: '100%',
99
+ overflow: 'auto',
100
+ }}
101
+ >
102
+ <h3 style={{ color: 'white', marginBottom: '20px' }}>📍 Custom POI</h3>
103
+ <PoiSlideInDefault {...props} />
104
+ </div>
105
+ );
106
+ };
@@ -0,0 +1,45 @@
1
+ import {
2
+ PinActions as PinActionsDefault,
3
+ PinActionButtonWithTooltipDefault,
4
+ } from '@clikvn/showroom-visualizer';
5
+
6
+ // đŸŽ¯ Custom PinActions Component
7
+ export const CustomPinActions = (props: any) => {
8
+ return (
9
+ <div style={{ filter: 'hue-rotate(180deg)' }}>
10
+ <PinActionsDefault {...props} />
11
+ </div>
12
+ );
13
+ };
14
+
15
+ // đŸŽ¯ Custom PinAction Button Component
16
+ export const CustomPinActionButton = (props: any) => {
17
+ return (
18
+ <div
19
+ style={{
20
+ filter: 'drop-shadow(0 0 3px rgba(255, 215, 0, 0.6))',
21
+ transform: props.disabled ? 'scale(0.95)' : 'scale(1)',
22
+ transition: 'all 0.2s ease',
23
+ display: 'inline-block',
24
+ backgroundColor: 'red',
25
+ }}
26
+ >
27
+ <button {...props} />
28
+ </div>
29
+ );
30
+ };
31
+
32
+ // đŸŽ¯ Custom PinAction ButtonWithTooltip Component
33
+ export const CustomPinActionButtonWithTooltip = (props: any) => {
34
+ return (
35
+ <div
36
+ style={{
37
+ border: '2px solid rgba(255, 215, 0, 0.5)',
38
+ borderRadius: '4px',
39
+ padding: '2px',
40
+ }}
41
+ >
42
+ <PinActionButtonWithTooltipDefault {...props} />
43
+ </div>
44
+ );
45
+ };
@@ -0,0 +1,41 @@
1
+ // đŸŽĩ Custom PlayBar Components
2
+ export const CustomPlayBarTooltip = (props: any) => {
3
+ return (
4
+ <div
5
+ style={{
6
+ border: '2px solid #ff6b6b',
7
+ borderRadius: '8px',
8
+ padding: '2px',
9
+ }}
10
+ >
11
+ {props.children}
12
+ </div>
13
+ );
14
+ };
15
+
16
+ export const CustomPlayBarButton = (props: any) => {
17
+ return (
18
+ <div
19
+ style={{
20
+ filter: 'drop-shadow(0 0 5px rgba(102, 126, 234, 0.5))',
21
+ transform: props.disabled ? 'none' : 'scale(1.05)',
22
+ transition: 'all 0.2s ease',
23
+ display: 'inline-block',
24
+ }}
25
+ >
26
+ {props.children || (
27
+ <button
28
+ {...props}
29
+ style={{
30
+ padding: '8px 16px',
31
+ borderRadius: '4px',
32
+ border: '1px solid #667eea',
33
+ background: props.disabled ? '#ccc' : '#667eea',
34
+ color: 'white',
35
+ cursor: props.disabled ? 'not-allowed' : 'pointer',
36
+ }}
37
+ />
38
+ )}
39
+ </div>
40
+ );
41
+ };
@@ -0,0 +1,296 @@
1
+ // đŸ“Ļ Custom PoiDetailSlideIn Components
2
+ export const CustomPoiDetailDrawer = (props: any) => {
3
+ return (
4
+ <div
5
+ style={{
6
+ border: '3px solid #48bb78',
7
+ borderRadius: '12px',
8
+ position: 'relative',
9
+ }}
10
+ >
11
+ {props.children}
12
+ </div>
13
+ );
14
+ };
15
+
16
+ export const CustomPoiDetailBottomSheet = (props: any) => {
17
+ return (
18
+ <div
19
+ style={{
20
+ border: '3px solid #ed8936',
21
+ borderRadius: '12px',
22
+ position: 'relative',
23
+ }}
24
+ >
25
+ {props.children}
26
+ </div>
27
+ );
28
+ };
29
+
30
+ export const CustomProductDetailHeader = (props: any) => {
31
+ return (
32
+ <div
33
+ style={{
34
+ background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
35
+ padding: '16px',
36
+ borderRadius: '8px',
37
+ marginBottom: '12px',
38
+ color: 'white',
39
+ }}
40
+ >
41
+ <div
42
+ style={{ fontWeight: 'bold', marginBottom: '8px', fontSize: '18px' }}
43
+ >
44
+ ✨ {props.title || 'Custom Header'}
45
+ </div>
46
+ {props.displayPrice && (
47
+ <div style={{ fontSize: '16px', opacity: 0.9 }}>
48
+ 💰 {props.displayPrice}
49
+ </div>
50
+ )}
51
+ {props.rating && props.rating > 0 && (
52
+ <div style={{ fontSize: '14px', marginTop: '8px' }}>
53
+ ⭐ Rating: {props.rating}/5
54
+ </div>
55
+ )}
56
+ {props.onBack && (
57
+ <button
58
+ onClick={props.onBack}
59
+ style={{
60
+ marginTop: '12px',
61
+ padding: '6px 12px',
62
+ borderRadius: '4px',
63
+ border: '1px solid rgba(255,255,255,0.3)',
64
+ background: 'rgba(255,255,255,0.1)',
65
+ color: 'white',
66
+ cursor: 'pointer',
67
+ }}
68
+ >
69
+ ← Back
70
+ </button>
71
+ )}
72
+ </div>
73
+ );
74
+ };
75
+
76
+ export const CustomGroupActionButton = (props: any) => {
77
+ return (
78
+ <div
79
+ style={{
80
+ background: 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
81
+ padding: '12px',
82
+ borderRadius: '8px',
83
+ marginBottom: '12px',
84
+ }}
85
+ >
86
+ <div
87
+ style={{
88
+ color: 'white',
89
+ fontSize: '12px',
90
+ marginBottom: '8px',
91
+ fontWeight: 'bold',
92
+ }}
93
+ >
94
+ đŸŽ¯ Custom Actions
95
+ </div>
96
+ <div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap' }}>
97
+ {props.actions?.map((action: any) => (
98
+ <button
99
+ key={action.key}
100
+ onClick={() => props.onClick?.(action.key)}
101
+ disabled={action.disabled}
102
+ style={{
103
+ flex: 1,
104
+ minWidth: '80px',
105
+ padding: '8px',
106
+ borderRadius: '6px',
107
+ border: '1px solid rgba(255,255,255,0.3)',
108
+ background:
109
+ props.activeKey === action.key
110
+ ? 'rgba(255,255,255,0.3)'
111
+ : 'rgba(255,255,255,0.1)',
112
+ color: 'white',
113
+ cursor: action.disabled ? 'not-allowed' : 'pointer',
114
+ opacity: action.disabled ? 0.5 : 1,
115
+ }}
116
+ >
117
+ {action.label}
118
+ </button>
119
+ ))}
120
+ </div>
121
+ </div>
122
+ );
123
+ };
124
+
125
+ export const CustomTabs = (props: any) => {
126
+ return (
127
+ <div
128
+ style={{
129
+ border: '2px dashed #4299e1',
130
+ borderRadius: '8px',
131
+ padding: '4px',
132
+ background: 'rgba(66, 153, 225, 0.1)',
133
+ }}
134
+ >
135
+ {props.children}
136
+ </div>
137
+ );
138
+ };
139
+
140
+ export const CustomTabsContent = (props: any) => {
141
+ return (
142
+ <div
143
+ style={{
144
+ border: '2px solid #ed8936',
145
+ borderRadius: '8px',
146
+ padding: '8px',
147
+ background: 'rgba(237, 137, 54, 0.1)',
148
+ }}
149
+ >
150
+ {props.children}
151
+ </div>
152
+ );
153
+ };
154
+
155
+ // 📄 Custom TabsContent Sub-components
156
+ export const CustomInfo = (props: any) => {
157
+ return (
158
+ <div
159
+ style={{
160
+ background: 'linear-gradient(135deg, #a8edea 0%, #fed6e3 100%)',
161
+ padding: '16px',
162
+ borderRadius: '8px',
163
+ minHeight: '200px',
164
+ }}
165
+ >
166
+ <div
167
+ style={{
168
+ color: '#333',
169
+ fontWeight: 'bold',
170
+ marginBottom: '12px',
171
+ fontSize: '16px',
172
+ }}
173
+ >
174
+ â„šī¸ Custom Info Tab
175
+ </div>
176
+ {props.description && (
177
+ <div style={{ marginBottom: '16px', color: '#555' }}>
178
+ <strong>Description:</strong>
179
+ <div style={{ marginTop: '8px' }}>{props.description}</div>
180
+ </div>
181
+ )}
182
+ {props.specification && (
183
+ <div style={{ color: '#555' }}>
184
+ <strong>Specification:</strong>
185
+ <div style={{ marginTop: '8px' }}>{props.specification}</div>
186
+ </div>
187
+ )}
188
+ {props.galleryProduct && props.galleryProduct.length > 0 && (
189
+ <div style={{ marginTop: '16px', color: '#555' }}>
190
+ <strong>Gallery Items: {props.galleryProduct.length}</strong>
191
+ </div>
192
+ )}
193
+ </div>
194
+ );
195
+ };
196
+
197
+ export const CustomGallery = (props: any) => {
198
+ return (
199
+ <div
200
+ style={{
201
+ background: 'linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%)',
202
+ padding: '16px',
203
+ borderRadius: '8px',
204
+ minHeight: '200px',
205
+ }}
206
+ >
207
+ <div
208
+ style={{
209
+ color: '#333',
210
+ fontWeight: 'bold',
211
+ marginBottom: '12px',
212
+ fontSize: '16px',
213
+ }}
214
+ >
215
+ đŸ–ŧī¸ Custom Gallery Tab
216
+ </div>
217
+ {props.items && props.items.length > 0 ? (
218
+ <div
219
+ style={{
220
+ display: 'grid',
221
+ gridTemplateColumns: 'repeat(auto-fill, minmax(150px, 1fr))',
222
+ gap: '12px',
223
+ }}
224
+ >
225
+ {props.items.map((item: any, index: number) => (
226
+ <div
227
+ key={index}
228
+ onClick={() => props.onClick?.(index, item.type)}
229
+ style={{
230
+ aspectRatio: '16/9',
231
+ background: 'rgba(255,255,255,0.5)',
232
+ borderRadius: '8px',
233
+ display: 'flex',
234
+ alignItems: 'center',
235
+ justifyContent: 'center',
236
+ cursor: 'pointer',
237
+ border: '2px solid rgba(0,0,0,0.1)',
238
+ }}
239
+ >
240
+ <span style={{ color: '#666' }}>📷 Item {index + 1}</span>
241
+ </div>
242
+ ))}
243
+ </div>
244
+ ) : (
245
+ <div style={{ color: '#666', textAlign: 'center', padding: '40px' }}>
246
+ No gallery items
247
+ </div>
248
+ )}
249
+ </div>
250
+ );
251
+ };
252
+
253
+ export const CustomArTab = (props: any) => {
254
+ return (
255
+ <div
256
+ style={{
257
+ background: 'linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%)',
258
+ padding: '16px',
259
+ borderRadius: '8px',
260
+ minHeight: '200px',
261
+ display: 'flex',
262
+ flexDirection: 'column',
263
+ alignItems: 'center',
264
+ justifyContent: 'center',
265
+ }}
266
+ >
267
+ <div
268
+ style={{
269
+ color: 'white',
270
+ fontWeight: 'bold',
271
+ marginBottom: '12px',
272
+ fontSize: '16px',
273
+ }}
274
+ >
275
+ 📱 Custom AR Tab
276
+ </div>
277
+ {props.ar && (
278
+ <div
279
+ style={{
280
+ background: 'rgba(255,255,255,0.2)',
281
+ padding: '20px',
282
+ borderRadius: '8px',
283
+ color: 'white',
284
+ textAlign: 'center',
285
+ }}
286
+ >
287
+ <div style={{ fontSize: '24px', marginBottom: '8px' }}>📱</div>
288
+ <div>AR Model Available</div>
289
+ <div style={{ fontSize: '12px', marginTop: '8px', opacity: 0.8 }}>
290
+ ID: {props.ar.id}
291
+ </div>
292
+ </div>
293
+ )}
294
+ </div>
295
+ );
296
+ };