use-password-policy 2.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  "use strict";
2
3
  var __create = Object.create;
3
4
  var __defProp = Object.defineProperty;
@@ -17,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
17
18
  }
18
19
  return to;
19
20
  };
21
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
20
22
  var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
23
  // If the importer is in node compatibility mode or this is not an ESM
22
24
  // file that has been converted to a CommonJS file using a Babel-
@@ -28,251 +30,290 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
30
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
31
 
30
32
  // src/index.ts
31
- var index_exports = {};
32
- __export(index_exports, {
33
+ var src_exports = {};
34
+ __export(src_exports, {
33
35
  PasswordPolicyInput: () => PasswordPolicyInput,
34
- usePasswordPolicy: () => usePasswordPolicy
36
+ passwordPolicyInputCss: () => passwordPolicyInputCss,
37
+ usePasswordPolicy: () => usePasswordPolicy,
38
+ usePwnedPassword: () => usePwnedPassword
35
39
  });
36
- module.exports = __toCommonJS(index_exports);
40
+ module.exports = __toCommonJS(src_exports);
37
41
 
38
42
  // src/use-password-policy.ts
39
43
  var import_react = require("react");
40
- var DEFAULT_POLICIES = [
41
- {
42
- name: "minLength",
43
- optionsKey: "minLength",
44
- test: (password, options) => password.length >= options.minLength
45
- },
46
- {
47
- name: "uppercase",
48
- optionsKey: "uppercaseCheck",
49
- test: (password, options) => options.uppercaseRegex.test(password)
50
- },
51
- {
52
- name: "lowercase",
53
- optionsKey: "lowercaseCheck",
54
- test: (password, options) => options.lowercaseRegex.test(password)
55
- },
56
- {
57
- name: "number",
58
- optionsKey: "numberCheck",
59
- test: (password, options) => options.numberRegex.test(password)
60
- },
61
- {
62
- name: "specialChar",
63
- optionsKey: "specialCharCheck",
64
- test: (password, options) => options.specialCharRegex.test(password)
65
- }
66
- ];
67
- var DEFAULT_OPTIONS = {
68
- minLength: 8,
69
- lowercaseCheck: true,
70
- uppercaseCheck: true,
71
- numberCheck: true,
72
- specialCharCheck: true,
73
- customRules: [],
74
- lowercaseRegex: /[a-z]/,
75
- uppercaseRegex: /[A-Z]/,
76
- numberRegex: /\d/,
77
- specialCharRegex: /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?`~]/
78
- };
44
+ var import_core = require("use-password-policy/core");
45
+ var import_core2 = require("use-password-policy/core");
79
46
  var usePasswordPolicy = (options = {}) => {
80
47
  const { password = "" } = options;
81
- const mergedOptions = (0, import_react.useMemo)(
82
- () => ({ ...DEFAULT_OPTIONS, ...options }),
83
- [options]
84
- );
85
- const activePolicies = (0, import_react.useMemo)(() => {
86
- const activeDefaultPolicies = DEFAULT_POLICIES.filter(
87
- (policy) => policy.optionsKey && mergedOptions[policy.optionsKey]
88
- );
89
- return [...activeDefaultPolicies, ...mergedOptions.customRules];
90
- }, [mergedOptions]);
91
- const policyState = (0, import_react.useMemo)(() => {
92
- const state = {};
93
- for (const policy of activePolicies) {
94
- state[policy.name] = policy.test(password, mergedOptions);
95
- }
96
- return state;
97
- }, [password, activePolicies, mergedOptions]);
98
- const { score, label, isValid } = (0, import_react.useMemo)(() => {
99
- const passedPolicies = Object.values(policyState).filter(Boolean);
100
- const score2 = passedPolicies.length;
101
- const totalPolicies = activePolicies.length;
102
- const strengthPercentage = totalPolicies > 0 ? score2 / totalPolicies : 0;
103
- let label2 = "Very Weak";
104
- if (strengthPercentage >= 1) {
105
- label2 = "Very Strong";
106
- } else if (strengthPercentage >= 0.75) {
107
- label2 = "Strong";
108
- } else if (strengthPercentage >= 0.5) {
109
- label2 = "Medium";
110
- } else if (strengthPercentage > 0) {
111
- label2 = "Weak";
48
+ const result = (0, import_react.useMemo)(() => (0, import_core.validatePassword)(password, options), [password, options]);
49
+ const breach = options.breachCheck ? options.breachCheck === true ? {} : options.breachCheck : null;
50
+ const pwned = usePwnedPassword(password, {
51
+ enabled: Boolean(breach) && result.isValid,
52
+ debounceMs: breach == null ? void 0 : breach.debounceMs,
53
+ fetch: breach == null ? void 0 : breach.fetch,
54
+ endpoint: breach == null ? void 0 : breach.endpoint,
55
+ padding: breach == null ? void 0 : breach.padding
56
+ });
57
+ if (!breach) return { password, ...result };
58
+ return { password, ...(0, import_core.applyBreachResult)(result, { status: pwned.status, count: pwned.count }, options) };
59
+ };
60
+ function usePwnedPassword(password, options = {}) {
61
+ const { enabled = true, debounceMs = 500, fetch: customFetch, endpoint, padding } = options;
62
+ const [state, setState] = (0, import_react.useState)({ status: "idle", count: 0, isPwned: false });
63
+ (0, import_react.useEffect)(() => {
64
+ if (!enabled || !password) {
65
+ setState({ status: "idle", count: 0, isPwned: false });
66
+ return;
112
67
  }
113
- return {
114
- score: score2,
115
- label: label2,
116
- isValid: score2 === totalPolicies && totalPolicies > 0
68
+ const controller = new AbortController();
69
+ setState((s) => s.status === "checking" ? s : { status: "checking", count: 0, isPwned: false });
70
+ const timer = setTimeout(() => {
71
+ (0, import_core2.checkPwnedPassword)(password, { signal: controller.signal, fetch: customFetch, endpoint, padding }).then((count) => {
72
+ if (!controller.signal.aborted) {
73
+ setState({ status: count > 0 ? "pwned" : "safe", count, isPwned: count > 0 });
74
+ }
75
+ }).catch((error) => {
76
+ if (!controller.signal.aborted) setState({ status: "error", count: 0, isPwned: false, error });
77
+ });
78
+ }, debounceMs);
79
+ return () => {
80
+ clearTimeout(timer);
81
+ controller.abort();
117
82
  };
118
- }, [policyState, activePolicies]);
119
- return {
120
- password,
121
- policyState,
122
- isValid,
123
- strengthScore: score,
124
- strengthLabel: label
125
- };
126
- };
83
+ }, [password, enabled, debounceMs, customFetch, endpoint, padding]);
84
+ return state;
85
+ }
127
86
 
128
87
  // src/PasswordPolicyInput.tsx
88
+ var React = __toESM(require("react"));
129
89
  var import_react2 = require("react");
130
- var import_styled_components = __toESM(require("styled-components"));
131
- var import_jsx_runtime = require("react/jsx-runtime");
132
- var STRENGTH_COLOR_MAP = {
133
- "Very Weak": "var(--rpp-weak)",
134
- "Weak": "var(--rpp-weak)",
135
- "Medium": "var(--rpp-medium)",
136
- "Strong": "var(--rpp-success)",
137
- "Very Strong": "var(--rpp-success)"
138
- };
139
- var Container = import_styled_components.default.div`
140
- /* CSS variables define the component's internal theme */
90
+
91
+ // src/styles.ts
92
+ var passwordPolicyInputCss = `
93
+ :where(.rpp-root) {
141
94
  --rpp-accent: #646cff;
142
- --rpp-success: #27ae60;
95
+ --rpp-success: #1e8449;
143
96
  --rpp-danger: #c0392b;
144
- --rpp-weak: #f39c12;
145
- --rpp-medium: #d35400;
146
- --rpp-bg: #f9f9f9;
147
- --rpp-border: #e0e0e0;
148
- --rpp-text: #333;
149
-
150
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
97
+ --rpp-weak: #d35400;
98
+ --rpp-medium: #b8860b;
99
+ --rpp-bg: #ffffff;
100
+ --rpp-border: #d0d0d0;
101
+ --rpp-text: #222222;
102
+ --rpp-muted: #6b6b6b;
103
+ --rpp-radius: 6px;
104
+ font-family: inherit;
105
+ color: var(--rpp-text);
151
106
  display: flex;
152
107
  flex-direction: column;
153
108
  gap: 0.75rem;
154
- `;
155
- var InputWrapper = import_styled_components.default.div`
156
- position: relative;
157
- `;
158
- var Input = import_styled_components.default.input`
109
+ }
110
+ :where(.rpp-root) .rpp-field { position: relative; }
111
+ :where(.rpp-root) .rpp-input {
159
112
  box-sizing: border-box;
160
113
  width: 100%;
161
- padding: 0.75rem;
114
+ padding: 0.75rem 2.75rem 0.75rem 0.75rem;
162
115
  border: 1px solid var(--rpp-border);
163
- border-radius: 6px;
116
+ border-radius: var(--rpp-radius);
117
+ background: var(--rpp-bg);
118
+ color: var(--rpp-text);
119
+ font: inherit;
164
120
  font-size: 1rem;
165
-
166
- &:focus {
167
- border-color: var(--rpp-accent);
168
- outline: none;
169
- }
170
- `;
171
- var ToggleButton = import_styled_components.default.button`
121
+ }
122
+ :where(.rpp-root) .rpp-input:focus-visible {
123
+ outline: 2px solid var(--rpp-accent);
124
+ outline-offset: 1px;
125
+ border-color: var(--rpp-accent);
126
+ }
127
+ :where(.rpp-root) .rpp-toggle {
172
128
  position: absolute;
173
129
  top: 50%;
174
- right: 0.5rem;
130
+ right: 0.375rem;
175
131
  transform: translateY(-50%);
176
- background: none;
177
- border: none;
178
- cursor: pointer;
179
- padding: 0.5rem;
180
- color: #888;
181
132
  display: flex;
182
133
  align-items: center;
183
- `;
184
- var StrengthMeter = import_styled_components.default.div`
185
- display: flex;
186
- gap: 0.25rem;
187
- height: 6px;
188
- `;
189
- var StrengthMeterSegment = import_styled_components.default.div`
134
+ padding: 0.375rem;
135
+ border: 0;
136
+ border-radius: var(--rpp-radius);
137
+ background: none;
138
+ color: var(--rpp-muted);
139
+ cursor: pointer;
140
+ }
141
+ :where(.rpp-root) .rpp-toggle:focus-visible { outline: 2px solid var(--rpp-accent); }
142
+ :where(.rpp-root) .rpp-toggle:focus:not(:focus-visible) { outline: none; }
143
+ :where(.rpp-root) .rpp-meter { display: flex; gap: 0.25rem; height: 6px; }
144
+ :where(.rpp-root) .rpp-segment {
190
145
  flex: 1;
191
- background-color: var(--rpp-border);
192
146
  border-radius: 3px;
193
- transition: background-color 0.3s;
194
-
195
- ${({ isFilled, strengthLabel }) => (
196
- // FIX: Explicitly type props
197
- isFilled && import_styled_components.css`
198
- background-color: ${STRENGTH_COLOR_MAP[strengthLabel]};
199
- `
200
- )}
201
- `;
202
- var RequirementsList = import_styled_components.default.ul`
147
+ background: var(--rpp-border);
148
+ transition: background-color 0.25s;
149
+ }
150
+ :where(.rpp-root[data-strength="very-weak"]) .rpp-segment[data-filled] { background: var(--rpp-danger); }
151
+ :where(.rpp-root[data-strength="weak"]) .rpp-segment[data-filled] { background: var(--rpp-weak); }
152
+ :where(.rpp-root[data-strength="medium"]) .rpp-segment[data-filled] { background: var(--rpp-medium); }
153
+ :where(.rpp-root[data-strength="strong"]) .rpp-segment[data-filled],
154
+ :where(.rpp-root[data-strength="very-strong"]) .rpp-segment[data-filled] { background: var(--rpp-success); }
155
+ :where(.rpp-root) .rpp-strength-label,
156
+ :where(.rpp-root) .rpp-feedback { margin: 0; font-size: 0.8125rem; color: var(--rpp-muted); }
157
+ :where(.rpp-root) .rpp-requirements {
203
158
  list-style: none;
204
- padding: 0;
205
159
  margin: 0;
160
+ padding: 0;
206
161
  display: flex;
207
162
  flex-direction: column;
208
- gap: 0.5rem;
163
+ gap: 0.375rem;
209
164
  font-size: 0.875rem;
210
- `;
211
- var RequirementItem = import_styled_components.default.li`
212
- display: flex;
213
- align-items: center;
214
- gap: 0.5rem;
215
- transition: color 0.2s;
216
- /* FIX: Explicitly type props */
217
- color: ${({ passed }) => passed ? "var(--rpp-success)" : "var(--rpp-danger)"};
218
- `;
219
- var EyeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
165
+ }
166
+ :where(.rpp-root) .rpp-requirement { display: flex; align-items: center; gap: 0.5rem; color: var(--rpp-danger); }
167
+ :where(.rpp-root) .rpp-requirement[data-passed] { color: var(--rpp-success); }
168
+ :where(.rpp-root) .rpp-requirement[data-pending] { color: var(--rpp-muted); }
169
+ :where(.rpp-root) .rpp-icon { width: 1em; text-align: center; font-weight: 700; }
170
+ :where(.rpp-root) .rpp-sr-only {
171
+ position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
172
+ overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
173
+ }
174
+ `.trim();
175
+
176
+ // src/PasswordPolicyInput.tsx
177
+ var import_jsx_runtime = require("react/jsx-runtime");
178
+ var idCounter = 0;
179
+ var useFallbackId = () => {
180
+ const [id] = (0, import_react2.useState)(() => `rpp-${++idCounter}`);
181
+ return id;
182
+ };
183
+ var _a;
184
+ var useStableId = (_a = React.useId) != null ? _a : useFallbackId;
185
+ var EyeIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { "aria-hidden": "true", focusable: "false", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
220
186
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z" }),
221
187
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "3" })
222
188
  ] });
223
- var EyeOffIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
189
+ var EyeOffIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { "aria-hidden": "true", focusable: "false", width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
224
190
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19m-6.72-1.07a3 3 0 1 1-4.24-4.24" }),
225
191
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "1", y1: "1", x2: "23", y2: "23" })
226
192
  ] });
227
- var PasswordPolicyInput = ({
228
- policyOptions,
229
- onPasswordChange,
230
- showStrengthMeter = true,
231
- showRequirementsList = true,
232
- showToggleButton = true,
233
- className,
234
- ...restInputProps
235
- }) => {
236
- const [password, setPassword] = (0, import_react2.useState)("");
237
- const [showPassword, setShowPassword] = (0, import_react2.useState)(false);
238
- const validation = usePasswordPolicy({ ...policyOptions, password });
239
- const { policyState, strengthScore, strengthLabel } = validation;
240
- (0, import_react2.useEffect)(() => {
241
- onPasswordChange?.(password, validation);
242
- }, [password, validation, onPasswordChange]);
243
- const formatPolicyName = (name) => name.replace(/([A-Z])/g, " $1").replace(/^./, (s) => s.toUpperCase());
244
- const handlePasswordChange = (e) => {
245
- setPassword(e.target.value);
246
- };
247
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Container, { className, children: [
248
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(InputWrapper, { children: [
249
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
250
- Input,
193
+ var strengthKey = (label) => label.toLowerCase().replace(/\s+/g, "-");
194
+ var PasswordPolicyInput = (0, import_react2.forwardRef)(
195
+ function PasswordPolicyInput2({
196
+ value,
197
+ defaultValue,
198
+ policyOptions,
199
+ onPasswordChange,
200
+ onChange,
201
+ showStrengthMeter = true,
202
+ showStrengthLabel = false,
203
+ showRequirementsList = true,
204
+ showToggleButton = true,
205
+ toggleLabels = { show: "Show password", hide: "Hide password" },
206
+ unstyled = false,
207
+ className,
208
+ inputClassName,
209
+ id,
210
+ "aria-describedby": ariaDescribedBy,
211
+ ...inputProps
212
+ }, ref) {
213
+ var _a2, _b;
214
+ const generatedId = useStableId();
215
+ const inputId = id != null ? id : `${generatedId}-input`;
216
+ const listId = `${generatedId}-requirements`;
217
+ const feedbackId = `${generatedId}-feedback`;
218
+ const isControlled = value !== void 0;
219
+ const [internalValue, setInternalValue] = (0, import_react2.useState)(defaultValue != null ? defaultValue : "");
220
+ const password = isControlled ? value : internalValue;
221
+ const [visible, setVisible] = (0, import_react2.useState)(false);
222
+ const validation = usePasswordPolicy({ ...policyOptions, password });
223
+ const { requirements, strengthPercent, strengthLabel, isValid, estimate } = validation;
224
+ const onPasswordChangeRef = (0, import_react2.useRef)(onPasswordChange);
225
+ onPasswordChangeRef.current = onPasswordChange;
226
+ const reportKey = `${password}\0${isValid}\0${(_b = (_a2 = validation.breach) == null ? void 0 : _a2.status) != null ? _b : ""}`;
227
+ const lastReported = (0, import_react2.useRef)(reportKey);
228
+ (0, import_react2.useEffect)(() => {
229
+ var _a3;
230
+ if (lastReported.current === reportKey) return;
231
+ lastReported.current = reportKey;
232
+ (_a3 = onPasswordChangeRef.current) == null ? void 0 : _a3.call(onPasswordChangeRef, password, validation);
233
+ });
234
+ const handleChange = (e) => {
235
+ if (!isControlled) setInternalValue(e.target.value);
236
+ onChange == null ? void 0 : onChange(e);
237
+ };
238
+ const segments = 5;
239
+ const filled = strengthPercent > 0 ? Math.max(1, Math.round(strengthPercent * segments)) : 0;
240
+ const feedback = password && (estimate == null ? void 0 : estimate.feedback);
241
+ const describedBy = [ariaDescribedBy, showRequirementsList ? listId : null, feedback ? feedbackId : null].filter(Boolean).join(" ") || void 0;
242
+ const rootClass = className ? `rpp-root ${className}` : "rpp-root";
243
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: rootClass, "data-strength": strengthKey(strengthLabel), "data-valid": isValid || void 0, children: [
244
+ !unstyled && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: passwordPolicyInputCss }),
245
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "rpp-field", children: [
246
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
247
+ "input",
248
+ {
249
+ ...inputProps,
250
+ ref,
251
+ id: inputId,
252
+ className: inputClassName ? `rpp-input ${inputClassName}` : "rpp-input",
253
+ type: visible ? "text" : "password",
254
+ value: password,
255
+ onChange: handleChange,
256
+ "aria-describedby": describedBy,
257
+ "aria-invalid": password.length > 0 && !isValid ? true : void 0
258
+ }
259
+ ),
260
+ showToggleButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
261
+ "button",
262
+ {
263
+ type: "button",
264
+ className: "rpp-toggle",
265
+ onClick: () => setVisible((v) => !v),
266
+ "aria-label": visible ? toggleLabels.hide : toggleLabels.show,
267
+ "aria-pressed": visible,
268
+ "aria-controls": inputId,
269
+ children: visible ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EyeOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EyeIcon, {})
270
+ }
271
+ )
272
+ ] }),
273
+ showStrengthMeter && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
274
+ "div",
251
275
  {
252
- type: showPassword ? "text" : "password",
253
- value: password,
254
- onChange: handlePasswordChange,
255
- ...restInputProps
276
+ className: "rpp-meter",
277
+ role: "meter",
278
+ "aria-label": "Password strength",
279
+ "aria-valuemin": 0,
280
+ "aria-valuemax": 100,
281
+ "aria-valuenow": Math.round(strengthPercent * 100),
282
+ "aria-valuetext": strengthLabel,
283
+ children: Array.from({ length: segments }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "rpp-segment", "data-filled": i < filled || void 0 }, i))
256
284
  }
257
285
  ),
258
- showToggleButton && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ToggleButton, { type: "button", onClick: () => setShowPassword(!showPassword), children: showPassword ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EyeOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(EyeIcon, {}) })
259
- ] }),
260
- showStrengthMeter && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StrengthMeter, { children: Array.from({ length: 5 }).map((_, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
261
- StrengthMeterSegment,
262
- {
263
- isFilled: strengthScore > index,
264
- strengthLabel
265
- },
266
- index
267
- )) }),
268
- showRequirementsList && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(RequirementsList, { children: Object.entries(policyState).map(([name, passed]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(RequirementItem, { passed, children: [
269
- passed ? "\u2713" : "\u2717",
270
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: formatPolicyName(name) })
271
- ] }, name)) })
272
- ] });
273
- };
286
+ showStrengthMeter && showStrengthLabel && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rpp-strength-label", children: strengthLabel }),
287
+ showStrengthMeter && feedback && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "rpp-feedback", id: feedbackId, children: feedback }),
288
+ showRequirementsList && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { className: "rpp-requirements", id: listId, "aria-label": "Password requirements", children: requirements.map(({ name, passed, message, pending }) => {
289
+ var _a3, _b2;
290
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
291
+ "li",
292
+ {
293
+ className: "rpp-requirement",
294
+ "data-passed": passed || void 0,
295
+ "data-pending": pending || void 0,
296
+ "data-rule": name,
297
+ children: [
298
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rpp-icon", "aria-hidden": "true", children: pending ? ((_a3 = validation.breach) == null ? void 0 : _a3.status) === "checking" ? "\u2026" : "\u25CB" : passed ? "\u2713" : "\u2717" }),
299
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: message }),
300
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "rpp-sr-only", children: pending ? ((_b2 = validation.breach) == null ? void 0 : _b2.status) === "checking" ? " (checking)" : " (checked once the others are met)" : passed ? " (met)" : " (not met)" })
301
+ ]
302
+ },
303
+ name
304
+ );
305
+ }) })
306
+ ] });
307
+ }
308
+ );
309
+
310
+ // src/index.ts
311
+ __reExport(src_exports, require("use-password-policy/core"), module.exports);
274
312
  // Annotate the CommonJS export names for ESM import in node:
275
313
  0 && (module.exports = {
276
314
  PasswordPolicyInput,
277
- usePasswordPolicy
315
+ passwordPolicyInputCss,
316
+ usePasswordPolicy,
317
+ usePwnedPassword,
318
+ ...require("use-password-policy/core")
278
319
  });