UNPKG

react-forminate

Version:

React.js + Typescript package that creates dynamic UI forms based on the JSON schema

199 lines (198 loc) 6.51 kB
import { a as M, c as K, j as n } from "./index-BPZpMa2Y.js"; import L, { useState as b, useRef as y, useMemo as D, useEffect as m } from "react"; /* empty css */ const T = (N) => { const { processedProps: c, fieldParams: I, eventHandlers: h, fieldValue: p, fieldId: s, dynamicOptions: $, fieldErrors: O, setValue: x, validateField: A } = M(N), [a, i] = b(!1), [d, u] = b(""), [l, w] = b([]), [o, g] = b(-1), S = y(null), C = y(null), k = y(null), f = D(() => { const e = $?.[s] || c.options || []; return typeof e[0] == "string" ? e.map((t) => ({ label: t, value: t })) : e; }, [$, s, c.options]), E = K( (e) => u(e), c.debounceSearch || 300 ), v = D(() => d ? f.filter( (e) => e.label.toLowerCase().includes(d.toLowerCase()) ) : f, [f, d]); m(() => { p !== void 0 && w(Array.isArray(p) ? p : [p]); }, [p]), m(() => { const e = (t) => { S.current && !S.current.contains(t.target) && (i(!1), u("")); }; return document.addEventListener("mousedown", e), () => document.removeEventListener("mousedown", e); }, []), m(() => { a && C.current && (C.current.focus(), g(-1)); }, [a]), m(() => { if (o >= 0 && k.current) { const e = k.current.querySelectorAll( ".multiselect-option-item" ); e[o] && e[o].scrollIntoView({ block: "nearest", behavior: "smooth" }); } }, [o]), m(() => { h.customHandlers?.onChangeItems && h.customHandlers.onChangeItems(l, s); }, [l]), m(() => { h.customHandlers?.onSearch && h.customHandlers.onSearch( f, l, s, d ); }, [d]); const R = (e) => { if (!a) { ["ArrowDown", "ArrowUp", "Enter", " "].includes(e.key) && (i(!0), e.preventDefault()); return; } switch (e.key) { case "ArrowDown": g( (t) => Math.min(t + 1, v.length - 1) ), e.preventDefault(); break; case "ArrowUp": g((t) => Math.max(t - 1, -1)), e.preventDefault(); break; case "Enter": case " ": o >= 0 && o < v.length && j(v[o].value), e.preventDefault(); break; case "Escape": i(!1), u(""), e.preventDefault(); break; case "Tab": i(!1), u(""); break; } }, V = () => { i(!a), u(""); }, j = (e) => { const t = l.includes(e) ? l.filter((r) => r !== e) : [...l, e]; w(t), x(s, t), c?.validateOnChange && A(s, t); }, P = (e, t) => { t.stopPropagation(); const r = l.filter((H) => H !== e); w(r), x(s, r); }, F = (e) => { e.stopPropagation(), w([]), x(s, []), i(!1); }; return /* @__PURE__ */ n.jsxs( "div", { className: `multiselect-wrapper ${c.className || ""}`, ref: S, onKeyDown: R, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": a, "aria-owns": `${s}-dropdown`, "aria-controls": `${s}-dropdown`, ...I, children: [ /* @__PURE__ */ n.jsxs( "div", { className: `form-element multiselect-input-container ${O ? "form-element-error" : ""} ${a ? "multiselect-input-container-open" : ""}`, onClick: V, tabIndex: 0, children: [ l.length === 0 ? /* @__PURE__ */ n.jsx("span", { className: "multiselect-placeholder", children: c.placeholder || "Select options" }) : l.map((e) => { const t = f.find((r) => r.value === e); return /* @__PURE__ */ n.jsxs("div", { className: "multiselect-selected-tag", children: [ t ? t.label : e, /* @__PURE__ */ n.jsx( "span", { className: "multiselect-remove-tag", onClick: (r) => P(e, r), "aria-label": `Remove ${t?.label || e}`, children: "×" } ) ] }, e); }), c.showClearAll && l.length > 0 && /* @__PURE__ */ n.jsx( "button", { type: "button", className: "multiselect-clear-all", onClick: F, "aria-label": "Clear all selections", onKeyDown: (e) => e.stopPropagation(), children: "Clear all" } ), /* @__PURE__ */ n.jsx( "span", { className: `multiselect-chevron-icon ${a ? "multiselect-chevron-icon-open" : ""}`, "aria-hidden": "true", children: "▼" } ) ] } ), /* @__PURE__ */ n.jsxs( "div", { className: `multiselect-dropdown ${a ? "" : "multiselect-dropdown-hidden"}`, ref: k, role: "listbox", id: `${s}-dropdown`, "aria-multiselectable": "true", children: [ /* @__PURE__ */ n.jsx("div", { className: "multiselect-search-container", children: /* @__PURE__ */ n.jsx( "input", { ref: C, type: "text", className: "multiselect-search-input", placeholder: "Search...", value: d, onChange: (e) => { u(e.target.value), E(e.target.value); }, onClick: (e) => e.stopPropagation(), "aria-label": "Search options", onKeyDown: (e) => { e.key === "Escape" && i(!1); } } ) }), v.map((e, t) => /* @__PURE__ */ n.jsxs( "div", { className: `multiselect-option-item ${l.includes(e.value) ? "multiselect-option-selected" : ""} ${t === o ? "multiselect-option-focused" : ""}`, onClick: () => j(e.value), role: "option", "aria-selected": l.includes(e.value), id: `${s}-option-${t}`, children: [ e.label, l.includes(e.value) && " ✓" ] }, e.value )) ] } ) ] } ); }, B = L.memo(T); export { B as default };