react-unique-dynamic-form
Version:
A reusable React library with Form, useForm hook, and Bootstrap-styled Modal component
1,393 lines (1,355 loc) • 44.2 kB
JavaScript
import React, { useState, useCallback } from 'react';
import PropTypes from 'prop-types';
function _arrayLikeToArray(r, a) {
(null == a || a > r.length) && (a = r.length);
for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e];
return n;
}
function _arrayWithHoles(r) {
if (Array.isArray(r)) return r;
}
function _arrayWithoutHoles(r) {
if (Array.isArray(r)) return _arrayLikeToArray(r);
}
function _assertThisInitialized(e) {
if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
return e;
}
function asyncGeneratorStep(n, t, e, r, o, a, c) {
try {
var i = n[a](c),
u = i.value;
} catch (n) {
return void e(n);
}
i.done ? t(u) : Promise.resolve(u).then(r, o);
}
function _asyncToGenerator(n) {
return function () {
var t = this,
e = arguments;
return new Promise(function (r, o) {
var a = n.apply(t, e);
function _next(n) {
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
}
function _throw(n) {
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
}
_next(void 0);
});
};
}
function _callSuper(t, o, e) {
return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e));
}
function _classCallCheck(a, n) {
if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function");
}
function _defineProperties(e, r) {
for (var t = 0; t < r.length; t++) {
var o = r[t];
o.enumerable = o.enumerable || false, o.configurable = true, "value" in o && (o.writable = true), Object.defineProperty(e, _toPropertyKey(o.key), o);
}
}
function _createClass(e, r, t) {
return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", {
writable: false
}), e;
}
function _defineProperty(e, r, t) {
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: true,
configurable: true,
writable: true
}) : e[r] = t, e;
}
function _getPrototypeOf(t) {
return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) {
return t.__proto__ || Object.getPrototypeOf(t);
}, _getPrototypeOf(t);
}
function _inherits(t, e) {
if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function");
t.prototype = Object.create(e && e.prototype, {
constructor: {
value: t,
writable: true,
configurable: true
}
}), Object.defineProperty(t, "prototype", {
writable: false
}), e && _setPrototypeOf(t, e);
}
function _isNativeReflectConstruct() {
try {
var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {}));
} catch (t) {}
return (_isNativeReflectConstruct = function () {
return !!t;
})();
}
function _iterableToArray(r) {
if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r);
}
function _iterableToArrayLimit(r, l) {
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
if (null != t) {
var e,
n,
i,
u,
a = [],
f = true,
o = false;
try {
if (i = (t = t.call(r)).next, 0 === l) {
if (Object(t) !== t) return;
f = !1;
} else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
} catch (r) {
o = true, n = r;
} finally {
try {
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
} finally {
if (o) throw n;
}
}
return a;
}
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}
function ownKeys(e, r) {
var t = Object.keys(e);
if (Object.getOwnPropertySymbols) {
var o = Object.getOwnPropertySymbols(e);
r && (o = o.filter(function (r) {
return Object.getOwnPropertyDescriptor(e, r).enumerable;
})), t.push.apply(t, o);
}
return t;
}
function _objectSpread2(e) {
for (var r = 1; r < arguments.length; r++) {
var t = null != arguments[r] ? arguments[r] : {};
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
_defineProperty(e, r, t[r]);
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
});
}
return e;
}
function _possibleConstructorReturn(t, e) {
if (e && ("object" == typeof e || "function" == typeof e)) return e;
if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined");
return _assertThisInitialized(t);
}
function _regeneratorRuntime() {
_regeneratorRuntime = function () {
return r;
};
var t,
r = {},
e = Object.prototype,
n = e.hasOwnProperty,
o = "function" == typeof Symbol ? Symbol : {},
i = o.iterator || "@@iterator",
a = o.asyncIterator || "@@asyncIterator",
u = o.toStringTag || "@@toStringTag";
function c(t, r, e, n) {
return Object.defineProperty(t, r, {
value: e,
enumerable: !n,
configurable: !n,
writable: !n
});
}
try {
c({}, "");
} catch (t) {
c = function (t, r, e) {
return t[r] = e;
};
}
function h(r, e, n, o) {
var i = e && e.prototype instanceof Generator ? e : Generator,
a = Object.create(i.prototype);
return c(a, "_invoke", function (r, e, n) {
var o = 1;
return function (i, a) {
if (3 === o) throw Error("Generator is already running");
if (4 === o) {
if ("throw" === i) throw a;
return {
value: t,
done: true
};
}
for (n.method = i, n.arg = a;;) {
var u = n.delegate;
if (u) {
var c = d(u, n);
if (c) {
if (c === f) continue;
return c;
}
}
if ("next" === n.method) n.sent = n._sent = n.arg;else if ("throw" === n.method) {
if (1 === o) throw o = 4, n.arg;
n.dispatchException(n.arg);
} else "return" === n.method && n.abrupt("return", n.arg);
o = 3;
var h = s(r, e, n);
if ("normal" === h.type) {
if (o = n.done ? 4 : 2, h.arg === f) continue;
return {
value: h.arg,
done: n.done
};
}
"throw" === h.type && (o = 4, n.method = "throw", n.arg = h.arg);
}
};
}(r, n, new Context(o || [])), true), a;
}
function s(t, r, e) {
try {
return {
type: "normal",
arg: t.call(r, e)
};
} catch (t) {
return {
type: "throw",
arg: t
};
}
}
r.wrap = h;
var f = {};
function Generator() {}
function GeneratorFunction() {}
function GeneratorFunctionPrototype() {}
var l = {};
c(l, i, function () {
return this;
});
var p = Object.getPrototypeOf,
y = p && p(p(x([])));
y && y !== e && n.call(y, i) && (l = y);
var v = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(l);
function g(t) {
["next", "throw", "return"].forEach(function (r) {
c(t, r, function (t) {
return this._invoke(r, t);
});
});
}
function AsyncIterator(t, r) {
function e(o, i, a, u) {
var c = s(t[o], t, i);
if ("throw" !== c.type) {
var h = c.arg,
f = h.value;
return f && "object" == typeof f && n.call(f, "__await") ? r.resolve(f.__await).then(function (t) {
e("next", t, a, u);
}, function (t) {
e("throw", t, a, u);
}) : r.resolve(f).then(function (t) {
h.value = t, a(h);
}, function (t) {
return e("throw", t, a, u);
});
}
u(c.arg);
}
var o;
c(this, "_invoke", function (t, n) {
function i() {
return new r(function (r, o) {
e(t, n, r, o);
});
}
return o = o ? o.then(i, i) : i();
}, true);
}
function d(r, e) {
var n = e.method,
o = r.i[n];
if (o === t) return e.delegate = null, "throw" === n && r.i.return && (e.method = "return", e.arg = t, d(r, e), "throw" === e.method) || "return" !== n && (e.method = "throw", e.arg = new TypeError("The iterator does not provide a '" + n + "' method")), f;
var i = s(o, r.i, e.arg);
if ("throw" === i.type) return e.method = "throw", e.arg = i.arg, e.delegate = null, f;
var a = i.arg;
return a ? a.done ? (e[r.r] = a.value, e.next = r.n, "return" !== e.method && (e.method = "next", e.arg = t), e.delegate = null, f) : a : (e.method = "throw", e.arg = new TypeError("iterator result is not an object"), e.delegate = null, f);
}
function w(t) {
this.tryEntries.push(t);
}
function m(r) {
var e = r[4] || {};
e.type = "normal", e.arg = t, r[4] = e;
}
function Context(t) {
this.tryEntries = [[-1]], t.forEach(w, this), this.reset(true);
}
function x(r) {
if (null != r) {
var e = r[i];
if (e) return e.call(r);
if ("function" == typeof r.next) return r;
if (!isNaN(r.length)) {
var o = -1,
a = function e() {
for (; ++o < r.length;) if (n.call(r, o)) return e.value = r[o], e.done = false, e;
return e.value = t, e.done = true, e;
};
return a.next = a;
}
}
throw new TypeError(typeof r + " is not iterable");
}
return GeneratorFunction.prototype = GeneratorFunctionPrototype, c(v, "constructor", GeneratorFunctionPrototype), c(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = c(GeneratorFunctionPrototype, u, "GeneratorFunction"), r.isGeneratorFunction = function (t) {
var r = "function" == typeof t && t.constructor;
return !!r && (r === GeneratorFunction || "GeneratorFunction" === (r.displayName || r.name));
}, r.mark = function (t) {
return Object.setPrototypeOf ? Object.setPrototypeOf(t, GeneratorFunctionPrototype) : (t.__proto__ = GeneratorFunctionPrototype, c(t, u, "GeneratorFunction")), t.prototype = Object.create(v), t;
}, r.awrap = function (t) {
return {
__await: t
};
}, g(AsyncIterator.prototype), c(AsyncIterator.prototype, a, function () {
return this;
}), r.AsyncIterator = AsyncIterator, r.async = function (t, e, n, o, i) {
void 0 === i && (i = Promise);
var a = new AsyncIterator(h(t, e, n, o), i);
return r.isGeneratorFunction(e) ? a : a.next().then(function (t) {
return t.done ? t.value : a.next();
});
}, g(v), c(v, u, "Generator"), c(v, i, function () {
return this;
}), c(v, "toString", function () {
return "[object Generator]";
}), r.keys = function (t) {
var r = Object(t),
e = [];
for (var n in r) e.unshift(n);
return function t() {
for (; e.length;) if ((n = e.pop()) in r) return t.value = n, t.done = false, t;
return t.done = true, t;
};
}, r.values = x, Context.prototype = {
constructor: Context,
reset: function (r) {
if (this.prev = this.next = 0, this.sent = this._sent = t, this.done = false, this.delegate = null, this.method = "next", this.arg = t, this.tryEntries.forEach(m), !r) for (var e in this) "t" === e.charAt(0) && n.call(this, e) && !isNaN(+e.slice(1)) && (this[e] = t);
},
stop: function () {
this.done = true;
var t = this.tryEntries[0][4];
if ("throw" === t.type) throw t.arg;
return this.rval;
},
dispatchException: function (r) {
if (this.done) throw r;
var e = this;
function n(t) {
a.type = "throw", a.arg = r, e.next = t;
}
for (var o = e.tryEntries.length - 1; o >= 0; --o) {
var i = this.tryEntries[o],
a = i[4],
u = this.prev,
c = i[1],
h = i[2];
if (-1 === i[0]) return n("end"), false;
if (!c && !h) throw Error("try statement without catch or finally");
if (null != i[0] && i[0] <= u) {
if (u < c) return this.method = "next", this.arg = t, n(c), true;
if (u < h) return n(h), false;
}
}
},
abrupt: function (t, r) {
for (var e = this.tryEntries.length - 1; e >= 0; --e) {
var n = this.tryEntries[e];
if (n[0] > -1 && n[0] <= this.prev && this.prev < n[2]) {
var o = n;
break;
}
}
o && ("break" === t || "continue" === t) && o[0] <= r && r <= o[2] && (o = null);
var i = o ? o[4] : {};
return i.type = t, i.arg = r, o ? (this.method = "next", this.next = o[2], f) : this.complete(i);
},
complete: function (t, r) {
if ("throw" === t.type) throw t.arg;
return "break" === t.type || "continue" === t.type ? this.next = t.arg : "return" === t.type ? (this.rval = this.arg = t.arg, this.method = "return", this.next = "end") : "normal" === t.type && r && (this.next = r), f;
},
finish: function (t) {
for (var r = this.tryEntries.length - 1; r >= 0; --r) {
var e = this.tryEntries[r];
if (e[2] === t) return this.complete(e[4], e[3]), m(e), f;
}
},
catch: function (t) {
for (var r = this.tryEntries.length - 1; r >= 0; --r) {
var e = this.tryEntries[r];
if (e[0] === t) {
var n = e[4];
if ("throw" === n.type) {
var o = n.arg;
m(e);
}
return o;
}
}
throw Error("illegal catch attempt");
},
delegateYield: function (r, e, n) {
return this.delegate = {
i: x(r),
r: e,
n: n
}, "next" === this.method && (this.arg = t), f;
}
}, r;
}
function _setPrototypeOf(t, e) {
return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) {
return t.__proto__ = e, t;
}, _setPrototypeOf(t, e);
}
function _slicedToArray(r, e) {
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
}
function _toConsumableArray(r) {
return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread();
}
function _toPrimitive(t, r) {
if ("object" != typeof t || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r);
if ("object" != typeof i) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (String )(t);
}
function _toPropertyKey(t) {
var i = _toPrimitive(t, "string");
return "symbol" == typeof i ? i : i + "";
}
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
return typeof o;
} : function (o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
function _unsupportedIterableToArray(r, a) {
if (r) {
if ("string" == typeof r) return _arrayLikeToArray(r, a);
var t = {}.toString.call(r).slice(8, -1);
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
}
}
var useForm = function useForm() {
var initialValues = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var validate = arguments.length > 1 ? arguments[1] : undefined;
var _useState = useState(initialValues || {}),
_useState2 = _slicedToArray(_useState, 2),
values = _useState2[0],
setValues = _useState2[1];
var _useState3 = useState({}),
_useState4 = _slicedToArray(_useState3, 2),
errors = _useState4[0],
setErrors = _useState4[1];
var _useState5 = useState(false),
_useState6 = _slicedToArray(_useState5, 2),
isSubmitting = _useState6[0],
setIsSubmitting = _useState6[1];
var handleChange = useCallback(function (event) {
var _event$target = event.target,
name = _event$target.name,
value = _event$target.value;
setValues(function (prev) {
var newValues = _objectSpread2(_objectSpread2({}, prev), {}, _defineProperty({}, name, value));
return newValues;
});
}, []);
var handleSubmit = useCallback(function (onSubmit) {
return /*#__PURE__*/function () {
var _ref = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee(event) {
var validationErrors;
return _regeneratorRuntime().wrap(function _callee$(_context) {
while (1) switch (_context.prev = _context.next) {
case 0:
if (event && typeof event.preventDefault === 'function') {
event.preventDefault();
} else {
console.error('useForm: Invalid event object:', event);
}
setIsSubmitting(true);
validationErrors = validate ? validate(values) : {};
setErrors(validationErrors);
if (!(Object.keys(validationErrors).length === 0)) {
_context.next = 13;
break;
}
_context.prev = 5;
_context.next = 8;
return onSubmit(values);
case 8:
_context.next = 13;
break;
case 10:
_context.prev = 10;
_context.t0 = _context["catch"](5);
setErrors({
submit: _context.t0.message
});
case 13:
setIsSubmitting(false);
case 14:
case "end":
return _context.stop();
}
}, _callee, null, [[5, 10]]);
}));
return function (_x) {
return _ref.apply(this, arguments);
};
}();
}, [values, validate]);
var resetForm = useCallback(function () {
setValues(initialValues || {});
setErrors({});
setIsSubmitting(false);
}, [initialValues]);
return {
values: values,
errors: errors,
isSubmitting: isSubmitting,
handleChange: handleChange,
handleSubmit: handleSubmit,
resetForm: resetForm
};
};
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var classnames = {exports: {}};
/*!
Copyright (c) 2018 Jed Watson.
Licensed under the MIT License (MIT), see
http://jedwatson.github.io/classnames
*/
(function (module) {
/* global define */
(function () {
var hasOwn = {}.hasOwnProperty;
function classNames () {
var classes = '';
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i];
if (arg) {
classes = appendClass(classes, parseValue(arg));
}
}
return classes;
}
function parseValue (arg) {
if (typeof arg === 'string' || typeof arg === 'number') {
return arg;
}
if (typeof arg !== 'object') {
return '';
}
if (Array.isArray(arg)) {
return classNames.apply(null, arg);
}
if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes('[native code]')) {
return arg.toString();
}
var classes = '';
for (var key in arg) {
if (hasOwn.call(arg, key) && arg[key]) {
classes = appendClass(classes, key);
}
}
return classes;
}
function appendClass (value, newClass) {
if (!newClass) {
return value;
}
if (value) {
return value + ' ' + newClass;
}
return value + newClass;
}
if (module.exports) {
classNames.default = classNames;
module.exports = classNames;
} else {
window.classNames = classNames;
}
}());
} (classnames));
var classnamesExports = classnames.exports;
var classNames = /*@__PURE__*/getDefaultExportFromCjs(classnamesExports);
// Define styles as a JavaScript object
var styles$1 = {
customForm: {
maxWidth: '500px',
margin: '2rem auto',
padding: '2rem',
backgroundColor: '#ffffff',
borderRadius: '12px',
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
},
fieldGroup: {
marginBottom: '1.5rem'
},
formField: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: '1rem',
marginBottom: '1rem'
},
nestedField: {
marginLeft: '2rem',
marginBottom: '0.5rem'
},
label: {
fontSize: '1rem',
fontWeight: 500,
color: '#333',
flex: '0 0 120px'
},
input: {
flex: 1,
padding: '0.75rem',
border: '1px solid #ccc',
borderRadius: '8px',
fontSize: '1rem'
},
checkbox: {
appearance: 'none',
width: '1.25rem',
height: '1.25rem',
border: '2px solid #ccc',
borderRadius: '4px',
marginRight: '0.5rem',
verticalAlign: 'middle',
cursor: 'pointer'
},
checkboxChecked: {
backgroundColor: '#007bff',
backgroundSize: 'cover',
borderColor: '#007bff'
},
radio: {
appearance: 'none',
width: '1.25rem',
height: '1.25rem',
border: '2px solid #ccc',
borderRadius: '50%',
marginRight: '0.5rem',
verticalAlign: 'middle',
cursor: 'pointer'
},
radioChecked: {
backgroundColor: '#007bff',
backgroundSize: 'cover',
borderColor: '#007bff'
},
checkboxContainer: {
display: 'flex',
alignItems: 'center',
gap: '1rem',
flexWrap: 'wrap'
},
radioContainer: {
display: 'flex',
alignItems: 'center',
gap: '1rem',
flexWrap: 'wrap'
},
containerLabel: {
display: 'flex',
alignItems: 'center',
fontWeight: 400,
cursor: 'pointer',
margin: 0
},
formButtons: {
display: 'flex',
gap: '1rem',
justifyContent: 'center',
marginTop: '1rem'
},
button: {
backgroundColor: '#007bff',
border: 'none',
borderRadius: '8px',
color: '#fff',
cursor: 'pointer',
fontSize: '1rem',
padding: '0.75rem 2rem'
},
resetButton: {
backgroundColor: '#6c757d'
},
buttonDisabled: {
backgroundColor: '#ccc',
cursor: 'not-allowed'
},
fieldError: {
color: '#dc3545',
fontSize: '0.875rem',
marginLeft: '120px',
flex: 1
},
formError: {
color: '#dc3545',
fontSize: '0.875rem',
marginTop: '0.5rem',
textAlign: 'center'
},
formErrorBoundary: {
color: '#dc3545',
padding: '1rem',
border: '1px solid #dc3545',
borderRadius: '8px',
backgroundColor: '#fff5f5',
textAlign: 'center'
},
formErrorBoundaryH2: {
fontSize: '1.2rem',
marginBottom: '0.5rem'
},
formErrorBoundaryP: {
fontSize: '0.875rem',
margin: '0.25rem 0'
}
};
// Error Boundary Component
var FormErrorBoundary = /*#__PURE__*/function (_React$Component) {
function FormErrorBoundary() {
var _this;
_classCallCheck(this, FormErrorBoundary);
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _callSuper(this, FormErrorBoundary, [].concat(args));
_defineProperty(_this, "state", {
hasError: false,
error: null
});
return _this;
}
_inherits(FormErrorBoundary, _React$Component);
return _createClass(FormErrorBoundary, [{
key: "componentDidCatch",
value: function componentDidCatch(error, errorInfo) {
console.error("Error in Form component:", error, errorInfo);
}
}, {
key: "render",
value: function render() {
if (this.state.hasError) {
var _this$state$error;
return /*#__PURE__*/React.createElement("div", {
style: styles$1.formErrorBoundary
}, /*#__PURE__*/React.createElement("h2", {
style: styles$1.formErrorBoundaryH2
}, "Something went wrong in the Form."), /*#__PURE__*/React.createElement("p", {
style: styles$1.formErrorBoundaryP
}, ((_this$state$error = this.state.error) === null || _this$state$error === void 0 ? void 0 : _this$state$error.message) || "Unknown error"), /*#__PURE__*/React.createElement("p", {
style: styles$1.formErrorBoundaryP
}, "Please check your initialValues structure or contact support."));
}
return this.props.children;
}
}], [{
key: "getDerivedStateFromError",
value: function getDerivedStateFromError(error) {
return {
hasError: true,
error: error
};
}
}]);
}(React.Component); // Utility to flatten nested objects and arrays into a single-level object with dot-notation keys
var _flattenObject$1 = function flattenObject(obj) {
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var result = {};
Object.keys(obj).forEach(function (key) {
var value = obj[key];
var newKey = prefix ? "".concat(prefix, ".").concat(key) : key;
if (Array.isArray(value)) {
var hasObjects = value.some(function (item) {
return item && _typeof(item) === 'object' && !Array.isArray(item);
});
var hasStrings = value.some(function (item) {
return typeof item === 'string';
});
if (hasObjects) {
value.forEach(function (item, index) {
if (item && _typeof(item) === 'object' && !Array.isArray(item)) {
Object.assign(result, _flattenObject$1(item, "".concat(newKey, "[").concat(index, "]")));
}
});
}
if (hasStrings) {
var stringOptions = value.filter(function (item) {
return typeof item === 'string';
});
if (stringOptions.length > 0) {
result[newKey] = stringOptions;
}
}
} else if (value && _typeof(value) === 'object' && !('value' in value)) {
Object.assign(result, _flattenObject$1(value, newKey));
} else {
result[newKey] = value;
}
});
return result;
};
// Utility to group flattened keys by their top-level key (for nested fields only)
var groupFields = function groupFields(flattenedObj) {
var grouped = {};
var flatFields = [];
Object.keys(flattenedObj).forEach(function (key) {
if (key.includes('.') || key.includes('[')) {
var _key$split = key.split(/\[|\./),
_key$split2 = _slicedToArray(_key$split, 1),
group = _key$split2[0];
grouped[group] = grouped[group] || [];
grouped[group].push(key);
} else {
flatFields.push(key);
}
});
return {
flatFields: flatFields,
groupedFields: grouped
};
};
// Utility to extract the actual value and optional flag from a field
var getFieldConfig = function getFieldConfig(field) {
if (field && _typeof(field) === 'object' && 'value' in field) {
return {
value: field.value,
optional: !!field.optional
};
}
return {
value: field,
optional: false
};
};
// Utility to generate a display label from a key (e.g., "study.degree" → "Study Degree")
var generateLabel = function generateLabel(key) {
return key.split(/\[|\./).filter(function (part) {
return !part.match(/^\d+\]$/);
}).map(function (part) {
return part.charAt(0).toUpperCase() + part.slice(1);
}).join(' ');
};
// Default validation function
var defaultValidate = function defaultValidate(values, initialValuesFlat) {
var errors = {};
var emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
var phoneRegex = /^\d{10}$/;
Object.keys(initialValuesFlat).forEach(function (key) {
var _getFieldConfig = getFieldConfig(initialValuesFlat[key]),
value = _getFieldConfig.value,
optional = _getFieldConfig.optional;
var fieldValue = values[key];
// Skip optional fields if empty
if (optional && (!fieldValue || fieldValue.trim() === '')) {
return;
}
// Required string fields
if (typeof value === 'string' && (!fieldValue || !fieldValue.trim())) {
errors[key] = "".concat(generateLabel(key), " is required");
}
// Email validation
if (key === 'email' && fieldValue && !emailRegex.test(fieldValue)) {
errors[key] = 'Invalid email format';
}
// Phone validation
if (key === 'phone' && fieldValue && !phoneRegex.test(fieldValue)) {
errors[key] = 'Phone number must be exactly 10 digits';
}
// Array (e.g., gender) validation
if (Array.isArray(value) && !fieldValue) {
errors[key] = "Please select a ".concat(generateLabel(key).toLowerCase(), " option");
}
});
return errors;
};
var Form = function Form(_ref) {
var initialValues = _ref.initialValues,
validate = _ref.validate,
onSubmit = _ref.onSubmit,
className = _ref.className,
customStyles = _ref.customStyles,
children = _ref.children,
_ref$reset = _ref.reset,
reset = _ref$reset === void 0 ? true : _ref$reset;
var initialValuesFlat = _flattenObject$1(initialValues);
var formInitialValues = {};
Object.keys(initialValuesFlat).forEach(function (key) {
var _getFieldConfig2 = getFieldConfig(initialValuesFlat[key]),
value = _getFieldConfig2.value;
formInitialValues[key] = value;
});
var _useForm = useForm(formInitialValues, function (values) {
return validate ? validate(values) : defaultValidate(values, initialValuesFlat);
}),
values = _useForm.values,
errors = _useForm.errors,
isSubmitting = _useForm.isSubmitting,
handleChange = _useForm.handleChange,
handleSubmit = _useForm.handleSubmit,
resetForm = _useForm.resetForm;
if (children) {
return /*#__PURE__*/React.createElement("form", {
onSubmit: handleSubmit(onSubmit),
className: classNames('custom-form', className, customStyles),
style: styles$1.customForm
}, children({
values: values || {},
errors: errors,
handleChange: handleChange,
isSubmitting: isSubmitting,
resetForm: resetForm
}), errors.submit && /*#__PURE__*/React.createElement("div", {
style: styles$1.formError
}, errors.submit));
}
var _groupFields = groupFields(initialValuesFlat),
flatFields = _groupFields.flatFields,
groupedFields = _groupFields.groupedFields;
var renderField = function renderField(key) {
var isNested = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
var group = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '';
var _getFieldConfig3 = getFieldConfig(initialValuesFlat[key]),
value = _getFieldConfig3.value;
var fieldType = _typeof(value);
var isArray = Array.isArray(value);
var label = isNested ? generateLabel(key.replace("".concat(group, "."), '')) : generateLabel(key);
if (fieldType === 'string' && !isArray) {
return /*#__PURE__*/React.createElement("div", {
key: key,
style: _objectSpread2(_objectSpread2({}, styles$1.formField), isNested ? styles$1.nestedField : {})
}, /*#__PURE__*/React.createElement("label", {
htmlFor: key,
style: styles$1.label
}, label, ":"), /*#__PURE__*/React.createElement("input", {
id: key,
name: key,
value: values[key] || '',
onChange: handleChange,
placeholder: "Enter ".concat(label.toLowerCase()),
style: styles$1.input
}), errors[key] && /*#__PURE__*/React.createElement("span", {
style: styles$1.fieldError
}, errors[key]));
}
if (fieldType === 'boolean') {
return /*#__PURE__*/React.createElement("div", {
key: key,
style: _objectSpread2(_objectSpread2({}, styles$1.formField), isNested ? styles$1.nestedField : {})
}, /*#__PURE__*/React.createElement("label", {
style: styles$1.label
}, label, ":"), /*#__PURE__*/React.createElement("div", {
style: styles$1.checkboxContainer
}, /*#__PURE__*/React.createElement("label", {
style: styles$1.containerLabel
}, /*#__PURE__*/React.createElement("input", {
type: "checkbox",
name: key,
checked: values[key] || false,
onChange: function onChange(e) {
var syntheticEvent = {
target: {
name: e.target.name,
value: e.target.checked
}
};
handleChange(syntheticEvent);
},
style: values[key] ? _objectSpread2(_objectSpread2({}, styles$1.checkbox), styles$1.checkboxChecked) : styles$1.checkbox
}), values[key] ? 'Yes' : 'No')));
}
if (isArray) {
return /*#__PURE__*/React.createElement("div", {
key: key,
style: _objectSpread2(_objectSpread2({}, styles$1.formField), isNested ? styles$1.nestedField : {})
}, /*#__PURE__*/React.createElement("label", {
style: styles$1.label
}, isNested && group === key ? 'Options' : label, ":"), /*#__PURE__*/React.createElement("div", {
style: styles$1.radioContainer
}, value.map(function (option) {
return /*#__PURE__*/React.createElement("label", {
key: String(option),
style: styles$1.containerLabel
}, /*#__PURE__*/React.createElement("input", {
type: "radio",
name: key,
value: option,
checked: values[key] === option,
onChange: handleChange,
style: values[key] === option ? _objectSpread2(_objectSpread2({}, styles$1.radio), styles$1.radioChecked) : styles$1.radio
}), typeof option === 'string' ? option.charAt(0).toUpperCase() + option.slice(1) : String(option));
})), errors[key] && /*#__PURE__*/React.createElement("span", {
style: styles$1.fieldError
}, errors[key]));
}
return null;
};
return /*#__PURE__*/React.createElement(FormErrorBoundary, null, /*#__PURE__*/React.createElement("form", {
onSubmit: handleSubmit(onSubmit),
className: classNames('custom-form', className, customStyles),
style: styles$1.customForm
}, flatFields.map(function (key) {
return renderField(key);
}), Object.keys(groupedFields).map(function (group) {
return /*#__PURE__*/React.createElement("div", {
key: group,
style: styles$1.fieldGroup
}, /*#__PURE__*/React.createElement("div", {
style: styles$1.formField
}, /*#__PURE__*/React.createElement("label", {
style: styles$1.label
}, generateLabel(group), ":")), groupedFields[group].map(function (key) {
return renderField(key, true, group);
}));
}), /*#__PURE__*/React.createElement("div", {
style: styles$1.formButtons
}, /*#__PURE__*/React.createElement("button", {
type: "submit",
disabled: isSubmitting,
style: isSubmitting ? _objectSpread2(_objectSpread2({}, styles$1.button), styles$1.buttonDisabled) : styles$1.button
}, isSubmitting ? 'Submitting...' : 'Submit'), reset && /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: resetForm,
disabled: isSubmitting,
style: isSubmitting ? _objectSpread2(_objectSpread2(_objectSpread2({}, styles$1.button), styles$1.resetButton), styles$1.buttonDisabled) : _objectSpread2(_objectSpread2({}, styles$1.button), styles$1.resetButton)
}, "Reset")), errors.submit && /*#__PURE__*/React.createElement("div", {
style: styles$1.formError
}, errors.submit)));
};
Form.propTypes = {
initialValues: PropTypes.object.isRequired,
validate: PropTypes.func,
onSubmit: PropTypes.func.isRequired,
className: PropTypes.string,
customStyles: PropTypes.string,
children: PropTypes.func,
reset: PropTypes.bool
};
Form.defaultProps = {
reset: true
};
var styles = {
modal: {
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1050
},
modalDialog: {
maxWidth: '500px',
width: '90%',
backgroundColor: '#fff',
borderRadius: '12px',
boxShadow: '0 8px 30px rgba(0, 0, 0, 0.2)',
position: 'relative'
},
modalContent: {
padding: '1rem'
},
modalHeader: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '0.5rem',
borderBottom: '1px solid #dee2e6',
backgroundColor: '#f8f9fa'
},
modalTitle: {
fontSize: '1.5rem',
fontWeight: 600,
margin: 0
},
closeButton: {
background: 'none',
border: 'none',
fontSize: '1.5rem',
cursor: 'pointer',
color: '#333',
padding: '0.5rem'
},
modalBody: {
padding: '1rem',
maxHeight: '60vh',
overflowY: 'auto'
},
modalFooter: {
display: 'flex',
justifyContent: 'flex-end',
gap: '0.5rem',
padding: '1rem',
borderTop: '1px solid #dee2e6'
},
btn: {
padding: '0.5rem 1rem',
borderRadius: '8px',
border: 'none',
cursor: 'pointer',
fontSize: '1rem',
color: '#fff'
},
btnPrimary: {
backgroundColor: '#007bff'
},
btnSecondary: {
backgroundColor: '#6c757d'
},
modalBackdrop: {
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
zIndex: 1040
},
message: {
fontSize: '1.25rem',
color: '#333',
marginBottom: '1rem'
},
defaultMessage: {
fontSize: '1rem',
color: '#6c757d',
fontStyle: 'italic'
},
dataList: {
fontSize: '1rem',
color: '#333',
marginBottom: '1rem'
},
dataItem: {
marginBottom: '0.5rem'
},
dataKey: {
fontWeight: 600,
marginRight: '0.5rem'
},
dataValue: {},
table: {
width: '100%',
borderCollapse: 'collapse',
border: '1px solid #dee2e6'
},
tableHeader: {
backgroundColor: '#f8f9fa',
fontWeight: 600
},
tableCell: {
padding: '0.75rem',
border: '1px solid #dee2e6'
}
};
var _flattenObject = function flattenObject(obj) {
var prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
var result = [];
Object.entries(obj).forEach(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
key = _ref2[0],
value = _ref2[1];
var newKey = prefix ? "".concat(prefix, ".").concat(key) : key;
if (_typeof(value) === 'object' && value !== null && !Array.isArray(value)) {
result.push.apply(result, _toConsumableArray(_flattenObject(value, newKey)));
} else {
result.push({
key: newKey,
value: value.toString()
});
}
});
return result;
};
var ModalWrapper = function ModalWrapper(_ref3) {
var title = _ref3.title,
message = _ref3.message,
data = _ref3.data,
table = _ref3.table,
consoleLog = _ref3.console,
show = _ref3.show,
onClose = _ref3.onClose,
onConfirm = _ref3.onConfirm,
className = _ref3.className,
style = _ref3.style,
modalDialogClassName = _ref3.modalDialogClassName,
modalDialogStyle = _ref3.modalDialogStyle;
React.useEffect(function () {
if (show) {
document.body.classList.add('unique-modal-open');
document.body.style.overflow = 'hidden';
} else {
document.body.classList.remove('unique-modal-open');
document.body.style.overflow = '';
}
return function () {
document.body.classList.remove('unique-modal-open');
document.body.style.overflow = '';
};
}, [show]);
React.useEffect(function () {
if (consoleLog && data) {
console.log('ModalWrapper data:', data);
}
}, [consoleLog, data]);
if (!show) return null;
var hasTitle = title && title.trim();
var hasMessage = message && message.trim();
var hasData = data && Object.keys(data).length > 0;
var isEmpty = !hasTitle && !hasMessage && !hasData;
var renderData = function renderData() {
if (!hasData) return null;
var flattened = _flattenObject(data);
if (table) {
return /*#__PURE__*/React.createElement("div", {
style: {
overflowX: 'auto'
}
}, /*#__PURE__*/React.createElement("table", {
style: styles.table
}, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", {
style: styles.tableHeader
}, /*#__PURE__*/React.createElement("th", {
style: styles.tableCell
}, "Field"), /*#__PURE__*/React.createElement("th", {
style: styles.tableCell
}, "Value"))), /*#__PURE__*/React.createElement("tbody", null, flattened.map(function (_ref4) {
var key = _ref4.key,
value = _ref4.value;
return /*#__PURE__*/React.createElement("tr", {
key: key
}, /*#__PURE__*/React.createElement("td", {
style: styles.tableCell
}, key), /*#__PURE__*/React.createElement("td", {
style: styles.tableCell
}, value));
}))));
}
return /*#__PURE__*/React.createElement("div", {
style: styles.dataList
}, flattened.map(function (_ref5) {
var key = _ref5.key,
value = _ref5.value;
return /*#__PURE__*/React.createElement("div", {
key: key,
style: styles.dataItem
}, /*#__PURE__*/React.createElement("span", {
style: styles.dataKey
}, key, ":"), /*#__PURE__*/React.createElement("span", {
style: styles.dataValue
}, value));
}));
};
var renderContent = function renderContent() {
if (isEmpty) {
return /*#__PURE__*/React.createElement("p", {
style: styles.defaultMessage
}, "Data isn't provided");
}
return /*#__PURE__*/React.createElement(React.Fragment, null, renderData(), hasMessage && /*#__PURE__*/React.createElement("p", {
style: styles.message
}, message));
};
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
className: classNames('unique-modal-wrapper', className),
style: _objectSpread2(_objectSpread2({}, styles.modal), style),
tabIndex: "-1",
role: "dialog"
}, /*#__PURE__*/React.createElement("div", {
className: classNames('modal-dialog', modalDialogClassName),
style: _objectSpread2(_objectSpread2({}, styles.modalDialog), modalDialogStyle),
role: "document"
}, /*#__PURE__*/React.createElement("div", {
style: styles.modalContent
}, hasTitle && /*#__PURE__*/React.createElement("div", {
style: styles.modalHeader
}, /*#__PURE__*/React.createElement("h5", {
style: styles.modalTitle
}, title), /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: onClose,
style: styles.closeButton,
"aria-label": "Close"
}, /*#__PURE__*/React.createElement("span", null, "\xD7"))), /*#__PURE__*/React.createElement("div", {
style: styles.modalBody
}, renderContent()), /*#__PURE__*/React.createElement("div", {
style: styles.modalFooter
}, /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: onClose,
style: _objectSpread2(_objectSpread2({}, styles.btn), styles.btnSecondary)
}, "Close"), /*#__PURE__*/React.createElement("button", {
type: "button",
onClick: onConfirm,
style: _objectSpread2(_objectSpread2({}, styles.btn), styles.btnPrimary)
}, "Confirm"))))), /*#__PURE__*/React.createElement("div", {
style: styles.modalBackdrop
}));
};
ModalWrapper.propTypes = {
title: PropTypes.string,
message: PropTypes.string,
data: PropTypes.object,
table: PropTypes.bool,
console: PropTypes.bool,
show: PropTypes.bool.isRequired,
onClose: PropTypes.func.isRequired,
onConfirm: PropTypes.func.isRequired,
className: PropTypes.string,
style: PropTypes.object,
modalDialogClassName: PropTypes.string,
modalDialogStyle: PropTypes.object
};
ModalWrapper.defaultProps = {
title: '',
message: '',
data: {},
table: false,
console: false,
className: '',
style: {},
modalDialogClassName: '',
modalDialogStyle: {}
};
export { Form, ModalWrapper };
//# sourceMappingURL=index.js.map