funuicss 3.8.12 → 3.8.14

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.
@@ -54,7 +54,9 @@ var componentUtils_1 = require("../../utils/componentUtils");
54
54
  var Text_1 = __importDefault(require("../text/Text"));
55
55
  var Button_1 = __importDefault(require("../button/Button"));
56
56
  var getDynamicIcon_1 = require("../../utils/getDynamicIcon");
57
- var Carousel_1 = __importDefault(require("../carousel/Carousel")); // Import the Carousel component
57
+ var Carousel_1 = __importDefault(require("../carousel/Carousel"));
58
+ var theme_1 = require("../theme/theme");
59
+ var pi_1 = require("react-icons/pi");
58
60
  var useDynamicIcon = function (iconString) {
59
61
  var _a = (0, react_1.useState)(null), iconNode = _a[0], setIconNode = _a[1];
60
62
  var _b = (0, react_1.useState)(false), hasValidIcon = _b[0], setHasValidIcon = _b[1];
@@ -77,52 +79,98 @@ var useDynamicIcon = function (iconString) {
77
79
  }, [iconString]);
78
80
  return { iconNode: iconNode, hasValidIcon: hasValidIcon };
79
81
  };
80
- var FeatureIcon = function (_a) {
81
- var icon = _a.icon, iconColor = _a.iconColor, _b = _a.iconSize, iconSize = _b === void 0 ? 24 : _b, _c = _a.iconClassName, iconClassName = _c === void 0 ? '' : _c, layout = _a.layout, _d = _a.checklistIcon, checklistIcon = _d === void 0 ? 'PiCheck' : _d, _e = _a.checklistColor, checklistColor = _e === void 0 ? 'success' : _e, _f = _a.checklistSize, checklistSize = _f === void 0 ? 20 : _f, _g = _a.checklistClassName, checklistClassName = _g === void 0 ? '' : _g;
82
+ // Dynamic Icon Component with proper typing
83
+ var DynamicIcon = function (_a) {
84
+ var icon = _a.icon, color = _a.color, _b = _a.size, size = _b === void 0 ? 24 : _b;
82
85
  var isStringIcon = icon && typeof icon === 'string';
83
- var _h = useDynamicIcon(isStringIcon ? icon : undefined), dynamicIconNode = _h.iconNode, hasValidDynamicIcon = _h.hasValidIcon;
84
- var _j = useDynamicIcon(layout === 'checklist' ? checklistIcon : undefined), checkmarkIconNode = _j.iconNode, hasValidCheckmarkIcon = _j.hasValidIcon;
85
- var getIconColorStyle = function (color) {
86
+ var _c = useDynamicIcon(isStringIcon ? icon : undefined), iconNode = _c.iconNode, hasValidIcon = _c.hasValidIcon;
87
+ var getIconColorStyle = function () {
86
88
  if (!color)
87
89
  return {};
88
- if (color.startsWith('text-') || color.startsWith('bg-') || color.startsWith('border-')) {
89
- return {};
90
- }
91
- var colorNames = ['primary', 'secondary', 'accent', 'success', 'warning', 'error', 'info', 'dark', 'light'];
92
- if (colorNames.includes(color)) {
93
- var cssValue = (0, getCssVariable_1.getCssVariableValue)(color);
94
- if (cssValue) {
95
- return { color: cssValue };
96
- }
90
+ var cssValue = (0, getCssVariable_1.getCssVariableValue)(color);
91
+ if (cssValue && cssValue !== color) {
92
+ return { color: cssValue };
97
93
  }
98
94
  return { color: color };
99
95
  };
100
- var iconColorStyle = getIconColorStyle(iconColor);
101
- var checklistColorStyle = getIconColorStyle(checklistColor);
102
- var renderIconWithProps = function (iconElement, className, style, size) {
103
- if (!react_1.default.isValidElement(iconElement))
104
- return iconElement;
105
- var props = {
106
- className: className,
107
- style: __assign(__assign({}, style), iconElement.props.style),
108
- };
109
- if (size !== undefined) {
110
- props.size = size;
111
- }
112
- return react_1.default.cloneElement(iconElement, props);
113
- };
114
96
  if (icon && typeof icon !== 'string' && react_1.default.isValidElement(icon)) {
115
- return renderIconWithProps(icon, "feature-section__icon ".concat(iconClassName), iconColorStyle, iconSize);
116
- }
117
- if (isStringIcon && hasValidDynamicIcon && dynamicIconNode) {
118
- return renderIconWithProps(dynamicIconNode, "feature-section__icon ".concat(iconClassName), iconColorStyle, iconSize);
97
+ // Handle React element icons
98
+ var iconElement = icon;
99
+ return react_1.default.cloneElement(iconElement, {
100
+ size: size,
101
+ style: __assign(__assign({}, getIconColorStyle()), iconElement.props.style),
102
+ });
119
103
  }
120
- if (layout === 'checklist' && hasValidCheckmarkIcon && checkmarkIconNode) {
121
- return renderIconWithProps(checkmarkIconNode, "feature-section__checkmark ".concat(checklistClassName), checklistColorStyle, checklistSize);
104
+ if (isStringIcon && hasValidIcon && iconNode && react_1.default.isValidElement(iconNode)) {
105
+ // Handle dynamically loaded icons
106
+ var dynamicIconElement = iconNode;
107
+ var newProps = {
108
+ size: size,
109
+ style: getIconColorStyle(),
110
+ };
111
+ // Preserve existing props
112
+ if (dynamicIconElement.props.className) {
113
+ newProps.className = dynamicIconElement.props.className;
114
+ }
115
+ return react_1.default.cloneElement(dynamicIconElement, newProps);
122
116
  }
123
117
  return null;
124
118
  };
125
- // Helper function to convert shorthand flex values to proper CSS values
119
+ // Star Rating Component with dynamic icon
120
+ var StarRating = function (_a) {
121
+ var rating = _a.rating, _b = _a.icon, icon = _b === void 0 ? 'PiStar' : _b, _c = _a.color, color = _c === void 0 ? 'warning' : _c, _d = _a.size, size = _d === void 0 ? 16 : _d;
122
+ var _e = (0, react_1.useState)(null), ratingIconNode = _e[0], setRatingIconNode = _e[1];
123
+ var iconNode = useDynamicIcon(icon).iconNode;
124
+ (0, react_1.useEffect)(function () {
125
+ if (iconNode) {
126
+ setRatingIconNode(iconNode);
127
+ }
128
+ }, [iconNode]);
129
+ var renderIcon = function (type, index) {
130
+ var colorValue = (0, getCssVariable_1.getCssVariableValue)(color) || color;
131
+ var emptyColor = 'var(--muted)';
132
+ // If we have a dynamic icon and it's not empty
133
+ if (ratingIconNode && react_1.default.isValidElement(ratingIconNode) && type !== 'empty') {
134
+ var iconElement = ratingIconNode;
135
+ // Create a new props object
136
+ var newProps = {
137
+ key: index,
138
+ style: __assign({ color: colorValue }, iconElement.props.style)
139
+ };
140
+ // Add size prop if it exists
141
+ if (size !== undefined) {
142
+ newProps.size = size;
143
+ }
144
+ return react_1.default.cloneElement(iconElement, newProps);
145
+ }
146
+ // For empty stars or fallback, use PiStar icons
147
+ if (type === 'full') {
148
+ return react_1.default.createElement(pi_1.PiStarFill, { key: index, size: size, style: { color: colorValue } });
149
+ }
150
+ else if (type === 'half') {
151
+ return react_1.default.createElement(pi_1.PiStarHalf, { key: index, size: size, style: { color: colorValue } });
152
+ }
153
+ else {
154
+ return react_1.default.createElement(pi_1.PiStar, { key: index, size: size, style: { color: emptyColor } });
155
+ }
156
+ };
157
+ var stars = [];
158
+ var fullStars = Math.floor(rating);
159
+ var hasHalfStar = rating % 1 >= 0.5;
160
+ for (var i = 1; i <= 5; i++) {
161
+ if (i <= fullStars) {
162
+ stars.push(renderIcon('full', i));
163
+ }
164
+ else if (hasHalfStar && i === fullStars + 1) {
165
+ stars.push(renderIcon('half', i));
166
+ }
167
+ else {
168
+ stars.push(renderIcon('empty', i));
169
+ }
170
+ }
171
+ return (react_1.default.createElement("div", { className: "star-rating", style: { display: 'flex', gap: '2px', alignItems: 'center' } }, stars));
172
+ };
173
+ // Helper function to convert shorthand flex values
126
174
  var convertFlexValue = function (value) {
127
175
  if (!value)
128
176
  return undefined;
@@ -132,188 +180,878 @@ var convertFlexValue = function (value) {
132
180
  'center': 'center',
133
181
  'between': 'space-between',
134
182
  'around': 'space-around',
135
- 'stretch': 'stretch',
136
183
  };
137
184
  return flexMap[value] || value;
138
185
  };
186
+ // Format date
187
+ var formatDate = function (dateString) {
188
+ if (!dateString)
189
+ return '';
190
+ try {
191
+ var date = new Date(dateString);
192
+ if (isNaN(date.getTime()))
193
+ return '';
194
+ return date.toLocaleDateString('en-US', {
195
+ month: 'short',
196
+ day: 'numeric',
197
+ year: 'numeric'
198
+ });
199
+ }
200
+ catch (_a) {
201
+ return dateString;
202
+ }
203
+ };
204
+ // Truncate HTML content safely
205
+ var truncateHtml = function (html, maxLength) {
206
+ if (!html)
207
+ return { truncated: '', isTruncated: false };
208
+ // Strip HTML tags for length calculation
209
+ var text = html.replace(/<[^>]*>/g, '');
210
+ if (text.length <= maxLength) {
211
+ return { truncated: html, isTruncated: false };
212
+ }
213
+ // Truncate text
214
+ var truncatedText = text.substring(0, maxLength) + '...';
215
+ return { truncated: truncatedText, isTruncated: true };
216
+ };
139
217
  var Feature = function (localProps) {
140
218
  var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Feature', localProps.variant).mergeWithLocal;
141
219
  var mergedProps = mergeWithLocal(localProps).props;
142
220
  var final = mergedProps;
143
- var _a = (0, react_1.useState)([]), featuresArray = _a[0], setFeaturesArray = _a[1];
144
- // Parse features
221
+ var _a = (0, react_1.useState)([]), itemsArray = _a[0], setItemsArray = _a[1];
222
+ var _b = (0, react_1.useState)(new Set()), expandedItems = _b[0], setExpandedItems = _b[1];
223
+ // Use bucket data if bucket is provided
224
+ var _c = (0, theme_1.usePaginatedRecords)(final.bucket || '', final.bucketPage || 1, final.bucketSize || 50), bucketRecords = _c.records, bucketLoading = _c.loading;
225
+ // Parse items from props or bucket
145
226
  (0, react_1.useEffect)(function () {
146
- if (typeof final.features === 'string') {
147
- try {
148
- var parsed = JSON.parse(final.features);
149
- setFeaturesArray(Array.isArray(parsed) ? parsed : [parsed]);
227
+ var parseItems = function () {
228
+ if (final.bucket && bucketRecords) {
229
+ // Map bucket records to content format
230
+ var mappedItems = bucketRecords.map(function (record) {
231
+ var _a, _b;
232
+ var values = record.values || record;
233
+ if (final.isTestimonial) {
234
+ return {
235
+ customerName: values.customerName || values.name || values.customer,
236
+ company: values.company || values.organization,
237
+ avatar: ((_a = values === null || values === void 0 ? void 0 : values.avatar) === null || _a === void 0 ? void 0 : _a.url) || values.imageUrl || values.photo,
238
+ content: values.content || values.testimonial || values.description,
239
+ rating: values.rating || values.stars || 5,
240
+ role: values.role || values.position,
241
+ project: values.project || values.service,
242
+ date: values.date || values.createdAt,
243
+ featured: values.featured || values.highlighted || false,
244
+ title: values.customerName || values.name,
245
+ description: values.content || values.testimonial,
246
+ imageUrl: values.avatar || values.imageUrl,
247
+ icon: final.quoteIcon || 'PiQuotes',
248
+ iconColor: final.quoteColor || 'primary'
249
+ };
250
+ }
251
+ else {
252
+ return __assign({ title: values.title || values.name, description: values.description || values.content, icon: values.icon, iconColor: values.iconColor, imageUrl: values.imageUrl || ((_b = values.avatar) === null || _b === void 0 ? void 0 : _b.url) }, values);
253
+ }
254
+ });
255
+ setItemsArray(mappedItems);
150
256
  }
151
- catch (error) {
152
- console.error('Error parsing features JSON:', error);
153
- setFeaturesArray([]);
257
+ else if (typeof final.items === 'string') {
258
+ try {
259
+ var parsed = JSON.parse(final.items);
260
+ setItemsArray(Array.isArray(parsed) ? parsed : [parsed]);
261
+ }
262
+ catch (error) {
263
+ console.error('Error parsing items JSON:', error);
264
+ setItemsArray([]);
265
+ }
154
266
  }
155
- }
156
- else if (Array.isArray(final.features)) {
157
- setFeaturesArray(final.features);
158
- }
159
- else {
160
- setFeaturesArray([]);
161
- }
162
- }, [final.features]);
163
- var getSpacingValue = function (value, defaultValue) {
164
- if (defaultValue === void 0) { defaultValue = '0'; }
165
- if (!value)
166
- return defaultValue;
167
- if (/^\d+$/.test(value)) {
168
- return "".concat(parseInt(value) * 0.25, "rem");
169
- }
170
- return value;
171
- };
172
- var renderItemCTA = function (item) {
173
- if (!item.ctaText)
174
- return null;
175
- return (react_1.default.createElement("a", { href: item.ctaUrl, onClick: item.ctaOnClick, className: "feature-section__item-cta ".concat(item.ctaClassName || ''), style: {
176
- marginTop: '1rem',
177
- display: 'inline-block',
178
- textDecoration: 'none',
179
- color: 'var(--primary)',
180
- fontWeight: 500,
181
- fontSize: '0.875rem',
182
- } }, item.ctaText));
267
+ else if (Array.isArray(final.items)) {
268
+ setItemsArray(final.items);
269
+ }
270
+ else {
271
+ setItemsArray([]);
272
+ }
273
+ };
274
+ parseItems();
275
+ }, [final.items, final.isTestimonial, final.bucket, bucketRecords, final.quoteIcon, final.quoteColor]);
276
+ // Toggle expanded state for an item
277
+ var toggleExpand = function (index) {
278
+ setExpandedItems(function (prev) {
279
+ var newSet = new Set(prev);
280
+ if (newSet.has(index)) {
281
+ newSet.delete(index);
282
+ }
283
+ else {
284
+ newSet.add(index);
285
+ }
286
+ return newSet;
287
+ });
183
288
  };
184
- var renderFeatureItem = function (item, index) {
185
- var _a;
186
- if (item.customRender) {
187
- return item.customRender();
289
+ var renderItem = function (item, index) {
290
+ var isExpanded = expandedItems.has(index);
291
+ var contentLimit = final.contentLimit || 150;
292
+ // Get content to display
293
+ var displayContent = item.description || item.content || '';
294
+ var isTruncated = false;
295
+ if (typeof displayContent === 'string' && displayContent.length > contentLimit && !isExpanded) {
296
+ var _a = truncateHtml(displayContent, contentLimit), truncated = _a.truncated, truncatedFlag = _a.isTruncated;
297
+ displayContent = truncated;
298
+ isTruncated = truncatedFlag;
188
299
  }
189
- var iconColor = item.iconColor || final.iconColor;
190
- var iconSize = item.iconSize || final.iconSize || 24;
191
- var iconClassName = item.iconClassName || final.iconClassName || '';
192
- var checkmarkIcon = final.checkmarkIcon || 'PiCheck';
193
- var checkmarkColor = final.checkmarkColor || 'success';
194
- var checkmarkSize = final.checkmarkSize || 20;
195
- var checkmarkClassName = final.checkmarkClassName || '';
196
- var cardPadding = final.cardPadding || '1.5rem';
197
- var cardRounded = final.cardRounded || '0.5rem';
198
- var cardShadow = final.cardShadow || 'md';
199
- var cardBorder = (_a = final.cardBorder) !== null && _a !== void 0 ? _a : true;
200
- var cardBorderColor = final.cardBorderColor || 'var(--borderRgb)';
201
- var cardHoverEffect = final.cardHoverEffect || 'none';
202
- var titleSize = item.titleSize || final.itemTitleSize || '1.125rem';
203
- var titleWeight = item.titleWeight || final.itemTitleWeight || 600;
204
- var titleColor = item.titleColor || final.itemTitleColor || 'var(--text-color)';
205
- var titleClassName = item.titleClassName || '';
206
- var descriptionSize = item.descriptionSize || final.itemDescriptionSize || '0.875rem';
207
- var descriptionWeight = item.descriptionWeight || final.itemDescriptionWeight || 400;
208
- var descriptionColor = item.descriptionColor || final.itemDescriptionColor || 'var(--text-muted)';
209
- var descriptionClassName = item.descriptionClassName || '';
210
- var featureContent = (react_1.default.createElement("div", { className: "feature-section__item ".concat(item.className || ''), style: item.style },
211
- (item.icon || item.imageUrl || final.layout === 'checklist') && (react_1.default.createElement("div", { className: "feature-section__icon-container", style: { marginBottom: '1rem' } }, item.imageUrl ? (react_1.default.createElement("img", { src: item.imageUrl, alt: item.imageAlt || '', className: "feature-section__image ".concat(item.imageClassName || ''), style: __assign({ width: "".concat(iconSize, "px"), height: "".concat(iconSize, "px"), objectFit: 'cover', borderRadius: '50%' }, item.imageStyle) })) : (react_1.default.createElement("div", { className: "feature-section__icon-wrapper" },
212
- react_1.default.createElement(FeatureIcon, { icon: item.icon, iconColor: iconColor, iconSize: iconSize, iconClassName: iconClassName, layout: final.layout, checklistIcon: checkmarkIcon, checklistColor: checkmarkColor, checklistSize: checkmarkSize, checklistClassName: checkmarkClassName }))))),
213
- item.title && (react_1.default.createElement(Text_1.default, { block: true, size: titleSize, weight: titleWeight, color: titleColor, funcss: "feature-section__title ".concat(titleClassName), style: { marginBottom: '0.75rem' } }, item.title)),
214
- item.description && (react_1.default.createElement(Text_1.default, { block: true, size: descriptionSize, weight: descriptionWeight, color: descriptionColor, funcss: "feature-section__description ".concat(descriptionClassName) }, item.description)),
215
- item.content && (react_1.default.createElement("div", { className: "feature-section__additional-content", style: { marginTop: '1rem' } }, item.content)),
216
- renderItemCTA(item)));
217
- // Apply card styling if card prop is true
300
+ // Item content
301
+ var itemContent = (react_1.default.createElement(react_1.default.Fragment, null,
302
+ final.isTestimonial && final.showQuote && (react_1.default.createElement("div", { className: "feature__quote-icon", style: { marginBottom: '1rem' } }, react_1.default.isValidElement(final.quoteIcon) ? final.quoteIcon : (react_1.default.createElement(DynamicIcon, { icon: final.quoteIcon || 'PiQuotes', color: final.quoteColor, size: final.iconSize })))),
303
+ (item.icon || item.imageUrl) && !final.isTestimonial && (react_1.default.createElement("div", { className: "feature__icon-container", style: { marginBottom: '1rem' } }, item.imageUrl ? (react_1.default.createElement("img", { src: item.imageUrl, alt: item.imageAlt || '', className: "feature__image", style: {
304
+ width: "".concat(final.iconSize || 24, "px"),
305
+ height: "".concat(final.iconSize || 24, "px"),
306
+ objectFit: 'cover',
307
+ borderRadius: '50%',
308
+ } })) : (react_1.default.createElement(DynamicIcon, { icon: item.icon, color: item.iconColor || final.iconColor, size: final.iconSize })))),
309
+ item.title && (react_1.default.createElement(Text_1.default, { block: true, size: final.itemTitleSize || 'lg', weight: 600, color: "default", style: { marginBottom: '0.75rem' } }, item.title)),
310
+ (item.description || item.content) && (react_1.default.createElement(react_1.default.Fragment, null,
311
+ react_1.default.createElement(Text_1.default, { block: true, size: final.itemDescriptionSize || 'base', weight: 400, color: "muted", dangerouslySetInnerHTML: true, text: displayContent }),
312
+ isTruncated && final.showExpand && (react_1.default.createElement("button", { onClick: function () { return toggleExpand(index); }, className: "feature__expand-btn", style: {
313
+ background: 'none',
314
+ border: 'none',
315
+ color: 'var(--primary)',
316
+ cursor: 'pointer',
317
+ fontSize: '0.875rem',
318
+ marginTop: '0.5rem',
319
+ padding: 0,
320
+ textDecoration: 'underline'
321
+ } }, isExpanded ? (final.collapseText || 'Show less') : (final.expandText || 'Read more'))))),
322
+ final.isTestimonial && (react_1.default.createElement("div", { className: "feature__testimonial-info", style: { marginTop: '1rem' } },
323
+ final.showStars && item.rating && (react_1.default.createElement("div", { style: { marginBottom: '0.5rem' } },
324
+ react_1.default.createElement(StarRating, { rating: item.rating, icon: final.ratingIcon, color: final.starColor, size: 16 }))),
325
+ react_1.default.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '0.75rem' } },
326
+ item.avatar && (react_1.default.createElement("img", { src: item.avatar, alt: item.customerName || 'Customer', style: {
327
+ width: '40px',
328
+ height: '40px',
329
+ borderRadius: '50%',
330
+ objectFit: 'cover'
331
+ } })),
332
+ react_1.default.createElement("div", null,
333
+ item.customerName && (react_1.default.createElement(Text_1.default, { block: true, size: "sm", weight: 600, style: { marginBottom: '0.25rem' } }, item.customerName)),
334
+ react_1.default.createElement("div", { style: { fontSize: '0.75rem', color: 'var(--text-muted)' } },
335
+ item.role && final.showRole && react_1.default.createElement("span", null, item.role),
336
+ item.company && final.showCompany && (react_1.default.createElement("span", null,
337
+ item.role ? ' at ' : '',
338
+ item.company)),
339
+ item.date && final.showDate && react_1.default.createElement("span", null,
340
+ " \u2022 ",
341
+ formatDate(item.date))))))),
342
+ !final.isTestimonial && final.showCTA && final.ctaText && (react_1.default.createElement("div", { style: { marginTop: '1rem' } },
343
+ react_1.default.createElement(Button_1.default, { url: final.ctaUrl, color: "primary", text: final.ctaText, funcss: 'p-0' })))));
344
+ // Apply card styling if enabled
218
345
  if (final.card) {
219
- var cardClasses = [
220
- 'feature-section__card',
221
- 'card',
222
- cardHoverEffect !== 'none' ? "card--hover-".concat(cardHoverEffect) : '',
223
- item.className || '',
224
- final.cardClassName || '',
225
- ].filter(Boolean).join(' ');
226
- var cardStyles = __assign({ padding: getSpacingValue(cardPadding, '1.5rem'), borderRadius: cardRounded, boxShadow: cardShadow !== 'none' ? (0, getCssVariable_1.getCssVariableValue)("shadow-".concat(cardShadow)) || undefined : undefined, border: cardBorder ? "1px solid ".concat((0, getCssVariable_1.getCssVariableValue)(cardBorderColor) || cardBorderColor) : 'none', height: '100%', maxWidth: final.itemMaxWidth || '100%' }, item.style);
227
- return (react_1.default.createElement("div", { key: index, className: cardClasses, style: cardStyles }, featureContent));
346
+ var shadowValue = final.cardShadow !== 'none' ?
347
+ (0, getCssVariable_1.getCssVariableValue)("shadow-".concat(final.cardShadow)) || undefined :
348
+ undefined;
349
+ return (react_1.default.createElement("div", { key: index, className: "feature__card ".concat(final.cardClassName || ''), style: __assign({ padding: final.cardPadding || '1.5rem', borderRadius: final.cardRounded || '0.5rem', boxShadow: shadowValue, border: '1px solid var(--borderRgb)', height: '100%', maxWidth: final.itemMaxWidth || '100%' }, item.style) }, itemContent));
228
350
  }
229
351
  // Regular item without card
230
- return (react_1.default.createElement("div", { key: index, className: "feature-section__item-wrapper ".concat(item.className || ''), style: __assign({ maxWidth: final.itemMaxWidth || '100%' }, item.style) }, featureContent));
352
+ return (react_1.default.createElement("div", { key: index, className: "feature__item", style: __assign({ maxWidth: final.itemMaxWidth || '100%' }, item.style) }, itemContent));
231
353
  };
232
- var renderFlexFeatures = function () {
233
- if (featuresArray.length === 0)
354
+ var renderFlexItems = function () {
355
+ if (itemsArray.length === 0)
234
356
  return null;
235
357
  var gapValue = final.gap !== undefined ? "".concat(final.gap * 0.25, "rem") : '2rem';
236
- var flexGap = gapValue;
237
358
  if (final.layout === 'centered') {
238
359
  var maxWidth = final.maxWidth || '48rem';
239
- return (react_1.default.createElement("div", { className: "feature-section__centered-container", style: {
360
+ return (react_1.default.createElement("div", { className: "feature__centered-container", style: {
240
361
  maxWidth: maxWidth,
241
362
  margin: '0 auto',
242
- } }, featuresArray.map(function (item, index) { return renderFeatureItem(item, index); })));
363
+ } }, itemsArray.map(function (item, index) { return renderItem(item, index); })));
243
364
  }
244
- // Use Flex layout with proper flexbox values
245
- return (react_1.default.createElement("div", { className: "feature-section__flex-container", style: {
365
+ // Use Flex layout
366
+ return (react_1.default.createElement("div", { className: "feature__flex-container", style: {
246
367
  display: 'flex',
247
368
  flexWrap: final.wrap !== false ? 'wrap' : 'nowrap',
248
- gap: flexGap,
369
+ gap: gapValue,
249
370
  alignItems: convertFlexValue(final.align) || 'stretch',
250
371
  justifyContent: convertFlexValue(final.justify) || 'flex-start',
251
372
  maxWidth: final.maxWidth || '100%',
252
373
  margin: '0 auto',
253
- } }, featuresArray.map(function (item, index) { return (react_1.default.createElement("div", { key: index, className: "feature-section__flex-item" }, renderFeatureItem(item, index))); })));
374
+ } }, itemsArray.map(function (item, index) { return (react_1.default.createElement("div", { key: index, className: "feature__flex-item", style: { flex: '1 1 300px' } }, renderItem(item, index))); })));
254
375
  };
255
- var renderCarouselFeatures = function () {
256
- if (featuresArray.length === 0)
376
+ var renderCarouselItems = function () {
377
+ if (itemsArray.length === 0)
257
378
  return null;
258
379
  // Prepare carousel items
259
- var carouselItems = featuresArray.map(function (item, index) {
260
- return renderFeatureItem(item, index);
261
- });
262
- return (react_1.default.createElement("div", { className: "feature-section__carousel-container ".concat(final.carouselContainerClassName || ''), style: final.carouselContainerStyle },
263
- react_1.default.createElement(Carousel_1.default, { scrollNumber: final.scrollNumber, gap: final.gap || 1, funcss: final.carouselFuncss, showDashes: final.showDashes, allowVerticalOverflow: final.allowVerticalOverflow, itemPadding: final.itemPadding || '0.5rem', controlerSize: final.controlerSize, controlerIconSize: final.controlerIconSize, infiniteScroll: final.infiniteScroll, infiniteScrollSpeed: final.infiniteScrollSpeed, infiniteScrollDirection: final.infiniteScrollDirection }, carouselItems)));
380
+ var carouselItems = itemsArray.map(function (item, index) { return renderItem(item, index); });
381
+ return (react_1.default.createElement("div", { className: "feature__carousel-container" },
382
+ react_1.default.createElement(Carousel_1.default, { scrollNumber: final.scrollNumber || 320, gap: final.gap || 1, funcss: final.carouselFuncss, showDashes: final.showDashes !== false }, carouselItems)));
264
383
  };
265
- var renderFeaturesContent = function () {
266
- if (featuresArray.length === 0)
384
+ var renderContent = function () {
385
+ if (itemsArray.length === 0)
267
386
  return null;
268
387
  // Use carousel if isCarousel is true
269
388
  if (final.isCarousel) {
270
- return renderCarouselFeatures();
389
+ return renderCarouselItems();
271
390
  }
272
391
  // Otherwise use flex layout
273
- return renderFlexFeatures();
274
- };
275
- var getLayoutClasses = function () {
276
- var classes = ['feature-section'];
277
- if (final.layout) {
278
- classes.push("feature-section--".concat(final.layout));
279
- }
280
- if (final.isCarousel) {
281
- classes.push('feature-section--carousel');
282
- }
283
- if (final.className) {
284
- classes.push(final.className);
285
- }
286
- if (final.sectionClass) {
287
- classes.push(final.sectionClass);
288
- }
289
- if (final.funcss) {
290
- classes.push(final.funcss);
291
- }
292
- return classes.filter(Boolean).join(' ');
293
- };
294
- var getContainerStyles = function () {
295
- var padding = getSpacingValue(final.padding, '3rem 0');
296
- return __assign({ padding: padding }, final.style);
392
+ return renderFlexItems();
297
393
  };
298
- var getTextAlign = function (align) {
299
- return {
300
- textAlign: align || 'center',
301
- };
302
- };
303
- return (react_1.default.createElement("section", { id: final.id, className: getLayoutClasses(), style: getContainerStyles() },
304
- react_1.default.createElement("div", { className: "feature-section__container ".concat(final.containerClassName || ''), style: __assign({ maxWidth: final.maxWidth || '1280px', margin: '0 auto', padding: '0 1rem' }, final.containerStyle) },
305
- (final.title || final.subtitle || final.description) && (react_1.default.createElement("div", { className: "feature-section__header", style: __assign({ marginBottom: '3rem', maxWidth: final.layout === 'centered' ? '48rem' : '100%', marginLeft: 'auto', marginRight: 'auto' }, getTextAlign(final.titleAlign)) },
306
- final.subtitle && (react_1.default.createElement(Text_1.default, { block: true, size: final.subtitleSize || 'sm', weight: final.subtitleWeight || 600, color: final.subtitleColor || 'var(--primary)', funcss: "feature-section__subtitle ".concat(final.subtitleClassName || ''), style: {
394
+ return (react_1.default.createElement("section", { id: final.id, className: "feature-section ".concat(final.className || '', " ").concat(final.funcss || ''), style: {
395
+ padding: final.padding || '3rem 0',
396
+ } },
397
+ react_1.default.createElement("div", { className: "feature__container ".concat(final.containerClassName || ''), style: {
398
+ maxWidth: final.maxWidth || '1280px',
399
+ margin: '0 auto',
400
+ padding: '0 1rem',
401
+ } },
402
+ (final.title || final.subtitle || final.description) && (react_1.default.createElement("div", { className: "feature__header", style: {
403
+ marginBottom: '3rem',
404
+ maxWidth: final.layout === 'centered' ? '48rem' : '100%',
405
+ marginLeft: 'auto',
406
+ marginRight: 'auto',
407
+ textAlign: final.titleAlign || 'center',
408
+ } },
409
+ final.subtitle && (react_1.default.createElement(Text_1.default, { block: true, size: final.subtitleSize || 'sm', weight: 600, color: final.subtitleColor || 'primary', style: {
307
410
  textTransform: 'uppercase',
308
411
  letterSpacing: '0.05em',
309
412
  marginBottom: '0.5rem',
310
413
  } }, final.subtitle)),
311
- final.title && (react_1.default.createElement(Text_1.default, { block: true, size: final.titleSize || 'xl', weight: final.titleWeight || 700, color: final.titleColor || 'var(--text-color)', funcss: "feature-section__main-title ".concat(final.titleClassName || ''), style: { marginBottom: '1rem' } }, final.title)),
312
- final.description && (react_1.default.createElement(Text_1.default, { block: true, size: final.descriptionSize || 'sm', weight: final.descriptionWeight || 400, color: final.descriptionColor || 'var(--text-muted)', funcss: "feature-section__section-description ".concat(final.descriptionClassName || '') }, final.description)))),
313
- react_1.default.createElement("div", { className: "feature-section__content" },
314
- renderFeaturesContent(),
414
+ final.title && (react_1.default.createElement(Text_1.default, { block: true, size: final.titleSize || 'xl', weight: 700, color: final.titleColor || 'default', style: { marginBottom: '1rem' } }, final.title)),
415
+ final.description && (react_1.default.createElement(Text_1.default, { block: true, size: final.descriptionSize || 'base', weight: 400, color: final.descriptionColor || 'muted' }, final.description)))),
416
+ react_1.default.createElement("div", { className: "feature__content" },
417
+ renderContent(),
315
418
  final.children),
316
- final.ctaText && (react_1.default.createElement("div", { className: "feature-section__cta-container", style: __assign({ marginTop: '2.5rem' }, getTextAlign(final.ctaAlign)) },
317
- react_1.default.createElement(Button_1.default, { onClick: final.ctaOnClick || (function () { return final.ctaUrl && (window.location.href = final.ctaUrl); }), funcss: "feature-section__cta ".concat(final.ctaClassName || ''), stringPrefix: final.ctaStringPrefix, stringSuffix: final.ctaStringSuffix, startIcon: final.ctaStartIcon, endIcon: final.ctaEndIcon, iconSize: final.ctaIconSize, bg: final.ctaBg || 'primary', isLoading: final.ctaIsLoading, status: final.ctaStatus, url: final.ctaUrl }, final.ctaText))))));
419
+ final.ctaText && (react_1.default.createElement("div", { className: "feature__cta-container", style: {
420
+ marginTop: '2.5rem',
421
+ textAlign: final.ctaAlign || 'center',
422
+ } },
423
+ react_1.default.createElement(Button_1.default, { url: final.ctaUrl, bg: final.ctaBg || 'primary', text: final.ctaText }))))));
318
424
  };
319
425
  exports.default = Feature;
426
+ // 'use client';
427
+ // import React, { useState, useEffect } from 'react';
428
+ // import { getCssVariableValue } from '../../utils/getCssVariable';
429
+ // import { useComponentConfiguration } from '../../utils/componentUtils';
430
+ // import Text from '../text/Text';
431
+ // import Button from '../button/Button';
432
+ // import { getDynamicIcon } from '../../utils/getDynamicIcon';
433
+ // import Carousel from '../carousel/Carousel'; // Import the Carousel component
434
+ // type FeatureItem = {
435
+ // icon?: string | React.ReactNode;
436
+ // iconColor?: string;
437
+ // iconSize?: number;
438
+ // iconClassName?: string;
439
+ // title?: React.ReactNode;
440
+ // titleSize?: string;
441
+ // titleWeight?: number;
442
+ // titleColor?: string;
443
+ // titleClassName?: string;
444
+ // description?: React.ReactNode;
445
+ // descriptionSize?: string;
446
+ // descriptionWeight?: number;
447
+ // descriptionColor?: string;
448
+ // descriptionClassName?: string;
449
+ // imageUrl?: string;
450
+ // imageAlt?: string;
451
+ // imageClassName?: string;
452
+ // imageStyle?: React.CSSProperties;
453
+ // content?: React.ReactNode;
454
+ // className?: string;
455
+ // style?: React.CSSProperties;
456
+ // ctaText?: string;
457
+ // ctaUrl?: string;
458
+ // ctaOnClick?: () => void;
459
+ // ctaClassName?: string;
460
+ // customRender?: () => React.ReactNode;
461
+ // };
462
+ // // Carousel-specific props
463
+ // interface CarouselOptions {
464
+ // isCarousel?: boolean;
465
+ // // Carousel props
466
+ // scrollNumber?: number;
467
+ // gap?: number;
468
+ // carouselFuncss?: string;
469
+ // showDashes?: boolean;
470
+ // allowVerticalOverflow?: boolean;
471
+ // itemPadding?: string;
472
+ // controlerSize?: number;
473
+ // controlerIconSize?: number;
474
+ // infiniteScroll?: boolean;
475
+ // infiniteScrollSpeed?: number;
476
+ // infiniteScrollDirection?: 'left' | 'right' | 'alternate';
477
+ // // Carousel container styling
478
+ // carouselContainerClassName?: string;
479
+ // carouselContainerStyle?: React.CSSProperties;
480
+ // }
481
+ // type FeatureProps = {
482
+ // variant?: string;
483
+ // layout?: 'checklist' | 'centered' | 'grid';
484
+ // title?: React.ReactNode;
485
+ // titleSize?: string;
486
+ // titleWeight?: number;
487
+ // titleColor?: string;
488
+ // titleClassName?: string;
489
+ // titleAlign?: 'left' | 'center' | 'right';
490
+ // subtitle?: React.ReactNode;
491
+ // subtitleSize?: string;
492
+ // subtitleWeight?: number;
493
+ // subtitleColor?: string;
494
+ // subtitleClassName?: string;
495
+ // description?: React.ReactNode;
496
+ // descriptionSize?: string;
497
+ // descriptionWeight?: number;
498
+ // descriptionColor?: string;
499
+ // descriptionClassName?: string;
500
+ // features?: FeatureItem[] | string;
501
+ // gap?: number;
502
+ // itemMaxWidth?: string;
503
+ // align?: 'start' | 'center' | 'end' | 'stretch';
504
+ // justify?: 'start' | 'center' | 'end' | 'between' | 'around';
505
+ // wrap?: boolean;
506
+ // card?: boolean;
507
+ // cardPadding?: string;
508
+ // cardRounded?: string;
509
+ // cardShadow?: 'sm' | 'md' | 'lg' | 'xl' | 'none';
510
+ // cardBorder?: boolean;
511
+ // cardBorderColor?: string;
512
+ // cardHoverEffect?: 'lift' | 'glow' | 'scale' | 'none';
513
+ // cardClassName?: string;
514
+ // padding?: string;
515
+ // className?: string;
516
+ // style?: React.CSSProperties;
517
+ // containerClassName?: string;
518
+ // containerStyle?: React.CSSProperties;
519
+ // iconColor?: string;
520
+ // iconSize?: number;
521
+ // iconClassName?: string;
522
+ // itemTitleSize?: string;
523
+ // itemTitleWeight?: number;
524
+ // itemTitleColor?: string;
525
+ // itemDescriptionSize?: string;
526
+ // itemDescriptionWeight?: number;
527
+ // itemDescriptionColor?: string;
528
+ // checkmarkIcon?: string;
529
+ // checkmarkColor?: string;
530
+ // checkmarkSize?: number;
531
+ // checkmarkClassName?: string;
532
+ // ctaText?: string;
533
+ // ctaUrl?: string;
534
+ // ctaOnClick?: () => void;
535
+ // ctaClassName?: string;
536
+ // ctaAlign?: 'left' | 'center' | 'right';
537
+ // ctaStringPrefix?: string;
538
+ // ctaStringSuffix?: string;
539
+ // ctaStartIcon?: React.ReactNode;
540
+ // ctaEndIcon?: React.ReactNode;
541
+ // ctaIconSize?: number;
542
+ // ctaIsLoading?: boolean;
543
+ // ctaStatus?: 'success' | 'warning' | 'info' | 'error';
544
+ // ctaBg?: string;
545
+ // children?: React.ReactNode;
546
+ // id?: string;
547
+ // funcss?: string;
548
+ // sectionClass?: string;
549
+ // maxWidth?: string;
550
+ // } & CarouselOptions; // Merge CarouselOptions into FeatureProps
551
+ // const useDynamicIcon = (iconString?: string) => {
552
+ // const [iconNode, setIconNode] = useState<React.ReactNode>(null);
553
+ // const [hasValidIcon, setHasValidIcon] = useState(false);
554
+ // useEffect(() => {
555
+ // if (!iconString || typeof iconString !== 'string' || iconString.trim() === '') {
556
+ // setIconNode(null);
557
+ // setHasValidIcon(false);
558
+ // return;
559
+ // }
560
+ // getDynamicIcon(iconString).then((node) => {
561
+ // if (node) {
562
+ // setIconNode(node);
563
+ // setHasValidIcon(true);
564
+ // } else {
565
+ // setIconNode(null);
566
+ // setHasValidIcon(false);
567
+ // }
568
+ // });
569
+ // }, [iconString]);
570
+ // return { iconNode, hasValidIcon };
571
+ // };
572
+ // const FeatureIcon: React.FC<{
573
+ // icon?: string | React.ReactNode;
574
+ // iconColor?: string;
575
+ // iconSize?: number;
576
+ // iconClassName?: string;
577
+ // layout?: string;
578
+ // checklistIcon?: string;
579
+ // checklistColor?: string;
580
+ // checklistSize?: number;
581
+ // checklistClassName?: string;
582
+ // }> = ({
583
+ // icon,
584
+ // iconColor,
585
+ // iconSize = 24,
586
+ // iconClassName = '',
587
+ // layout,
588
+ // checklistIcon = 'PiCheck',
589
+ // checklistColor = 'success',
590
+ // checklistSize = 20,
591
+ // checklistClassName = ''
592
+ // }) => {
593
+ // const isStringIcon = icon && typeof icon === 'string';
594
+ // const { iconNode: dynamicIconNode, hasValidIcon: hasValidDynamicIcon } = useDynamicIcon(
595
+ // isStringIcon ? icon as string : undefined
596
+ // );
597
+ // const { iconNode: checkmarkIconNode, hasValidIcon: hasValidCheckmarkIcon } = useDynamicIcon(
598
+ // layout === 'checklist' ? checklistIcon : undefined
599
+ // );
600
+ // const getIconColorStyle = (color?: string): React.CSSProperties => {
601
+ // if (!color) return {};
602
+ // if (color.startsWith('text-') || color.startsWith('bg-') || color.startsWith('border-')) {
603
+ // return {};
604
+ // }
605
+ // const colorNames = ['primary', 'secondary', 'accent', 'success', 'warning', 'error', 'info', 'dark', 'light'];
606
+ // if (colorNames.includes(color)) {
607
+ // const cssValue = getCssVariableValue(color);
608
+ // if (cssValue) {
609
+ // return { color: cssValue };
610
+ // }
611
+ // }
612
+ // return { color };
613
+ // };
614
+ // const iconColorStyle = getIconColorStyle(iconColor);
615
+ // const checklistColorStyle = getIconColorStyle(checklistColor);
616
+ // const renderIconWithProps = (iconElement: React.ReactNode, className: string, style: React.CSSProperties, size?: number) => {
617
+ // if (!React.isValidElement(iconElement)) return iconElement;
618
+ // const props: any = {
619
+ // className,
620
+ // style: { ...style, ...(iconElement.props as any).style },
621
+ // };
622
+ // if (size !== undefined) {
623
+ // props.size = size;
624
+ // }
625
+ // return React.cloneElement(iconElement, props);
626
+ // };
627
+ // if (icon && typeof icon !== 'string' && React.isValidElement(icon)) {
628
+ // return renderIconWithProps(
629
+ // icon,
630
+ // `feature-section__icon ${iconClassName}`,
631
+ // iconColorStyle,
632
+ // iconSize
633
+ // );
634
+ // }
635
+ // if (isStringIcon && hasValidDynamicIcon && dynamicIconNode) {
636
+ // return renderIconWithProps(
637
+ // dynamicIconNode,
638
+ // `feature-section__icon ${iconClassName}`,
639
+ // iconColorStyle,
640
+ // iconSize
641
+ // );
642
+ // }
643
+ // if (layout === 'checklist' && hasValidCheckmarkIcon && checkmarkIconNode) {
644
+ // return renderIconWithProps(
645
+ // checkmarkIconNode,
646
+ // `feature-section__checkmark ${checklistClassName}`,
647
+ // checklistColorStyle,
648
+ // checklistSize
649
+ // );
650
+ // }
651
+ // return null;
652
+ // };
653
+ // // Helper function to convert shorthand flex values to proper CSS values
654
+ // const convertFlexValue = (value?: string): string | undefined => {
655
+ // if (!value) return undefined;
656
+ // const flexMap: Record<string, string> = {
657
+ // 'start': 'flex-start',
658
+ // 'end': 'flex-end',
659
+ // 'center': 'center',
660
+ // 'between': 'space-between',
661
+ // 'around': 'space-around',
662
+ // 'stretch': 'stretch',
663
+ // };
664
+ // return flexMap[value] || value;
665
+ // };
666
+ // const Feature: React.FC<FeatureProps> = (localProps) => {
667
+ // const { mergeWithLocal } = useComponentConfiguration('Feature', localProps.variant);
668
+ // const { props: mergedProps } = mergeWithLocal(localProps);
669
+ // const final = mergedProps;
670
+ // const [featuresArray, setFeaturesArray] = useState<FeatureItem[]>([]);
671
+ // // Parse features
672
+ // useEffect(() => {
673
+ // if (typeof final.features === 'string') {
674
+ // try {
675
+ // const parsed = JSON.parse(final.features);
676
+ // setFeaturesArray(Array.isArray(parsed) ? parsed : [parsed]);
677
+ // } catch (error) {
678
+ // console.error('Error parsing features JSON:', error);
679
+ // setFeaturesArray([]);
680
+ // }
681
+ // } else if (Array.isArray(final.features)) {
682
+ // setFeaturesArray(final.features);
683
+ // } else {
684
+ // setFeaturesArray([]);
685
+ // }
686
+ // }, [final.features]);
687
+ // const getSpacingValue = (value?: string, defaultValue: string = '0'): string => {
688
+ // if (!value) return defaultValue;
689
+ // if (/^\d+$/.test(value)) {
690
+ // return `${parseInt(value) * 0.25}rem`;
691
+ // }
692
+ // return value;
693
+ // };
694
+ // const renderItemCTA = (item: FeatureItem) => {
695
+ // if (!item.ctaText) return null;
696
+ // return (
697
+ // <a
698
+ // href={item.ctaUrl}
699
+ // onClick={item.ctaOnClick}
700
+ // className={`feature-section__item-cta ${item.ctaClassName || ''}`}
701
+ // style={{
702
+ // marginTop: '1rem',
703
+ // display: 'inline-block',
704
+ // textDecoration: 'none',
705
+ // color: 'var(--primary)',
706
+ // fontWeight: 500,
707
+ // fontSize: '0.875rem',
708
+ // }}
709
+ // >
710
+ // {item.ctaText}
711
+ // </a>
712
+ // );
713
+ // };
714
+ // const renderFeatureItem = (item: FeatureItem, index: number) => {
715
+ // if (item.customRender) {
716
+ // return item.customRender();
717
+ // }
718
+ // const iconColor = item.iconColor || final.iconColor;
719
+ // const iconSize = item.iconSize || final.iconSize || 24;
720
+ // const iconClassName = item.iconClassName || final.iconClassName || '';
721
+ // const checkmarkIcon = final.checkmarkIcon || 'PiCheck';
722
+ // const checkmarkColor = final.checkmarkColor || 'success';
723
+ // const checkmarkSize = final.checkmarkSize || 20;
724
+ // const checkmarkClassName = final.checkmarkClassName || '';
725
+ // const cardPadding = final.cardPadding || '1.5rem';
726
+ // const cardRounded = final.cardRounded || '0.5rem';
727
+ // const cardShadow = final.cardShadow || 'md';
728
+ // const cardBorder = final.cardBorder ?? true;
729
+ // const cardBorderColor = final.cardBorderColor || 'var(--borderRgb)';
730
+ // const cardHoverEffect = final.cardHoverEffect || 'none';
731
+ // const titleSize = item.titleSize || final.itemTitleSize || '1.125rem';
732
+ // const titleWeight = item.titleWeight || final.itemTitleWeight || 600;
733
+ // const titleColor = item.titleColor || final.itemTitleColor || 'var(--text-color)';
734
+ // const titleClassName = item.titleClassName || '';
735
+ // const descriptionSize = item.descriptionSize || final.itemDescriptionSize || '0.875rem';
736
+ // const descriptionWeight = item.descriptionWeight || final.itemDescriptionWeight || 400;
737
+ // const descriptionColor = item.descriptionColor || final.itemDescriptionColor || 'var(--text-muted)';
738
+ // const descriptionClassName = item.descriptionClassName || '';
739
+ // const featureContent = (
740
+ // <div className={`feature-section__item ${item.className || ''}`} style={item.style}>
741
+ // {(item.icon || item.imageUrl || final.layout === 'checklist') && (
742
+ // <div
743
+ // className="feature-section__icon-container"
744
+ // style={{ marginBottom: '1rem' }}
745
+ // >
746
+ // {item.imageUrl ? (
747
+ // <img
748
+ // src={item.imageUrl}
749
+ // alt={item.imageAlt || ''}
750
+ // className={`feature-section__image ${item.imageClassName || ''}`}
751
+ // style={{
752
+ // width: `${iconSize}px`,
753
+ // height: `${iconSize}px`,
754
+ // objectFit: 'cover',
755
+ // borderRadius: '50%',
756
+ // ...item.imageStyle,
757
+ // }}
758
+ // />
759
+ // ) : (
760
+ // <div className="feature-section__icon-wrapper">
761
+ // <FeatureIcon
762
+ // icon={item.icon}
763
+ // iconColor={iconColor}
764
+ // iconSize={iconSize}
765
+ // iconClassName={iconClassName}
766
+ // layout={final.layout}
767
+ // checklistIcon={checkmarkIcon}
768
+ // checklistColor={checkmarkColor}
769
+ // checklistSize={checkmarkSize}
770
+ // checklistClassName={checkmarkClassName}
771
+ // />
772
+ // </div>
773
+ // )}
774
+ // </div>
775
+ // )}
776
+ // {item.title && (
777
+ // <Text
778
+ // block
779
+ // size={titleSize}
780
+ // weight={titleWeight}
781
+ // color={titleColor}
782
+ // funcss={`feature-section__title ${titleClassName}`}
783
+ // style={{ marginBottom: '0.75rem' }}
784
+ // >
785
+ // {item.title}
786
+ // </Text>
787
+ // )}
788
+ // {item.description && (
789
+ // <Text
790
+ // block
791
+ // size={descriptionSize}
792
+ // weight={descriptionWeight}
793
+ // color={descriptionColor}
794
+ // funcss={`feature-section__description ${descriptionClassName}`}
795
+ // >
796
+ // {item.description}
797
+ // </Text>
798
+ // )}
799
+ // {item.content && (
800
+ // <div
801
+ // className="feature-section__additional-content"
802
+ // style={{ marginTop: '1rem' }}
803
+ // >
804
+ // {item.content}
805
+ // </div>
806
+ // )}
807
+ // {renderItemCTA(item)}
808
+ // </div>
809
+ // );
810
+ // // Apply card styling if card prop is true
811
+ // if (final.card) {
812
+ // const cardClasses = [
813
+ // 'feature-section__card',
814
+ // 'card',
815
+ // cardHoverEffect !== 'none' ? `card--hover-${cardHoverEffect}` : '',
816
+ // item.className || '',
817
+ // final.cardClassName || '',
818
+ // ].filter(Boolean).join(' ');
819
+ // const cardStyles: React.CSSProperties = {
820
+ // padding: getSpacingValue(cardPadding, '1.5rem'),
821
+ // borderRadius: cardRounded,
822
+ // boxShadow: cardShadow !== 'none' ? getCssVariableValue(`shadow-${cardShadow}`) || undefined : undefined,
823
+ // border: cardBorder ? `1px solid ${getCssVariableValue(cardBorderColor) || cardBorderColor}` : 'none',
824
+ // height: '100%',
825
+ // maxWidth: final.itemMaxWidth || '100%',
826
+ // ...item.style,
827
+ // };
828
+ // return (
829
+ // <div key={index} className={cardClasses} style={cardStyles}>
830
+ // {featureContent}
831
+ // </div>
832
+ // );
833
+ // }
834
+ // // Regular item without card
835
+ // return (
836
+ // <div
837
+ // key={index}
838
+ // className={`feature-section__item-wrapper ${item.className || ''}`}
839
+ // style={{
840
+ // maxWidth: final.itemMaxWidth || '100%',
841
+ // ...item.style
842
+ // }}
843
+ // >
844
+ // {featureContent}
845
+ // </div>
846
+ // );
847
+ // };
848
+ // const renderFlexFeatures = () => {
849
+ // if (featuresArray.length === 0) return null;
850
+ // const gapValue = final.gap !== undefined ? `${final.gap * 0.25}rem` : '2rem';
851
+ // const flexGap = gapValue;
852
+ // if (final.layout === 'centered') {
853
+ // const maxWidth = final.maxWidth || '48rem';
854
+ // return (
855
+ // <div
856
+ // className="feature-section__centered-container"
857
+ // style={{
858
+ // maxWidth,
859
+ // margin: '0 auto',
860
+ // }}
861
+ // >
862
+ // {featuresArray.map((item, index) => renderFeatureItem(item, index))}
863
+ // </div>
864
+ // );
865
+ // }
866
+ // // Use Flex layout with proper flexbox values
867
+ // return (
868
+ // <div
869
+ // className="feature-section__flex-container"
870
+ // style={{
871
+ // display: 'flex',
872
+ // flexWrap: final.wrap !== false ? 'wrap' : 'nowrap',
873
+ // gap: flexGap,
874
+ // alignItems: convertFlexValue(final.align) || 'stretch',
875
+ // justifyContent: convertFlexValue(final.justify) || 'flex-start',
876
+ // maxWidth: final.maxWidth || '100%',
877
+ // margin: '0 auto',
878
+ // }}
879
+ // >
880
+ // {featuresArray.map((item, index) => (
881
+ // <div key={index} className="feature-section__flex-item">
882
+ // {renderFeatureItem(item, index)}
883
+ // </div>
884
+ // ))}
885
+ // </div>
886
+ // );
887
+ // };
888
+ // const renderCarouselFeatures = () => {
889
+ // if (featuresArray.length === 0) return null;
890
+ // // Prepare carousel items
891
+ // const carouselItems = featuresArray.map((item, index) =>
892
+ // renderFeatureItem(item, index)
893
+ // );
894
+ // return (
895
+ // <div
896
+ // className={`feature-section__carousel-container ${final.carouselContainerClassName || ''}`}
897
+ // style={final.carouselContainerStyle}
898
+ // >
899
+ // <Carousel
900
+ // scrollNumber={final.scrollNumber}
901
+ // gap={final.gap || 1} // Default gap for carousel
902
+ // funcss={final.carouselFuncss}
903
+ // showDashes={final.showDashes}
904
+ // allowVerticalOverflow={final.allowVerticalOverflow}
905
+ // itemPadding={final.itemPadding || '0.5rem'}
906
+ // controlerSize={final.controlerSize}
907
+ // controlerIconSize={final.controlerIconSize}
908
+ // infiniteScroll={final.infiniteScroll}
909
+ // infiniteScrollSpeed={final.infiniteScrollSpeed}
910
+ // infiniteScrollDirection={final.infiniteScrollDirection}
911
+ // >
912
+ // {carouselItems}
913
+ // </Carousel>
914
+ // </div>
915
+ // );
916
+ // };
917
+ // const renderFeaturesContent = () => {
918
+ // if (featuresArray.length === 0) return null;
919
+ // // Use carousel if isCarousel is true
920
+ // if (final.isCarousel) {
921
+ // return renderCarouselFeatures();
922
+ // }
923
+ // // Otherwise use flex layout
924
+ // return renderFlexFeatures();
925
+ // };
926
+ // const getLayoutClasses = () => {
927
+ // const classes = ['feature-section'];
928
+ // if (final.layout) {
929
+ // classes.push(`feature-section--${final.layout}`);
930
+ // }
931
+ // if (final.isCarousel) {
932
+ // classes.push('feature-section--carousel');
933
+ // }
934
+ // if (final.className) {
935
+ // classes.push(final.className);
936
+ // }
937
+ // if (final.sectionClass) {
938
+ // classes.push(final.sectionClass);
939
+ // }
940
+ // if (final.funcss) {
941
+ // classes.push(final.funcss);
942
+ // }
943
+ // return classes.filter(Boolean).join(' ');
944
+ // };
945
+ // const getContainerStyles = (): React.CSSProperties => {
946
+ // const padding = getSpacingValue(final.padding, '3rem 0');
947
+ // return {
948
+ // padding: padding,
949
+ // ...final.style,
950
+ // };
951
+ // };
952
+ // const getTextAlign = (align?: 'left' | 'center' | 'right'): React.CSSProperties => {
953
+ // return {
954
+ // textAlign: align || 'center',
955
+ // };
956
+ // };
957
+ // return (
958
+ // <section
959
+ // id={final.id}
960
+ // className={getLayoutClasses()}
961
+ // style={getContainerStyles()}
962
+ // >
963
+ // <div
964
+ // className={`feature-section__container ${final.containerClassName || ''}`}
965
+ // style={{
966
+ // maxWidth: final.maxWidth || '1280px',
967
+ // margin: '0 auto',
968
+ // padding: '0 1rem',
969
+ // ...final.containerStyle,
970
+ // }}
971
+ // >
972
+ // {(final.title || final.subtitle || final.description) && (
973
+ // <div
974
+ // className="feature-section__header"
975
+ // style={{
976
+ // marginBottom: '3rem',
977
+ // maxWidth: final.layout === 'centered' ? '48rem' : '100%',
978
+ // marginLeft: 'auto',
979
+ // marginRight: 'auto',
980
+ // ...getTextAlign(final.titleAlign),
981
+ // }}
982
+ // >
983
+ // {final.subtitle && (
984
+ // <Text
985
+ // block
986
+ // size={final.subtitleSize || 'sm'}
987
+ // weight={final.subtitleWeight || 600}
988
+ // color={final.subtitleColor || 'var(--primary)'}
989
+ // funcss={`feature-section__subtitle ${final.subtitleClassName || ''}`}
990
+ // style={{
991
+ // textTransform: 'uppercase',
992
+ // letterSpacing: '0.05em',
993
+ // marginBottom: '0.5rem',
994
+ // }}
995
+ // >
996
+ // {final.subtitle}
997
+ // </Text>
998
+ // )}
999
+ // {final.title && (
1000
+ // <Text
1001
+ // block
1002
+ // size={final.titleSize || 'xl'}
1003
+ // weight={final.titleWeight || 700}
1004
+ // color={final.titleColor || 'var(--text-color)'}
1005
+ // funcss={`feature-section__main-title ${final.titleClassName || ''}`}
1006
+ // style={{ marginBottom: '1rem' }}
1007
+ // >
1008
+ // {final.title}
1009
+ // </Text>
1010
+ // )}
1011
+ // {final.description && (
1012
+ // <Text
1013
+ // block
1014
+ // size={final.descriptionSize || 'sm'}
1015
+ // weight={final.descriptionWeight || 400}
1016
+ // color={final.descriptionColor || 'var(--text-muted)'}
1017
+ // funcss={`feature-section__section-description ${final.descriptionClassName || ''}`}
1018
+ // >
1019
+ // {final.description}
1020
+ // </Text>
1021
+ // )}
1022
+ // </div>
1023
+ // )}
1024
+ // <div className="feature-section__content">
1025
+ // {renderFeaturesContent()}
1026
+ // {final.children}
1027
+ // </div>
1028
+ // {final.ctaText && (
1029
+ // <div
1030
+ // className="feature-section__cta-container"
1031
+ // style={{
1032
+ // marginTop: '2.5rem',
1033
+ // ...getTextAlign(final.ctaAlign),
1034
+ // }}
1035
+ // >
1036
+ // <Button
1037
+ // onClick={final.ctaOnClick || (() => final.ctaUrl && (window.location.href = final.ctaUrl))}
1038
+ // funcss={`feature-section__cta ${final.ctaClassName || ''}`}
1039
+ // stringPrefix={final.ctaStringPrefix}
1040
+ // stringSuffix={final.ctaStringSuffix}
1041
+ // startIcon={final.ctaStartIcon}
1042
+ // endIcon={final.ctaEndIcon}
1043
+ // iconSize={final.ctaIconSize}
1044
+ // bg={final.ctaBg || 'primary'}
1045
+ // isLoading={final.ctaIsLoading}
1046
+ // status={final.ctaStatus}
1047
+ // url={final.ctaUrl}
1048
+ // >
1049
+ // {final.ctaText}
1050
+ // </Button>
1051
+ // </div>
1052
+ // )}
1053
+ // </div>
1054
+ // </section>
1055
+ // );
1056
+ // };
1057
+ // export default Feature;