input-states-react
Version:
Reusable UI components for forms and steps
1,071 lines (1,070 loc) • 35.9 kB
JavaScript
import le, { forwardRef as X, useState as F, useRef as P, useImperativeHandle as q, useEffect as ce, useLayoutEffect as fe, Fragment as me } from "react";
var Q = { exports: {} }, J = {};
/**
* @license React
* react-jsx-runtime.production.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var ne;
function pe() {
if (ne) return J;
ne = 1;
var n = Symbol.for("react.transitional.element"), s = Symbol.for("react.fragment");
function r(o, d, f) {
var b = null;
if (f !== void 0 && (b = "" + f), d.key !== void 0 && (b = "" + d.key), "key" in d) {
f = {};
for (var N in d)
N !== "key" && (f[N] = d[N]);
} else f = d;
return d = f.ref, {
$$typeof: n,
type: o,
key: b,
ref: d !== void 0 ? d : null,
props: f
};
}
return J.Fragment = s, J.jsx = r, J.jsxs = r, J;
}
var Z = {};
/**
* @license React
* react-jsx-runtime.development.js
*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var se;
function he() {
return se || (se = 1, process.env.NODE_ENV !== "production" && function() {
function n(e) {
if (e == null) return null;
if (typeof e == "function")
return e.$$typeof === U ? null : e.displayName || e.name || null;
if (typeof e == "string") return e;
switch (e) {
case T:
return "Fragment";
case k:
return "Profiler";
case g:
return "StrictMode";
case Y:
return "Suspense";
case G:
return "SuspenseList";
case W:
return "Activity";
}
if (typeof e == "object")
switch (typeof e.tag == "number" && console.error(
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
), e.$$typeof) {
case h:
return "Portal";
case M:
return (e.displayName || "Context") + ".Provider";
case _:
return (e._context.displayName || "Context") + ".Consumer";
case V:
var i = e.render;
return e = e.displayName, e || (e = i.displayName || i.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e;
case w:
return i = e.displayName || null, i !== null ? i : n(e.type) || "Memo";
case H:
i = e._payload, e = e._init;
try {
return n(e(i));
} catch {
}
}
return null;
}
function s(e) {
return "" + e;
}
function r(e) {
try {
s(e);
var i = !1;
} catch {
i = !0;
}
if (i) {
i = console;
var p = i.error, j = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
return p.call(
i,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
j
), s(e);
}
}
function o(e) {
if (e === T) return "<>";
if (typeof e == "object" && e !== null && e.$$typeof === H)
return "<...>";
try {
var i = n(e);
return i ? "<" + i + ">" : "<...>";
} catch {
return "<...>";
}
}
function d() {
var e = D.A;
return e === null ? null : e.getOwner();
}
function f() {
return Error("react-stack-top-frame");
}
function b(e) {
if (m.call(e, "key")) {
var i = Object.getOwnPropertyDescriptor(e, "key").get;
if (i && i.isReactWarning) return !1;
}
return e.key !== void 0;
}
function N(e, i) {
function p() {
v || (v = !0, console.error(
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
i
));
}
p.isReactWarning = !0, Object.defineProperty(e, "key", {
get: p,
configurable: !0
});
}
function x() {
var e = n(this.type);
return L[e] || (L[e] = !0, console.error(
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
)), e = this.props.ref, e !== void 0 ? e : null;
}
function R(e, i, p, j, C, S, K, ee) {
return p = S.ref, e = {
$$typeof: c,
type: e,
key: i,
props: S,
_owner: C
}, (p !== void 0 ? p : null) !== null ? Object.defineProperty(e, "ref", {
enumerable: !1,
get: x
}) : Object.defineProperty(e, "ref", { enumerable: !1, value: null }), e._store = {}, Object.defineProperty(e._store, "validated", {
configurable: !1,
enumerable: !1,
writable: !0,
value: 0
}), Object.defineProperty(e, "_debugInfo", {
configurable: !1,
enumerable: !1,
writable: !0,
value: null
}), Object.defineProperty(e, "_debugStack", {
configurable: !1,
enumerable: !1,
writable: !0,
value: K
}), Object.defineProperty(e, "_debugTask", {
configurable: !1,
enumerable: !1,
writable: !0,
value: ee
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
}
function a(e, i, p, j, C, S, K, ee) {
var y = i.children;
if (y !== void 0)
if (j)
if (E(y)) {
for (j = 0; j < y.length; j++)
l(y[j]);
Object.freeze && Object.freeze(y);
} else
console.error(
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
);
else l(y);
if (m.call(i, "key")) {
y = n(e);
var z = Object.keys(i).filter(function(de) {
return de !== "key";
});
j = 0 < z.length ? "{key: someKey, " + z.join(": ..., ") + ": ...}" : "{key: someKey}", I[y + j] || (z = 0 < z.length ? "{" + z.join(": ..., ") + ": ...}" : "{}", console.error(
`A props object containing a "key" prop is being spread into JSX:
let props = %s;
<%s {...props} />
React keys must be passed directly to JSX without using spread:
let props = %s;
<%s key={someKey} {...props} />`,
j,
y,
z,
y
), I[y + j] = !0);
}
if (y = null, p !== void 0 && (r(p), y = "" + p), b(i) && (r(i.key), y = "" + i.key), "key" in i) {
p = {};
for (var te in i)
te !== "key" && (p[te] = i[te]);
} else p = i;
return y && N(
p,
typeof e == "function" ? e.displayName || e.name || "Unknown" : e
), R(
e,
y,
S,
C,
d(),
p,
K,
ee
);
}
function l(e) {
typeof e == "object" && e !== null && e.$$typeof === c && e._store && (e._store.validated = 1);
}
var u = le, c = Symbol.for("react.transitional.element"), h = Symbol.for("react.portal"), T = Symbol.for("react.fragment"), g = Symbol.for("react.strict_mode"), k = Symbol.for("react.profiler"), _ = Symbol.for("react.consumer"), M = Symbol.for("react.context"), V = Symbol.for("react.forward_ref"), Y = Symbol.for("react.suspense"), G = Symbol.for("react.suspense_list"), w = Symbol.for("react.memo"), H = Symbol.for("react.lazy"), W = Symbol.for("react.activity"), U = Symbol.for("react.client.reference"), D = u.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, m = Object.prototype.hasOwnProperty, E = Array.isArray, O = console.createTask ? console.createTask : function() {
return null;
};
u = {
"react-stack-bottom-frame": function(e) {
return e();
}
};
var v, L = {}, $ = u["react-stack-bottom-frame"].bind(
u,
f
)(), A = O(o(f)), I = {};
Z.Fragment = T, Z.jsx = function(e, i, p, j, C) {
var S = 1e4 > D.recentlyCreatedOwnerStacks++;
return a(
e,
i,
p,
!1,
j,
C,
S ? Error("react-stack-top-frame") : $,
S ? O(o(e)) : A
);
}, Z.jsxs = function(e, i, p, j, C) {
var S = 1e4 > D.recentlyCreatedOwnerStacks++;
return a(
e,
i,
p,
!0,
j,
C,
S ? Error("react-stack-top-frame") : $,
S ? O(o(e)) : A
);
};
}()), Z;
}
var oe;
function ge() {
return oe || (oe = 1, process.env.NODE_ENV === "production" ? Q.exports = pe() : Q.exports = he()), Q.exports;
}
var t = ge();
const ue = (n) => /* @__PURE__ */ t.jsxs(
"svg",
{
width: "24",
height: "24",
viewBox: "0 0 24 24",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
...n,
children: [
/* @__PURE__ */ t.jsx(
"path",
{
d: "M12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z",
stroke: "#FF0000",
strokeWidth: "2",
strokeMiterlimit: "10"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M12 17V11",
stroke: "#FF0000",
strokeWidth: "2",
strokeMiterlimit: "10"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M11.9998 7.5C12.4415 7.5 12.7995 7.85807 12.7996 8.2998C12.7996 8.74163 12.4416 9.09961 11.9998 9.09961C11.558 9.0995 11.2 8.74157 11.2 8.2998C11.2001 7.85813 11.5581 7.50011 11.9998 7.5Z",
fill: "#FF0000",
stroke: "#FF0000",
strokeMiterlimit: "10"
}
)
]
}
), re = (n) => /* @__PURE__ */ t.jsx(
"svg",
{
width: "24",
height: "24",
viewBox: "0 0 24 24",
fill: "none",
xmlns: "http://www.w3.org/2000/svg",
...n,
children: /* @__PURE__ */ t.jsx(
"path",
{
d: "M2 12.6924L8.245 19L22 5",
stroke: "#2DCD73",
strokeWidth: "2",
strokeMiterlimit: "10"
}
)
}
), xe = X(
({
height: n = 200,
checked: s,
onChange: r,
children: o,
errorMessage: d = "กรุณากรอกข้อมูลให้ถูกต้อง",
requireFullScroll: f = !0,
scrollThreshold: b = 0.95
}, N) => {
const [x, R] = F(!1), [a, l] = F(!1), [u, c] = F(!1), [h, T] = F(0), g = P(null), k = P(null);
q(N, () => ({
validate: () => (R(!0), s === !0),
focus: () => {
k.current && k.current.scrollIntoView({
behavior: "smooth",
block: "center"
}), setTimeout(() => {
g.current && g.current.focus();
}, 300);
}
}));
const _ = P(null), [M, V] = F(!1);
ce(() => {
const w = _.current, H = () => {
w.scrollTop + w.clientHeight >= w.scrollHeight - 1 && (V(!0), l(!1), c(!0));
};
if (w.scrollHeight <= w.clientHeight && V(!0), w)
return w.scrollHeight <= w.clientHeight && (V(!0), c(!0)), w.addEventListener("scroll", H), () => w.removeEventListener("scroll", H);
}, []);
const Y = () => {
M || l(!0);
}, G = (w) => {
const H = w.target, W = H.scrollTop, U = H.scrollHeight, D = H.clientHeight, m = W / (U - D);
T(Math.min(m, 1)), m >= b && c(!0);
};
return /* @__PURE__ */ t.jsxs("div", { className: "input-group consent-scroll-box", ref: k, children: [
/* @__PURE__ */ t.jsxs("label", { className: "consent-container", onClick: Y, children: [
/* @__PURE__ */ t.jsx(
"input",
{
ref: g,
type: "checkbox",
checked: s,
disabled: !M,
onChange: (w) => {
M && (r(w.target.checked), l(!1)), R(!0);
}
}
),
/* @__PURE__ */ t.jsx("span", { className: "custom-checkbox", children: s ? /* @__PURE__ */ t.jsxs("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: [
/* @__PURE__ */ t.jsx(
"rect",
{
x: "2",
y: "2",
width: "20",
height: "20",
rx: "4",
stroke: "#007BFF",
strokeWidth: "2"
}
),
/* @__PURE__ */ t.jsx("path", { d: "M7 12L10 15L17 8", stroke: "#007BFF", strokeWidth: "2" })
] }) : /* @__PURE__ */ t.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ t.jsx(
"rect",
{
x: "2",
y: "2",
width: "20",
height: "20",
rx: "4",
stroke: "#ccc",
strokeWidth: "2"
}
) }) }),
/* @__PURE__ */ t.jsxs("div", { className: "scroll-container", style: { position: "relative", width: "100%" }, children: [
/* @__PURE__ */ t.jsx(
"div",
{
ref: _,
className: `scroll-content ${a ? "error" : ""}`,
style: {
height: n,
border: `1px solid ${a ? "var(--font-color-error-pws)" : "#ddd"}`
},
onScroll: G,
tabIndex: 0,
children: /* @__PURE__ */ t.jsx("div", { dangerouslySetInnerHTML: { __html: o } })
}
),
f && /* @__PURE__ */ t.jsx(
"div",
{
style: {
position: "absolute",
bottom: "8px",
right: "8px",
backgroundColor: u ? "" : "#007bff",
color: "white",
padding: "4px 8px",
borderRadius: "12px",
fontSize: "12px",
fontWeight: "bold"
},
children: u ? /* @__PURE__ */ t.jsx(re, {}) : `${Math.round(h * 100)}%`
}
)
] })
] }),
a ? /* @__PURE__ */ t.jsx("div", { className: "text-error-message", children: "※ กรุณาเลื่อนอ่านข้อมูลให้ครบก่อนติ๊กยินยอม" }) : x && !s ? /* @__PURE__ */ t.jsx("div", { className: "text-error-message", children: d || "※ กรุณายินยอมก่อนดำเนินการต่อ" }) : null
] });
}
), ve = X(
({ head: n, label: s, value: r, onChange: o, errorMessage: d, required: f }, b) => {
const [N, x] = F(!1), a = ((h) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(h))(r), u = N && (f || r !== "") && !a, c = P(null);
return q(b, () => ({
validate: () => (x(!0), a),
focus: () => {
c.current && (c.current.focus(), setTimeout(() => {
const h = c.current.getBoundingClientRect();
window.scrollTo({
top: window.scrollY + h.top - 80 - 24,
behavior: "smooth"
});
}, 10));
}
})), /* @__PURE__ */ t.jsxs(
"div",
{
className: `input-group ${u ? "error" : ""} ${!u && N && a ? "valid" : ""}`,
children: [
n && /* @__PURE__ */ t.jsx("div", { className: "group-label", children: n }),
/* @__PURE__ */ t.jsxs("div", { className: "input-inner", children: [
/* @__PURE__ */ t.jsx(
"input",
{
ref: c,
type: "email",
className: "form-input",
placeholder: " ",
value: r,
onChange: (h) => {
o(h.target.value), x(!0);
},
onBlur: () => x(!0)
}
),
/* @__PURE__ */ t.jsxs("label", { className: "input-label", children: [
s,
f && " "
] }),
/* @__PURE__ */ t.jsx("span", { className: "validation-icon valid-icon", children: /* @__PURE__ */ t.jsx(re, {}) }),
/* @__PURE__ */ t.jsx("span", { className: "validation-icon error-icon", children: /* @__PURE__ */ t.jsx(ue, {}) }),
u && /* @__PURE__ */ t.jsx("div", { className: "text-error-message", children: d })
] })
]
}
);
}
);
function be({ html: n, children: s, className: r = "", style: o = {} }) {
return n ? /* @__PURE__ */ t.jsx(
"div",
{
className: `text-default label-standard ${r}`,
style: o,
dangerouslySetInnerHTML: { __html: n }
}
) : /* @__PURE__ */ t.jsx("div", { className: `text-default label-standard ${r}`, style: o, children: s });
}
const ie = (n, s = 0) => {
const r = (n ?? "").toString().replace(/,/g, "");
if (r === "") return "";
if (r.endsWith(".") && s > 0) {
const d = r.slice(0, -1);
if (d === "" && r === ".") return "0.";
const f = parseFloat(d);
return isNaN(f) ? r : f.toLocaleString(void 0, {
minimumFractionDigits: 0,
// Format integer part only
maximumFractionDigits: 0
}) + ".";
}
const o = parseFloat(r);
return isNaN(o) ? r : o.toLocaleString(void 0, {
minimumFractionDigits: s,
maximumFractionDigits: s
});
}, B = (n, s) => {
let r = "", o = !1;
typeof n != "string" && (n = (n ?? "").toString());
for (let d = 0; d < n.length; d++) {
const f = n[d];
/\d/.test(f) ? r += f : f === "." && !o && s > 0 ? (r += ".", o = !0) : f === "-" && d === 0 && r === "" && (r += "-");
}
return r === "." && s > 0 ? "0." : r === "-." && s > 0 ? "-0." : r.startsWith(".") && s > 0 && r.length > 1 ? "0" + r : r.startsWith("-.") && s > 0 && r.length > 2 ? "-0" + r.substring(1) : r;
}, Ee = X(
({
head: n = "หัวข้อ",
label: s = "Label",
suggest: r = "",
value: o,
// Expects a raw number or numeric string (unformatted)
onChange: d,
min: f = -1 / 0,
max: b = 1 / 0,
errorMessage: N = "กรุณากรอกข้อมูลให้ถูกต้อง",
required: x = !1,
maxDigit: R = null,
// Max digits for the integer part
decimalPlaces: a = 0
}, l) => {
const [u, c] = F(""), [h, T] = F(!1), [g, k] = F(!1), _ = P(null), M = P({ value: "", cursor: 0 });
ce(() => {
const m = o == null ? "" : o.toString(), E = B(m, a);
if (!g)
c(ie(E, a));
else {
const O = B(u, a);
E !== O && (c(E), _.current && (M.current = {
value: E,
cursor: E.length
}));
}
}, [o, g, a]);
const V = parseFloat(
B(u, a)
), Y = B(u, a), G = !x && Y === "" || Y === "-" && !x || // Allow just "-" if not required
!isNaN(V) && V >= f && V <= b;
q(l, () => ({
validate: () => {
T(!0);
const m = B(u, a);
if (!x && m === "" || m === "-" && !x) return !0;
const E = parseFloat(m);
return !isNaN(E) && E >= f && E <= b;
},
focus: () => {
_.current && (_.current.focus(), setTimeout(() => {
const m = _.current.getBoundingClientRect();
window.scrollTo({
top: window.scrollY + m.top - 100 - 24,
behavior: "smooth"
});
}, 10));
}
}));
const w = h && !G && !!N, H = () => {
k(!0);
const m = B(u, a);
c(m), _.current && (M.current = {
value: m,
cursor: m.length
});
}, W = (m) => {
const E = m.target.value, O = m.target.selectionStart;
M.current = { value: E, cursor: O };
let v = "", L = !1, $ = !1;
for (let C = 0; C < E.length; C++) {
const S = E[C];
/\d/.test(S) ? v += S : S === "." && !L && a > 0 ? (v += S, L = !0) : S === "-" && C === 0 && !$ && (v += S, $ = !0);
}
v === "." && a > 0 && (v = "0."), v === "-." && a > 0 && (v = "-0.");
let A = "", I = v;
v.startsWith("-") && (A = "-", I = v.substring(1));
let [e, i] = I.split(".");
e = e || "", R && e.length > R && (e = e.slice(0, R)), i !== void 0 ? (a != null && i.length > a && (i = i.slice(0, a)), I = e + "." + i) : I = e, v = A + I;
let p = e;
if (e) {
const C = parseFloat(e);
(!isNaN(C) || e.match(/^0+$/)) && (p = C.toLocaleString(void 0, {
minimumFractionDigits: 0,
maximumFractionDigits: 0
}));
}
let j = A + p;
i !== void 0 ? j += "." + i : I.endsWith(".") && a > 0 && I.length > 0 && e.length >= 0 && (j === A && I === "." ? j = A + "0." : j.endsWith(".") || (j += ".")), v === "0." && a > 0 && (j = "0."), v === "-0." && a > 0 && (j = "-0."), c(j), d(v), h || T(!0);
};
fe(() => {
if (g && _.current) {
const m = _.current, { value: E, cursor: O } = M.current, v = u;
if (E === v && m.value === v && m.selectionStart === O)
return;
let L = 0;
for (let e = 0; e < O; e++)
E[e] !== "," && L++;
let $ = 0, A = 0;
for (let e = 0; e < v.length && (v[e] !== "," && A++, $++, !(A >= L)); e++)
;
if (A < L && A === 0 && v.length > 0)
$ = 0, v.startsWith("-") && ($ = 1);
else if (A < L) {
let e = 0, i = 0;
for (let p = 0; p < v.length && (v[p] !== "," && i++, e++, !(i >= A)); p++)
;
$ = e;
}
const I = Math.max(
0,
Math.min($, m.value.length)
);
m.value === v && m.setSelectionRange(I, I);
}
}, [u, g]);
const U = () => {
k(!1), T(!0);
const m = B(u, a);
let E = m;
if (m === "" || m === "-")
c(m === "-" ? "-" : ""), E = m === "-" ? "-" : "";
else {
const O = parseFloat(m);
isNaN(O) ? (c(m), E = m) : (E = O.toFixed(a), c(ie(E, a)));
}
d(E);
}, D = u;
return /* @__PURE__ */ t.jsxs(
"div",
{
className: `input-group numeric-input-wrapper ${w ? "error" : ""}`,
children: [
n && /* @__PURE__ */ t.jsx("div", { className: "group-label", children: n }),
/* @__PURE__ */ t.jsxs("div", { className: "numeric-input-inner", children: [
/* @__PURE__ */ t.jsx("span", { className: "left-label", children: s }),
/* @__PURE__ */ t.jsx(
"input",
{
ref: _,
type: "text",
value: D,
onChange: W,
onFocus: H,
onBlur: U,
className: `numeric-input ${w ? "input-error" : ""}`,
placeholder: r,
inputMode: "decimal",
onKeyDown: (m) => {
m.key;
}
}
)
] }),
w && /* @__PURE__ */ t.jsx("div", { className: "text-error-message", children: N })
]
}
);
}
), je = X(
({
head: n,
name: s,
options: r,
value: o,
onChange: d,
errorMessage: f = "กรุณากรอกข้อมูลให้ถูกต้อง",
direction: b = "horizontal"
// ✅ เพิ่มตรงนี้ vertical
}, N) => {
const [x, R] = F(!1), [a, l] = F(null), u = P(null), c = P(null);
q(N, () => ({
validate: () => (R(!0), !!o),
focus: () => {
u.current && u.current.scrollIntoView({
behavior: "smooth",
block: "center"
}), setTimeout(() => {
c.current && c.current.focus();
}, 300);
}
}));
const h = x && !o, T = b === "vertical" ? "radio-options-row-Vertical" : "radio-options-row-Horizontal";
return /* @__PURE__ */ t.jsxs("div", { ref: u, className: "input-group radio-group-horizontal", children: [
n && /* @__PURE__ */ t.jsx("div", { className: "group-label", children: n }),
/* @__PURE__ */ t.jsx("div", { className: T, children: r.map((g, k) => {
const _ = o === g.value, M = a === g.value;
return /* @__PURE__ */ t.jsxs(
"label",
{
className: "radio-option",
onMouseEnter: () => l(g.value),
onMouseLeave: () => l(null),
children: [
/* @__PURE__ */ t.jsx(
"input",
{
ref: k === 0 ? c : null,
type: "radio",
name: s,
value: g.value,
checked: _,
onChange: d
}
),
/* @__PURE__ */ t.jsx("span", { className: "custom-radio-customForm", children: _ ? /* @__PURE__ */ t.jsxs("svg", { width: "25", height: "25", viewBox: "0 0 24 24", fill: "none", children: [
/* @__PURE__ */ t.jsx(
"circle",
{
cx: "12",
cy: "12",
r: "10",
stroke: "#0064FF",
strokeWidth: "2"
}
),
/* @__PURE__ */ t.jsx(
"path",
{
d: "M7 12L10 15L16 8",
stroke: "#0064FF",
strokeWidth: "2"
}
)
] }) : M ? /* @__PURE__ */ t.jsx("svg", { width: "25", height: "25", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ t.jsx(
"circle",
{
cx: "12",
cy: "12",
r: "10",
stroke: "#0064FF",
strokeWidth: "2"
}
) }) : /* @__PURE__ */ t.jsx("svg", { width: "25", height: "25", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ t.jsx(
"circle",
{
cx: "12",
cy: "12",
r: "10",
stroke: "#ccc",
strokeWidth: "2"
}
) }) }),
/* @__PURE__ */ t.jsx("span", { className: "radio-text", children: g.label })
]
},
g.value
);
}) }),
h && /* @__PURE__ */ t.jsx("div", { className: "text-error-message", children: f || "กรุณาเลือกเพศ" })
] });
}
), Ne = X(
({
head: n,
label: s,
value: r,
onChange: o,
errorMessage: d = "กรุณากรอกข้อมูลให้ถูกต้อง",
required: f
}, b) => {
const [N, x] = F(!1), R = P(null), a = /^[a-zA-Z\u0E00-\u0E7F\s]+$/, u = ((g) => {
const k = g || "";
return !f || k.trim() !== "" && a.test(k);
})(r), h = N && (f || r !== "") && !u, T = (g) => {
let k = g.target.value;
k = k.replace(/[^a-zA-Z\u0E00-\u0E7F\s]/g, ""), o(k), x(!0);
};
return q(b, () => ({
validate: () => (x(!0), u),
focus: () => {
R.current && (R.current.focus(), setTimeout(() => {
const g = R.current.getBoundingClientRect();
window.scrollTo({
top: window.scrollY + g.top - 80 - 24,
behavior: "smooth"
});
}, 10));
}
})), /* @__PURE__ */ t.jsxs(
"div",
{
className: `input-group ${h ? "error" : ""} ${!h && N && u ? "valid" : ""}`,
children: [
n && /* @__PURE__ */ t.jsx("div", { className: "group-label", children: n }),
/* @__PURE__ */ t.jsxs("div", { className: "input-inner", children: [
/* @__PURE__ */ t.jsx(
"input",
{
ref: R,
type: "text",
className: "form-input",
placeholder: " ",
value: r || "",
onChange: T,
onBlur: () => x(!0)
}
),
/* @__PURE__ */ t.jsxs("label", { className: "input-label", children: [
s,
f && " "
] }),
/* @__PURE__ */ t.jsx("span", { className: "validation-icon valid-icon", children: /* @__PURE__ */ t.jsx(re, {}) }),
/* @__PURE__ */ t.jsx("span", { className: "validation-icon error-icon", children: /* @__PURE__ */ t.jsx(ue, {}) }),
h && /* @__PURE__ */ t.jsx("div", { className: "text-error-message", children: d })
] })
]
}
);
}
), Re = ({
children: n,
type: s = "button",
className: r = "",
...o
}) => /* @__PURE__ */ t.jsx(
"button",
{
type: s,
className: `btn-primary ${r}`,
...o,
children: n
}
), Se = ({ steps: n, initialStep: s = 1 }) => {
const [r, o] = F(s), [d, f] = F({}), b = (a) => {
console.log(
`Stepper: Step ${r} completed. Data:`,
a
), f((l) => ({
...l,
[r - 1]: a
})), r < n.length ? o((l) => l + 1) : console.log("Stepper: All steps completed!");
}, N = (a) => {
a < r && o(a);
}, x = n[r - 1];
let R;
return x && (R = le.cloneElement(x.component, {
onStepComplete: b,
stepsData: d
// ✅ ส่งเข้าไปให้ step
})), /* @__PURE__ */ t.jsxs("div", { className: "stepper-container", children: [
/* @__PURE__ */ t.jsx("div", { className: "stepper-row", children: n.map((a, l) => {
const u = l + 1, c = u < r, h = u === r, T = c;
let g = "stepper-item__indicator";
c ? g += " stepper-item__indicator--completed" : h ? g += " stepper-item__indicator--active" : g += " stepper-item__indicator--upcoming", T && (g += " stepper-item__indicator--clickable");
let k = "stepper-item__label";
c || h ? k += " stepper-item__label--highlighted" : k += " stepper-item__label--dimmed";
let _ = "stepper-line";
return c && (_ += " stepper-line--completed"), /* @__PURE__ */ t.jsxs(me, { children: [
/* @__PURE__ */ t.jsxs("div", { className: "stepper-item", children: [
/* @__PURE__ */ t.jsx(
"div",
{
className: g,
onClick: () => T ? N(u) : null,
children: c ? (
// ไอคอนเครื่องหมายถูกสำหรับขั้นตอนที่เสร็จสมบูรณ์
/* @__PURE__ */ t.jsx(
"svg",
{
className: "stepper-item__icon",
viewBox: "0 0 20 20",
fill: "currentColor",
children: /* @__PURE__ */ t.jsx(
"path",
{
fillRule: "evenodd",
d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z",
clipRule: "evenodd"
}
)
}
)
) : (
// หมายเลขขั้นตอนสำหรับขั้นตอนที่กำลังใช้งานอยู่หรือกำลังจะมาถึง
/* @__PURE__ */ t.jsx("span", { className: "stepper-item__number", children: u })
)
}
),
/* @__PURE__ */ t.jsx("p", { className: k, children: a.name })
] }),
u < n.length && /* @__PURE__ */ t.jsx("div", { className: _ })
] }, a.name + l);
}) }),
/* @__PURE__ */ t.jsx("div", { className: "stepper-content", children: R })
] });
};
function Ce(n) {
const s = {};
return n.forEach((r) => {
var o;
(!r.type || r.type === "input") && r.name && (r.name === "consent" ? s[r.name] = !1 : s[r.name] = ((o = r.props) == null ? void 0 : o.defaultValue) ?? "");
}), s;
}
const ke = {
RadioGroup: je,
NumericTextInput: Ee,
EmailInput: ve,
ConsentCheckbox: xe,
TextInput: Ne,
StandardLabel: be
};
function ye(n) {
return (n || []).map((s) => {
const r = typeof s.component == "string" ? s.component.trim() : s.component;
return {
...s,
component: typeof r == "string" ? ke[r] : r
};
});
}
function we() {
const [n, s] = F({});
return { errors: n, setErrors: s, clearFieldError: (o) => {
s((d) => {
const { [o]: f, ...b } = d;
return b;
});
} };
}
const ae = (n, s, r) => (o) => {
var f;
const d = ((f = o == null ? void 0 : o.target) == null ? void 0 : f.value) ?? o;
s((b) => ({ ...b, [n]: d })), r((b) => {
const { [n]: N, ...x } = b;
return x;
});
};
function Te(n, s) {
const r = {};
return Object.keys(n).forEach((o) => {
var d;
(d = n[o].current) != null && d.validate() || (r[o] = s[o]);
}), r;
}
const Fe = ({
onFormSubmitAndValidated: n,
// Callback เมื่อฟอร์มผ่าน validation และ submit สำเร็จ
fields: s,
// Array ของ config field ทั้งหมด
formData: r,
// State object ของข้อมูลในฟอร์มแต่ละช่อง
setFormData: o,
// Setter สำหรับเปลี่ยนค่า formData
buttonLabel: d
}) => {
const { errors: f, setErrors: b } = we(), [N, x] = F(!1), R = Object.fromEntries(
s.filter((l) => l.type !== "label" && l.name).map((l) => [l.name, P()])
), a = async (l) => {
l.preventDefault(), x(!0);
const u = Te(
R,
Object.fromEntries(
s.filter((c) => !c.type || c.type !== "label").map((c) => [c.name, c.errorMessage])
)
);
if (b(u), Object.keys(u).length > 0) {
const c = Object.keys(u)[0], h = R[c];
h && h.current && typeof h.current.focus == "function" && h.current.focus(), x(!1);
return;
}
try {
await new Promise((c) => setTimeout(c, 3e3)), n && n(r);
} catch (c) {
console.error(c), alert("เกิดข้อผิดพลาด กรุณาลองใหม่อีกครั้ง");
}
x(!1);
};
return /* @__PURE__ */ t.jsxs("form", { onSubmit: a, children: [
s.map((l, u) => {
if (!l.component) return null;
if (l.type === "custom") {
const T = l.component;
return /* @__PURE__ */ t.jsx(T, { ...l.props }, u);
}
const c = l.component, h = R[l.name];
return l.name === "consent" ? /* @__PURE__ */ t.jsx(
c,
{
ref: h,
...l.props,
checked: !!r[l.name],
onChange: ae(
l.name,
o,
() => {
},
l.errorMessage
),
errorMessage: l.errorMessage
},
u
) : /* @__PURE__ */ t.jsx(
c,
{
ref: h,
...l.props,
value: r[l.name],
onChange: ae(
l.name,
o,
() => {
},
l.errorMessage
),
errorMessage: l.errorMessage
},
u
);
}),
/* @__PURE__ */ t.jsx("div", { className: "submit-container", children: /* @__PURE__ */ t.jsx(
Re,
{
type: "submit",
className: "btn-primary",
disabled: N,
children: d
}
) })
] });
};
function Ae(n) {
const s = parseInt((n || "").toString().replace(/[^\d]/g, ""), 10);
return isNaN(s) ? "-" : s.toLocaleString();
}
export {
Fe as BaseForm,
Re as ButtonPrimary,
xe as ConsentCheckbox,
ve as EmailInput,
be as Label,
Ee as NumericTextInput,
je as RadioGroup,
Se as Stepper,
Ne as TextInput,
Ae as formatNumber,
Ce as getInitialFormData,
ye as mapFieldComponents,
ae as updateFieldState,
we as useFormErrors,
Te as validateFields
};