@clikvn/showroom-visualizer 0.3.0-dev-08 → 0.3.0-dev-10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +19 -0
- package/DEVELOPMENT.md +120 -0
- package/EXAMPLES.md +967 -0
- package/README.md +137 -3
- package/SETUP_COMPLETE.md +149 -0
- package/dist/commons/SkinLayer/components/Button/index.d.ts +4 -4
- package/dist/commons/SkinLayer/components/Button/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/DefaultLayout/index.d.ts +8 -0
- package/dist/components/SkinLayer/DefaultLayout/index.d.ts.map +1 -0
- package/dist/components/SkinLayer/Floorplan/Map.d.ts.map +1 -1
- package/dist/components/SkinLayer/Floorplan/Minimap/MiniMapMarker.d.ts.map +1 -1
- package/dist/components/SkinLayer/Floorplan/Minimap/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/HotspotCategorySlideIn/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/HotspotOverview/index.d.ts +1 -0
- package/dist/components/SkinLayer/HotspotOverview/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/Layout/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/PinActionButtons/index.d.ts +19 -0
- package/dist/components/SkinLayer/PinActionButtons/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/PlayBar/index.d.ts +19 -1
- package/dist/components/SkinLayer/PlayBar/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/PoiDetailSlideIn/Detail.d.ts +5 -0
- package/dist/components/SkinLayer/PoiDetailSlideIn/Detail.d.ts.map +1 -1
- package/dist/components/SkinLayer/PoiDetailSlideIn/TabsContent/index.d.ts +4 -0
- package/dist/components/SkinLayer/PoiDetailSlideIn/TabsContent/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/PoiDetailSlideIn/index.d.ts +23 -1
- package/dist/components/SkinLayer/PoiDetailSlideIn/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/SearchAndDiscoverySlideIn/DisplayActionPart/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/SearchAndDiscoverySlideIn/HelpActionPart.d.ts.map +1 -1
- package/dist/components/SkinLayer/SearchAndDiscoverySlideIn/PoiInfoActionPart/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/SearchAndDiscoverySlideIn/PromotionPart/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/SearchAndDiscoverySlideIn/ScenariosPart/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/SearchAndDiscoverySlideIn/TourInfoActionPart.d.ts.map +1 -1
- package/dist/components/SkinLayer/SearchAndDiscoverySlideIn/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/index.d.ts +49 -0
- package/dist/components/SkinLayer/index.d.ts.map +1 -1
- package/dist/constants/SkinLayer/customLayoutPaths.d.ts +84 -0
- package/dist/constants/SkinLayer/customLayoutPaths.d.ts.map +1 -0
- package/dist/constants/SkinLayer/index.d.ts +1 -0
- package/dist/constants/SkinLayer/index.d.ts.map +1 -1
- package/dist/context/CustomLayoutContext.d.ts +20 -0
- package/dist/context/CustomLayoutContext.d.ts.map +1 -0
- package/dist/context/SwizzleContext.d.ts +21 -0
- package/dist/context/SwizzleContext.d.ts.map +1 -0
- package/dist/features/ShowroomVisualizer/VirtualTour.d.ts +5 -0
- package/dist/features/ShowroomVisualizer/VirtualTour.d.ts.map +1 -1
- package/dist/features/ShowroomVisualizer/VirtualTourContainer.d.ts +4 -3
- package/dist/features/ShowroomVisualizer/VirtualTourContainer.d.ts.map +1 -1
- package/dist/features/ShowroomVisualizer/index.d.ts +24 -3
- package/dist/features/ShowroomVisualizer/index.d.ts.map +1 -1
- package/dist/hooks/headless/index.d.ts +150 -0
- package/dist/hooks/headless/index.d.ts.map +1 -0
- package/dist/hooks/headless/useFloorplanControl.d.ts +18 -0
- package/dist/hooks/headless/useFloorplanControl.d.ts.map +1 -0
- package/dist/hooks/headless/usePOIInteraction.d.ts +23 -0
- package/dist/hooks/headless/usePOIInteraction.d.ts.map +1 -0
- package/dist/hooks/headless/useScenarioControl.d.ts +22 -0
- package/dist/hooks/headless/useScenarioControl.d.ts.map +1 -0
- package/dist/hooks/headless/useSceneNavigation.d.ts +26 -0
- package/dist/hooks/headless/useSceneNavigation.d.ts.map +1 -0
- package/dist/hooks/headless/useTourCore.d.ts +23 -0
- package/dist/hooks/headless/useTourCore.d.ts.map +1 -0
- package/dist/hooks/headless/useViewportControl.d.ts +22 -0
- package/dist/hooks/headless/useViewportControl.d.ts.map +1 -0
- package/dist/hooks/useActionMiddleware.d.ts.map +1 -1
- package/dist/hooks/useConfiguration.d.ts +0 -1
- package/dist/hooks/useConfiguration.d.ts.map +1 -1
- package/dist/hooks/useToolConfig.d.ts.map +1 -1
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.html +110 -0
- package/dist/index.js +1 -0
- package/dist/register.d.ts +3 -0
- package/dist/register.d.ts.map +1 -1
- package/dist/types/SkinLayer/tool.type.d.ts +6 -0
- package/dist/types/SkinLayer/tool.type.d.ts.map +1 -1
- package/dist/types/SkinLayer/visualizer.type.d.ts +3 -0
- package/dist/types/SkinLayer/visualizer.type.d.ts.map +1 -1
- package/dist/types/custom-layout.d.ts +167 -0
- package/dist/types/custom-layout.d.ts.map +1 -0
- package/dist/types/swizzle.d.ts +59 -0
- package/dist/types/swizzle.d.ts.map +1 -0
- package/dist/web.js +1 -1
- package/example/CSS_HANDLING.md +141 -0
- package/example/FIXES_SUMMARY.md +121 -0
- package/example/PATH_ALIASES.md +103 -0
- package/example/README.md +64 -0
- package/example/index.html +13 -0
- package/example/package.json +25 -0
- package/example/postcss.config.cjs +6 -0
- package/example/tailwind.config.cjs +12 -0
- package/example/tsconfig.node.json +12 -0
- package/example/vite.config.ts +126 -0
- package/package.json +9 -1
- package/rollup.config.js +334 -4
- package/dist/utils/middleware/listenerWrapper.d.ts +0 -31
- package/dist/utils/middleware/listenerWrapper.d.ts.map +0 -1
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# 🎨 CSS Handling in Example App
|
|
2
|
+
|
|
3
|
+
## Vấn đề
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
Uncaught SyntaxError: The requested module '.../actionsChangeSceneStyles.css' does not provide an export named 'default'
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Nguyên nhân
|
|
10
|
+
|
|
11
|
+
### Thư viện (Rollup Build)
|
|
12
|
+
|
|
13
|
+
Thư viện sử dụng Rollup với PostCSS plugin config:
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
postcss({
|
|
17
|
+
inject: false, // ← Không inject CSS vào DOM
|
|
18
|
+
extract: false, // ← Export CSS as string
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Điều này cho phép import CSS như strings:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import styles from './styles.css';
|
|
26
|
+
// styles = "css content as string"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Và render trong component `CssStyles.tsx`:
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
<style>{styles}</style>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Vite (Development)
|
|
36
|
+
|
|
37
|
+
Vite mặc định **inject CSS trực tiếp vào DOM** và không export CSS as strings.
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import styles from './styles.css';
|
|
41
|
+
// Vite inject CSS → styles = undefined
|
|
42
|
+
// ❌ Error: does not provide an export named 'default'
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Giải pháp
|
|
46
|
+
|
|
47
|
+
### Custom Vite Plugin: `cssAsStringPlugin`
|
|
48
|
+
|
|
49
|
+
Tạo plugin trong `vite.config.ts` để xử lý CSS từ thư viện như strings:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
const cssAsStringPlugin = () => ({
|
|
53
|
+
name: 'css-as-string',
|
|
54
|
+
enforce: 'pre', // ⭐ Run BEFORE other plugins (critical!)
|
|
55
|
+
load(id: string) {
|
|
56
|
+
// Chỉ xử lý CSS từ thư viện
|
|
57
|
+
if (
|
|
58
|
+
id.endsWith('.css') &&
|
|
59
|
+
(id.includes('/src/assets/') || id.includes('/@clikvn/'))
|
|
60
|
+
) {
|
|
61
|
+
const cssContent = fs.readFileSync(id, 'utf-8');
|
|
62
|
+
return `export default ${JSON.stringify(cssContent)}`;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Plugin order matters!
|
|
69
|
+
plugins: [cssAsStringPlugin(), react()]
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Key Points:**
|
|
73
|
+
- ⭐ **`enforce: 'pre'`**: Chạy trước Vite's built-in CSS plugin
|
|
74
|
+
- ⭐ **`load` hook**: Intercept file loading, không dùng `transform`
|
|
75
|
+
- ⭐ **Plugin order**: `cssAsStringPlugin()` phải đứng TRƯỚC `react()`
|
|
76
|
+
|
|
77
|
+
### Cách hoạt động
|
|
78
|
+
|
|
79
|
+
1. **CSS từ thư viện** (`/src/assets/`) → Export as string
|
|
80
|
+
2. **CSS từ @clikvn packages** → Export as string
|
|
81
|
+
3. **CSS khác** (antd, example app CSS) → Vite xử lý bình thường
|
|
82
|
+
|
|
83
|
+
### Files được xử lý
|
|
84
|
+
|
|
85
|
+
Plugin chỉ xử lý CSS files trong:
|
|
86
|
+
|
|
87
|
+
- ✅ `/Users/tungthai/Desktop/Develop/showroom-visualizer/src/assets/*.css`
|
|
88
|
+
- ✅ `node_modules/@clikvn/*/dist/**/*.css`
|
|
89
|
+
- ❌ `node_modules/antd/**/*.css` (Vite xử lý bình thường)
|
|
90
|
+
- ❌ `example/src/**/*.css` (Vite xử lý bình thường)
|
|
91
|
+
|
|
92
|
+
## Kết quả
|
|
93
|
+
|
|
94
|
+
### ✅ Trước (Rollup Build):
|
|
95
|
+
|
|
96
|
+
```typescript
|
|
97
|
+
import styles from './styles.css';
|
|
98
|
+
<style>{styles}</style> // ✅ Works
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### ✅ Sau (Vite Dev with Plugin):
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import styles from './styles.css';
|
|
105
|
+
<style>{styles}</style> // ✅ Works (plugin export CSS as string)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### ✅ CSS từ example app:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// example/src/App.css
|
|
112
|
+
import './App.css'; // ✅ Vite inject vào DOM bình thường
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## 🔍 Debug
|
|
116
|
+
|
|
117
|
+
Nếu vẫn có lỗi CSS, kiểm tra:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
# 1. Restart dev server
|
|
121
|
+
cd example
|
|
122
|
+
yarn dev
|
|
123
|
+
|
|
124
|
+
# 2. Clear Vite cache
|
|
125
|
+
rm -rf node_modules/.vite
|
|
126
|
+
yarn dev
|
|
127
|
+
|
|
128
|
+
# 3. Kiểm tra plugin đang hoạt động
|
|
129
|
+
# Trong browser console, check xem CSS đã được inject chưa
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## 📚 Related Files
|
|
133
|
+
|
|
134
|
+
- `example/vite.config.ts` - Chứa `cssAsStringPlugin`
|
|
135
|
+
- `src/features/ShowroomVisualizer/CssStyles.tsx` - Render CSS as `<style>` tags
|
|
136
|
+
- `rollup.config.js` - PostCSS config của thư viện
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
✅ **Fixed!** CSS từ thư viện giờ được export as strings trong Vite dev mode.
|
|
141
|
+
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# 🎯 Example App - Fixes Summary
|
|
2
|
+
|
|
3
|
+
## 2 vấn đề đã được fix:
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1️⃣ Path Aliases Resolution ✅
|
|
8
|
+
|
|
9
|
+
### Lỗi:
|
|
10
|
+
```
|
|
11
|
+
[plugin:vite:import-analysis] Failed to resolve import "commons/SkinLayer/components/Drawer"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Root Cause:
|
|
15
|
+
Thư viện sử dụng `baseUrl: "./src"` cho phép imports:
|
|
16
|
+
```typescript
|
|
17
|
+
import Drawer from 'commons/SkinLayer/components/Drawer';
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Example app không biết về aliases này.
|
|
21
|
+
|
|
22
|
+
### Fix:
|
|
23
|
+
Thêm 10 path aliases vào `vite.config.ts` và `tsconfig.json`:
|
|
24
|
+
- `commons/*`, `components/*`, `constants/*`, `context/*`, `features/*`
|
|
25
|
+
- `hooks/*`, `models/*`, `services/*`, `types/*`, `utils/*`
|
|
26
|
+
|
|
27
|
+
### Status: ✅ Fixed
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 2️⃣ CSS Imports as Strings ✅
|
|
32
|
+
|
|
33
|
+
### Lỗi:
|
|
34
|
+
```
|
|
35
|
+
Uncaught SyntaxError: The requested module '.../actionsChangeSceneStyles.css'
|
|
36
|
+
does not provide an export named 'default'
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Root Cause:
|
|
40
|
+
- **Thư viện (Rollup)**: CSS exported as strings với `postcss({ inject: false })`
|
|
41
|
+
- **Vite**: Mặc định inject CSS, không export strings
|
|
42
|
+
- **CssStyles.tsx**: Cần CSS as strings để render `<style>{css}</style>`
|
|
43
|
+
|
|
44
|
+
### Fix:
|
|
45
|
+
Tạo custom Vite plugin `cssAsStringPlugin` với 3 key points:
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
const cssAsStringPlugin = () => ({
|
|
49
|
+
name: 'css-as-string',
|
|
50
|
+
enforce: 'pre', // ⭐ Critical: Run BEFORE other plugins
|
|
51
|
+
load(id: string) { // ⭐ Use 'load' hook, not 'transform'
|
|
52
|
+
if (
|
|
53
|
+
id.endsWith('.css') &&
|
|
54
|
+
(id.includes('/src/assets/') || id.includes('/@clikvn/'))
|
|
55
|
+
) {
|
|
56
|
+
const cssContent = fs.readFileSync(id, 'utf-8');
|
|
57
|
+
return `export default ${JSON.stringify(cssContent)}`;
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ⭐ Plugin order matters!
|
|
63
|
+
plugins: [cssAsStringPlugin(), react()]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**3 điều quan trọng:**
|
|
67
|
+
1. `enforce: 'pre'` - Chạy trước Vite CSS plugin
|
|
68
|
+
2. `load()` hook - Intercept file loading sớm
|
|
69
|
+
3. Plugin order - Đặt TRƯỚC `react()`
|
|
70
|
+
|
|
71
|
+
Plugin chỉ xử lý:
|
|
72
|
+
- ✅ CSS từ `/src/assets/` → Export as string
|
|
73
|
+
- ✅ CSS từ `@clikvn/*` packages → Export as string
|
|
74
|
+
- ❌ CSS khác (antd, example CSS) → Vite xử lý bình thường
|
|
75
|
+
|
|
76
|
+
### Status: ✅ Fixed
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## 📊 Tổng kết
|
|
81
|
+
|
|
82
|
+
| Issue | Status | Files Changed |
|
|
83
|
+
|-------|--------|---------------|
|
|
84
|
+
| Path Aliases | ✅ Fixed | `vite.config.ts`, `tsconfig.json` |
|
|
85
|
+
| CSS Imports | ✅ Fixed | `vite.config.ts` (plugin) |
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 🚀 Kết quả
|
|
90
|
+
|
|
91
|
+
**Example app giờ hoạt động 100%!**
|
|
92
|
+
|
|
93
|
+
✅ Dev server: http://localhost:3001
|
|
94
|
+
✅ Import từ `src/` trực tiếp
|
|
95
|
+
✅ Hot reload
|
|
96
|
+
✅ Path aliases
|
|
97
|
+
✅ CSS handling
|
|
98
|
+
✅ Test custom layout
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## 📚 Documents
|
|
103
|
+
|
|
104
|
+
- [PATH_ALIASES.md](./PATH_ALIASES.md) - Chi tiết về path aliases
|
|
105
|
+
- [CSS_HANDLING.md](./CSS_HANDLING.md) - Chi tiết về CSS plugin
|
|
106
|
+
- [CHANGELOG.md](./CHANGELOG.md) - Lịch sử thay đổi
|
|
107
|
+
- [README.md](./README.md) - Hướng dẫn sử dụng
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 🎉 Ready to Use!
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
cd example
|
|
115
|
+
yarn dev
|
|
116
|
+
|
|
117
|
+
# Open: http://localhost:3001
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Thay đổi code trong `../src/` → Tự động reload! 🔥
|
|
121
|
+
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 📁 Path Aliases Configuration
|
|
2
|
+
|
|
3
|
+
## Vấn đề
|
|
4
|
+
|
|
5
|
+
Thư viện `showroom-visualizer` sử dụng `baseUrl: "./src"` trong `tsconfig.json`, cho phép import trực tiếp từ root của `src/`:
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// Thay vì:
|
|
9
|
+
import Drawer from '../../commons/SkinLayer/components/Drawer';
|
|
10
|
+
|
|
11
|
+
// Có thể viết:
|
|
12
|
+
import Drawer from 'commons/SkinLayer/components/Drawer';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Giải pháp
|
|
16
|
+
|
|
17
|
+
Example app cần cấu hình tương ứng để Vite và TypeScript có thể resolve các imports này.
|
|
18
|
+
|
|
19
|
+
### 1. Vite Config (`vite.config.ts`)
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
resolve: {
|
|
23
|
+
alias: {
|
|
24
|
+
'@clikvn/showroom-visualizer': path.resolve(__dirname, '../src'),
|
|
25
|
+
'commons': path.resolve(__dirname, '../src/commons'),
|
|
26
|
+
'components': path.resolve(__dirname, '../src/components'),
|
|
27
|
+
'constants': path.resolve(__dirname, '../src/constants'),
|
|
28
|
+
'context': path.resolve(__dirname, '../src/context'),
|
|
29
|
+
'features': path.resolve(__dirname, '../src/features'),
|
|
30
|
+
'hooks': path.resolve(__dirname, '../src/hooks'),
|
|
31
|
+
'models': path.resolve(__dirname, '../src/models'),
|
|
32
|
+
'services': path.resolve(__dirname, '../src/services'),
|
|
33
|
+
'types': path.resolve(__dirname, '../src/types'),
|
|
34
|
+
'utils': path.resolve(__dirname, '../src/utils'),
|
|
35
|
+
},
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. TypeScript Config (`tsconfig.json`)
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"compilerOptions": {
|
|
44
|
+
"baseUrl": ".",
|
|
45
|
+
"paths": {
|
|
46
|
+
"commons": ["../src/commons"],
|
|
47
|
+
"commons/*": ["../src/commons/*"],
|
|
48
|
+
"components": ["../src/components"],
|
|
49
|
+
"components/*": ["../src/components/*"],
|
|
50
|
+
// ... các aliases khác
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Các Aliases Được Hỗ Trợ
|
|
57
|
+
|
|
58
|
+
| Alias | Trỏ đến | Ví dụ |
|
|
59
|
+
|-------|---------|-------|
|
|
60
|
+
| `commons/*` | `../src/commons/*` | `import Drawer from 'commons/SkinLayer/components/Drawer'` |
|
|
61
|
+
| `components/*` | `../src/components/*` | `import Layout from 'components/SkinLayer/Layout'` |
|
|
62
|
+
| `constants/*` | `../src/constants/*` | `import { WIDTH_SLIDE_IN } from 'constants/SkinLayer'` |
|
|
63
|
+
| `context/*` | `../src/context/*` | `import { useCustomLayout } from 'context/CustomLayoutContext'` |
|
|
64
|
+
| `features/*` | `../src/features/*` | `import Visualizer from 'features/ShowroomVisualizer'` |
|
|
65
|
+
| `hooks/*` | `../src/hooks/*` | `import { useStore } from 'hooks/useStore'` |
|
|
66
|
+
| `models/*` | `../src/models/*` | `import PoiItemInfo from 'models/Visualizer/Poi/PoiItemInfo'` |
|
|
67
|
+
| `services/*` | `../src/services/*` | `import ApiService from 'services/Visualizer/ApiService'` |
|
|
68
|
+
| `types/*` | `../src/types/*` | `import { CustomLayoutConfig } from 'types/custom-layout'` |
|
|
69
|
+
| `utils/*` | `../src/utils/*` | `import { formatDate } from 'utils/Visualizer/date'` |
|
|
70
|
+
|
|
71
|
+
## ⚠️ Lưu ý
|
|
72
|
+
|
|
73
|
+
1. **Restart dev server** sau khi thay đổi `vite.config.ts` hoặc `tsconfig.json`
|
|
74
|
+
2. **Không cần** thêm aliases này vào thư viện chính - chỉ cần trong example app
|
|
75
|
+
3. Nếu thêm folder mới trong `src/`, cần thêm alias tương ứng
|
|
76
|
+
|
|
77
|
+
## 🐛 Troubleshooting
|
|
78
|
+
|
|
79
|
+
### Lỗi: "Failed to resolve import"
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
# Kiểm tra alias có đúng không
|
|
83
|
+
cat example/vite.config.ts
|
|
84
|
+
|
|
85
|
+
# Restart dev server
|
|
86
|
+
cd example
|
|
87
|
+
yarn dev
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### TypeScript không tìm thấy types
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# Kiểm tra paths trong tsconfig.json
|
|
94
|
+
cat example/tsconfig.json
|
|
95
|
+
|
|
96
|
+
# Restart TypeScript server trong VSCode
|
|
97
|
+
# Cmd/Ctrl + Shift + P → "TypeScript: Restart TS Server"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
✅ Đã cấu hình xong! Example app giờ có thể import từ source code giống như thư viện chính.
|
|
103
|
+
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Showroom Visualizer - Example App
|
|
2
|
+
|
|
3
|
+
Đây là example app để test và develop thư viện `@clikvn/showroom-visualizer` trong môi trường local.
|
|
4
|
+
|
|
5
|
+
## 🚀 Cách sử dụng
|
|
6
|
+
|
|
7
|
+
### 1. Cài đặt dependencies
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
cd example
|
|
11
|
+
yarn install
|
|
12
|
+
# hoặc
|
|
13
|
+
npm install
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### 2. Chạy dev server
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
yarn dev
|
|
20
|
+
# hoặc
|
|
21
|
+
npm run dev
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
App sẽ chạy tại: http://localhost:3001
|
|
25
|
+
|
|
26
|
+
### 3. Test thư viện
|
|
27
|
+
|
|
28
|
+
- **Import trực tiếp từ source**: Example app sẽ import trực tiếp từ `../src/` thay vì build
|
|
29
|
+
- **Hot reload**: Mọi thay đổi trong `../src/` hoặc `example/src/` đều tự động reload
|
|
30
|
+
- **Test custom layout**: Bật/tắt custom components bằng checkbox trong UI
|
|
31
|
+
- **Test props**: Thay đổi language, API URL, etc.
|
|
32
|
+
|
|
33
|
+
## 📝 Lưu ý
|
|
34
|
+
|
|
35
|
+
1. **Không cần build**: Example app import trực tiếp từ TypeScript source
|
|
36
|
+
2. **React version**: Đảm bảo cùng version (18.3.1) với thư viện chính
|
|
37
|
+
3. **Không publish**: Folder này chỉ dùng cho development, không publish lên npm
|
|
38
|
+
|
|
39
|
+
## 🎯 Use Cases
|
|
40
|
+
|
|
41
|
+
- ✅ Test features mới
|
|
42
|
+
- ✅ Debug issues
|
|
43
|
+
- ✅ Test custom layout components
|
|
44
|
+
- ✅ Kiểm tra performance
|
|
45
|
+
- ✅ Preview trước khi publish
|
|
46
|
+
|
|
47
|
+
## 🔗 Import từ source
|
|
48
|
+
|
|
49
|
+
Trong `vite.config.ts`, chúng ta đã setup alias:
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
resolve: {
|
|
53
|
+
alias: {
|
|
54
|
+
'@clikvn/showroom-visualizer': path.resolve(__dirname, '../src'),
|
|
55
|
+
},
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Nên bạn có thể import như thật:
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
import { ShowroomVisualizer } from '@clikvn/showroom-visualizer';
|
|
63
|
+
```
|
|
64
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Showroom Visualizer - Example</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<div id="root"></div>
|
|
10
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
13
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "showroom-visualizer-example",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"preview": "vite preview"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"react": "^19.1.0",
|
|
13
|
+
"react-dom": "^19.1.0"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/react": "^19.1.0",
|
|
17
|
+
"@types/react-dom": "^19.1.0",
|
|
18
|
+
"@vitejs/plugin-react": "^5.0.0",
|
|
19
|
+
"autoprefixer": "^10.4.22",
|
|
20
|
+
"postcss": "^8.5.6",
|
|
21
|
+
"tailwindcss": "^3.4.0",
|
|
22
|
+
"typescript": "^5.6.3",
|
|
23
|
+
"vite": "^6.0.0"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** @type {import('tailwindcss').Config} */
|
|
2
|
+
module.exports = {
|
|
3
|
+
// Extend the parent tailwind config
|
|
4
|
+
presets: [require('../tailwind.config.cjs')],
|
|
5
|
+
content: [
|
|
6
|
+
'./index.html',
|
|
7
|
+
'./src/**/*.{js,ts,jsx,tsx}',
|
|
8
|
+
// Include parent library source files
|
|
9
|
+
'../src/**/*.{js,ts,jsx,tsx}',
|
|
10
|
+
],
|
|
11
|
+
important: true,
|
|
12
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { defineConfig, Plugin } from 'vite';
|
|
2
|
+
import react from '@vitejs/plugin-react';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import postcss from 'postcss';
|
|
6
|
+
import tailwindcss from 'tailwindcss';
|
|
7
|
+
import autoprefixer from 'autoprefixer';
|
|
8
|
+
|
|
9
|
+
// Custom plugin to handle CSS imports as strings (matching Rollup's postcss behavior)
|
|
10
|
+
const cssAsStringPlugin = (): Plugin => {
|
|
11
|
+
let postcssProcessor: any;
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
name: 'css-as-string',
|
|
15
|
+
enforce: 'pre',
|
|
16
|
+
|
|
17
|
+
async configResolved(config) {
|
|
18
|
+
// Initialize PostCSS processor with Tailwind
|
|
19
|
+
postcssProcessor = postcss([
|
|
20
|
+
tailwindcss({
|
|
21
|
+
config: path.resolve(__dirname, 'tailwind.config.cjs'),
|
|
22
|
+
}),
|
|
23
|
+
autoprefixer(),
|
|
24
|
+
]);
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
async resolveId(source, importer) {
|
|
28
|
+
// Handle CSS imports from the library
|
|
29
|
+
if (source.endsWith('.css') && importer) {
|
|
30
|
+
// Check if this is from our library (any src folder) or @clikvn packages
|
|
31
|
+
const isLibraryCSS =
|
|
32
|
+
importer.includes('/showroom-visualizer/src/') ||
|
|
33
|
+
source.includes('@clikvn/');
|
|
34
|
+
|
|
35
|
+
if (isLibraryCSS) {
|
|
36
|
+
// Resolve the full path
|
|
37
|
+
let resolvedPath: string;
|
|
38
|
+
|
|
39
|
+
if (source.startsWith('.') || source.startsWith('/')) {
|
|
40
|
+
resolvedPath = path.resolve(path.dirname(importer), source);
|
|
41
|
+
} else if (source.startsWith('@clikvn/')) {
|
|
42
|
+
// Handle @clikvn packages - look in parent node_modules
|
|
43
|
+
const packagePath = source.replace('@clikvn/', '../node_modules/@clikvn/');
|
|
44
|
+
resolvedPath = path.resolve(__dirname, packagePath);
|
|
45
|
+
} else {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Add a virtual marker to bypass Vite's CSS processing
|
|
50
|
+
return '\0' + resolvedPath + '.string';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
async load(id) {
|
|
57
|
+
// Handle our virtual CSS string modules
|
|
58
|
+
if (id.startsWith('\0') && id.endsWith('.css.string')) {
|
|
59
|
+
const realPath = id.slice(1, -7); // Remove \0 prefix and .string suffix
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const content = await fs.promises.readFile(realPath, 'utf-8');
|
|
63
|
+
|
|
64
|
+
// Process all CSS through PostCSS/Tailwind to ensure Tailwind utilities work
|
|
65
|
+
let processedContent = content;
|
|
66
|
+
try {
|
|
67
|
+
const result = await postcssProcessor.process(content, { from: realPath });
|
|
68
|
+
processedContent = result.css;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
console.warn(`PostCSS processing failed for ${realPath}:`, error);
|
|
71
|
+
// Fall back to original content if processing fails
|
|
72
|
+
processedContent = content;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
code: `export default ${JSON.stringify(processedContent)};`,
|
|
77
|
+
map: null,
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.error(`Failed to load CSS file: ${realPath}`, error);
|
|
81
|
+
return {
|
|
82
|
+
code: `export default "";`,
|
|
83
|
+
map: null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// https://vitejs.dev/config/
|
|
93
|
+
export default defineConfig({
|
|
94
|
+
plugins: [cssAsStringPlugin(), react()],
|
|
95
|
+
resolve: {
|
|
96
|
+
alias: {
|
|
97
|
+
// Force use of example's React to avoid duplicate instances
|
|
98
|
+
'react': path.resolve(__dirname, 'node_modules/react'),
|
|
99
|
+
'react-dom': path.resolve(__dirname, 'node_modules/react-dom'),
|
|
100
|
+
'react/jsx-runtime': path.resolve(__dirname, 'node_modules/react/jsx-runtime'),
|
|
101
|
+
// Alias để import trực tiếp từ source code thay vì build
|
|
102
|
+
'@clikvn/showroom-visualizer': path.resolve(__dirname, '../src'),
|
|
103
|
+
// Thư viện sử dụng baseUrl: "./src" nên tất cả imports cần aliases
|
|
104
|
+
commons: path.resolve(__dirname, '../src/commons'),
|
|
105
|
+
components: path.resolve(__dirname, '../src/components'),
|
|
106
|
+
constants: path.resolve(__dirname, '../src/constants'),
|
|
107
|
+
context: path.resolve(__dirname, '../src/context'),
|
|
108
|
+
features: path.resolve(__dirname, '../src/features'),
|
|
109
|
+
hooks: path.resolve(__dirname, '../src/hooks'),
|
|
110
|
+
models: path.resolve(__dirname, '../src/models'),
|
|
111
|
+
services: path.resolve(__dirname, '../src/services'),
|
|
112
|
+
types: path.resolve(__dirname, '../src/types'),
|
|
113
|
+
utils: path.resolve(__dirname, '../src/utils'),
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
server: {
|
|
117
|
+
port: 3001,
|
|
118
|
+
open: true,
|
|
119
|
+
},
|
|
120
|
+
optimizeDeps: {
|
|
121
|
+
// Force prebundle để tránh conflict React versions
|
|
122
|
+
include: ['react', 'react-dom'],
|
|
123
|
+
// Ensure all React references use the same instance
|
|
124
|
+
dedupe: ['react', 'react-dom'],
|
|
125
|
+
},
|
|
126
|
+
});
|
package/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clikvn/showroom-visualizer",
|
|
3
3
|
"description": "Showroom Visualizer",
|
|
4
|
-
"version": "0.3.0-dev-
|
|
4
|
+
"version": "0.3.0-dev-10",
|
|
5
5
|
"author": "Clik JSC",
|
|
6
6
|
"license": "ISC",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./dist/web": "./dist/web.js",
|
|
16
|
+
"./dist/web.js": "./dist/web.js"
|
|
17
|
+
},
|
|
10
18
|
"scripts": {
|
|
11
19
|
"dev": "rollup --watch --config rollup.config.js",
|
|
12
20
|
"build": "rollup --config rollup.config.js",
|