@costilladante/password-validator
Version:
A customizable React password validator component with accessibility features
519 lines (518 loc) • 16.3 kB
JavaScript
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