funuicss 3.8.6 → 3.8.8

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.
@@ -0,0 +1,658 @@
1
+ "use strict";
2
+ 'use client';
3
+ var __assign = (this && this.__assign) || function () {
4
+ __assign = Object.assign || function(t) {
5
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
6
+ s = arguments[i];
7
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
8
+ t[p] = s[p];
9
+ }
10
+ return t;
11
+ };
12
+ return __assign.apply(this, arguments);
13
+ };
14
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ var desc = Object.getOwnPropertyDescriptor(m, k);
17
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
18
+ desc = { enumerable: true, get: function() { return m[k]; } };
19
+ }
20
+ Object.defineProperty(o, k2, desc);
21
+ }) : (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ o[k2] = m[k];
24
+ }));
25
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
26
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
27
+ }) : function(o, v) {
28
+ o["default"] = v;
29
+ });
30
+ var __importStar = (this && this.__importStar) || (function () {
31
+ var ownKeys = function(o) {
32
+ ownKeys = Object.getOwnPropertyNames || function (o) {
33
+ var ar = [];
34
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
35
+ return ar;
36
+ };
37
+ return ownKeys(o);
38
+ };
39
+ return function (mod) {
40
+ if (mod && mod.__esModule) return mod;
41
+ var result = {};
42
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
43
+ __setModuleDefault(result, mod);
44
+ return result;
45
+ };
46
+ })();
47
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
48
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
49
+ return new (P || (P = Promise))(function (resolve, reject) {
50
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
51
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
52
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
53
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
54
+ });
55
+ };
56
+ var __generator = (this && this.__generator) || function (thisArg, body) {
57
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
58
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
59
+ function verb(n) { return function (v) { return step([n, v]); }; }
60
+ function step(op) {
61
+ if (f) throw new TypeError("Generator is already executing.");
62
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
63
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
64
+ if (y = 0, t) op = [op[0] & 2, t.value];
65
+ switch (op[0]) {
66
+ case 0: case 1: t = op; break;
67
+ case 4: _.label++; return { value: op[1], done: false };
68
+ case 5: _.label++; y = op[1]; op = [0]; continue;
69
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
70
+ default:
71
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
72
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
73
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
74
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
75
+ if (t[2]) _.ops.pop();
76
+ _.trys.pop(); continue;
77
+ }
78
+ op = body.call(thisArg, _);
79
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
80
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
81
+ }
82
+ };
83
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
84
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
85
+ if (ar || !(i in from)) {
86
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
87
+ ar[i] = from[i];
88
+ }
89
+ }
90
+ return to.concat(ar || Array.prototype.slice.call(from));
91
+ };
92
+ var __importDefault = (this && this.__importDefault) || function (mod) {
93
+ return (mod && mod.__esModule) ? mod : { "default": mod };
94
+ };
95
+ Object.defineProperty(exports, "__esModule", { value: true });
96
+ var react_1 = __importStar(require("react"));
97
+ var Button_1 = __importDefault(require("../button/Button"));
98
+ var Input_1 = __importDefault(require("../input/Input"));
99
+ var Flex_1 = __importDefault(require("../flex/Flex"));
100
+ var Div_1 = __importDefault(require("../div/Div"));
101
+ var Text_1 = __importDefault(require("../text/Text"));
102
+ var pi_1 = require("react-icons/pi");
103
+ // Custom Checkbox Component
104
+ var FormCheckbox = function (_a) {
105
+ var label = _a.label, checked = _a.checked, onChange = _a.onChange, disabled = _a.disabled, required = _a.required, value = _a.value, id = _a.id;
106
+ return (react_1.default.createElement("label", { className: "funui_form-checkbox", style: {
107
+ display: 'flex',
108
+ alignItems: 'center',
109
+ gap: '0.5rem',
110
+ cursor: disabled ? 'not-allowed' : 'pointer',
111
+ userSelect: 'none',
112
+ width: 'fit-content',
113
+ } },
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: { display: 'none' } }),
115
+ react_1.default.createElement("div", { className: "funui_form-checkbox-box", style: {
116
+ width: '1.25rem',
117
+ height: '1.25rem',
118
+ border: checked ? '2px solid var(--primary)' : '2px solid var(--border)',
119
+ borderRadius: '0.25rem',
120
+ backgroundColor: checked ? 'var(--primary)' : 'transparent',
121
+ position: 'relative',
122
+ transition: 'all 0.2s ease',
123
+ display: 'flex',
124
+ alignItems: 'center',
125
+ justifyContent: 'center',
126
+ flexShrink: 0,
127
+ } }, checked && (react_1.default.createElement("div", { style: {
128
+ width: '0.75rem',
129
+ height: '0.75rem',
130
+ backgroundColor: 'white',
131
+ borderRadius: '0.125rem',
132
+ } }))),
133
+ label && (react_1.default.createElement("span", { className: "funui_form-checkbox-label", style: { fontSize: '0.875rem' } },
134
+ label,
135
+ required && ' *'))));
136
+ };
137
+ // Custom Radio Component
138
+ var FormRadio = function (_a) {
139
+ var label = _a.label, checked = _a.checked, onChange = _a.onChange, disabled = _a.disabled, required = _a.required, value = _a.value, id = _a.id;
140
+ return (react_1.default.createElement("label", { className: "funui_form-radio", style: {
141
+ display: 'flex',
142
+ alignItems: 'center',
143
+ gap: '0.5rem',
144
+ cursor: disabled ? 'not-allowed' : 'pointer',
145
+ userSelect: 'none',
146
+ width: 'fit-content',
147
+ } },
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: { display: 'none' } }),
149
+ react_1.default.createElement("div", { className: "funui_form-radio-circle", style: {
150
+ width: '1.25rem',
151
+ height: '1.25rem',
152
+ border: checked ? '2px solid var(--primary)' : '2px solid var(--border)',
153
+ borderRadius: '50%',
154
+ backgroundColor: 'transparent',
155
+ position: 'relative',
156
+ transition: 'all 0.2s ease',
157
+ display: 'flex',
158
+ alignItems: 'center',
159
+ justifyContent: 'center',
160
+ flexShrink: 0,
161
+ } }, checked && (react_1.default.createElement("div", { style: {
162
+ width: '0.75rem',
163
+ height: '0.75rem',
164
+ backgroundColor: 'var(--primary)',
165
+ borderRadius: '50%',
166
+ } }))),
167
+ label && (react_1.default.createElement("span", { className: "funui_form-radio-label", style: { fontSize: '0.875rem' } },
168
+ label,
169
+ required && ' *'))));
170
+ };
171
+ // Password Toggle
172
+ var PasswordToggle = function (_a) {
173
+ var isVisible = _a.isVisible, onToggle = _a.onToggle, disabled = _a.disabled;
174
+ return (react_1.default.createElement("button", { type: "button", onClick: onToggle, disabled: disabled, className: "funui_form-password-toggle", style: {
175
+ background: 'none',
176
+ border: 'none',
177
+ padding: '0.5rem',
178
+ cursor: disabled ? 'not-allowed' : 'pointer',
179
+ opacity: disabled ? 0.5 : 1,
180
+ display: 'flex',
181
+ alignItems: 'center',
182
+ justifyContent: 'center',
183
+ }, "aria-label": isVisible ? 'Hide password' : 'Show password' }, isVisible ? react_1.default.createElement(pi_1.PiEyeSlash, { size: 18 }) : react_1.default.createElement(pi_1.PiEye, { size: 18 })));
184
+ };
185
+ // WhatsApp Button Component
186
+ var WhatsAppButton = function (_a) {
187
+ var onClick = _a.onClick, disabled = _a.disabled, _b = _a.text, text = _b === void 0 ? 'Send via WhatsApp' : _b;
188
+ return (react_1.default.createElement(Button_1.default, { type: "button", text: text, bg: "#25D366", color: "white", raised: true, startIcon: react_1.default.createElement(pi_1.PiWhatsappLogo, null), disabled: disabled, onClick: onClick, funcss: "funui_form-whatsapp-button" }));
189
+ };
190
+ // Function to format WhatsApp message
191
+ var formatWhatsAppMessage = function (values, fields, headerMessage, footerMessage) {
192
+ var fieldLines = fields
193
+ .filter(function (field) { return values[field.name] !== undefined && values[field.name] !== null && values[field.name] !== ''; })
194
+ .map(function (field) {
195
+ var value = values[field.name];
196
+ var displayValue = value;
197
+ // Format array values (for multiple checkboxes)
198
+ if (Array.isArray(value)) {
199
+ displayValue = value.join(', ');
200
+ }
201
+ // Format checkbox values
202
+ if (field.type === 'checkbox' && !field.multiple) {
203
+ displayValue = value ? 'Yes' : 'No';
204
+ }
205
+ // Format select/radio values
206
+ if ((field.type === 'select' || field.type === 'radio') && field.options) {
207
+ var option = field.options.find(function (opt) { return opt.value === value; });
208
+ displayValue = option ? option.label : value;
209
+ }
210
+ return "*".concat(field.label || field.name, ":* ").concat(displayValue);
211
+ })
212
+ .join('\n');
213
+ var message = '';
214
+ if (headerMessage) {
215
+ message += "".concat(headerMessage, "\n\n");
216
+ }
217
+ message += fieldLines;
218
+ if (footerMessage) {
219
+ message += "\n\n".concat(footerMessage);
220
+ }
221
+ return encodeURIComponent(message);
222
+ };
223
+ // Main Form Component
224
+ var Form = function (_a) {
225
+ var fields = _a.fields, onSubmit = _a.onSubmit, _b = _a.defaultValues, defaultValues = _b === void 0 ? {} : _b, _c = _a.submitText, submitText = _c === void 0 ? 'Submit' : _c, _d = _a.resetText, resetText = _d === void 0 ? 'Reset' : _d, _e = _a.showReset, showReset = _e === void 0 ? true : _e, _f = _a.isLoading, isLoading = _f === void 0 ? false : _f, _g = _a.className, className = _g === void 0 ? '' : _g, _h = _a.layout, layout = _h === void 0 ? 'vertical' : _h, _j = _a.gap, gap = _j === void 0 ? '1.5rem' : _j, whatsappIntegration = _a.whatsappIntegration;
226
+ // State management
227
+ var _k = (0, react_1.useState)({}), formValues = _k[0], setFormValues = _k[1];
228
+ var _l = (0, react_1.useState)({}), errors = _l[0], setErrors = _l[1];
229
+ var _m = (0, react_1.useState)({}), touched = _m[0], setTouched = _m[1];
230
+ var _o = (0, react_1.useState)({}), showPassword = _o[0], setShowPassword = _o[1];
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 () {
235
+ var initialValues = {};
236
+ fields.forEach(function (field) {
237
+ var _a, _b;
238
+ // Priority: field.value > defaultValues > default based on type
239
+ if (field.value !== undefined) {
240
+ initialValues[field.name] = field.value;
241
+ }
242
+ else if (defaultValues[field.name] !== undefined) {
243
+ initialValues[field.name] = defaultValues[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] = '';
253
+ }
254
+ else {
255
+ initialValues[field.name] = '';
256
+ }
257
+ // Initialize password visibility
258
+ if (field.type === 'password') {
259
+ setShowPassword(function (prev) {
260
+ var _a;
261
+ return (__assign(__assign({}, prev), (_a = {}, _a[field.name] = false, _a)));
262
+ });
263
+ }
264
+ });
265
+ setFormValues(initialValues);
266
+ }, [fields, defaultValues]);
267
+ // Initialize WhatsApp phone number
268
+ (0, react_1.useEffect)(function () {
269
+ if (whatsappIntegration === null || whatsappIntegration === void 0 ? void 0 : whatsappIntegration.phoneNumber) {
270
+ // Clean the phone number (remove +, spaces, etc.)
271
+ var cleanPhone = whatsappIntegration.phoneNumber.replace(/[\s+\-()]/g, '');
272
+ setWhatsappPhone(cleanPhone);
273
+ }
274
+ }, [whatsappIntegration]);
275
+ // Validate a single field
276
+ var validateField = (0, react_1.useCallback)(function (field, value) {
277
+ var _a, _b, _c, _d, _e;
278
+ // Required validation
279
+ if (field.required) {
280
+ if (value === undefined || value === null || value === '') {
281
+ return "".concat(field.label || field.name, " is required");
282
+ }
283
+ if (field.type === 'checkbox' && field.multiple && Array.isArray(value) && value.length === 0) {
284
+ return "".concat(field.label || field.name, " is required");
285
+ }
286
+ if (field.type === 'checkbox' && !field.multiple && value === false) {
287
+ return "".concat(field.label || field.name, " is required");
288
+ }
289
+ }
290
+ // Type-specific validations
291
+ if (value && value !== '') {
292
+ // Email validation
293
+ if (field.type === 'email') {
294
+ var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
295
+ if (!emailRegex.test(value)) {
296
+ return 'Please enter a valid email address';
297
+ }
298
+ }
299
+ // Number validation
300
+ if (field.type === 'number') {
301
+ var numValue = parseFloat(value);
302
+ if (isNaN(numValue)) {
303
+ return 'Please enter a valid number';
304
+ }
305
+ var min = (_a = field.inputProps) === null || _a === void 0 ? void 0 : _a.min;
306
+ var max = (_b = field.inputProps) === null || _b === void 0 ? void 0 : _b.max;
307
+ if (min !== undefined && numValue < parseFloat(min.toString())) {
308
+ return "Minimum value is ".concat(min);
309
+ }
310
+ if (max !== undefined && numValue > parseFloat(max.toString())) {
311
+ return "Maximum value is ".concat(max);
312
+ }
313
+ }
314
+ // Phone validation (basic)
315
+ if (field.type === 'tel') {
316
+ var phoneRegex = /^[\+]?[1-9][\d]{0,17}$/;
317
+ if (!phoneRegex.test(value.replace(/[\s+\-()]/g, ''))) {
318
+ return 'Please enter a valid phone number';
319
+ }
320
+ }
321
+ // Length validation
322
+ if (typeof value === 'string') {
323
+ var minLength = (_c = field.inputProps) === null || _c === void 0 ? void 0 : _c.minLength;
324
+ var maxLength = (_d = field.inputProps) === null || _d === void 0 ? void 0 : _d.maxLength;
325
+ if (minLength && value.length < minLength) {
326
+ return "Minimum ".concat(minLength, " characters required");
327
+ }
328
+ if (maxLength && value.length > maxLength) {
329
+ return "Maximum ".concat(maxLength, " characters allowed");
330
+ }
331
+ }
332
+ // Pattern validation if provided
333
+ if ((_e = field.inputProps) === null || _e === void 0 ? void 0 : _e.pattern) {
334
+ var regex = new RegExp(field.inputProps.pattern);
335
+ if (!regex.test(value)) {
336
+ return 'Invalid format';
337
+ }
338
+ }
339
+ }
340
+ return null;
341
+ }, []);
342
+ // Handle field change
343
+ var handleFieldChange = (0, react_1.useCallback)(function (fieldName, value) {
344
+ var field = fields.find(function (f) { return f.name === fieldName; });
345
+ if (!field)
346
+ return;
347
+ setFormValues(function (prev) {
348
+ var _a;
349
+ var newValues = __assign(__assign({}, prev), (_a = {}, _a[fieldName] = value, _a));
350
+ // Validate on change if field has been touched
351
+ if (touched[fieldName]) {
352
+ var error_1 = validateField(field, value);
353
+ setErrors(function (prevErrors) {
354
+ var _a;
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;
366
+ });
367
+ }, [fields, touched, validateField]);
368
+ // Handle field blur
369
+ var handleFieldBlur = (0, react_1.useCallback)(function (fieldName) {
370
+ var field = fields.find(function (f) { return f.name === fieldName; });
371
+ if (!field)
372
+ return;
373
+ setTouched(function (prev) {
374
+ var _a;
375
+ return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = true, _a)));
376
+ });
377
+ // Validate on blur
378
+ var value = formValues[fieldName];
379
+ var error = validateField(field, value);
380
+ setErrors(function (prev) {
381
+ var _a;
382
+ if (error) {
383
+ return __assign(__assign({}, prev), (_a = {}, _a[fieldName] = error, _a));
384
+ }
385
+ else {
386
+ var newErrors = __assign({}, prev);
387
+ delete newErrors[fieldName];
388
+ return newErrors;
389
+ }
390
+ });
391
+ }, [fields, formValues, validateField]);
392
+ // Toggle password visibility
393
+ var togglePasswordVisibility = (0, react_1.useCallback)(function (fieldName) {
394
+ setShowPassword(function (prev) {
395
+ var _a;
396
+ return (__assign(__assign({}, prev), (_a = {}, _a[fieldName] = !prev[fieldName], _a)));
397
+ });
398
+ }, []);
399
+ // Handle WhatsApp submission
400
+ var handleWhatsAppSubmit = (0, react_1.useCallback)(function () {
401
+ if (!(whatsappIntegration === null || whatsappIntegration === void 0 ? void 0 : whatsappIntegration.enabled) || !whatsappPhone) {
402
+ console.error('WhatsApp integration not properly configured');
403
+ return;
404
+ }
405
+ // Validate form before sending
406
+ var newErrors = {};
407
+ var hasErrors = false;
408
+ fields.forEach(function (field) {
409
+ var value = formValues[field.name];
410
+ var error = validateField(field, value);
411
+ if (error) {
412
+ newErrors[field.name] = error;
413
+ hasErrors = true;
414
+ }
415
+ });
416
+ setErrors(newErrors);
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]);
433
+ // Handle form submission
434
+ var handleSubmit = (0, react_1.useCallback)(function (e) { return __awaiter(void 0, void 0, void 0, function () {
435
+ var allTouched, newErrors, hasErrors, error_2;
436
+ return __generator(this, function (_a) {
437
+ switch (_a.label) {
438
+ case 0:
439
+ e.preventDefault();
440
+ allTouched = {};
441
+ fields.forEach(function (field) {
442
+ allTouched[field.name] = true;
443
+ });
444
+ setTouched(allTouched);
445
+ newErrors = {};
446
+ hasErrors = false;
447
+ fields.forEach(function (field) {
448
+ var value = formValues[field.name];
449
+ var error = validateField(field, value);
450
+ if (error) {
451
+ newErrors[field.name] = error;
452
+ hasErrors = true;
453
+ }
454
+ });
455
+ setErrors(newErrors);
456
+ if (hasErrors)
457
+ return [2 /*return*/];
458
+ // Submit
459
+ setIsSubmitting(true);
460
+ _a.label = 1;
461
+ case 1:
462
+ _a.trys.push([1, 3, 4, 5]);
463
+ return [4 /*yield*/, onSubmit(formValues)];
464
+ case 2:
465
+ _a.sent();
466
+ return [3 /*break*/, 5];
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];
472
+ case 4:
473
+ setIsSubmitting(false);
474
+ return [7 /*endfinally*/];
475
+ case 5: return [2 /*return*/];
476
+ }
477
+ });
478
+ }); }, [fields, formValues, validateField, onSubmit]);
479
+ // Handle form reset
480
+ var handleReset = (0, react_1.useCallback)(function () {
481
+ var resetValues = {};
482
+ fields.forEach(function (field) {
483
+ var _a, _b;
484
+ if (field.type === 'checkbox') {
485
+ resetValues[field.name] = field.multiple ? [] : false;
486
+ }
487
+ else if (field.type === 'radio' && ((_a = field.options) === null || _a === void 0 ? void 0 : _a.length)) {
488
+ resetValues[field.name] = '';
489
+ }
490
+ else if (field.type === 'select' && ((_b = field.options) === null || _b === void 0 ? void 0 : _b.length)) {
491
+ resetValues[field.name] = '';
492
+ }
493
+ else {
494
+ resetValues[field.name] = '';
495
+ }
496
+ });
497
+ setFormValues(resetValues);
498
+ setErrors({});
499
+ setTouched({});
500
+ setShowPassword({});
501
+ }, [fields]);
502
+ // Get field status for Input component
503
+ var getFieldStatus = (0, react_1.useCallback)(function (fieldName) {
504
+ var error = errors[fieldName];
505
+ var isTouched = touched[fieldName];
506
+ var value = formValues[fieldName];
507
+ if (error)
508
+ return 'error';
509
+ if (isTouched && !error && value && value !== '' && !(Array.isArray(value) && value.length === 0)) {
510
+ return 'success';
511
+ }
512
+ return 'default';
513
+ }, [errors, touched, formValues]);
514
+ // Get column class based on layout and column setting
515
+ var getColumnClass = (0, react_1.useCallback)(function (field) {
516
+ if (layout === 'grid') {
517
+ switch (field.column) {
518
+ case 'half': return 'funui_form-col-half';
519
+ case 'third': return 'funui_form-col-third';
520
+ case 'quarter': return 'funui_form-col-quarter';
521
+ case 'full':
522
+ default: return 'funui_form-col-full';
523
+ }
524
+ }
525
+ return '';
526
+ }, [layout]);
527
+ // Render field based on type
528
+ var renderField = (0, react_1.useCallback)(function (field) {
529
+ var _a, _b, _c, _d, _e, _f;
530
+ var value = (_a = formValues[field.name]) !== null && _a !== void 0 ? _a : '';
531
+ var status = getFieldStatus(field.name);
532
+ var error = errors[field.name];
533
+ var isTouched = touched[field.name];
534
+ var showError = error && isTouched;
535
+ // Field wrapper classes
536
+ var wrapperClass = "funui_form-field ".concat(getColumnClass(field), " ").concat(showError ? 'funui_form-field-error' : '').trim();
537
+ // Helper text (error takes priority)
538
+ var helperText = showError ? error : field.helperText;
539
+ var helperIcon = showError ? react_1.default.createElement(pi_1.PiWarningCircle, null) : status === 'success' ? react_1.default.createElement(pi_1.PiCheckCircle, null) : undefined;
540
+ // Base props for Input component
541
+ var baseProps = __assign({ id: ((_b = field.inputProps) === null || _b === void 0 ? void 0 : _b.id) || field.name, name: field.name, label: field.label, placeholder: field.placeholder, helperText: helperText, status: status, disabled: field.disabled || isLoading, fullWidth: true }, field.inputProps);
542
+ // Render based on field type
543
+ switch (field.type) {
544
+ case 'checkbox':
545
+ if ((_c = field.options) === null || _c === void 0 ? void 0 : _c.length) {
546
+ // Multiple checkboxes (checkbox group)
547
+ return (react_1.default.createElement(Div_1.default, { key: field.name, className: wrapperClass },
548
+ field.label && (react_1.default.createElement("div", { className: "funui_form-label", style: { marginBottom: '0.5rem' } },
549
+ react_1.default.createElement(Text_1.default, { text: field.label + (field.required ? ' *' : ''), size: "sm", color: "text", bold: true }))),
550
+ react_1.default.createElement(Flex_1.default, { direction: "column", gap: "0.5rem" }, field.options.map(function (option, index) {
551
+ var isChecked = field.multiple
552
+ ? Array.isArray(value) && value.includes(option.value)
553
+ : value === option.value;
554
+ return (react_1.default.createElement(FormCheckbox, { key: "".concat(field.name, "_").concat(index), id: "".concat(field.name, "_").concat(index), label: option.label, checked: !!isChecked, onChange: function (checked) {
555
+ if (field.multiple) {
556
+ var currentValues = Array.isArray(value) ? value : [];
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
+ }
563
+ }
564
+ else {
565
+ handleFieldChange(field.name, checked ? option.value : false);
566
+ }
567
+ }, disabled: field.disabled || option.disabled || isLoading, required: field.required && index === 0, value: option.value }));
568
+ }))));
569
+ }
570
+ else {
571
+ // Single checkbox (boolean)
572
+ return (react_1.default.createElement(Div_1.default, { key: field.name, className: wrapperClass },
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: field.name })));
574
+ }
575
+ case 'radio':
576
+ if (!((_d = field.options) === null || _d === void 0 ? void 0 : _d.length))
577
+ return null;
578
+ return (react_1.default.createElement(Div_1.default, { key: field.name, className: wrapperClass },
579
+ field.label && (react_1.default.createElement("div", { className: "funui_form-label", style: { marginBottom: '0.5rem' } },
580
+ 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(field.name, "_").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
+ case 'textarea':
583
+ return (react_1.default.createElement(Div_1.default, { key: field.name, className: wrapperClass },
584
+ react_1.default.createElement(Input_1.default, { multiline: true, rows: ((_e = field.inputProps) === null || _e === void 0 ? void 0 : _e.rows) || 4, value: value, onChange: function (e) { return handleFieldChange(field.name, e.target.value); }, onBlur: function () { return handleFieldBlur(field.name); } })));
585
+ case 'select':
586
+ return (react_1.default.createElement(Div_1.default, { key: field.name, className: wrapperClass },
587
+ react_1.default.createElement(Input_1.default, { select: true, options: ((_f = field.options) === null || _f === void 0 ? void 0 : _f.map(function (opt) { return ({ text: opt.label, value: opt.value }); })) || [], value: value, onChange: function (e) { return handleFieldChange(field.name, e.target.value); }, onBlur: function () { return handleFieldBlur(field.name); } })));
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 }) })));
591
+ default:
592
+ // text, email, number, tel, date, file
593
+ return (react_1.default.createElement(Div_1.default, { key: field.name, className: wrapperClass },
594
+ react_1.default.createElement(Input_1.default, { type: field.type, value: value, onChange: function (e) { return handleFieldChange(field.name, e.target.value); }, onBlur: function () { return handleFieldBlur(field.name); } })));
595
+ }
596
+ }, [formValues, errors, touched, showPassword, isLoading, getFieldStatus, getColumnClass, handleFieldChange, handleFieldBlur, togglePasswordVisibility]);
597
+ // Check if form is valid
598
+ var isFormValid = (0, react_1.useMemo)(function () {
599
+ return Object.keys(errors).length === 0;
600
+ }, [errors]);
601
+ // Check if form has empty required fields
602
+ var hasEmptyRequiredFields = (0, react_1.useMemo)(function () {
603
+ return fields.some(function (field) {
604
+ if (!field.required)
605
+ return false;
606
+ var value = formValues[field.name];
607
+ if (field.type === 'checkbox' && field.multiple) {
608
+ return !Array.isArray(value) || value.length === 0;
609
+ }
610
+ if (field.type === 'checkbox' && !field.multiple) {
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" })))));
657
+ };
658
+ exports.default = Form;