UNPKG

@costilladante/password-validator

Version:

A customizable React password validator component with accessibility features

519 lines (518 loc) 16.3 kB
import ue, { useState as M, useEffect as ce, useCallback as L } from "react"; var N = { exports: {} }, O = {}; /** * @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 Z; function de() { if (Z) return O; Z = 1; var a = Symbol.for("react.transitional.element"), r = Symbol.for("react.fragment"); function s(n, l, d) { var b = null; if (d !== void 0 && (b = "" + d), l.key !== void 0 && (b = "" + l.key), "key" in l) { d = {}; for (var p in l) p !== "key" && (d[p] = l[p]); } else d = l; return l = d.ref, { $$typeof: a, type: n, key: b, ref: l !== void 0 ? l : null, props: d }; } return O.Fragment = r, O.jsx = s, O.jsxs = s, O; } var S = {}; /** * @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 Q; function fe() { return Q || (Q = 1, process.env.NODE_ENV !== "production" && function() { function a(e) { if (e == null) return null; if (typeof e == "function") return e.$$typeof === oe ? null : e.displayName || e.name || null; if (typeof e == "string") return e; switch (e) { case x: return "Fragment"; case k: return "Profiler"; case f: return "StrictMode"; case te: return "Suspense"; case se: return "SuspenseList"; case ne: 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 T: return "Portal"; case I: return (e.displayName || "Context") + ".Provider"; case g: return (e._context.displayName || "Context") + ".Consumer"; case re: var t = e.render; return e = e.displayName, e || (e = t.displayName || t.name || "", e = e !== "" ? "ForwardRef(" + e + ")" : "ForwardRef"), e; case ae: return t = e.displayName || null, t !== null ? t : a(e.type) || "Memo"; case W: t = e._payload, e = e._init; try { return a(e(t)); } catch { } } return null; } function r(e) { return "" + e; } function s(e) { try { r(e); var t = !1; } catch { t = !0; } if (t) { t = console; var o = t.error, u = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object"; return o.call( t, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", u ), r(e); } } function n(e) { if (e === x) return "<>"; if (typeof e == "object" && e !== null && e.$$typeof === W) return "<...>"; try { var t = a(e); return t ? "<" + t + ">" : "<...>"; } catch { return "<...>"; } } function l() { var e = $.A; return e === null ? null : e.getOwner(); } function d() { return Error("react-stack-top-frame"); } function b(e) { if (J.call(e, "key")) { var t = Object.getOwnPropertyDescriptor(e, "key").get; if (t && t.isReactWarning) return !1; } return e.key !== void 0; } function p(e, t) { function o() { z || (z = !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)", t )); } o.isReactWarning = !0, Object.defineProperty(e, "key", { get: o, configurable: !0 }); } function R() { var e = a(this.type); return G[e] || (G[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 y(e, t, o, u, P, m, q, F) { return o = m.ref, e = { $$typeof: i, type: e, key: t, props: m, _owner: P }, (o !== void 0 ? o : null) !== null ? Object.defineProperty(e, "ref", { enumerable: !1, get: R }) : 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: q }), Object.defineProperty(e, "_debugTask", { configurable: !1, enumerable: !1, writable: !0, value: F }), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e; } function v(e, t, o, u, P, m, q, F) { var c = t.children; if (c !== void 0) if (u) if (le(c)) { for (u = 0; u < c.length; u++) A(c[u]); Object.freeze && Object.freeze(c); } 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 A(c); if (J.call(t, "key")) { c = a(e); var j = Object.keys(t).filter(function(ie) { return ie !== "key"; }); u = 0 < j.length ? "{key: someKey, " + j.join(": ..., ") + ": ...}" : "{key: someKey}", H[c + u] || (j = 0 < j.length ? "{" + j.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} />`, u, c, j, c ), H[c + u] = !0); } if (c = null, o !== void 0 && (s(o), c = "" + o), b(t) && (s(t.key), c = "" + t.key), "key" in t) { o = {}; for (var D in t) D !== "key" && (o[D] = t[D]); } else o = t; return c && p( o, typeof e == "function" ? e.displayName || e.name || "Unknown" : e ), y( e, c, m, P, l(), o, q, F ); } function A(e) { typeof e == "object" && e !== null && e.$$typeof === i && e._store && (e._store.validated = 1); } var w = ue, i = Symbol.for("react.transitional.element"), T = Symbol.for("react.portal"), x = Symbol.for("react.fragment"), f = Symbol.for("react.strict_mode"), k = Symbol.for("react.profiler"), g = Symbol.for("react.consumer"), I = Symbol.for("react.context"), re = Symbol.for("react.forward_ref"), te = Symbol.for("react.suspense"), se = Symbol.for("react.suspense_list"), ae = Symbol.for("react.memo"), W = Symbol.for("react.lazy"), ne = Symbol.for("react.activity"), oe = Symbol.for("react.client.reference"), $ = w.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, J = Object.prototype.hasOwnProperty, le = Array.isArray, Y = console.createTask ? console.createTask : function() { return null; }; w = { "react-stack-bottom-frame": function(e) { return e(); } }; var z, G = {}, B = w["react-stack-bottom-frame"].bind( w, d )(), X = Y(n(d)), H = {}; S.Fragment = x, S.jsx = function(e, t, o, u, P) { var m = 1e4 > $.recentlyCreatedOwnerStacks++; return v( e, t, o, !1, u, P, m ? Error("react-stack-top-frame") : B, m ? Y(n(e)) : X ); }, S.jsxs = function(e, t, o, u, P) { var m = 1e4 > $.recentlyCreatedOwnerStacks++; return v( e, t, o, !0, u, P, m ? Error("react-stack-top-frame") : B, m ? Y(n(e)) : X ); }; }()), S; } var K; function pe() { return K || (K = 1, process.env.NODE_ENV === "production" ? N.exports = de() : N.exports = fe()), N.exports; } var E = pe(); function V(a) { var r, s, n = ""; if (typeof a == "string" || typeof a == "number") n += a; else if (typeof a == "object") if (Array.isArray(a)) { var l = a.length; for (r = 0; r < l; r++) a[r] && (s = V(a[r])) && (n && (n += " "), n += s); } else for (s in a) a[s] && (n && (n += " "), n += s); return n; } function C() { for (var a, r, s = 0, n = "", l = arguments.length; s < l; s++) (a = arguments[s]) && (r = V(a)) && (n && (n += " "), n += r); return n; } const ve = { valid: "✅", invalid: "❌" }; class ee { /** * @param name - A name for the rule * @param message - The message to return when validation fails */ // ? Idea: what about a unique id? // * Idea: consider adding a description prop constructor(r, s) { this.name = r, this.message = s; } } class U extends ee { /** * @param name - A name for the rule * @param message - The message to return when validation fails * @param pattern - The regular expression to validate the password against */ constructor(r, s, n) { super(r, s), this.pattern = n; } /** @inheritdoc */ validate(r) { return this.pattern.test(r) ? null : this.message; } } class me extends ee { /** * @param name - A name for the rule * @param message - The message to return when validation fails * @param validator - A function that returns true if the password is valid */ constructor(r, s, n) { super(r, s), this.validator = n; } /** @inheritdoc */ validate(r) { return this.validator(r) ? null : this.message; } } class _e { /** * Validates the password against all rules. * @param password - The password to validate * @returns An array of error messages for each failed rule, or an empty array if all pass */ constructor(r) { this.rules = r; } /** * Validates the password against all rules. * @param password - The password to validate * @returns An array of error messages for each failed rule, or an empty array if all pass */ validate(r) { return this.rules.map((s) => s.validate(r)).filter((s) => s !== null); } // * Idea: Add a method to get a list of the rules that failed // * Idea: Add a method to validate all the rules // * Idea: Add a method to get a list of the rules that passed // * Idea: Add a method to get all the rules names and probably the messages and the validator function or the regex } const be = (a) => !/(.)\1\1/.test(a), Ee = new _e([ new U( "specialChar", "Must include at least one special character (!@#$%^&*)", /[!@#$%^&*]/ ), new U("number", "Must include at least one number", /[0-9]/), new U("uppercase", "Must include at least one uppercase letter", /[A-Z]/), new me( "noConsecutive", "Must not have three or more consecutive identical characters", be ) ]), Re = (a, r, s) => { const [n, l] = M(""), [d, b] = M(!0), [p, R] = M( a.rules.map((i) => ({ rule: i, isValid: !1 })) ), y = p.some((i) => !i.isValid); ce(() => { r == null || r(!1, p), s == null || s(""); }, []); const v = L( (i) => { if (i.length === 0) { const f = a.rules.map((k) => ({ rule: k, isValid: !1 })); return R(f), r == null || r(!1, f), !1; } const T = a.rules.map((f) => ({ rule: f, isValid: f.validate(i) === null })); R(T); const x = T.every((f) => f.isValid); return r == null || r(x, T), T.every((f) => f.isValid); }, [a, r] ), A = L( (i) => { l(i), v(i), s == null || s(i); }, [v, s] ), w = L(() => { b((i) => !i); }, []); return { inputValue: n, validationResults: p, changeInputChange: A, isPasswordVisible: d, hasInvalidRules: y, togglePasswordVisibility: w }; }, _ = { "password-validator-container": "_password-validator-container_1slrq_1", "password-validator-input-wrapper": "_password-validator-input-wrapper_1slrq_8", "password-validator-input": "_password-validator-input_1slrq_8", "password-validator-toggle": "_password-validator-toggle_1slrq_27", "password-validator-list": "_password-validator-list_1slrq_43", "password-validator-list-item": "_password-validator-list-item_1slrq_49", "password-validator-list-item-message": "_password-validator-list-item-message_1slrq_52", "is-valid": "_is-valid_1slrq_56", "is-invalid": "_is-invalid_1slrq_60" }, h = "password-validator", Te = ({ ruleSet: a = Ee, showToggle: r = !0, indicators: s = ve, onValidationChange: n, onValueChange: l, className: d, inputClassName: b, indicatorClassName: p }) => { const { inputValue: R, validationResults: y, isPasswordVisible: v, hasInvalidRules: A, changeInputChange: w, togglePasswordVisibility: i } = Re(a, n, l), T = "password-input", x = "password-validation-list"; return /* @__PURE__ */ E.jsxs("div", { className: C(_[`${h}-container`], d), role: "group", children: [ /* @__PURE__ */ E.jsxs("div", { className: _[`${h}-input-wrapper`], children: [ /* @__PURE__ */ E.jsx( "input", { id: T, className: C(_[`${h}-input`], b), placeholder: "Enter Password", type: v ? "text" : "password", value: R, onChange: (k) => w(k.target.value), tabIndex: 0, "aria-label": "Enter Password", "aria-describedby": R ? x : void 0, "aria-invalid": A, "aria-required": "true" } ), r && /* @__PURE__ */ E.jsx( "button", { id: "password-toggle", type: "button", className: _[`${h}-toggle`], onClick: i, "aria-label": v ? "Hide password" : "Show password", "aria-pressed": v, children: v ? "👁️" : "👁️‍🗨️" } ) ] }), /* @__PURE__ */ E.jsx( "div", { id: "password-rules", className: _[`${h}-rules`], role: "region", "aria-live": "polite", "aria-relevant": "additions removals", children: R && /* @__PURE__ */ E.jsx( "ul", { id: x, className: _[`${h}-list`], "aria-label": "Password requirements", children: y.map(({ rule: k, isValid: g }, I) => /* @__PURE__ */ E.jsxs( "li", { id: `rule-${I}`, className: C( _["password-validator-list-item"], { [_["is-valid"]]: g, [_["is-invalid"]]: !g }, p ), "aria-label": `${g ? "Valid" : "Invalid"}`, children: [ /* @__PURE__ */ E.jsx("span", { "aria-hidden": "true", role: "img", "aria-label": g ? "Valid" : "Invalid", children: g ? s.valid : s.invalid }), /* @__PURE__ */ E.jsx("span", { className: _[`${h}-list-item-message`], children: k.message }) ] }, k.name )) } ) } ) ] }); }; export { ve as DEFAULT_INDICATORS, me as FunctionRule, Te as PasswordValidator, U as RegExpRule, _e as RuleSet, Ee as defaultRules }; //# sourceMappingURL=password-validator.es.js.map