@clikvn/showroom-visualizer 0.2.2-dev-09 β 0.2.2-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/DEVELOPMENT.md +120 -0
- package/EXAMPLES.md +967 -0
- package/README.md +133 -26
- package/SETUP_COMPLETE.md +149 -0
- package/dist/components/SkinLayer/DefaultLayout/index.d.ts.map +1 -1
- 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/Layout/index.d.ts.map +1 -1
- package/dist/components/SkinLayer/index.d.ts +32 -0
- package/dist/components/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/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 +0 -31
- package/dist/hooks/headless/index.d.ts.map +1 -1
- package/dist/hooks/useToolConfig.d.ts.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- 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 +63 -0
- package/dist/types/custom-layout.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 +270 -3
package/rollup.config.js
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ============================================================================
|
|
3
|
+
* SHOWROOM VISUALIZER - ROLLUP BUILD CONFIGURATION
|
|
4
|
+
* ============================================================================
|
|
5
|
+
*
|
|
6
|
+
* π― MỀC TIΓU:
|
|
7
|
+
* TαΊ‘o ra 2 build outputs phα»₯c vα»₯ 2 use cases khΓ‘c nhau:
|
|
8
|
+
*
|
|
9
|
+
* 1οΈβ£ NPM Package (dist/index.js) - EXTERNAL REACT
|
|
10
|
+
* - DΓΉng React tα»« host app (Next.js, React apps)
|
|
11
|
+
* - β
HỠtrợ Custom Layout overrides
|
|
12
|
+
* - File nhα» hΖ‘n (~1.8MB)
|
|
13
|
+
* - Use: import { ShowroomVisualizer } from '@clikvn/showroom-visualizer'
|
|
14
|
+
*
|
|
15
|
+
* 2οΈβ£ Web Component (dist/web.js) - BUNDLED REACT
|
|
16
|
+
* - Bundle React 19 vΓ o file
|
|
17
|
+
* - β KHΓNG hα» trợ custom layout overrides
|
|
18
|
+
* - File lα»n hΖ‘n (~2.0MB)
|
|
19
|
+
* - Use: <script type="module" src="web.js"></script>
|
|
20
|
+
*
|
|
21
|
+
* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
22
|
+
*
|
|
23
|
+
* π SO SΓNH:
|
|
24
|
+
*
|
|
25
|
+
* | Feature | NPM Package | Web Component |
|
|
26
|
+
* |----------------------|-------------|---------------|
|
|
27
|
+
* | React Source | Host app | Bundled |
|
|
28
|
+
* | Custom Layout | β
Yes | β No |
|
|
29
|
+
* | File Size | ~1.8MB | ~2.0MB |
|
|
30
|
+
* | Dependencies | Need React | Standalone |
|
|
31
|
+
* | Use Case | React apps | Vanilla JS |
|
|
32
|
+
*
|
|
33
|
+
* ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
34
|
+
*/
|
|
35
|
+
|
|
1
36
|
import resolve from '@rollup/plugin-node-resolve';
|
|
2
37
|
import commonjs from '@rollup/plugin-commonjs';
|
|
3
38
|
import typescript from '@rollup/plugin-typescript';
|
|
@@ -16,8 +51,163 @@ const extensions = ['.ts', '.tsx', '.js'];
|
|
|
16
51
|
const isDev =
|
|
17
52
|
process.env.NODE_ENV === 'development' || process.env.ROLLUP_WATCH === 'true';
|
|
18
53
|
|
|
54
|
+
// ============================================================================
|
|
55
|
+
// CUSTOM PLUGIN: Fix React-DOM Imports
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// React 18's ESM build khΓ΄ng export findDOMNode, nhΖ°ng CommonJS build cΓ³.
|
|
58
|
+
// Plugin nΓ y rewrite code Δα» chα» dΓΉng default import vΓ access properties,
|
|
59
|
+
// trΓ‘nh Rollup extract named imports.
|
|
60
|
+
const fixReactDomImports = () => ({
|
|
61
|
+
name: 'fix-react-dom-imports',
|
|
62
|
+
renderChunk(code) {
|
|
63
|
+
let fixed = code;
|
|
64
|
+
|
|
65
|
+
// Fix invalid variable declarations with dots in the name
|
|
66
|
+
// This pattern appears in minified code from third-party libraries
|
|
67
|
+
fixed = fixed.replace(
|
|
68
|
+
/var\s+_ReactDOM\$ReactDOM__default\.findDOMNode;/g,
|
|
69
|
+
'var _ReactDOM$findDOMNode;'
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
// Fix all occurrences of the invalid variable name
|
|
73
|
+
fixed = fixed.replace(
|
|
74
|
+
/_ReactDOM\$ReactDOM__default\.findDOMNode/g,
|
|
75
|
+
'_ReactDOM$findDOMNode'
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// Fix double ReactDOM__default references
|
|
79
|
+
fixed = fixed.replace(
|
|
80
|
+
/ReactDOM__default\.ReactDOM__default\./g,
|
|
81
|
+
'ReactDOM__default.'
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Additional fix for similar patterns with other methods
|
|
85
|
+
fixed = fixed.replace(
|
|
86
|
+
/var\s+_ReactDOM\$ReactDOM__default\.(\w+);/g,
|
|
87
|
+
'var _ReactDOM$$1;'
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
// Fix minified code that creates invalid variable names
|
|
91
|
+
fixed = fixed.replace(
|
|
92
|
+
/var\s+([a-zA-Z_$][a-zA-Z0-9_$]*)\$([a-zA-Z_$][a-zA-Z0-9_$]*)\.[a-zA-Z_$][a-zA-Z0-9_$]*;/g,
|
|
93
|
+
function (match, prefix, suffix) {
|
|
94
|
+
return `var ${prefix}$${suffix}_temp;`;
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// First, remove any findDOMNode from named imports
|
|
99
|
+
fixed = fixed.replace(
|
|
100
|
+
/import\s*\{([^}]*)\}\s*from\s*['"]react-dom['"]/g,
|
|
101
|
+
(match, imports) => {
|
|
102
|
+
if (imports.includes('findDOMNode')) {
|
|
103
|
+
const cleanedImports = imports
|
|
104
|
+
.split(',')
|
|
105
|
+
.map((imp) => imp.trim())
|
|
106
|
+
.filter((imp) => !imp.includes('findDOMNode'))
|
|
107
|
+
.join(', ');
|
|
108
|
+
|
|
109
|
+
if (cleanedImports.trim()) {
|
|
110
|
+
return `import { ${cleanedImports} } from 'react-dom'`;
|
|
111
|
+
}
|
|
112
|
+
return '';
|
|
113
|
+
}
|
|
114
|
+
return match;
|
|
115
|
+
}
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Handle combined default and named imports
|
|
119
|
+
fixed = fixed.replace(
|
|
120
|
+
/import\s+(\w+),\s*\{\s*([^}]+)\s*\}\s*from\s*['"]react-dom['"]/g,
|
|
121
|
+
(match, defaultImport, namedImports) => {
|
|
122
|
+
// Check if named imports contains invalid syntax like "ReactDOM__default.createPortal"
|
|
123
|
+
if (
|
|
124
|
+
namedImports.includes('ReactDOM__default.') ||
|
|
125
|
+
namedImports.includes('findDOMNode')
|
|
126
|
+
) {
|
|
127
|
+
// Extract valid imports only
|
|
128
|
+
const validImports = namedImports
|
|
129
|
+
.split(',')
|
|
130
|
+
.map((imp) => imp.trim())
|
|
131
|
+
.filter((imp) => {
|
|
132
|
+
// Remove any import that has dots or includes findDOMNode
|
|
133
|
+
return !imp.includes('.') && !imp.includes('findDOMNode');
|
|
134
|
+
})
|
|
135
|
+
.map((imp) => {
|
|
136
|
+
// Clean up "as" aliases
|
|
137
|
+
const parts = imp.split(/\s+as\s+/);
|
|
138
|
+
if (parts.length === 2 && !parts[0].includes('.')) {
|
|
139
|
+
return imp;
|
|
140
|
+
}
|
|
141
|
+
return '';
|
|
142
|
+
})
|
|
143
|
+
.filter(Boolean)
|
|
144
|
+
.join(', ');
|
|
145
|
+
|
|
146
|
+
if (validImports) {
|
|
147
|
+
return `import ${defaultImport}, { ${validImports} } from 'react-dom'`;
|
|
148
|
+
}
|
|
149
|
+
return `import ${defaultImport} from 'react-dom'`;
|
|
150
|
+
}
|
|
151
|
+
return match;
|
|
152
|
+
}
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
// Replace all variations of findDOMNode (but not in function declarations)
|
|
156
|
+
fixed = fixed.replace(/\bfindDOMNode\$?\d*\b/g, (match, offset) => {
|
|
157
|
+
// Check if this is a function declaration
|
|
158
|
+
const beforeMatch = fixed.substring(Math.max(0, offset - 20), offset);
|
|
159
|
+
if (beforeMatch.trim().endsWith('function')) {
|
|
160
|
+
return match; // Don't replace in function declarations
|
|
161
|
+
}
|
|
162
|
+
return 'ReactDOM__default.findDOMNode';
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
// Fix property access patterns
|
|
166
|
+
fixed = fixed.replace(/(\w+)\.findDOMNode\b/g, (match, obj) => {
|
|
167
|
+
if (obj === 'ReactDOM__default') return match;
|
|
168
|
+
return 'ReactDOM__default.findDOMNode';
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
// Replace other methods - but NOT when they're being used in import statements
|
|
172
|
+
const methodsToReplace = [
|
|
173
|
+
'createPortal',
|
|
174
|
+
'unstable_batchedUpdates',
|
|
175
|
+
'flushSync',
|
|
176
|
+
];
|
|
177
|
+
|
|
178
|
+
methodsToReplace.forEach((method) => {
|
|
179
|
+
// Only replace when not in import context
|
|
180
|
+
const regex = new RegExp(
|
|
181
|
+
`\\b${method}\\$?\\d*\\b(?![:\\.]|\\s*as\\s*\\w+)`,
|
|
182
|
+
'g'
|
|
183
|
+
);
|
|
184
|
+
fixed = fixed.replace(regex, (match, offset) => {
|
|
185
|
+
// Check if this is within an import statement
|
|
186
|
+
const beforeMatch = fixed.substring(Math.max(0, offset - 100), offset);
|
|
187
|
+
if (beforeMatch.includes('import') && beforeMatch.includes('{')) {
|
|
188
|
+
return match;
|
|
189
|
+
}
|
|
190
|
+
return `ReactDOM__default.${method}`;
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
return { code: fixed, map: null };
|
|
195
|
+
},
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
// ============================================================================
|
|
199
|
+
// CONFIG CHO NPM PACKAGE - External React
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// DΓΉng khi: import { ShowroomVisualizer } from '@clikvn/showroom-visualizer'
|
|
202
|
+
// - React Δược external β DΓΉng React version cα»§a host app (Next.js, React app)
|
|
203
|
+
// - Cho phép custom layout overrides vì share cùng React instance
|
|
204
|
+
// - File nhỠhƑn vì không bundle React
|
|
19
205
|
const indexConfig = {
|
|
20
206
|
context: 'this',
|
|
207
|
+
|
|
208
|
+
// β
External React - Library sαΊ½ dΓΉng React tα»« host app
|
|
209
|
+
external: ['react', 'react-dom', 'react/jsx-runtime', 'react-dom/client'],
|
|
210
|
+
|
|
21
211
|
onwarn(warning, warn) {
|
|
22
212
|
// Bα» qua warning vα» "use client" directive
|
|
23
213
|
if (
|
|
@@ -33,9 +223,21 @@ const indexConfig = {
|
|
|
33
223
|
resolve({
|
|
34
224
|
extensions,
|
|
35
225
|
browser: true,
|
|
36
|
-
|
|
226
|
+
preferBuiltins: false,
|
|
227
|
+
dedupe: [
|
|
228
|
+
'react',
|
|
229
|
+
'react-dom',
|
|
230
|
+
'useTranslation',
|
|
231
|
+
'i18n',
|
|
232
|
+
'I18nextProvider',
|
|
233
|
+
],
|
|
234
|
+
}),
|
|
235
|
+
commonjs({
|
|
236
|
+
esmExternals: true,
|
|
237
|
+
requireReturnsDefault: 'auto',
|
|
238
|
+
// KhΓ΄ng extract named imports tα»« external modules
|
|
239
|
+
ignoreDynamicRequires: false,
|
|
37
240
|
}),
|
|
38
|
-
commonjs(),
|
|
39
241
|
// Skip uglify in dev mode - tα»n thα»i gian
|
|
40
242
|
!isDev && uglify(),
|
|
41
243
|
json(),
|
|
@@ -79,10 +281,75 @@ const indexConfig = {
|
|
|
79
281
|
typescriptPaths({ preserveExtensions: true }),
|
|
80
282
|
// Skip terser trong dev - tα»n rαΊ₯t nhiα»u thα»i gian
|
|
81
283
|
!isDev && terser({ output: { comments: false } }),
|
|
284
|
+
// β οΈ QUAN TRα»NG: Fix react-dom imports sau khi bundle
|
|
285
|
+
// PhαΊ£i ΔαΊ·t α» cuα»i Δα» chαΊ‘y sau tαΊ₯t cαΊ£ transformations
|
|
286
|
+
fixReactDomImports(),
|
|
82
287
|
].filter(Boolean), // Remove false values
|
|
83
288
|
};
|
|
84
289
|
|
|
290
|
+
// ============================================================================
|
|
291
|
+
// CONFIG CHO WEB COMPONENT - Bundled React
|
|
292
|
+
// ============================================================================
|
|
293
|
+
// DΓΉng khi: <script src="web.js"> hoαΊ·c dynamic import('web.js')
|
|
294
|
+
// - React Δược BUNDLE vΓ o β Standalone, khΓ΄ng cαΊ§n dependencies
|
|
295
|
+
// - KHΓNG hα» trợ custom layout overrides (vΓ¬ khΓ‘c React instance vα»i host app)
|
|
296
|
+
// - File lα»n hΖ‘n vΓ¬ bundle React (~200KB extra)
|
|
297
|
+
// - Phù hợp cho vanilla JS/HTML projects
|
|
298
|
+
const browserConfig = {
|
|
299
|
+
context: 'this',
|
|
300
|
+
// β KHΓNG external React - Bundle React version 19 vΓ o file
|
|
301
|
+
// external: [], // KhΓ΄ng khai bΓ‘o external = bundle tαΊ₯t cαΊ£
|
|
302
|
+
onwarn: indexConfig.onwarn,
|
|
303
|
+
plugins: indexConfig.plugins,
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
// ============================================================================
|
|
307
|
+
// DUAL BUILD STRATEGY
|
|
308
|
+
// ============================================================================
|
|
85
309
|
const configs = [
|
|
310
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
311
|
+
// BUILD 1: NPM Package (dist/index.js)
|
|
312
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
313
|
+
// π¦ Sα» dα»₯ng: import { ShowroomVisualizer } from '@clikvn/showroom-visualizer'
|
|
314
|
+
//
|
|
315
|
+
// β
Ζ―u Δiα»m:
|
|
316
|
+
// - DΓΉng React version cα»§a host app (Next.js, React app)
|
|
317
|
+
// - Cho phΓ©p SWIZZLE components (share React instance)
|
|
318
|
+
// - File nhỠ(~1.8MB) vì không bundle React
|
|
319
|
+
//
|
|
320
|
+
// π Use cases:
|
|
321
|
+
// - React/Next.js applications
|
|
322
|
+
// - CαΊ§n customize components qua custom layout overrides
|
|
323
|
+
// - Muα»n kiα»m soΓ‘t React version
|
|
324
|
+
{
|
|
325
|
+
input: './src/index.ts',
|
|
326
|
+
output: {
|
|
327
|
+
file: 'dist/index.js',
|
|
328
|
+
format: 'esm',
|
|
329
|
+
inlineDynamicImports: true,
|
|
330
|
+
},
|
|
331
|
+
...indexConfig, // β
External React dependencies
|
|
332
|
+
},
|
|
333
|
+
|
|
334
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
335
|
+
// BUILD 2: Web Component (dist/web.js)
|
|
336
|
+
// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
337
|
+
// π Sα» dα»₯ng: <script type="module" src="web.js"></script>
|
|
338
|
+
// hoαΊ·c: await import('web.js')
|
|
339
|
+
//
|
|
340
|
+
// β
Ζ―u Δiα»m:
|
|
341
|
+
// - Standalone, khΓ΄ng cαΊ§n install dependencies
|
|
342
|
+
// - HoαΊ‘t Δα»ng trong vanilla JS/HTML
|
|
343
|
+
// - KhΓ΄ng cαΊ§n build tools
|
|
344
|
+
//
|
|
345
|
+
// β HαΊ‘n chαΊΏ:
|
|
346
|
+
// - KHΓNG hα» trợ custom layout overrides (khΓ‘c React instance)
|
|
347
|
+
// - File lα»n hΖ‘n (~2.0MB) vΓ¬ bundle React
|
|
348
|
+
//
|
|
349
|
+
// π Use cases:
|
|
350
|
+
// - Vanilla JS/HTML projects
|
|
351
|
+
// - KhΓ΄ng cαΊ§n customize UI
|
|
352
|
+
// - Quick integration
|
|
86
353
|
{
|
|
87
354
|
input: './src/web.ts',
|
|
88
355
|
output: {
|
|
@@ -90,7 +357,7 @@ const configs = [
|
|
|
90
357
|
format: 'esm',
|
|
91
358
|
inlineDynamicImports: true,
|
|
92
359
|
},
|
|
93
|
-
...
|
|
360
|
+
...browserConfig, // β
Bundle React version 19
|
|
94
361
|
},
|
|
95
362
|
];
|
|
96
363
|
|