funuicss 3.8.8 → 3.8.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/fun.css +311 -1
- package/index.d.ts +2 -0
- package/index.js +6 -2
- package/package.json +1 -1
- package/ui/button/Button.d.ts +4 -4
- package/ui/button/Button.js +187 -82
- package/ui/carousel/Carousel.d.ts +3 -0
- package/ui/carousel/Carousel.js +140 -16
- package/ui/feature/Feature.d.ts +26 -39
- package/ui/feature/Feature.js +87 -148
- package/ui/flex/Flex.d.ts +11 -10
- package/ui/flex/Flex.js +102 -6
- package/ui/form/Form.d.ts +21 -12
- package/ui/form/Form.js +428 -319
- package/ui/input/Input.d.ts +16 -21
- package/ui/input/Input.js +156 -1345
- package/ui/notification/Notification.js +6 -2
- package/ui/products/ProductDetail.js +31 -23
- package/ui/products/Store.js +5 -5
- package/ui/sidebar/SideBar.js +1 -2
- package/ui/specials/CircleGroup.d.ts +2 -1
- package/ui/specials/CircleGroup.js +3 -3
package/ui/form/Form.js
CHANGED
|
@@ -97,10 +97,43 @@ var react_1 = __importStar(require("react"));
|
|
|
97
97
|
var Button_1 = __importDefault(require("../button/Button"));
|
|
98
98
|
var Input_1 = __importDefault(require("../input/Input"));
|
|
99
99
|
var Flex_1 = __importDefault(require("../flex/Flex"));
|
|
100
|
-
var Div_1 = __importDefault(require("../div/Div"));
|
|
101
100
|
var Text_1 = __importDefault(require("../text/Text"));
|
|
102
101
|
var pi_1 = require("react-icons/pi");
|
|
103
|
-
|
|
102
|
+
var componentUtils_1 = require("../../utils/componentUtils");
|
|
103
|
+
// Helper function to parse JSON input
|
|
104
|
+
var parseJsonInput = function (input, defaultValue) {
|
|
105
|
+
if (input === undefined || input === null) {
|
|
106
|
+
return defaultValue;
|
|
107
|
+
}
|
|
108
|
+
// If it's already the correct type, return as is
|
|
109
|
+
if (typeof input !== 'string') {
|
|
110
|
+
return input;
|
|
111
|
+
}
|
|
112
|
+
try {
|
|
113
|
+
// Try to parse as JSON
|
|
114
|
+
var parsed = JSON.parse(input);
|
|
115
|
+
return parsed;
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
console.warn('Failed to parse JSON input:', input, error);
|
|
119
|
+
// If parsing fails, try to interpret as a string that might be valid
|
|
120
|
+
try {
|
|
121
|
+
// Try to handle common cases like arrays or objects without quotes
|
|
122
|
+
var trimmed = input.trim();
|
|
123
|
+
if (trimmed.startsWith('[') && trimmed.endsWith(']')) {
|
|
124
|
+
return JSON.parse(trimmed);
|
|
125
|
+
}
|
|
126
|
+
else if (trimmed.startsWith('{') && trimmed.endsWith('}')) {
|
|
127
|
+
return JSON.parse(trimmed);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
// If still fails, return default
|
|
132
|
+
}
|
|
133
|
+
return defaultValue;
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
// Custom Checkbox Component (unchanged)
|
|
104
137
|
var FormCheckbox = function (_a) {
|
|
105
138
|
var label = _a.label, checked = _a.checked, onChange = _a.onChange, disabled = _a.disabled, required = _a.required, value = _a.value, id = _a.id;
|
|
106
139
|
return (react_1.default.createElement("label", { className: "funui_form-checkbox", style: {
|
|
@@ -110,12 +143,19 @@ var FormCheckbox = function (_a) {
|
|
|
110
143
|
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
111
144
|
userSelect: 'none',
|
|
112
145
|
width: 'fit-content',
|
|
146
|
+
padding: '0.25rem 0',
|
|
113
147
|
} },
|
|
114
|
-
react_1.default.createElement("input", { type: "checkbox", id: id, checked: checked, onChange: function (e) { return !disabled && onChange(e.target.checked); }, disabled: disabled, required: required, value: value, style: {
|
|
148
|
+
react_1.default.createElement("input", { type: "checkbox", id: id, checked: checked, onChange: function (e) { return !disabled && onChange(e.target.checked); }, disabled: disabled, required: required, value: value, style: {
|
|
149
|
+
position: 'absolute',
|
|
150
|
+
opacity: 0,
|
|
151
|
+
width: 0,
|
|
152
|
+
height: 0,
|
|
153
|
+
pointerEvents: 'none'
|
|
154
|
+
} }),
|
|
115
155
|
react_1.default.createElement("div", { className: "funui_form-checkbox-box", style: {
|
|
116
156
|
width: '1.25rem',
|
|
117
157
|
height: '1.25rem',
|
|
118
|
-
border: checked ? '2px solid var(--primary)' : '2px solid var(--
|
|
158
|
+
border: checked ? '2px solid var(--primary)' : '2px solid var(--borderColor)',
|
|
119
159
|
borderRadius: '0.25rem',
|
|
120
160
|
backgroundColor: checked ? 'var(--primary)' : 'transparent',
|
|
121
161
|
position: 'relative',
|
|
@@ -124,17 +164,22 @@ var FormCheckbox = function (_a) {
|
|
|
124
164
|
alignItems: 'center',
|
|
125
165
|
justifyContent: 'center',
|
|
126
166
|
flexShrink: 0,
|
|
127
|
-
} }, checked && (react_1.default.createElement("
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
} }
|
|
133
|
-
|
|
167
|
+
} }, checked && (react_1.default.createElement("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", xmlns: "http://www.w3.org2000/svg", style: {
|
|
168
|
+
stroke: 'white',
|
|
169
|
+
strokeWidth: '2',
|
|
170
|
+
strokeLinecap: 'round',
|
|
171
|
+
strokeLinejoin: 'round',
|
|
172
|
+
} },
|
|
173
|
+
react_1.default.createElement("path", { d: "M3 7L6 10L11 4" })))),
|
|
174
|
+
label && (react_1.default.createElement("span", { className: "funui_form-checkbox-label", style: {
|
|
175
|
+
fontSize: '0.875rem',
|
|
176
|
+
color: disabled ? 'var(--text-muted)' : 'var(--text)',
|
|
177
|
+
fontWeight: checked ? '500' : '400',
|
|
178
|
+
} },
|
|
134
179
|
label,
|
|
135
180
|
required && ' *'))));
|
|
136
181
|
};
|
|
137
|
-
// Custom Radio Component
|
|
182
|
+
// Custom Radio Component (unchanged)
|
|
138
183
|
var FormRadio = function (_a) {
|
|
139
184
|
var label = _a.label, checked = _a.checked, onChange = _a.onChange, disabled = _a.disabled, required = _a.required, value = _a.value, id = _a.id;
|
|
140
185
|
return (react_1.default.createElement("label", { className: "funui_form-radio", style: {
|
|
@@ -144,12 +189,19 @@ var FormRadio = function (_a) {
|
|
|
144
189
|
cursor: disabled ? 'not-allowed' : 'pointer',
|
|
145
190
|
userSelect: 'none',
|
|
146
191
|
width: 'fit-content',
|
|
192
|
+
padding: '0.25rem 0',
|
|
147
193
|
} },
|
|
148
|
-
react_1.default.createElement("input", { type: "radio", id: id, checked: checked, onChange: function (e) { return !disabled && onChange(e.target.checked); }, disabled: disabled, required: required, value: value, style: {
|
|
194
|
+
react_1.default.createElement("input", { type: "radio", id: id, checked: checked, onChange: function (e) { return !disabled && onChange(e.target.checked); }, disabled: disabled, required: required, value: value, style: {
|
|
195
|
+
position: 'absolute',
|
|
196
|
+
opacity: 0,
|
|
197
|
+
width: 0,
|
|
198
|
+
height: 0,
|
|
199
|
+
pointerEvents: 'none'
|
|
200
|
+
} }),
|
|
149
201
|
react_1.default.createElement("div", { className: "funui_form-radio-circle", style: {
|
|
150
202
|
width: '1.25rem',
|
|
151
203
|
height: '1.25rem',
|
|
152
|
-
border: checked ? '2px solid var(--primary)' : '2px solid var(--
|
|
204
|
+
border: checked ? '2px solid var(--primary)' : '2px solid var(--borderColor)',
|
|
153
205
|
borderRadius: '50%',
|
|
154
206
|
backgroundColor: 'transparent',
|
|
155
207
|
position: 'relative',
|
|
@@ -164,34 +216,41 @@ var FormRadio = function (_a) {
|
|
|
164
216
|
backgroundColor: 'var(--primary)',
|
|
165
217
|
borderRadius: '50%',
|
|
166
218
|
} }))),
|
|
167
|
-
label && (react_1.default.createElement("span", { className: "funui_form-radio-label", style: {
|
|
219
|
+
label && (react_1.default.createElement("span", { className: "funui_form-radio-label", style: {
|
|
220
|
+
fontSize: '0.875rem',
|
|
221
|
+
color: disabled ? 'var(--text-muted)' : 'var(--text)',
|
|
222
|
+
fontWeight: checked ? '500' : '400',
|
|
223
|
+
} },
|
|
168
224
|
label,
|
|
169
225
|
required && ' *'))));
|
|
170
226
|
};
|
|
171
|
-
//
|
|
172
|
-
var
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
//
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
227
|
+
// Function to format WhatsApp message - UPDATED with proper formatting
|
|
228
|
+
var formatWhatsAppMessage = function (values, fields, header, footer) {
|
|
229
|
+
// Build message lines
|
|
230
|
+
var message = '';
|
|
231
|
+
// Add header if provided
|
|
232
|
+
if (header) {
|
|
233
|
+
message += "".concat(header, "\n\n");
|
|
234
|
+
}
|
|
235
|
+
// Filter out empty/null/undefined values
|
|
236
|
+
var nonEmptyFields = fields.filter(function (field) {
|
|
237
|
+
var value = values[field.name];
|
|
238
|
+
// Skip if value is undefined, null, or empty string
|
|
239
|
+
if (value === undefined || value === null || value === '') {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
// Skip if array is empty
|
|
243
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
// Skip if checkbox is false
|
|
247
|
+
if (field.type === 'checkbox' && !field.multiple && value === false) {
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
return true;
|
|
251
|
+
});
|
|
252
|
+
// Format each field
|
|
253
|
+
var fieldLines = nonEmptyFields.map(function (field) {
|
|
195
254
|
var value = values[field.name];
|
|
196
255
|
var displayValue = value;
|
|
197
256
|
// Format array values (for multiple checkboxes)
|
|
@@ -207,71 +266,122 @@ var formatWhatsAppMessage = function (values, fields, headerMessage, footerMessa
|
|
|
207
266
|
var option = field.options.find(function (opt) { return opt.value === value; });
|
|
208
267
|
displayValue = option ? option.label : value;
|
|
209
268
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
269
|
+
// Ensure displayValue is a string and preserve spaces/newlines
|
|
270
|
+
displayValue = String(displayValue);
|
|
271
|
+
// WhatsApp formatting:
|
|
272
|
+
// - Field label on its own line
|
|
273
|
+
// - Value on next line wrapped in backticks
|
|
274
|
+
// - Double newline between fields for readability
|
|
275
|
+
return "".concat(field.label || field.name, "\n`").concat(displayValue, "`");
|
|
276
|
+
});
|
|
277
|
+
// Join with double newline for spacing
|
|
278
|
+
message += fieldLines.join('\n\n');
|
|
279
|
+
// Add footer if provided
|
|
280
|
+
if (footer) {
|
|
281
|
+
message += "\n\n".concat(footer);
|
|
220
282
|
}
|
|
221
283
|
return encodeURIComponent(message);
|
|
222
284
|
};
|
|
223
|
-
// Main Form Component
|
|
224
|
-
var Form = function (
|
|
225
|
-
var
|
|
285
|
+
// Main Form Component - FIXED
|
|
286
|
+
var Form = function (props) {
|
|
287
|
+
var fieldsProp = props.fields, onSubmitProp = props.onSubmit, _a = props.defaultValues, defaultValuesProp = _a === void 0 ? {} : _a, _b = props.submitText, submitTextProp = _b === void 0 ? 'Submit' : _b, _c = props.submitBg, submitBgProp = _c === void 0 ? 'primary' : _c, submitPrefixProp = props.submitPrefix, submitSuffixProp = props.submitSuffix, _d = props.resetText, resetTextProp = _d === void 0 ? 'Reset' : _d, _e = props.showReset, showResetProp = _e === void 0 ? true : _e, _f = props.isLoading, isLoadingProp = _f === void 0 ? false : _f, _g = props.className, classNameProp = _g === void 0 ? '' : _g, _h = props.layout, layoutProp = _h === void 0 ? 'vertical' : _h, _j = props.gap, gapProp = _j === void 0 ? '1.5rem' : _j, titleProp = props.title, titleSizeProp = props.titleSize, titleColorProp = props.titleColor, descriptionProp = props.description, descriptionSizeProp = props.descriptionSize, descriptionColorProp = props.descriptionColor, whatsappContactProp = props.whatsappContact, widthProp = props.width, centeredProp = props.centered, whatsappHeaderProp = props.whatsappHeader, whatsappFooterProp = props.whatsappFooter, _k = props.fullWidth, fullWidthProp = _k === void 0 ? true : _k, _l = props.variant, variant = _l === void 0 ? '' : _l;
|
|
288
|
+
// Use component configuration with variant
|
|
289
|
+
var mergeWithLocal = (0, componentUtils_1.useComponentConfiguration)('Form', variant).mergeWithLocal;
|
|
290
|
+
// Create local props object
|
|
291
|
+
var localProps = {
|
|
292
|
+
fields: fieldsProp,
|
|
293
|
+
onSubmit: onSubmitProp,
|
|
294
|
+
defaultValues: defaultValuesProp,
|
|
295
|
+
submitText: submitTextProp,
|
|
296
|
+
submitBg: submitBgProp,
|
|
297
|
+
submitPrefix: submitPrefixProp,
|
|
298
|
+
submitSuffix: submitSuffixProp,
|
|
299
|
+
resetText: resetTextProp,
|
|
300
|
+
showReset: showResetProp,
|
|
301
|
+
isLoading: isLoadingProp,
|
|
302
|
+
className: classNameProp,
|
|
303
|
+
layout: layoutProp,
|
|
304
|
+
gap: gapProp,
|
|
305
|
+
title: titleProp,
|
|
306
|
+
titleSize: titleSizeProp,
|
|
307
|
+
titleColor: titleColorProp,
|
|
308
|
+
description: descriptionProp,
|
|
309
|
+
descriptionSize: descriptionSizeProp,
|
|
310
|
+
descriptionColor: descriptionColorProp,
|
|
311
|
+
whatsappContact: whatsappContactProp,
|
|
312
|
+
width: widthProp,
|
|
313
|
+
centered: centeredProp,
|
|
314
|
+
whatsappHeader: whatsappHeaderProp,
|
|
315
|
+
whatsappFooter: whatsappFooterProp,
|
|
316
|
+
fullWidth: fullWidthProp,
|
|
317
|
+
variant: variant,
|
|
318
|
+
};
|
|
319
|
+
// Merge with theme configuration
|
|
320
|
+
var mergedProps = mergeWithLocal(localProps).props;
|
|
321
|
+
// Destructure with proper priority: local props override config props
|
|
322
|
+
var fields = fieldsProp !== undefined ? fieldsProp : mergedProps.fields;
|
|
323
|
+
var onSubmit = onSubmitProp !== undefined ? onSubmitProp : mergedProps.onSubmit;
|
|
324
|
+
var defaultValues = defaultValuesProp !== undefined ? defaultValuesProp : mergedProps.defaultValues;
|
|
325
|
+
var submitText = submitTextProp !== undefined ? submitTextProp : mergedProps.submitText;
|
|
326
|
+
var submitBg = submitBgProp !== undefined ? submitBgProp : mergedProps.submitBg;
|
|
327
|
+
var submitPrefix = submitPrefixProp !== undefined ? submitPrefixProp : mergedProps.submitPrefix;
|
|
328
|
+
var submitSuffix = submitSuffixProp !== undefined ? submitSuffixProp : mergedProps.submitSuffix;
|
|
329
|
+
var resetText = resetTextProp !== undefined ? resetTextProp : mergedProps.resetText;
|
|
330
|
+
var showReset = showResetProp !== undefined ? showResetProp : mergedProps.showReset;
|
|
331
|
+
var isLoading = isLoadingProp !== undefined ? isLoadingProp : mergedProps.isLoading;
|
|
332
|
+
var className = classNameProp !== undefined ? classNameProp : mergedProps.className;
|
|
333
|
+
var layout = layoutProp !== undefined ? layoutProp : mergedProps.layout;
|
|
334
|
+
var gap = gapProp !== undefined ? gapProp : mergedProps.gap;
|
|
335
|
+
var title = titleProp !== undefined ? titleProp : mergedProps.title;
|
|
336
|
+
var titleSize = titleSizeProp !== undefined ? titleSizeProp : mergedProps.titleSize;
|
|
337
|
+
var titleColor = titleColorProp !== undefined ? titleColorProp : mergedProps.titleColor;
|
|
338
|
+
var description = descriptionProp !== undefined ? descriptionProp : mergedProps.description;
|
|
339
|
+
var descriptionSize = descriptionSizeProp !== undefined ? descriptionSizeProp : mergedProps.descriptionSize;
|
|
340
|
+
var descriptionColor = descriptionColorProp !== undefined ? descriptionColorProp : mergedProps.descriptionColor;
|
|
341
|
+
var whatsappContact = whatsappContactProp !== undefined ? whatsappContactProp : mergedProps.whatsappContact;
|
|
342
|
+
var width = widthProp !== undefined ? widthProp : mergedProps.width;
|
|
343
|
+
var centered = centeredProp !== undefined ? centeredProp : mergedProps.centered;
|
|
344
|
+
var whatsappHeader = whatsappHeaderProp !== undefined ? whatsappHeaderProp : mergedProps.whatsappHeader;
|
|
345
|
+
var whatsappFooter = whatsappFooterProp !== undefined ? whatsappFooterProp : mergedProps.whatsappFooter;
|
|
346
|
+
var fullWidth = fullWidthProp !== undefined ? fullWidthProp : mergedProps.fullWidth;
|
|
347
|
+
// Parse JSON inputs
|
|
348
|
+
var parsedFields = (0, react_1.useMemo)(function () { return parseJsonInput(fields, []); }, [fields]);
|
|
349
|
+
var parsedDefaultValues = (0, react_1.useMemo)(function () { return parseJsonInput(defaultValues, {}); }, [defaultValues]);
|
|
226
350
|
// State management
|
|
227
|
-
var
|
|
228
|
-
var
|
|
229
|
-
var
|
|
230
|
-
|
|
231
|
-
var _p = (0, react_1.useState)(false), isSubmitting = _p[0], setIsSubmitting = _p[1];
|
|
232
|
-
var _q = (0, react_1.useState)(''), whatsappPhone = _q[0], setWhatsappPhone = _q[1];
|
|
233
|
-
// Initialize form values
|
|
234
|
-
(0, react_1.useEffect)(function () {
|
|
351
|
+
var _m = (0, react_1.useState)({}), errors = _m[0], setErrors = _m[1];
|
|
352
|
+
var _o = (0, react_1.useState)({}), touched = _o[0], setTouched = _o[1];
|
|
353
|
+
var _p = (0, react_1.useState)(function () {
|
|
354
|
+
// Initialize form values from defaultValues and field values
|
|
235
355
|
var initialValues = {};
|
|
236
|
-
|
|
237
|
-
var _a, _b;
|
|
238
|
-
// Priority: field.value > defaultValues > default based on type
|
|
356
|
+
parsedFields.forEach(function (field) {
|
|
239
357
|
if (field.value !== undefined) {
|
|
240
358
|
initialValues[field.name] = field.value;
|
|
241
359
|
}
|
|
242
|
-
else if (
|
|
243
|
-
initialValues[field.name] =
|
|
244
|
-
}
|
|
245
|
-
else if (field.type === 'checkbox') {
|
|
246
|
-
initialValues[field.name] = field.multiple ? [] : false;
|
|
247
|
-
}
|
|
248
|
-
else if (field.type === 'radio' && ((_a = field.options) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
249
|
-
initialValues[field.name] = '';
|
|
250
|
-
}
|
|
251
|
-
else if (field.type === 'select' && ((_b = field.options) === null || _b === void 0 ? void 0 : _b.length)) {
|
|
252
|
-
initialValues[field.name] = '';
|
|
360
|
+
else if (parsedDefaultValues[field.name] !== undefined) {
|
|
361
|
+
initialValues[field.name] = parsedDefaultValues[field.name];
|
|
253
362
|
}
|
|
254
363
|
else {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
364
|
+
// Set default empty values
|
|
365
|
+
if (field.type === 'checkbox' && field.multiple) {
|
|
366
|
+
initialValues[field.name] = [];
|
|
367
|
+
}
|
|
368
|
+
else if (field.type === 'checkbox') {
|
|
369
|
+
initialValues[field.name] = false;
|
|
370
|
+
}
|
|
371
|
+
else {
|
|
372
|
+
initialValues[field.name] = '';
|
|
373
|
+
}
|
|
263
374
|
}
|
|
264
375
|
});
|
|
265
|
-
|
|
266
|
-
}, [
|
|
267
|
-
|
|
376
|
+
return initialValues;
|
|
377
|
+
}), formValues = _p[0], setFormValues = _p[1];
|
|
378
|
+
var _q = (0, react_1.useState)(false), isSubmitting = _q[0], setIsSubmitting = _q[1];
|
|
379
|
+
// Update form values when defaultValues prop changes
|
|
268
380
|
(0, react_1.useEffect)(function () {
|
|
269
|
-
if (
|
|
270
|
-
|
|
271
|
-
var cleanPhone = whatsappIntegration.phoneNumber.replace(/[\s+\-()]/g, '');
|
|
272
|
-
setWhatsappPhone(cleanPhone);
|
|
381
|
+
if (Object.keys(parsedDefaultValues).length > 0) {
|
|
382
|
+
setFormValues(function (prev) { return (__assign(__assign({}, prev), parsedDefaultValues)); });
|
|
273
383
|
}
|
|
274
|
-
}, [
|
|
384
|
+
}, [parsedDefaultValues]);
|
|
275
385
|
// Validate a single field
|
|
276
386
|
var validateField = (0, react_1.useCallback)(function (field, value) {
|
|
277
387
|
var _a, _b, _c, _d, _e;
|
|
@@ -287,10 +397,10 @@ var Form = function (_a) {
|
|
|
287
397
|
return "".concat(field.label || field.name, " is required");
|
|
288
398
|
}
|
|
289
399
|
}
|
|
290
|
-
// Type-specific validations
|
|
291
|
-
if (value && value !== '') {
|
|
400
|
+
// Type-specific validations (only for non-empty values)
|
|
401
|
+
if (value && (typeof value !== 'string' || value !== '')) {
|
|
292
402
|
// Email validation
|
|
293
|
-
if (field.type === 'email') {
|
|
403
|
+
if (field.type === 'email' && typeof value === 'string') {
|
|
294
404
|
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
295
405
|
if (!emailRegex.test(value)) {
|
|
296
406
|
return 'Please enter a valid email address';
|
|
@@ -298,7 +408,16 @@ var Form = function (_a) {
|
|
|
298
408
|
}
|
|
299
409
|
// Number validation
|
|
300
410
|
if (field.type === 'number') {
|
|
301
|
-
var numValue =
|
|
411
|
+
var numValue = void 0;
|
|
412
|
+
if (typeof value === 'string') {
|
|
413
|
+
numValue = parseFloat(value);
|
|
414
|
+
}
|
|
415
|
+
else if (typeof value === 'number') {
|
|
416
|
+
numValue = value;
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
return 'Please enter a valid number';
|
|
420
|
+
}
|
|
302
421
|
if (isNaN(numValue)) {
|
|
303
422
|
return 'Please enter a valid number';
|
|
304
423
|
}
|
|
@@ -311,14 +430,14 @@ var Form = function (_a) {
|
|
|
311
430
|
return "Maximum value is ".concat(max);
|
|
312
431
|
}
|
|
313
432
|
}
|
|
314
|
-
// Phone validation (basic)
|
|
315
|
-
if (field.type === 'tel') {
|
|
433
|
+
// Phone validation (basic) - only for strings
|
|
434
|
+
if (field.type === 'tel' && typeof value === 'string') {
|
|
316
435
|
var phoneRegex = /^[\+]?[1-9][\d]{0,17}$/;
|
|
317
436
|
if (!phoneRegex.test(value.replace(/[\s+\-()]/g, ''))) {
|
|
318
437
|
return 'Please enter a valid phone number';
|
|
319
438
|
}
|
|
320
439
|
}
|
|
321
|
-
// Length validation
|
|
440
|
+
// Length validation for strings
|
|
322
441
|
if (typeof value === 'string') {
|
|
323
442
|
var minLength = (_c = field.inputProps) === null || _c === void 0 ? void 0 : _c.minLength;
|
|
324
443
|
var maxLength = (_d = field.inputProps) === null || _d === void 0 ? void 0 : _d.maxLength;
|
|
@@ -329,53 +448,83 @@ var Form = function (_a) {
|
|
|
329
448
|
return "Maximum ".concat(maxLength, " characters allowed");
|
|
330
449
|
}
|
|
331
450
|
}
|
|
332
|
-
// Pattern validation if provided
|
|
333
|
-
if ((_e = field.inputProps) === null || _e === void 0 ? void 0 : _e.pattern) {
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
451
|
+
// Pattern validation if provided - only for strings
|
|
452
|
+
if (((_e = field.inputProps) === null || _e === void 0 ? void 0 : _e.pattern) && typeof value === 'string') {
|
|
453
|
+
try {
|
|
454
|
+
var regex = new RegExp(field.inputProps.pattern);
|
|
455
|
+
if (!regex.test(value)) {
|
|
456
|
+
return 'Invalid format';
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
catch (error) {
|
|
460
|
+
console.warn('Invalid regex pattern:', field.inputProps.pattern);
|
|
337
461
|
}
|
|
338
462
|
}
|
|
339
463
|
}
|
|
340
464
|
return null;
|
|
341
465
|
}, []);
|
|
342
|
-
//
|
|
343
|
-
var
|
|
344
|
-
var
|
|
345
|
-
|
|
346
|
-
|
|
466
|
+
// Validate form
|
|
467
|
+
var validateForm = (0, react_1.useCallback)(function () {
|
|
468
|
+
var newErrors = {};
|
|
469
|
+
var hasErrors = false;
|
|
470
|
+
parsedFields.forEach(function (field) {
|
|
471
|
+
var value = formValues[field.name];
|
|
472
|
+
var error = validateField(field, value);
|
|
473
|
+
if (error) {
|
|
474
|
+
newErrors[field.name] = error;
|
|
475
|
+
hasErrors = true;
|
|
476
|
+
}
|
|
477
|
+
});
|
|
478
|
+
setErrors(newErrors);
|
|
479
|
+
return !hasErrors;
|
|
480
|
+
}, [parsedFields, validateField, formValues]);
|
|
481
|
+
// Handle field change for checkboxes and radios
|
|
482
|
+
var handleFieldChange = (0, react_1.useCallback)(function (fieldName, newValue) {
|
|
483
|
+
// Update form values
|
|
347
484
|
setFormValues(function (prev) {
|
|
348
485
|
var _a;
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
if (error_1) {
|
|
356
|
-
return __assign(__assign({}, prevErrors), (_a = {}, _a[fieldName] = error_1, _a));
|
|
357
|
-
}
|
|
358
|
-
else {
|
|
359
|
-
var newErrors = __assign({}, prevErrors);
|
|
360
|
-
delete newErrors[fieldName];
|
|
361
|
-
return newErrors;
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
return newValues;
|
|
486
|
+
return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = newValue, _a)));
|
|
487
|
+
});
|
|
488
|
+
// Update touched state
|
|
489
|
+
setTouched(function (prev) {
|
|
490
|
+
var _a;
|
|
491
|
+
return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
|
|
366
492
|
});
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
var handleFieldBlur = (0, react_1.useCallback)(function (fieldName) {
|
|
370
|
-
var field = fields.find(function (f) { return f.name === fieldName; });
|
|
493
|
+
// Validate the changed field
|
|
494
|
+
var field = parsedFields.find(function (f) { return f.name === fieldName; });
|
|
371
495
|
if (!field)
|
|
372
496
|
return;
|
|
497
|
+
var error = validateField(field, newValue);
|
|
498
|
+
setErrors(function (prev) {
|
|
499
|
+
var _a;
|
|
500
|
+
if (error) {
|
|
501
|
+
return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
|
|
502
|
+
}
|
|
503
|
+
else {
|
|
504
|
+
var newErrors = __assign({}, prev);
|
|
505
|
+
delete newErrors[fieldName];
|
|
506
|
+
return newErrors;
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
}, [parsedFields, validateField]);
|
|
510
|
+
// FIXED: Handle input change - pass event directly to Input component
|
|
511
|
+
var handleInputEventChange = (0, react_1.useCallback)(function (e) {
|
|
512
|
+
var fieldName = e.target.name;
|
|
513
|
+
var value = e.target.value;
|
|
514
|
+
// Update form values - PASS VALUE AS-IS (preserves spaces)
|
|
515
|
+
setFormValues(function (prev) {
|
|
516
|
+
var _a;
|
|
517
|
+
return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = value, _a)));
|
|
518
|
+
});
|
|
519
|
+
// Update touched state
|
|
373
520
|
setTouched(function (prev) {
|
|
374
521
|
var _a;
|
|
375
522
|
return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
|
|
376
523
|
});
|
|
377
|
-
// Validate
|
|
378
|
-
var
|
|
524
|
+
// Validate the changed field
|
|
525
|
+
var field = parsedFields.find(function (f) { return f.name === fieldName; });
|
|
526
|
+
if (!field)
|
|
527
|
+
return;
|
|
379
528
|
var error = validateField(field, value);
|
|
380
529
|
setErrors(function (prev) {
|
|
381
530
|
var _a;
|
|
@@ -388,271 +537,231 @@ var Form = function (_a) {
|
|
|
388
537
|
return newErrors;
|
|
389
538
|
}
|
|
390
539
|
});
|
|
391
|
-
}, [
|
|
392
|
-
//
|
|
393
|
-
var
|
|
394
|
-
|
|
540
|
+
}, [parsedFields, validateField]);
|
|
541
|
+
// FIXED: Handle blur event - pass event directly to Input component
|
|
542
|
+
var handleInputEventBlur = (0, react_1.useCallback)(function (e) {
|
|
543
|
+
var fieldName = e.target.name;
|
|
544
|
+
setTouched(function (prev) {
|
|
395
545
|
var _a;
|
|
396
|
-
return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] =
|
|
546
|
+
return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
|
|
397
547
|
});
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
if (!(whatsappIntegration === null || whatsappIntegration === void 0 ? void 0 : whatsappIntegration.enabled) || !whatsappPhone) {
|
|
402
|
-
console.error('WhatsApp integration not properly configured');
|
|
548
|
+
// Validate the field
|
|
549
|
+
var field = parsedFields.find(function (f) { return f.name === fieldName; });
|
|
550
|
+
if (!field)
|
|
403
551
|
return;
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
fields.forEach(function (field) {
|
|
409
|
-
var value = formValues[field.name];
|
|
410
|
-
var error = validateField(field, value);
|
|
552
|
+
var value = formValues[fieldName];
|
|
553
|
+
var error = validateField(field, value);
|
|
554
|
+
setErrors(function (prev) {
|
|
555
|
+
var _a;
|
|
411
556
|
if (error) {
|
|
412
|
-
|
|
413
|
-
|
|
557
|
+
return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
|
|
558
|
+
}
|
|
559
|
+
else {
|
|
560
|
+
var newErrors = __assign({}, prev);
|
|
561
|
+
delete newErrors[fieldName];
|
|
562
|
+
return newErrors;
|
|
414
563
|
}
|
|
415
564
|
});
|
|
416
|
-
|
|
417
|
-
if (hasErrors) {
|
|
418
|
-
// Mark all fields as touched to show errors
|
|
419
|
-
var allTouched_1 = {};
|
|
420
|
-
fields.forEach(function (field) {
|
|
421
|
-
allTouched_1[field.name] = true;
|
|
422
|
-
});
|
|
423
|
-
setTouched(allTouched_1);
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
// Format the message
|
|
427
|
-
var message = formatWhatsAppMessage(formValues, fields, whatsappIntegration.headerMessage, whatsappIntegration.footerMessage);
|
|
428
|
-
// Create WhatsApp URL
|
|
429
|
-
var whatsappUrl = "https://wa.me/".concat(whatsappPhone, "?text=").concat(message);
|
|
430
|
-
// Open WhatsApp in new tab
|
|
431
|
-
window.open(whatsappUrl, '_blank');
|
|
432
|
-
}, [whatsappIntegration, whatsappPhone, fields, formValues, validateField]);
|
|
565
|
+
}, [parsedFields, validateField, formValues]);
|
|
433
566
|
// Handle form submission
|
|
434
567
|
var handleSubmit = (0, react_1.useCallback)(function (e) { return __awaiter(void 0, void 0, void 0, function () {
|
|
435
|
-
var allTouched,
|
|
568
|
+
var allTouched, isValid, firstErrorField, element, message, cleanPhone, whatsappUrl, error_1;
|
|
436
569
|
return __generator(this, function (_a) {
|
|
437
570
|
switch (_a.label) {
|
|
438
571
|
case 0:
|
|
439
572
|
e.preventDefault();
|
|
440
573
|
allTouched = {};
|
|
441
|
-
|
|
574
|
+
parsedFields.forEach(function (field) {
|
|
442
575
|
allTouched[field.name] = true;
|
|
443
576
|
});
|
|
444
577
|
setTouched(allTouched);
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
newErrors[field.name] = error;
|
|
452
|
-
hasErrors = true;
|
|
578
|
+
isValid = validateForm();
|
|
579
|
+
if (!isValid) {
|
|
580
|
+
firstErrorField = Object.keys(errors)[0];
|
|
581
|
+
if (firstErrorField) {
|
|
582
|
+
element = document.getElementById("form-field-".concat(firstErrorField));
|
|
583
|
+
element === null || element === void 0 ? void 0 : element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
453
584
|
}
|
|
454
|
-
});
|
|
455
|
-
setErrors(newErrors);
|
|
456
|
-
if (hasErrors)
|
|
457
585
|
return [2 /*return*/];
|
|
458
|
-
|
|
586
|
+
}
|
|
587
|
+
// Get form data and submit
|
|
459
588
|
setIsSubmitting(true);
|
|
460
589
|
_a.label = 1;
|
|
461
590
|
case 1:
|
|
462
|
-
_a.trys.push([1,
|
|
463
|
-
return [
|
|
591
|
+
_a.trys.push([1, 7, 8, 9]);
|
|
592
|
+
if (!whatsappContact) return [3 /*break*/, 4];
|
|
593
|
+
message = formatWhatsAppMessage(formValues, parsedFields, whatsappHeader, whatsappFooter);
|
|
594
|
+
cleanPhone = whatsappContact.replace(/[\s+\-()]/g, '');
|
|
595
|
+
whatsappUrl = "https://wa.me/".concat(cleanPhone, "?text=").concat(message);
|
|
596
|
+
window.open(whatsappUrl, '_blank');
|
|
597
|
+
if (!onSubmit) return [3 /*break*/, 3];
|
|
598
|
+
return [4 /*yield*/, onSubmit(formValues, true)];
|
|
464
599
|
case 2:
|
|
465
600
|
_a.sent();
|
|
466
|
-
|
|
467
|
-
case 3:
|
|
468
|
-
error_2 = _a.sent();
|
|
469
|
-
console.error('Form submission error:', error_2);
|
|
470
|
-
setErrors(function (prev) { return (__assign(__assign({}, prev), { _form: 'There was an error submitting the form. Please try again.' })); });
|
|
471
|
-
return [3 /*break*/, 5];
|
|
601
|
+
_a.label = 3;
|
|
602
|
+
case 3: return [3 /*break*/, 6];
|
|
472
603
|
case 4:
|
|
604
|
+
if (!onSubmit) return [3 /*break*/, 6];
|
|
605
|
+
return [4 /*yield*/, onSubmit(formValues, false)];
|
|
606
|
+
case 5:
|
|
607
|
+
_a.sent();
|
|
608
|
+
_a.label = 6;
|
|
609
|
+
case 6: return [3 /*break*/, 9];
|
|
610
|
+
case 7:
|
|
611
|
+
error_1 = _a.sent();
|
|
612
|
+
console.error('Form submission error:', error_1);
|
|
613
|
+
setErrors(function (prev) { return (__assign(__assign({}, prev), { _form: 'There was an error submitting the form. Please try again.' })); });
|
|
614
|
+
return [3 /*break*/, 9];
|
|
615
|
+
case 8:
|
|
473
616
|
setIsSubmitting(false);
|
|
474
617
|
return [7 /*endfinally*/];
|
|
475
|
-
case
|
|
618
|
+
case 9: return [2 /*return*/];
|
|
476
619
|
}
|
|
477
620
|
});
|
|
478
|
-
}); }, [
|
|
621
|
+
}); }, [parsedFields, validateForm, formValues, whatsappContact, whatsappHeader, whatsappFooter, onSubmit, errors]);
|
|
479
622
|
// Handle form reset
|
|
480
623
|
var handleReset = (0, react_1.useCallback)(function () {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
if (field.
|
|
485
|
-
|
|
486
|
-
}
|
|
487
|
-
else if (field.type === 'radio' && ((_a = field.options) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
488
|
-
resetValues[field.name] = '';
|
|
624
|
+
// Reset to initial values
|
|
625
|
+
var initialValues = {};
|
|
626
|
+
parsedFields.forEach(function (field) {
|
|
627
|
+
if (field.value !== undefined) {
|
|
628
|
+
initialValues[field.name] = field.value;
|
|
489
629
|
}
|
|
490
|
-
else if (field.
|
|
491
|
-
|
|
630
|
+
else if (parsedDefaultValues[field.name] !== undefined) {
|
|
631
|
+
initialValues[field.name] = parsedDefaultValues[field.name];
|
|
492
632
|
}
|
|
493
633
|
else {
|
|
494
|
-
|
|
634
|
+
if (field.type === 'checkbox' && field.multiple) {
|
|
635
|
+
initialValues[field.name] = [];
|
|
636
|
+
}
|
|
637
|
+
else if (field.type === 'checkbox') {
|
|
638
|
+
initialValues[field.name] = false;
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
initialValues[field.name] = '';
|
|
642
|
+
}
|
|
495
643
|
}
|
|
496
644
|
});
|
|
497
|
-
setFormValues(
|
|
645
|
+
setFormValues(initialValues);
|
|
498
646
|
setErrors({});
|
|
499
647
|
setTouched({});
|
|
500
|
-
|
|
501
|
-
}, [fields]);
|
|
648
|
+
}, [parsedFields, parsedDefaultValues]);
|
|
502
649
|
// Get field status for Input component
|
|
503
650
|
var getFieldStatus = (0, react_1.useCallback)(function (fieldName) {
|
|
504
651
|
var error = errors[fieldName];
|
|
505
652
|
var isTouched = touched[fieldName];
|
|
506
|
-
var value = formValues[fieldName];
|
|
507
653
|
if (error)
|
|
508
|
-
return '
|
|
509
|
-
if (isTouched && !error &&
|
|
654
|
+
return 'danger';
|
|
655
|
+
if (isTouched && !error && formValues[fieldName] !== '') {
|
|
510
656
|
return 'success';
|
|
511
657
|
}
|
|
512
|
-
return
|
|
658
|
+
return undefined;
|
|
513
659
|
}, [errors, touched, formValues]);
|
|
514
|
-
//
|
|
515
|
-
var
|
|
516
|
-
if
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
660
|
+
// Check if form is valid for submission
|
|
661
|
+
var isFormValid = (0, react_1.useMemo)(function () {
|
|
662
|
+
// Check if any required fields are empty
|
|
663
|
+
var hasEmptyRequiredFields = parsedFields.some(function (field) {
|
|
664
|
+
if (!field.required)
|
|
665
|
+
return false;
|
|
666
|
+
var value = formValues[field.name];
|
|
667
|
+
if (field.type === 'checkbox' && field.multiple) {
|
|
668
|
+
return !Array.isArray(value) || value.length === 0;
|
|
523
669
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
670
|
+
if (field.type === 'checkbox') {
|
|
671
|
+
return value === false;
|
|
672
|
+
}
|
|
673
|
+
return !value || value === '';
|
|
674
|
+
});
|
|
675
|
+
// Check if there are any validation errors
|
|
676
|
+
var hasValidationErrors = Object.keys(errors).length > 0;
|
|
677
|
+
return !hasEmptyRequiredFields && !hasValidationErrors;
|
|
678
|
+
}, [parsedFields, formValues, errors]);
|
|
679
|
+
// Submit button disabled state
|
|
680
|
+
var isSubmitDisabled = isSubmitting || isLoading || !isFormValid;
|
|
681
|
+
// Check if WhatsApp is configured
|
|
682
|
+
var hasWhatsApp = !!whatsappContact;
|
|
683
|
+
// Render field based on type - FIXED
|
|
528
684
|
var renderField = (0, react_1.useCallback)(function (field) {
|
|
529
|
-
var _a, _b, _c, _d, _e
|
|
530
|
-
var value = (_a = formValues[field.name]) !== null && _a !== void 0 ? _a : '';
|
|
685
|
+
var _a, _b, _c, _d, _e;
|
|
531
686
|
var status = getFieldStatus(field.name);
|
|
532
687
|
var error = errors[field.name];
|
|
533
688
|
var isTouched = touched[field.name];
|
|
534
689
|
var showError = error && isTouched;
|
|
690
|
+
var value = formValues[field.name];
|
|
535
691
|
// Field wrapper classes
|
|
536
|
-
var wrapperClass = "
|
|
692
|
+
var wrapperClass = "col min-w-200 field ".concat(showError ? 'field-error' : '').trim();
|
|
537
693
|
// Helper text (error takes priority)
|
|
538
694
|
var helperText = showError ? error : field.helperText;
|
|
539
|
-
|
|
695
|
+
// Generate unique ID for the input
|
|
696
|
+
var inputId = ((_a = field.inputProps) === null || _a === void 0 ? void 0 : _a.id) || "form-field-".concat(field.name);
|
|
540
697
|
// Base props for Input component
|
|
541
|
-
var baseProps = __assign({ id:
|
|
698
|
+
var baseProps = __assign({ id: inputId, name: field.name, label: field.label, placeholder: field.placeholder, helperText: helperText, disabled: field.disabled || isLoading, fullWidth: fullWidth }, field.inputProps);
|
|
699
|
+
// Only add status if it's not undefined
|
|
700
|
+
if (status !== undefined) {
|
|
701
|
+
baseProps.status = status;
|
|
702
|
+
}
|
|
542
703
|
// Render based on field type
|
|
543
704
|
switch (field.type) {
|
|
544
705
|
case 'checkbox':
|
|
545
|
-
if ((
|
|
706
|
+
if ((_b = field.options) === null || _b === void 0 ? void 0 : _b.length) {
|
|
546
707
|
// Multiple checkboxes (checkbox group)
|
|
547
|
-
|
|
548
|
-
|
|
708
|
+
var checkedValues_1 = Array.isArray(value) ? value : [];
|
|
709
|
+
return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
|
|
710
|
+
field.label && (react_1.default.createElement("div", { className: "form-label", style: { marginBottom: '0.5rem' } },
|
|
549
711
|
react_1.default.createElement(Text_1.default, { text: field.label + (field.required ? ' *' : ''), size: "sm", color: "text", bold: true }))),
|
|
550
712
|
react_1.default.createElement(Flex_1.default, { direction: "column", gap: "0.5rem" }, field.options.map(function (option, index) {
|
|
551
|
-
var isChecked =
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
if (checked) {
|
|
558
|
-
handleFieldChange(field.name, __spreadArray(__spreadArray([], currentValues, true), [option.value], false));
|
|
559
|
-
}
|
|
560
|
-
else {
|
|
561
|
-
handleFieldChange(field.name, currentValues.filter(function (v) { return v !== option.value; }));
|
|
562
|
-
}
|
|
713
|
+
var isChecked = checkedValues_1.includes(option.value);
|
|
714
|
+
return (react_1.default.createElement(FormCheckbox, { key: "".concat(field.name, "_").concat(index), id: "".concat(inputId, "_").concat(index), label: option.label, checked: isChecked, onChange: function (checked) {
|
|
715
|
+
if (checked) {
|
|
716
|
+
// Add value to array
|
|
717
|
+
var newValues = __spreadArray(__spreadArray([], checkedValues_1, true), [option.value], false);
|
|
718
|
+
handleFieldChange(field.name, newValues);
|
|
563
719
|
}
|
|
564
720
|
else {
|
|
565
|
-
|
|
721
|
+
// Remove value from array
|
|
722
|
+
var newValues = checkedValues_1.filter(function (v) { return v !== option.value; });
|
|
723
|
+
handleFieldChange(field.name, newValues);
|
|
566
724
|
}
|
|
567
725
|
}, disabled: field.disabled || option.disabled || isLoading, required: field.required && index === 0, value: option.value }));
|
|
568
726
|
}))));
|
|
569
727
|
}
|
|
570
728
|
else {
|
|
571
729
|
// Single checkbox (boolean)
|
|
572
|
-
return (react_1.default.createElement(
|
|
573
|
-
react_1.default.createElement(FormCheckbox, { label: field.label, checked: !!value, onChange: function (checked) { return handleFieldChange(field.name, checked); }, disabled: field.disabled || isLoading, required: field.required, id:
|
|
730
|
+
return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
|
|
731
|
+
react_1.default.createElement(FormCheckbox, { label: field.label, checked: !!value, onChange: function (checked) { return handleFieldChange(field.name, checked); }, disabled: field.disabled || isLoading, required: field.required, id: inputId })));
|
|
574
732
|
}
|
|
575
733
|
case 'radio':
|
|
576
|
-
if (!((
|
|
734
|
+
if (!((_c = field.options) === null || _c === void 0 ? void 0 : _c.length))
|
|
577
735
|
return null;
|
|
578
|
-
return (react_1.default.createElement(
|
|
579
|
-
field.label && (react_1.default.createElement("div", { className: "
|
|
736
|
+
return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
|
|
737
|
+
field.label && (react_1.default.createElement("div", { className: "form-label", style: { marginBottom: '0.5rem' } },
|
|
580
738
|
react_1.default.createElement(Text_1.default, { text: field.label + (field.required ? ' *' : ''), size: "sm", color: "text", bold: true }))),
|
|
581
|
-
react_1.default.createElement(Flex_1.default, { direction: "column", gap: "0.5rem" }, field.options.map(function (option, index) { return (react_1.default.createElement(FormRadio, { key: "".concat(field.name, "_").concat(index), id: "".concat(
|
|
739
|
+
react_1.default.createElement(Flex_1.default, { direction: "column", gap: "0.5rem" }, field.options.map(function (option, index) { return (react_1.default.createElement(FormRadio, { key: "".concat(field.name, "_").concat(index), id: "".concat(inputId, "_").concat(index), label: option.label, checked: value === option.value, onChange: function () { return handleFieldChange(field.name, option.value); }, disabled: field.disabled || option.disabled || isLoading, required: field.required && index === 0, value: option.value })); }))));
|
|
582
740
|
case 'textarea':
|
|
583
|
-
return (react_1.default.createElement(
|
|
584
|
-
react_1.default.createElement(Input_1.default, { multiline: true, rows: ((
|
|
741
|
+
return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
|
|
742
|
+
react_1.default.createElement(Input_1.default, __assign({ multiline: true, rows: ((_d = field.inputProps) === null || _d === void 0 ? void 0 : _d.rows) || 4, value: value || '', onChange: handleInputEventChange, onBlur: handleInputEventBlur }, baseProps))));
|
|
585
743
|
case 'select':
|
|
586
|
-
return (react_1.default.createElement(
|
|
587
|
-
react_1.default.createElement(Input_1.default, { select: true, options: ((
|
|
588
|
-
case 'password':
|
|
589
|
-
return (react_1.default.createElement(Div_1.default, { key: field.name, className: wrapperClass },
|
|
590
|
-
react_1.default.createElement(Input_1.default, { type: showPassword[field.name] ? 'text' : 'password', value: value, onChange: function (e) { return handleFieldChange(field.name, e.target.value); }, onBlur: function () { return handleFieldBlur(field.name); }, endIcon: react_1.default.createElement(PasswordToggle, { isVisible: !!showPassword[field.name], onToggle: function () { return togglePasswordVisibility(field.name); }, disabled: field.disabled || isLoading }) })));
|
|
744
|
+
return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
|
|
745
|
+
react_1.default.createElement(Input_1.default, __assign({ select: true, options: ((_e = field.options) === null || _e === void 0 ? void 0 : _e.map(function (opt) { return ({ text: opt.label, value: opt.value }); })) || [], value: value || '', onChange: handleInputEventChange, onBlur: handleInputEventBlur }, baseProps))));
|
|
591
746
|
default:
|
|
592
|
-
// text, email, number, tel, date, file
|
|
593
|
-
return (react_1.default.createElement(
|
|
594
|
-
react_1.default.createElement(Input_1.default, { type: field.type, value: value, onChange:
|
|
747
|
+
// text, email, number, tel, date, file, password
|
|
748
|
+
return (react_1.default.createElement("div", { key: field.name, className: wrapperClass },
|
|
749
|
+
react_1.default.createElement(Input_1.default, __assign({ type: field.type, value: value || '', onChange: handleInputEventChange, onBlur: handleInputEventBlur }, baseProps))));
|
|
595
750
|
}
|
|
596
|
-
}, [
|
|
597
|
-
//
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
return value === false;
|
|
612
|
-
}
|
|
613
|
-
return value === undefined || value === null || value === '';
|
|
614
|
-
});
|
|
615
|
-
}, [fields, formValues]);
|
|
616
|
-
// Submit button disabled state
|
|
617
|
-
var isSubmitDisabled = isSubmitting || isLoading || (!isFormValid && hasEmptyRequiredFields);
|
|
618
|
-
// WhatsApp button disabled state
|
|
619
|
-
var isWhatsAppDisabled = isSubmitDisabled || !whatsappPhone;
|
|
620
|
-
// Layout container
|
|
621
|
-
var LayoutContainer = (0, react_1.useMemo)(function () {
|
|
622
|
-
if (layout === 'grid') {
|
|
623
|
-
return function (_a) {
|
|
624
|
-
var children = _a.children;
|
|
625
|
-
return (react_1.default.createElement("div", { className: "funui_form-grid", style: { display: 'grid', gap: gap, gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))' } }, children));
|
|
626
|
-
};
|
|
627
|
-
}
|
|
628
|
-
else if (layout === 'horizontal') {
|
|
629
|
-
return function (_a) {
|
|
630
|
-
var children = _a.children;
|
|
631
|
-
return (react_1.default.createElement(Flex_1.default, { gap: gap, wrap: "wrap" }, children));
|
|
632
|
-
};
|
|
633
|
-
}
|
|
634
|
-
else {
|
|
635
|
-
// vertical layout (default)
|
|
636
|
-
return function (_a) {
|
|
637
|
-
var children = _a.children;
|
|
638
|
-
return (react_1.default.createElement(Flex_1.default, { direction: "column", gap: gap }, children));
|
|
639
|
-
};
|
|
640
|
-
}
|
|
641
|
-
}, [layout, gap]);
|
|
642
|
-
return (react_1.default.createElement("form", { className: "funui_form ".concat(className), onSubmit: handleSubmit, onReset: handleReset, style: { width: '100%' } },
|
|
643
|
-
errors._form && (react_1.default.createElement(Div_1.default, { className: "funui_form-error", style: { marginBottom: '1rem' } },
|
|
644
|
-
react_1.default.createElement(Flex_1.default, { gap: "0.5rem", alignItems: "center" },
|
|
645
|
-
react_1.default.createElement(pi_1.PiWarningCircle, { className: "text-error", size: 20 }),
|
|
646
|
-
react_1.default.createElement(Text_1.default, { text: errors._form, size: "sm", color: "error", bold: true })))),
|
|
647
|
-
(whatsappIntegration === null || whatsappIntegration === void 0 ? void 0 : whatsappIntegration.enabled) && !whatsappPhone && (react_1.default.createElement(Div_1.default, { className: "funui_form-warning", style: { marginBottom: '1rem', padding: '0.75rem', backgroundColor: 'var(--warning-light)', borderRadius: '0.375rem' } },
|
|
648
|
-
react_1.default.createElement(Flex_1.default, { gap: "0.5rem", alignItems: "center" },
|
|
649
|
-
react_1.default.createElement(pi_1.PiWarningCircle, { className: "text-warning", size: 20 }),
|
|
650
|
-
react_1.default.createElement(Text_1.default, { text: "WhatsApp phone number is not configured. Please provide a valid phone number.", size: "sm", color: "warning" })))),
|
|
651
|
-
react_1.default.createElement(LayoutContainer, null, fields.map(renderField)),
|
|
652
|
-
react_1.default.createElement(Flex_1.default, { direction: "column", gap: "1rem", style: { marginTop: '2rem' } },
|
|
653
|
-
react_1.default.createElement(Flex_1.default, { gap: "1rem", alignItems: "center", justify: "space-between", wrap: "wrap" },
|
|
654
|
-
showReset && (react_1.default.createElement(Button_1.default, { type: "reset", text: resetText, bg: "light", color: "text", disabled: isSubmitting || isLoading, funcss: "funui_form-reset-btn" })),
|
|
655
|
-
react_1.default.createElement(Button_1.default, { type: "submit", text: submitText, bg: "primary", color: "white", raised: true, startIcon: react_1.default.createElement(pi_1.PiPaperPlaneTilt, null), disabled: isSubmitDisabled, isLoading: isSubmitting || isLoading, funcss: "funui_form-submit-btn" })),
|
|
656
|
-
(whatsappIntegration === null || whatsappIntegration === void 0 ? void 0 : whatsappIntegration.enabled) && whatsappPhone && (react_1.default.createElement(WhatsAppButton, { onClick: handleWhatsAppSubmit, disabled: isWhatsAppDisabled, text: "Send via WhatsApp" })))));
|
|
751
|
+
}, [errors, touched, formValues, isLoading, getFieldStatus, handleFieldChange, handleInputEventChange, handleInputEventBlur, fullWidth]);
|
|
752
|
+
// Don't render if no fields are configured
|
|
753
|
+
if (parsedFields.length === 0) {
|
|
754
|
+
console.warn('Form: No fields configured. Please provide fields prop or configure via theme.');
|
|
755
|
+
return null;
|
|
756
|
+
}
|
|
757
|
+
return (react_1.default.createElement("div", { className: "form-wrapper ".concat(centered ? 'center' : '', " ").concat(className), style: { width: "100%", maxWidth: width || "450px" } },
|
|
758
|
+
title && (react_1.default.createElement("div", { className: "form-header", style: { marginBottom: '2rem' } },
|
|
759
|
+
react_1.default.createElement(Text_1.default, { text: title, size: titleSize || "3xl", color: titleColor || "", block: true }),
|
|
760
|
+
description && (react_1.default.createElement(Text_1.default, { article: true, size: descriptionSize || "sm", color: descriptionColor || "" },
|
|
761
|
+
react_1.default.createElement("div", { className: "article text-sm", dangerouslySetInnerHTML: { __html: description } }))))),
|
|
762
|
+
react_1.default.createElement("form", { className: "form", onSubmit: handleSubmit, style: { width: '100%' } },
|
|
763
|
+
react_1.default.createElement(Flex_1.default, { direction: layout === 'horizontal' ? 'row' : 'column', gap: gap, width: '100%' }, parsedFields.map(renderField)),
|
|
764
|
+
react_1.default.createElement(Flex_1.default, { direction: "column", gap: "1rem", style: { marginTop: '2rem', width: fullWidth ? '100%' : undefined } },
|
|
765
|
+
react_1.default.createElement(Button_1.default, { type: "submit", text: hasWhatsApp ? "Send via WhatsApp" : submitText, bg: submitBg || "primary", raised: true, prefix: submitPrefix || hasWhatsApp ? react_1.default.createElement(pi_1.PiWhatsappLogo, null) : react_1.default.createElement(pi_1.PiPaperPlaneTilt, null), suffix: submitSuffix, disabled: isSubmitDisabled, isLoading: isSubmitting || isLoading, fullWidth: fullWidth })))));
|
|
657
766
|
};
|
|
658
767
|
exports.default = Form;
|