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.
Files changed (43) hide show
  1. package/.env +11 -0
  2. package/README.md +255 -0
  3. package/dist/index.d.ts +5 -0
  4. package/dist/index.js +13 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/index.mjs +13 -0
  7. package/dist/index.mjs.map +1 -0
  8. package/package.json +33 -0
  9. package/rollup.config.js +43 -0
  10. package/src/Components/BoxRenderer.tsx +108 -0
  11. package/src/Components/ComponentRenderer.tsx +29 -0
  12. package/src/Components/ImageComponent.tsx +68 -0
  13. package/src/Components/RowComponent.tsx +66 -0
  14. package/src/Components/TextComponent.tsx +47 -0
  15. package/src/ErrorBoundary.tsx +35 -0
  16. package/src/Page.tsx +124 -0
  17. package/src/PageComponents/BoxComponent.tsx +397 -0
  18. package/src/PageComponents/RowComponent.tsx +113 -0
  19. package/src/PageComponents/Visual-Components/CarouselComponent.tsx +366 -0
  20. package/src/PageComponents/Visual-Components/GroupBrandComponent.tsx +391 -0
  21. package/src/PageComponents/Visual-Components/GroupCategoryComponent.tsx +425 -0
  22. package/src/PageComponents/Visual-Components/GroupImageList.tsx +669 -0
  23. package/src/PageComponents/Visual-Components/GroupProductComponent.tsx +671 -0
  24. package/src/PageComponents/Visual-Components/GroupVideoList.tsx +590 -0
  25. package/src/PageComponents/Visual-Components/ImageComponent.tsx +163 -0
  26. package/src/PageComponents/Visual-Components/LinkComponent.tsx +68 -0
  27. package/src/PageComponents/Visual-Components/LottieComponent.tsx +213 -0
  28. package/src/PageComponents/Visual-Components/NavigationComponent.tsx +178 -0
  29. package/src/PageComponents/Visual-Components/Styles/ProductListViewOne.tsx +102 -0
  30. package/src/PageComponents/Visual-Components/Styles/ProductListViewTwo.tsx +104 -0
  31. package/src/PageComponents/Visual-Components/Styles/product-list-view-one.css +166 -0
  32. package/src/PageComponents/Visual-Components/Styles/product-list-view-two.css +182 -0
  33. package/src/PageComponents/Visual-Components/TabComponent.tsx +1169 -0
  34. package/src/PageComponents/Visual-Components/TextComponent.tsx +114 -0
  35. package/src/PageComponents/Visual-Components/VideoComponent.tsx +191 -0
  36. package/src/PageComponents/Visual-Components/tab.css +697 -0
  37. package/src/common.interface.ts +216 -0
  38. package/src/const.ts +6 -0
  39. package/src/env.d.ts +15 -0
  40. package/src/index.css +82 -0
  41. package/src/index.ts +2 -0
  42. package/src/types.ts +234 -0
  43. 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
+ }
@@ -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