tee3apps-cms-sdk-react 0.0.1
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/.env +11 -0
- package/README.md +255 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +13 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +33 -0
- package/rollup.config.js +43 -0
- package/src/Components/BoxRenderer.tsx +108 -0
- package/src/Components/ComponentRenderer.tsx +29 -0
- package/src/Components/ImageComponent.tsx +68 -0
- package/src/Components/RowComponent.tsx +66 -0
- package/src/Components/TextComponent.tsx +47 -0
- package/src/ErrorBoundary.tsx +35 -0
- package/src/Page.tsx +124 -0
- package/src/PageComponents/BoxComponent.tsx +397 -0
- package/src/PageComponents/RowComponent.tsx +113 -0
- package/src/PageComponents/Visual-Components/CarouselComponent.tsx +366 -0
- package/src/PageComponents/Visual-Components/GroupBrandComponent.tsx +391 -0
- package/src/PageComponents/Visual-Components/GroupCategoryComponent.tsx +425 -0
- package/src/PageComponents/Visual-Components/GroupImageList.tsx +669 -0
- package/src/PageComponents/Visual-Components/GroupProductComponent.tsx +671 -0
- package/src/PageComponents/Visual-Components/GroupVideoList.tsx +590 -0
- package/src/PageComponents/Visual-Components/ImageComponent.tsx +163 -0
- package/src/PageComponents/Visual-Components/LinkComponent.tsx +68 -0
- package/src/PageComponents/Visual-Components/LottieComponent.tsx +213 -0
- package/src/PageComponents/Visual-Components/NavigationComponent.tsx +178 -0
- package/src/PageComponents/Visual-Components/Styles/ProductListViewOne.tsx +102 -0
- package/src/PageComponents/Visual-Components/Styles/ProductListViewTwo.tsx +104 -0
- package/src/PageComponents/Visual-Components/Styles/product-list-view-one.css +166 -0
- package/src/PageComponents/Visual-Components/Styles/product-list-view-two.css +182 -0
- package/src/PageComponents/Visual-Components/TabComponent.tsx +1169 -0
- package/src/PageComponents/Visual-Components/TextComponent.tsx +114 -0
- package/src/PageComponents/Visual-Components/VideoComponent.tsx +191 -0
- package/src/PageComponents/Visual-Components/tab.css +697 -0
- package/src/common.interface.ts +216 -0
- package/src/const.ts +6 -0
- package/src/env.d.ts +15 -0
- package/src/index.css +82 -0
- package/src/index.ts +2 -0
- package/src/types.ts +234 -0
- package/tsconfig.json +20 -0
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tee3apps-cms-sdk-react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "convert json to page",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"rollup": "rollup -c --bundleConfigAsCjs",
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"author": "",
|
|
13
|
+
"license": "ISC",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@rollup/plugin-commonjs": "^28.0.6",
|
|
16
|
+
"@rollup/plugin-json": "^6.1.0",
|
|
17
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
18
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
19
|
+
"@rollup/plugin-typescript": "^12.1.4",
|
|
20
|
+
"@types/react": "^19.1.12",
|
|
21
|
+
"@types/uuid": "^10.0.0",
|
|
22
|
+
"react": "^19.1.1",
|
|
23
|
+
"rollup-plugin-dts": "^6.2.3",
|
|
24
|
+
"rollup-plugin-peer-deps-external": "^2.2.4",
|
|
25
|
+
"tslib": "^2.8.1",
|
|
26
|
+
"typescript": "^5.9.2"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"lottie-react": "^2.4.1",
|
|
30
|
+
"rollup": "^4.50.1",
|
|
31
|
+
"rollup-plugin-postcss": "^4.0.2"
|
|
32
|
+
}
|
|
33
|
+
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import resolve from "@rollup/plugin-node-resolve";
|
|
2
|
+
import commonjs from "@rollup/plugin-commonjs";
|
|
3
|
+
import typescript from "@rollup/plugin-typescript";
|
|
4
|
+
import dts from "rollup-plugin-dts";
|
|
5
|
+
import terser from "@rollup/plugin-terser";
|
|
6
|
+
import peerDepsExternal from "rollup-plugin-peer-deps-external";
|
|
7
|
+
|
|
8
|
+
import postcss from "rollup-plugin-postcss";
|
|
9
|
+
|
|
10
|
+
const packageJson = require("./package.json");
|
|
11
|
+
|
|
12
|
+
export default [
|
|
13
|
+
{
|
|
14
|
+
input: "src/index.ts",
|
|
15
|
+
output: [
|
|
16
|
+
{
|
|
17
|
+
file: packageJson.main,
|
|
18
|
+
format: "cjs",
|
|
19
|
+
sourcemap: true,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
file: packageJson.module,
|
|
23
|
+
format: "esm",
|
|
24
|
+
sourcemap: true,
|
|
25
|
+
},
|
|
26
|
+
],
|
|
27
|
+
plugins: [
|
|
28
|
+
peerDepsExternal(),
|
|
29
|
+
resolve(),
|
|
30
|
+
commonjs(),
|
|
31
|
+
typescript({ tsconfig: "./tsconfig.json" }),
|
|
32
|
+
terser(),
|
|
33
|
+
postcss(),
|
|
34
|
+
],
|
|
35
|
+
external: ["react", "react-dom"],
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
input: "src/index.ts",
|
|
39
|
+
output: [{ file: packageJson.types }],
|
|
40
|
+
plugins: [dts.default()],
|
|
41
|
+
external: [/\.css$/],
|
|
42
|
+
},
|
|
43
|
+
];
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ComponentRenderer from './ComponentRenderer';
|
|
3
|
+
import { Box } from '../types';
|
|
4
|
+
|
|
5
|
+
interface BoxRendererProps {
|
|
6
|
+
box: Box;
|
|
7
|
+
deviceMode?: string;
|
|
8
|
+
autoAdjustForImages?: boolean;
|
|
9
|
+
totalColumns?: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const BoxRenderer: React.FC<BoxRendererProps> = ({
|
|
13
|
+
box,
|
|
14
|
+
deviceMode = 'web',
|
|
15
|
+
autoAdjustForImages = true,
|
|
16
|
+
totalColumns = 12
|
|
17
|
+
}) => {
|
|
18
|
+
// Get colspan based on device mode
|
|
19
|
+
const getColspan = () => {
|
|
20
|
+
switch(deviceMode) {
|
|
21
|
+
case 'mobileweb':
|
|
22
|
+
return box.props.mode.mobileweb?.colspan || 12;
|
|
23
|
+
case 'mobileapp':
|
|
24
|
+
return box.props.mode.mobileapp?.colspan || 12;
|
|
25
|
+
case 'tablet':
|
|
26
|
+
return box.props.mode.tablet?.colspan || 12;
|
|
27
|
+
case 'web':
|
|
28
|
+
default:
|
|
29
|
+
return box.props.mode.web.colspan || 12;
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
// Get device-specific mode properties
|
|
34
|
+
const getCurrentMode = () => {
|
|
35
|
+
switch(deviceMode) {
|
|
36
|
+
case 'mobileweb':
|
|
37
|
+
return box.props.mode.mobileweb || {};
|
|
38
|
+
case 'mobileapp':
|
|
39
|
+
return box.props.mode.mobileapp || {};
|
|
40
|
+
case 'tablet':
|
|
41
|
+
return box.props.mode.tablet || {};
|
|
42
|
+
case 'web':
|
|
43
|
+
default:
|
|
44
|
+
return box.props.mode.web;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const colspan = getColspan();
|
|
49
|
+
const currentMode = getCurrentMode();
|
|
50
|
+
const widthPercentage = (colspan / totalColumns) * 100;
|
|
51
|
+
|
|
52
|
+
// Dynamic height calculation based on content type
|
|
53
|
+
const getBoxHeight = () => {
|
|
54
|
+
if (!autoAdjustForImages) {
|
|
55
|
+
return currentMode.height || 'auto';
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const hasImageComponent = box.components.some(component =>
|
|
59
|
+
component.name === 'ImageComponent'
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (hasImageComponent) {
|
|
63
|
+
return 'auto';
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return currentMode.height || 'auto';
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div
|
|
71
|
+
style={{
|
|
72
|
+
backgroundColor: box.props.bgColor,
|
|
73
|
+
display: currentMode.isVisible !== false ? 'block' : 'none',
|
|
74
|
+
backgroundSize: box.props.bgsize || 'cover',
|
|
75
|
+
height: getBoxHeight(),
|
|
76
|
+
minHeight: autoAdjustForImages ? 'auto' : (currentMode.height || 'auto'),
|
|
77
|
+
borderRadius: currentMode.radius || '0px',
|
|
78
|
+
width: `${widthPercentage}%`,
|
|
79
|
+
float: 'left',
|
|
80
|
+
boxSizing: 'border-box',
|
|
81
|
+
padding: 'px',
|
|
82
|
+
margin: 0,
|
|
83
|
+
overflow: 'hidden',
|
|
84
|
+
position: 'relative'
|
|
85
|
+
}}
|
|
86
|
+
>
|
|
87
|
+
<div style={{
|
|
88
|
+
width: '100%',
|
|
89
|
+
height: autoAdjustForImages ? 'auto' : '100%',
|
|
90
|
+
display: 'flex',
|
|
91
|
+
flexDirection: 'column',
|
|
92
|
+
alignItems: box.props.align || 'flex-start',
|
|
93
|
+
justifyContent: box.props.justify || 'flex-start',
|
|
94
|
+
padding: 0,
|
|
95
|
+
margin: 0,
|
|
96
|
+
boxSizing: 'border-box'
|
|
97
|
+
}}>
|
|
98
|
+
{box.components.map((component, index) => (
|
|
99
|
+
<div key={index} className="relative" style={{width: '100%'}}>
|
|
100
|
+
<ComponentRenderer component={component} />
|
|
101
|
+
</div>
|
|
102
|
+
))}
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export default BoxRenderer;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Component } from '../types';
|
|
3
|
+
import TextComponent from './TextComponent';
|
|
4
|
+
|
|
5
|
+
import ImageComponent from './ImageComponent';
|
|
6
|
+
|
|
7
|
+
interface ComponentRendererProps {
|
|
8
|
+
component: Component;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const ComponentRenderer: React.FC<ComponentRendererProps> = ({ component }) => {
|
|
12
|
+
switch (component.name) {
|
|
13
|
+
|
|
14
|
+
case 'ImageComponent':
|
|
15
|
+
return <ImageComponent props={component.props} />;
|
|
16
|
+
|
|
17
|
+
case 'TextComponent':
|
|
18
|
+
return <TextComponent props={component.props} />;
|
|
19
|
+
|
|
20
|
+
default:
|
|
21
|
+
return (
|
|
22
|
+
<div className="mb-4 p-4 bg-gray-100 rounded-md border-2 border-dashed border-gray-300">
|
|
23
|
+
<p className="text-sm text-gray-500">Unknown component: {component.name}</p>
|
|
24
|
+
</div>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default ComponentRenderer;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ComponentProps } from '../types';
|
|
3
|
+
|
|
4
|
+
const ImageComponent: React.FC<{ props: ComponentProps; deviceMode?: string }> = ({
|
|
5
|
+
props,
|
|
6
|
+
deviceMode = 'web'
|
|
7
|
+
}) => {
|
|
8
|
+
// Safe access to nested properties with fallbacks
|
|
9
|
+
const getCurrentMode = () => {
|
|
10
|
+
if (!props.mode) return { borderRadius: 0 };
|
|
11
|
+
|
|
12
|
+
switch(deviceMode) {
|
|
13
|
+
case 'mobileweb':
|
|
14
|
+
return props.mode.mobileweb || props.mode.web || { borderRadius: 0 };
|
|
15
|
+
case 'mobileapp':
|
|
16
|
+
return props.mode.mobileapp || props.mode.web || { borderRadius: 0 };
|
|
17
|
+
case 'tablet':
|
|
18
|
+
return props.mode.tablet || props.mode.web || { borderRadius: 0 };
|
|
19
|
+
case 'web':
|
|
20
|
+
default:
|
|
21
|
+
return props.mode.web || { borderRadius: 0 };
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const currentMode = getCurrentMode();
|
|
26
|
+
const imageData = props.images?.all || { url: '' };
|
|
27
|
+
const link = props.link || { url: '', target: '_blank' };
|
|
28
|
+
|
|
29
|
+
const handleClick = () => {
|
|
30
|
+
if (props.linktype === 'EXTERNAL' && link.url) {
|
|
31
|
+
window.open(link.url, link.target || '_blank');
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const imageElement = (
|
|
36
|
+
<img src={imageData.url} alt="" />
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
if (props.linktype === 'EXTERNAL' && link.url) {
|
|
40
|
+
return (
|
|
41
|
+
<a
|
|
42
|
+
href={link.url}
|
|
43
|
+
target={link.target}
|
|
44
|
+
style={{
|
|
45
|
+
display: 'block',
|
|
46
|
+
width: '100%',
|
|
47
|
+
textDecoration: 'none'
|
|
48
|
+
}}
|
|
49
|
+
>
|
|
50
|
+
{imageElement}
|
|
51
|
+
</a>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<div
|
|
57
|
+
style={{
|
|
58
|
+
width: '100%',
|
|
59
|
+
cursor: props.linktype !== 'NONE' ? 'pointer' : 'default'
|
|
60
|
+
}}
|
|
61
|
+
onClick={handleClick}
|
|
62
|
+
>
|
|
63
|
+
{imageElement}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default ImageComponent;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import BoxRenderer from './BoxRenderer';
|
|
3
|
+
import { Row } from '../types';
|
|
4
|
+
|
|
5
|
+
interface RowComponentProps {
|
|
6
|
+
row: Row;
|
|
7
|
+
deviceMode?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const RowComponent: React.FC<RowComponentProps> = ({
|
|
11
|
+
row,
|
|
12
|
+
deviceMode = 'web'
|
|
13
|
+
}) => {
|
|
14
|
+
const getCurrentMode = () => {
|
|
15
|
+
switch(deviceMode) {
|
|
16
|
+
case 'mobileweb':
|
|
17
|
+
return row.props.mode.mobileweb || {};
|
|
18
|
+
case 'mobileapp':
|
|
19
|
+
return row.props.mode.mobileapp || {};
|
|
20
|
+
case 'tablet':
|
|
21
|
+
return row.props.mode.tablet || {};
|
|
22
|
+
case 'web':
|
|
23
|
+
default:
|
|
24
|
+
return row.props.mode.web;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const currentMode = getCurrentMode();
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div
|
|
32
|
+
style={{
|
|
33
|
+
minHeight: row.props.minHeight,
|
|
34
|
+
backgroundColor: row.props.bgColor,
|
|
35
|
+
backgroundImage: row.props.bgImage ? `url(${row.props.bgImage})` : 'none',
|
|
36
|
+
backgroundSize: row.props.bgsize,
|
|
37
|
+
backgroundPosition: 'center',
|
|
38
|
+
width: '100%',
|
|
39
|
+
marginBottom: '2px',
|
|
40
|
+
border: '1px solid #e0e0e0',
|
|
41
|
+
borderRadius: '4px',
|
|
42
|
+
boxSizing: 'border-box',
|
|
43
|
+
overflow: 'hidden',
|
|
44
|
+
position: 'relative',
|
|
45
|
+
display: currentMode.isVisible !== false ? 'block' : 'none',
|
|
46
|
+
}}
|
|
47
|
+
>
|
|
48
|
+
{/* Row Content */}
|
|
49
|
+
<div style={{
|
|
50
|
+
width: '100%',
|
|
51
|
+
display: 'block',
|
|
52
|
+
position: 'relative',
|
|
53
|
+
padding: '10px',
|
|
54
|
+
boxSizing: 'border-box'
|
|
55
|
+
}}>
|
|
56
|
+
{row.columns.map((box, boxIndex) => (
|
|
57
|
+
<BoxRenderer key={boxIndex} box={box} deviceMode={deviceMode} />
|
|
58
|
+
))}
|
|
59
|
+
{/* Clear float after all children */}
|
|
60
|
+
<div style={{ clear: 'both' }} />
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export default RowComponent;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ComponentProps } from '../types';
|
|
3
|
+
|
|
4
|
+
const TextComponent: React.FC<{ props: ComponentProps }> = ({ props }) => {
|
|
5
|
+
const { text, style } = props;
|
|
6
|
+
|
|
7
|
+
const tagName = style?.headingTag ?? 'p';
|
|
8
|
+
|
|
9
|
+
if (!text?.all) {
|
|
10
|
+
return <div className="text-sm text-gray-500">No text content</div>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const textStyle = {
|
|
14
|
+
fontSize: style?.fontSize ? `${style.fontSize}px` : '16px',
|
|
15
|
+
fontWeight: style?.fontStyle?.isBold ? 'bold' : 'normal',
|
|
16
|
+
fontStyle: style?.fontStyle?.isItalic ? 'italic' : 'normal',
|
|
17
|
+
textDecoration: style?.fontStyle?.isUnderLine ? 'underline' : 'none',
|
|
18
|
+
textDecorationLine: style?.fontStyle?.isStrikeThrough ? 'line-through' : 'none',
|
|
19
|
+
color: style?.fontColor || '#000',
|
|
20
|
+
textAlign: style?.textAlign || 'left',
|
|
21
|
+
fontFamily: style?.fontFamily || 'inherit',
|
|
22
|
+
margin: 5,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Create the text element
|
|
26
|
+
const textElement = React.createElement(
|
|
27
|
+
tagName,
|
|
28
|
+
{ style: textStyle },
|
|
29
|
+
text.all
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
if (props.linktype === 'EXTERNAL' && props.link?.url) {
|
|
33
|
+
return (
|
|
34
|
+
<a
|
|
35
|
+
href={props.link.url}
|
|
36
|
+
target={props.link.target}
|
|
37
|
+
style={{ textDecoration: 'none' }}
|
|
38
|
+
>
|
|
39
|
+
{textElement}
|
|
40
|
+
</a>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return textElement;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export default TextComponent;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
interface ErrorBoundaryProps {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface ErrorBoundaryState {
|
|
8
|
+
hasError: boolean;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class ErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
12
|
+
constructor(props: ErrorBoundaryProps) {
|
|
13
|
+
super(props);
|
|
14
|
+
this.state = { hasError: false };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static getDerivedStateFromError(error: Error) {
|
|
18
|
+
return { hasError: true };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
22
|
+
console.error("ErrorBoundary caught an error:", error, errorInfo);
|
|
23
|
+
// Optionally send error to a logging service
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
render() {
|
|
27
|
+
if (this.state.hasError) {
|
|
28
|
+
return <div style={{ padding: '2rem', color: 'red' }}>Failed to render this section. Please try again later.</div>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return this.props.children;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default ErrorBoundary;
|
package/src/Page.tsx
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import RowComponent from './PageComponents/RowComponent';
|
|
3
|
+
import BoxComponent from './PageComponents/BoxComponent';
|
|
4
|
+
import TextComponent from './PageComponents/Visual-Components/TextComponent';
|
|
5
|
+
import LinkComponent from './PageComponents/Visual-Components/LinkComponent';
|
|
6
|
+
import ImageComponent from './PageComponents/Visual-Components/ImageComponent';
|
|
7
|
+
import GroupProductComponent, { GroupProductComponentProps } from './PageComponents/Visual-Components/GroupProductComponent';
|
|
8
|
+
import VideoComponent, { VideoComponentProps } from './PageComponents/Visual-Components/VideoComponent';
|
|
9
|
+
import GroupBrandComponent, { GroupBrandComponentProps } from './PageComponents/Visual-Components/GroupBrandComponent';
|
|
10
|
+
import LottieComponent, { LottieComponentProps } from './PageComponents/Visual-Components/LottieComponent';
|
|
11
|
+
import { ImageComponentProps, LinkProps, TextProps } from './common.interface';
|
|
12
|
+
import CarouselComponent, { CarouselProps } from './PageComponents/Visual-Components/CarouselComponent';
|
|
13
|
+
import NavigationComponent, { NavigationProps } from './PageComponents/Visual-Components/NavigationComponent';
|
|
14
|
+
import './index.css'
|
|
15
|
+
import GroupVideoList, { GroupVideoListProps } from './PageComponents/Visual-Components/GroupVideoList';
|
|
16
|
+
import GroupCategoryComponent, { GroupCategoryComponentProps } from './PageComponents/Visual-Components/GroupCategoryComponent';
|
|
17
|
+
import GroupImageList, { GroupImageListProps } from './PageComponents/Visual-Components/GroupImageList';
|
|
18
|
+
import TabComponent, { TabComponentProps } from './PageComponents/Visual-Components/TabComponent';
|
|
19
|
+
import ErrorBoundary from './ErrorBoundary';
|
|
20
|
+
const Page = ({data}:any) => {
|
|
21
|
+
const [deviceMode, setDeviceMode] = useState<string>('web');
|
|
22
|
+
const [screenSize, setScreenSize] = useState({
|
|
23
|
+
width: 0,
|
|
24
|
+
height: 0
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Function to determine device mode based on screen width
|
|
28
|
+
const getDeviceMode = (width: number) => {
|
|
29
|
+
if (width <= 480) return 'mobileapp';
|
|
30
|
+
if (width <= 768) return 'mobileweb';
|
|
31
|
+
if (width <= 1024) return 'tablet';
|
|
32
|
+
return 'web';
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// Effect to handle window resize
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const handleResize = () => {
|
|
38
|
+
const width = window.innerWidth;
|
|
39
|
+
const height = window.innerHeight;
|
|
40
|
+
setScreenSize({ width, height });
|
|
41
|
+
setDeviceMode(getDeviceMode(width));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// Call once on mount
|
|
45
|
+
handleResize();
|
|
46
|
+
|
|
47
|
+
window.addEventListener('resize', handleResize);
|
|
48
|
+
return () => {
|
|
49
|
+
window.removeEventListener('resize', handleResize);
|
|
50
|
+
};
|
|
51
|
+
}, []);
|
|
52
|
+
return (
|
|
53
|
+
<>
|
|
54
|
+
<div className=''>
|
|
55
|
+
<div className=''>
|
|
56
|
+
|
|
57
|
+
<ErrorBoundary>
|
|
58
|
+
{data.map((row: { props: any; columns: any[]; }, rowIndex: React.Key | null | undefined) => (
|
|
59
|
+
<RowComponent key={rowIndex} props={row.props} deviceMode={deviceMode}>
|
|
60
|
+
{row.columns.map((box, boxIndex) => (
|
|
61
|
+
<BoxComponent
|
|
62
|
+
key={boxIndex}
|
|
63
|
+
props={box.props}
|
|
64
|
+
deviceMode={deviceMode}
|
|
65
|
+
autoAdjustForImages={true}
|
|
66
|
+
>
|
|
67
|
+
{box.components.map((component: { name: string | number | bigint | boolean | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | React.ReactPortal | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined; props: TextProps | LinkProps | ImageComponentProps | GroupProductComponentProps | VideoComponentProps | GroupBrandComponentProps | LottieComponentProps | CarouselProps | NavigationProps | GroupVideoListProps | GroupCategoryComponentProps | GroupImageListProps | TabComponentProps; }, compIndex: React.Key | null | undefined) => {
|
|
68
|
+
const getCurrentBoxHeight = () => {
|
|
69
|
+
const validModes = ['web', 'mobileweb', 'mobileapp', 'tablet'] as const;
|
|
70
|
+
const safeDeviceMode = validModes.includes(deviceMode as any)
|
|
71
|
+
? deviceMode as keyof typeof box.props.mode
|
|
72
|
+
: 'web';
|
|
73
|
+
if(component.name==='ImageComponent') return 'auto' // add this line
|
|
74
|
+
return box.props.mode[safeDeviceMode]?.height || 'auto';
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
try {
|
|
78
|
+
switch (component.name) {
|
|
79
|
+
case 'TextComponent':
|
|
80
|
+
return <TextComponent key={compIndex} props={component.props as TextProps} />;
|
|
81
|
+
case 'LinkComponent':
|
|
82
|
+
return <LinkComponent key={compIndex} props={component.props as LinkProps} />;
|
|
83
|
+
case 'ImageComponent':
|
|
84
|
+
return <ImageComponent key={compIndex} props={component.props as ImageComponentProps} deviceMode={deviceMode} boxHeight={getCurrentBoxHeight()} />;
|
|
85
|
+
case 'GroupProductComponent':
|
|
86
|
+
return <GroupProductComponent key={compIndex} props={component.props as GroupProductComponentProps} deviceMode={deviceMode} />;
|
|
87
|
+
case 'VideoComponent':
|
|
88
|
+
return <VideoComponent key={compIndex} props={component.props as VideoComponentProps} deviceMode={deviceMode} boxHeight={getCurrentBoxHeight()} />;
|
|
89
|
+
case 'GroupBrandComponent':
|
|
90
|
+
return <GroupBrandComponent key={compIndex} props={component.props as GroupBrandComponentProps} deviceMode={deviceMode} />;
|
|
91
|
+
case 'LottieComponent':
|
|
92
|
+
return <LottieComponent key={compIndex} props={component.props as LottieComponentProps} />;
|
|
93
|
+
case 'CarouselComponent':
|
|
94
|
+
return <CarouselComponent key={compIndex} props={component.props as CarouselProps} deviceMode={deviceMode} />;
|
|
95
|
+
case 'NavigationComponent':
|
|
96
|
+
return <NavigationComponent key={compIndex} props={component.props as NavigationProps} boxHeight={getCurrentBoxHeight()} />;
|
|
97
|
+
case 'GroupVideoComponent':
|
|
98
|
+
return <GroupVideoList key={compIndex} props={component.props as GroupVideoListProps} boxHeight={getCurrentBoxHeight()} />;
|
|
99
|
+
case 'GroupCategoryComponent':
|
|
100
|
+
return <GroupCategoryComponent key={compIndex} props={component.props as GroupCategoryComponentProps} deviceMode={deviceMode} />;
|
|
101
|
+
case 'GroupImageComponent':
|
|
102
|
+
return <GroupImageList key={compIndex} props={component.props as GroupImageListProps} deviceMode={deviceMode} />;
|
|
103
|
+
case 'TabComponent':
|
|
104
|
+
return <TabComponent key={compIndex} props={component.props as TabComponentProps} deviceMode={deviceMode} />;
|
|
105
|
+
default:
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
} catch (err) {
|
|
109
|
+
console.error(`Error rendering component: ${component.name}`, err);
|
|
110
|
+
return <div key={compIndex} style={{ color: 'red' }}>Failed to load component: {component.name}</div>;
|
|
111
|
+
}
|
|
112
|
+
})}
|
|
113
|
+
</BoxComponent>
|
|
114
|
+
))}
|
|
115
|
+
</RowComponent>
|
|
116
|
+
))}
|
|
117
|
+
</ErrorBoundary>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
</>
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export default Page
|