tee3apps-cms-sdk-react 0.0.5 → 0.0.6
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/dist/index.d.ts +189 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/App.css +37 -0
- package/src/PageFormComponents/BooleanField.tsx +56 -0
- package/src/PageFormComponents/BoxRenderer.tsx +229 -0
- package/src/PageFormComponents/Button.tsx +127 -0
- package/src/PageFormComponents/DateField.tsx +46 -0
- package/src/PageFormComponents/ImageComponent.tsx +163 -0
- package/src/PageFormComponents/InputField.tsx +62 -0
- package/src/PageFormComponents/NumberField.tsx +56 -0
- package/src/PageFormComponents/PageForm.css +67 -0
- package/src/PageFormComponents/PageForm.tsx +195 -0
- package/src/PageFormComponents/RadioField.tsx +59 -0
- package/src/PageFormComponents/RowComponent.tsx +82 -0
- package/src/PageFormComponents/SelectField.tsx +183 -0
- package/src/PageFormComponents/Styles/BooleanField.css +56 -0
- package/src/PageFormComponents/Styles/DateField.css +44 -0
- package/src/PageFormComponents/Styles/InputField.css +50 -0
- package/src/PageFormComponents/Styles/NumberField.css +57 -0
- package/src/PageFormComponents/Styles/RadioField.css +66 -0
- package/src/PageFormComponents/Styles/SelectField.css +264 -0
- package/src/PageFormComponents/TextComponent.tsx +45 -0
- package/src/index.ts +2 -2
package/package.json
CHANGED
package/src/App.css
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
.main {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.title {
|
|
7
|
+
display: flex;
|
|
8
|
+
font-weight: bold;
|
|
9
|
+
font-size: 1.875rem; /* 3xl = 30px (1.875rem) */
|
|
10
|
+
justify-content: center;
|
|
11
|
+
padding: 2px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.content-wrapper {
|
|
15
|
+
background-color: #f87171; /* Tailwind's red-400 */
|
|
16
|
+
padding: 1rem; /* 16px */
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.content-box {
|
|
20
|
+
background-color: white;
|
|
21
|
+
padding: 0.5rem; /* 8px */
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.image-box {
|
|
25
|
+
|
|
26
|
+
width: 100%;
|
|
27
|
+
/* height: 280px; */
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
display: flex;
|
|
30
|
+
align-items: center;
|
|
31
|
+
justify-content: center;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.fitted-image {
|
|
35
|
+
width: 100%;
|
|
36
|
+
height: 100%;
|
|
37
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ComponentProps } from '../types';
|
|
3
|
+
import './Styles/BooleanField.css'; // Importing the CSS file
|
|
4
|
+
|
|
5
|
+
interface BooleanFieldProps {
|
|
6
|
+
props: ComponentProps;
|
|
7
|
+
value?: any;
|
|
8
|
+
onChange?: (code: string, value: any) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const BooleanField: React.FC<BooleanFieldProps> = ({ props, value = false, onChange }) => {
|
|
12
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
13
|
+
if (onChange) {
|
|
14
|
+
const code = props.code || `booleanfield_${props.name?.all || 'field'}`;
|
|
15
|
+
onChange(code, e.target.checked);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<div className="boolean-field">
|
|
21
|
+
<div className="boolean-field__container">
|
|
22
|
+
<div className="boolean-field__checkbox-wrapper">
|
|
23
|
+
<input
|
|
24
|
+
type="checkbox"
|
|
25
|
+
checked={value || false}
|
|
26
|
+
onChange={handleChange}
|
|
27
|
+
className="boolean-field__checkbox"
|
|
28
|
+
required={props.required}
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
<div className="boolean-field__content">
|
|
32
|
+
<label className="boolean-field__label">
|
|
33
|
+
{props.name?.all || 'Boolean Field'}
|
|
34
|
+
{props.required && <span className="boolean-field__required">*</span>}
|
|
35
|
+
</label>
|
|
36
|
+
|
|
37
|
+
{props.termsandcondition?.all && (
|
|
38
|
+
<p className="boolean-field__terms">
|
|
39
|
+
{props.termsandcondition.all}
|
|
40
|
+
</p>
|
|
41
|
+
)}
|
|
42
|
+
|
|
43
|
+
{props.helperText && (
|
|
44
|
+
<p className="boolean-field__helper-text">{props.helperText}</p>
|
|
45
|
+
)}
|
|
46
|
+
|
|
47
|
+
<div className="boolean-field__status-text">
|
|
48
|
+
{props.onText || 'On'} / {props.offText || 'Off'}
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default BooleanField;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Box } from '../types';
|
|
3
|
+
import DateField from './DateField';
|
|
4
|
+
import NumberField from './NumberField';
|
|
5
|
+
import TextComponent from './TextComponent';
|
|
6
|
+
import BooleanField from './BooleanField';
|
|
7
|
+
import Button from './Button';
|
|
8
|
+
import InputField from './InputField';
|
|
9
|
+
import RadioField from './RadioField';
|
|
10
|
+
import SelectField from './SelectField';
|
|
11
|
+
import ImageComponent from './ImageComponent';
|
|
12
|
+
|
|
13
|
+
interface BoxRendererProps {
|
|
14
|
+
box: Box;
|
|
15
|
+
deviceMode?: string;
|
|
16
|
+
autoAdjustForImages?: boolean;
|
|
17
|
+
totalColumns?: number;
|
|
18
|
+
formValues?: Record<string, any>;
|
|
19
|
+
validationErrors?: Record<string, boolean>;
|
|
20
|
+
onFieldChange?: (code: string, value: any) => void;
|
|
21
|
+
onFormSubmit?: () => void;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const BoxRenderer: React.FC<BoxRendererProps> = ({
|
|
25
|
+
box,
|
|
26
|
+
deviceMode = 'web',
|
|
27
|
+
autoAdjustForImages = true,
|
|
28
|
+
totalColumns = 12,
|
|
29
|
+
formValues = {},
|
|
30
|
+
validationErrors = {},
|
|
31
|
+
onFieldChange,
|
|
32
|
+
onFormSubmit
|
|
33
|
+
}) => {
|
|
34
|
+
// Get colspan based on device mode
|
|
35
|
+
const getColspan = () => {
|
|
36
|
+
switch(deviceMode) {
|
|
37
|
+
case 'mobileweb':
|
|
38
|
+
return box.props.mode.mobileweb?.colspan || 12;
|
|
39
|
+
case 'mobileapp':
|
|
40
|
+
return box.props.mode.mobileapp?.colspan || 12;
|
|
41
|
+
case 'tablet':
|
|
42
|
+
return box.props.mode.tablet?.colspan || 12;
|
|
43
|
+
case 'web':
|
|
44
|
+
default:
|
|
45
|
+
return box.props.mode.web.colspan || 12;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Get device-specific mode properties
|
|
50
|
+
const getCurrentMode = () => {
|
|
51
|
+
switch(deviceMode) {
|
|
52
|
+
case 'mobileweb':
|
|
53
|
+
return box.props.mode.mobileweb || {};
|
|
54
|
+
case 'mobileapp':
|
|
55
|
+
return box.props.mode.mobileapp || {};
|
|
56
|
+
case 'tablet':
|
|
57
|
+
return box.props.mode.tablet || {};
|
|
58
|
+
case 'web':
|
|
59
|
+
default:
|
|
60
|
+
return box.props.mode.web;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const getFieldCode = (component: typeof box.components[0]) => {
|
|
65
|
+
return component.props.code || `${component.name.toLowerCase()}_${component.props.name?.all || 'field'}`;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
const getFieldValue = (code: string) => {
|
|
69
|
+
return formValues[code] ?? '';
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const colspan = getColspan();
|
|
73
|
+
const currentMode = getCurrentMode();
|
|
74
|
+
const widthPercentage = (colspan / totalColumns) * 100;
|
|
75
|
+
|
|
76
|
+
// Dynamic height calculation based on content type
|
|
77
|
+
const getBoxHeight = () => {
|
|
78
|
+
if (!autoAdjustForImages) {
|
|
79
|
+
return currentMode.height || 'auto';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const hasImageComponent = box.components.some(component =>
|
|
83
|
+
component.name === 'ImageComponent'
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
if (hasImageComponent) {
|
|
87
|
+
return 'auto';
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return currentMode.height || 'auto';
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div
|
|
95
|
+
style={{
|
|
96
|
+
backgroundColor: box.props.bgColor,
|
|
97
|
+
display: currentMode.isVisible !== false ? 'block' : 'none',
|
|
98
|
+
backgroundSize: box.props.bgsize || 'cover',
|
|
99
|
+
height: getBoxHeight(),
|
|
100
|
+
minHeight: autoAdjustForImages ? 'auto' : (currentMode.height || 'auto'),
|
|
101
|
+
borderRadius: currentMode.radius || '0px',
|
|
102
|
+
width: `${widthPercentage}%`,
|
|
103
|
+
float: 'left',
|
|
104
|
+
boxSizing: 'border-box',
|
|
105
|
+
padding: 'px',
|
|
106
|
+
margin: 0,
|
|
107
|
+
overflow: 'hidden',
|
|
108
|
+
position: 'relative'
|
|
109
|
+
}}
|
|
110
|
+
>
|
|
111
|
+
<div style={{
|
|
112
|
+
width: '100%',
|
|
113
|
+
height: autoAdjustForImages ? 'auto' : '100%',
|
|
114
|
+
display: 'flex',
|
|
115
|
+
flexDirection: 'column',
|
|
116
|
+
alignItems: box.props.align || 'flex-start',
|
|
117
|
+
justifyContent: box.props.justify || 'flex-start',
|
|
118
|
+
padding: 0,
|
|
119
|
+
margin: 0,
|
|
120
|
+
boxSizing: 'border-box'
|
|
121
|
+
}}>
|
|
122
|
+
{box.components.map((component, index) => {
|
|
123
|
+
const getCurrentBoxHeight = () => {
|
|
124
|
+
const validModes = ['web', 'mobileweb', 'mobileapp', 'tablet'] as const;
|
|
125
|
+
const safeDeviceMode = validModes.includes(deviceMode as any)
|
|
126
|
+
? deviceMode as keyof typeof box.props.mode
|
|
127
|
+
: 'web';
|
|
128
|
+
if (component.name === 'ImageComponent') return 'auto';
|
|
129
|
+
return box.props.mode[safeDeviceMode]?.height || 'auto';
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (component.name === 'DateField') {
|
|
133
|
+
const code = getFieldCode(component);
|
|
134
|
+
const hasError = validationErrors[code];
|
|
135
|
+
return (
|
|
136
|
+
<div key={index} style={{ width: '100%' }}>
|
|
137
|
+
<DateField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
|
|
138
|
+
{hasError && component.props.required && (
|
|
139
|
+
<div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
|
|
140
|
+
This field is required
|
|
141
|
+
</div>
|
|
142
|
+
)}
|
|
143
|
+
</div>
|
|
144
|
+
);
|
|
145
|
+
} else if (component.name === 'NumberField') {
|
|
146
|
+
const code = getFieldCode(component);
|
|
147
|
+
const hasError = validationErrors[code];
|
|
148
|
+
return (
|
|
149
|
+
<div key={index} style={{ width: '100%' }}>
|
|
150
|
+
<NumberField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
|
|
151
|
+
{hasError && component.props.required && (
|
|
152
|
+
<div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
|
|
153
|
+
This field is required
|
|
154
|
+
</div>
|
|
155
|
+
)}
|
|
156
|
+
</div>
|
|
157
|
+
);
|
|
158
|
+
} else if (component.name === 'SelectField') {
|
|
159
|
+
const code = getFieldCode(component);
|
|
160
|
+
const hasError = validationErrors[code];
|
|
161
|
+
return (
|
|
162
|
+
<div key={index} style={{ width: '100%' }}>
|
|
163
|
+
<SelectField props={component.props} value={formValues[code]} onChange={onFieldChange} />
|
|
164
|
+
{hasError && component.props.required && (
|
|
165
|
+
<div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
|
|
166
|
+
This field is required
|
|
167
|
+
</div>
|
|
168
|
+
)}
|
|
169
|
+
</div>
|
|
170
|
+
);
|
|
171
|
+
} else if (component.name === 'RadioField') {
|
|
172
|
+
const code = getFieldCode(component);
|
|
173
|
+
const hasError = validationErrors[code];
|
|
174
|
+
return (
|
|
175
|
+
<div key={index} style={{ width: '100%' }}>
|
|
176
|
+
<RadioField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
|
|
177
|
+
{hasError && component.props.required && (
|
|
178
|
+
<div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
|
|
179
|
+
This field is required
|
|
180
|
+
</div>
|
|
181
|
+
)}
|
|
182
|
+
</div>
|
|
183
|
+
);
|
|
184
|
+
} else if (component.name === 'InputField') {
|
|
185
|
+
const code = getFieldCode(component);
|
|
186
|
+
const hasError = validationErrors[code];
|
|
187
|
+
return (
|
|
188
|
+
<div key={index} style={{ width: '100%' }}>
|
|
189
|
+
<InputField props={component.props} value={getFieldValue(code)} onChange={onFieldChange} />
|
|
190
|
+
{hasError && component.props.required && (
|
|
191
|
+
<div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
|
|
192
|
+
This field is required
|
|
193
|
+
</div>
|
|
194
|
+
)}
|
|
195
|
+
</div>
|
|
196
|
+
);
|
|
197
|
+
} else if (component.name === 'ImageComponent') {
|
|
198
|
+
return <ImageComponent key={index} props={component.props as any} deviceMode={deviceMode} boxHeight={getCurrentBoxHeight()} />;
|
|
199
|
+
} else if (component.name === 'BooleanField') {
|
|
200
|
+
const code = getFieldCode(component);
|
|
201
|
+
const hasError = validationErrors[code];
|
|
202
|
+
return (
|
|
203
|
+
<div key={index} style={{ width: '100%' }}>
|
|
204
|
+
<BooleanField props={component.props} value={formValues[code] ?? false} onChange={onFieldChange} />
|
|
205
|
+
{hasError && component.props.required && (
|
|
206
|
+
<div style={{ color: 'red', fontSize: '12px', marginTop: '4px' }}>
|
|
207
|
+
This field is required
|
|
208
|
+
</div>
|
|
209
|
+
)}
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
} else if (component.name === 'TextComponent') {
|
|
213
|
+
return <TextComponent key={index} props={component.props} />;
|
|
214
|
+
} else if (component.name === 'ButtonField') {
|
|
215
|
+
return <Button key={index} props={component.props} onFormSubmit={onFormSubmit} />;
|
|
216
|
+
} else {
|
|
217
|
+
return (
|
|
218
|
+
<div key={index} className="mb-4 p-4 bg-gray-100 rounded-md border-2 border-dashed border-gray-300">
|
|
219
|
+
<p className="text-sm text-gray-500">Unknown component: {component.name}</p>
|
|
220
|
+
</div>
|
|
221
|
+
);
|
|
222
|
+
}
|
|
223
|
+
})}
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
);
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
export default BoxRenderer;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ComponentProps } from '../types';
|
|
3
|
+
|
|
4
|
+
// Define a proper type for button mode
|
|
5
|
+
interface ButtonModeProps {
|
|
6
|
+
radius?: string;
|
|
7
|
+
bgColor?: string;
|
|
8
|
+
textstyle?: {
|
|
9
|
+
fontSize: number;
|
|
10
|
+
fontColor: string;
|
|
11
|
+
fontStyle: {
|
|
12
|
+
isBold: boolean;
|
|
13
|
+
isItalic: boolean;
|
|
14
|
+
isUnderLine: boolean;
|
|
15
|
+
isStrikeThrough: boolean;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface ButtonProps {
|
|
21
|
+
props: ComponentProps;
|
|
22
|
+
onFormSubmit?: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const Button: React.FC<ButtonProps> = ({ props, onFormSubmit }) => {
|
|
26
|
+
// Get device-specific mode properties with proper typing
|
|
27
|
+
const getCurrentMode = (): ButtonModeProps => {
|
|
28
|
+
// Default to web mode if not specified
|
|
29
|
+
return (props.mode?.web as ButtonModeProps) || {
|
|
30
|
+
radius: '4px',
|
|
31
|
+
bgColor: '#3498db',
|
|
32
|
+
textstyle: {
|
|
33
|
+
fontSize: 16,
|
|
34
|
+
fontColor: '#ffffff',
|
|
35
|
+
fontStyle: {
|
|
36
|
+
isBold: false,
|
|
37
|
+
isItalic: false,
|
|
38
|
+
isUnderLine: false,
|
|
39
|
+
isStrikeThrough: false
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const currentMode = getCurrentMode();
|
|
46
|
+
const textStyle = currentMode.textstyle || {
|
|
47
|
+
fontSize: 16,
|
|
48
|
+
fontColor: '#ffffff',
|
|
49
|
+
fontStyle: {
|
|
50
|
+
isBold: false,
|
|
51
|
+
isItalic: false,
|
|
52
|
+
isUnderLine: false,
|
|
53
|
+
isStrikeThrough: false
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// Handle button click
|
|
58
|
+
const handleClick = () => {
|
|
59
|
+
// You can add button click logic here
|
|
60
|
+
console.log('Button clicked:', props.name?.all || 'Button');
|
|
61
|
+
|
|
62
|
+
// Trigger form submission if handler is provided
|
|
63
|
+
if (onFormSubmit) {
|
|
64
|
+
onFormSubmit();
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// If there's a link configured, handle it
|
|
68
|
+
if (props.linktype === 'EXTERNAL' && props.link?.url) {
|
|
69
|
+
window.open(props.link.url, props.link.target || '_blank');
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// Get button text - handle both string and {all: string} formats
|
|
74
|
+
const getButtonText = () => {
|
|
75
|
+
if (typeof props.text === 'string') {
|
|
76
|
+
return props.text;
|
|
77
|
+
} else if (props.text?.all) {
|
|
78
|
+
return props.text.all;
|
|
79
|
+
} else if (props.name?.all) {
|
|
80
|
+
return props.name.all;
|
|
81
|
+
}
|
|
82
|
+
return 'Button';
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div className="mb-6">
|
|
87
|
+
<button
|
|
88
|
+
onClick={handleClick}
|
|
89
|
+
disabled={props.disabled}
|
|
90
|
+
style={{
|
|
91
|
+
backgroundColor: currentMode.bgColor || '#3498db',
|
|
92
|
+
color: textStyle.fontColor,
|
|
93
|
+
fontSize: `${textStyle.fontSize}px`,
|
|
94
|
+
fontWeight: textStyle.fontStyle?.isBold ? 'bold' : 'normal',
|
|
95
|
+
fontStyle: textStyle.fontStyle?.isItalic ? 'italic' : 'normal',
|
|
96
|
+
textDecoration: textStyle.fontStyle?.isUnderLine ? 'underline' : 'none',
|
|
97
|
+
textDecorationLine: textStyle.fontStyle?.isStrikeThrough ? 'line-through' : 'none',
|
|
98
|
+
borderRadius: currentMode.radius || '4px',
|
|
99
|
+
padding: '10px 20px',
|
|
100
|
+
border: 'none',
|
|
101
|
+
cursor: props.disabled ? 'not-allowed' : 'pointer',
|
|
102
|
+
opacity: props.disabled ? 0.6 : 1,
|
|
103
|
+
transition: 'all 0.2s ease-in-out',
|
|
104
|
+
minWidth: '120px'
|
|
105
|
+
}}
|
|
106
|
+
onMouseEnter={(e) => {
|
|
107
|
+
if (!props.disabled) {
|
|
108
|
+
e.currentTarget.style.opacity = '0.8';
|
|
109
|
+
e.currentTarget.style.transform = 'translateY(-1px)';
|
|
110
|
+
}
|
|
111
|
+
}}
|
|
112
|
+
onMouseLeave={(e) => {
|
|
113
|
+
if (!props.disabled) {
|
|
114
|
+
e.currentTarget.style.opacity = '1';
|
|
115
|
+
e.currentTarget.style.transform = 'translateY(0)';
|
|
116
|
+
}
|
|
117
|
+
}}
|
|
118
|
+
>
|
|
119
|
+
{getButtonText()}
|
|
120
|
+
</button>
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export default Button;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ComponentProps } from '../types';
|
|
3
|
+
import './Styles/DateField.css'; // Import the external stylesheet
|
|
4
|
+
|
|
5
|
+
interface DateFieldProps {
|
|
6
|
+
props: ComponentProps;
|
|
7
|
+
value?: any;
|
|
8
|
+
onChange?: (code: string, value: any) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const DateField: React.FC<DateFieldProps> = ({ props, value = '', onChange }) => {
|
|
12
|
+
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
13
|
+
const newValue = e.target.value;
|
|
14
|
+
if (onChange) {
|
|
15
|
+
const code = props.code || `datefield_${props.name?.all || 'field'}`;
|
|
16
|
+
onChange(code, newValue);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<div className="date-field">
|
|
22
|
+
<label className="date-field__label">
|
|
23
|
+
{props.name?.all || 'Date Field'}
|
|
24
|
+
{props.required && <span className="date-field__required">*</span>}
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<input
|
|
28
|
+
type="date"
|
|
29
|
+
value={value || ''}
|
|
30
|
+
onChange={handleChange}
|
|
31
|
+
className="date-field__input"
|
|
32
|
+
required={props.required}
|
|
33
|
+
/>
|
|
34
|
+
|
|
35
|
+
{props.helperText && (
|
|
36
|
+
<p className="date-field__helper-text">{props.helperText}</p>
|
|
37
|
+
)}
|
|
38
|
+
|
|
39
|
+
<div className="date-field__pattern">
|
|
40
|
+
Pattern: {props.pattern || 'Default'}
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export default DateField;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../App.css';
|
|
3
|
+
// Import your CSS file here
|
|
4
|
+
|
|
5
|
+
interface ImageData {
|
|
6
|
+
isDynamic: boolean;
|
|
7
|
+
shape: string;
|
|
8
|
+
url: string;
|
|
9
|
+
alt: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ImageModeProps {
|
|
13
|
+
borderRadius: number;
|
|
14
|
+
width: string;
|
|
15
|
+
height: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface ImageComponentProps {
|
|
19
|
+
images: any;
|
|
20
|
+
mode: {
|
|
21
|
+
web: ImageModeProps;
|
|
22
|
+
mobileweb: ImageModeProps;
|
|
23
|
+
mobileapp: ImageModeProps;
|
|
24
|
+
tablet: ImageModeProps;
|
|
25
|
+
};
|
|
26
|
+
linktype: string;
|
|
27
|
+
link: {
|
|
28
|
+
url: string;
|
|
29
|
+
target: string;
|
|
30
|
+
};
|
|
31
|
+
product: {
|
|
32
|
+
_id: string;
|
|
33
|
+
code: string;
|
|
34
|
+
name: object;
|
|
35
|
+
pd_type: string;
|
|
36
|
+
};
|
|
37
|
+
page: {
|
|
38
|
+
_id: string;
|
|
39
|
+
code: string;
|
|
40
|
+
name: object;
|
|
41
|
+
pg_type: string;
|
|
42
|
+
facet_params: any[];
|
|
43
|
+
track_params: any[];
|
|
44
|
+
};
|
|
45
|
+
tag: {
|
|
46
|
+
_id: string;
|
|
47
|
+
code: string;
|
|
48
|
+
name: object;
|
|
49
|
+
tagtype: string;
|
|
50
|
+
};
|
|
51
|
+
type: any[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface ImageComponentMainProps {
|
|
55
|
+
props: ImageComponentProps;
|
|
56
|
+
deviceMode?: string;
|
|
57
|
+
boxHeight?: string; // Add this prop to receive box height
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const ImageComponent: React.FC<ImageComponentMainProps> = ({
|
|
61
|
+
props,
|
|
62
|
+
deviceMode = 'web',
|
|
63
|
+
boxHeight = '280px',
|
|
64
|
+
}) => {
|
|
65
|
+
|
|
66
|
+
const bannerLink = (element: any): string | null => {
|
|
67
|
+
if (!element || !element.linktype) return null;
|
|
68
|
+
|
|
69
|
+
switch (element.linktype) {
|
|
70
|
+
case 'NONE':
|
|
71
|
+
return null;
|
|
72
|
+
|
|
73
|
+
case 'EXTERNAL':
|
|
74
|
+
case 'EXTERNAL_LINK':
|
|
75
|
+
return element.link?.url || null;
|
|
76
|
+
|
|
77
|
+
case 'PRODUCT': {
|
|
78
|
+
const pdType = element.product?.pd_type;
|
|
79
|
+
const code =
|
|
80
|
+
element.product?.pd_id?.code ||
|
|
81
|
+
element.product?.code ||
|
|
82
|
+
element.product?.product_data?.code;
|
|
83
|
+
|
|
84
|
+
if (!code) return null;
|
|
85
|
+
|
|
86
|
+
return pdType === 'VARIANT'
|
|
87
|
+
? `/variant/${code}`
|
|
88
|
+
: `model/${code}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
case 'TAG': {
|
|
92
|
+
const tagCode = element.tag?.code;
|
|
93
|
+
if (!tagCode) return null;
|
|
94
|
+
// return `/${tagCode}/s?type=tag`;
|
|
95
|
+
return `/tag/${tagCode}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
case 'PAGE': {
|
|
99
|
+
const pageId = element.page?._id || element.page?.code;
|
|
100
|
+
const pgType = element.page?.pg_type;
|
|
101
|
+
if (!pageId || !pgType) return null;
|
|
102
|
+
return `/page/${pageId}?type=${pgType}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
default:
|
|
106
|
+
return element.slug || null;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const getCurrentMode = () => {
|
|
111
|
+
switch (deviceMode) {
|
|
112
|
+
case 'mobileweb':
|
|
113
|
+
return props.mode.mobileweb;
|
|
114
|
+
case 'mobileapp':
|
|
115
|
+
return props.mode.mobileapp;
|
|
116
|
+
case 'tablet':
|
|
117
|
+
return props.mode.tablet;
|
|
118
|
+
case 'web':
|
|
119
|
+
default:
|
|
120
|
+
return props.mode.web;
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const currentMode = getCurrentMode();
|
|
125
|
+
const containerHeight = boxHeight === 'auto' ? 'auto' : boxHeight;
|
|
126
|
+
const link = bannerLink(props);
|
|
127
|
+
const imageUrl = `https://pim.in-maa-1.linodeobjects.com/${props.images?.url || props.images?.all?.url}`;
|
|
128
|
+
const altText = props.images.alt || '';
|
|
129
|
+
|
|
130
|
+
const imageElement = (
|
|
131
|
+
<img
|
|
132
|
+
src={imageUrl}
|
|
133
|
+
alt={altText}
|
|
134
|
+
className="fitted-image"
|
|
135
|
+
style={{ cursor: link ? 'pointer' : 'default' }}
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<div
|
|
141
|
+
className="image-box"
|
|
142
|
+
style={{
|
|
143
|
+
borderRadius: `${currentMode.borderRadius}px`,
|
|
144
|
+
height: containerHeight,
|
|
145
|
+
overflow: 'hidden',
|
|
146
|
+
}}
|
|
147
|
+
>
|
|
148
|
+
{link ? (
|
|
149
|
+
<a
|
|
150
|
+
href={link}
|
|
151
|
+
target={props?.linktype=='EXTERNAL' ? props?.link?.target :'_self'}
|
|
152
|
+
style={{ display: 'block', width: '100%', height: '100%' }}
|
|
153
|
+
>
|
|
154
|
+
{imageElement}
|
|
155
|
+
</a>
|
|
156
|
+
) : (
|
|
157
|
+
imageElement
|
|
158
|
+
)}
|
|
159
|
+
</div>
|
|
160
|
+
);
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
export default ImageComponent;
|