@connextar/house 0.11.0 → 0.13.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.
Files changed (82) hide show
  1. package/README.md +581 -19
  2. package/dist/auth/index.d.ts +3 -1
  3. package/dist/auth/index.d.ts.map +1 -1
  4. package/dist/auth/index.js +3 -1
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/auth/second-factor-index.d.ts +7 -0
  7. package/dist/auth/second-factor-index.d.ts.map +1 -0
  8. package/dist/auth/second-factor-index.js +7 -0
  9. package/dist/auth/second-factor-index.js.map +1 -0
  10. package/dist/auth/second-factor-next.d.ts +39 -0
  11. package/dist/auth/second-factor-next.d.ts.map +1 -0
  12. package/dist/auth/second-factor-next.js +131 -0
  13. package/dist/auth/second-factor-next.js.map +1 -0
  14. package/dist/auth/second-factor-routes.d.ts +29 -0
  15. package/dist/auth/second-factor-routes.d.ts.map +1 -0
  16. package/dist/auth/second-factor-routes.js +35 -0
  17. package/dist/auth/second-factor-routes.js.map +1 -0
  18. package/dist/auth/second-factor.d.ts +117 -0
  19. package/dist/auth/second-factor.d.ts.map +1 -0
  20. package/dist/auth/second-factor.js +127 -0
  21. package/dist/auth/second-factor.js.map +1 -0
  22. package/dist/auth/two-factor-policy.d.ts +30 -1
  23. package/dist/auth/two-factor-policy.d.ts.map +1 -1
  24. package/dist/auth/two-factor-policy.js +39 -1
  25. package/dist/auth/two-factor-policy.js.map +1 -1
  26. package/dist/jobs/health.d.ts +17 -4
  27. package/dist/jobs/health.d.ts.map +1 -1
  28. package/dist/jobs/health.js +10 -7
  29. package/dist/jobs/health.js.map +1 -1
  30. package/dist/jobs/index.d.ts +4 -3
  31. package/dist/jobs/index.d.ts.map +1 -1
  32. package/dist/jobs/index.js +3 -2
  33. package/dist/jobs/index.js.map +1 -1
  34. package/dist/jobs/job-health-list.d.ts +15 -3
  35. package/dist/jobs/job-health-list.d.ts.map +1 -1
  36. package/dist/jobs/job-health-list.js +11 -7
  37. package/dist/jobs/job-health-list.js.map +1 -1
  38. package/dist/jobs/prune.d.ts +45 -0
  39. package/dist/jobs/prune.d.ts.map +1 -0
  40. package/dist/jobs/prune.js +58 -0
  41. package/dist/jobs/prune.js.map +1 -0
  42. package/dist/jobs/registry.d.ts +19 -4
  43. package/dist/jobs/registry.d.ts.map +1 -1
  44. package/dist/jobs/registry.js +16 -1
  45. package/dist/jobs/registry.js.map +1 -1
  46. package/dist/jobs/scheduler.d.ts +12 -1
  47. package/dist/jobs/scheduler.d.ts.map +1 -1
  48. package/dist/jobs/scheduler.js +24 -9
  49. package/dist/jobs/scheduler.js.map +1 -1
  50. package/dist/jobs/store.d.ts +26 -1
  51. package/dist/jobs/store.d.ts.map +1 -1
  52. package/dist/jobs/store.js +35 -4
  53. package/dist/jobs/store.js.map +1 -1
  54. package/dist/password/common.d.ts +2 -0
  55. package/dist/password/common.d.ts.map +1 -0
  56. package/dist/password/common.js +58 -0
  57. package/dist/password/common.js.map +1 -0
  58. package/dist/password/estimate-index.d.ts +10 -0
  59. package/dist/password/estimate-index.d.ts.map +1 -0
  60. package/dist/password/estimate-index.js +10 -0
  61. package/dist/password/estimate-index.js.map +1 -0
  62. package/dist/password/estimate.d.ts +65 -0
  63. package/dist/password/estimate.d.ts.map +1 -0
  64. package/dist/password/estimate.js +612 -0
  65. package/dist/password/estimate.js.map +1 -0
  66. package/dist/password/index.d.ts +22 -0
  67. package/dist/password/index.d.ts.map +1 -0
  68. package/dist/password/index.js +22 -0
  69. package/dist/password/index.js.map +1 -0
  70. package/dist/password/password-input.d.ts +55 -0
  71. package/dist/password/password-input.d.ts.map +1 -0
  72. package/dist/password/password-input.js +54 -0
  73. package/dist/password/password-input.js.map +1 -0
  74. package/dist/password/password-strength.d.ts +59 -0
  75. package/dist/password/password-strength.d.ts.map +1 -0
  76. package/dist/password/password-strength.js +74 -0
  77. package/dist/password/password-strength.js.map +1 -0
  78. package/dist/password/reveal.d.ts +56 -0
  79. package/dist/password/reveal.d.ts.map +1 -0
  80. package/dist/password/reveal.js +109 -0
  81. package/dist/password/reveal.js.map +1 -0
  82. package/package.json +19 -1
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@connextar/house/password` — the password field every form uses, and the
3
+ * strength meter for the ones where a password is being chosen.
4
+ *
5
+ * Ten apps had password fields and not one could show what had been typed.
6
+ * One showed a strength meter — a hand-rolled checklist, with an unused copy in
7
+ * a second app — and "Password1!" ticks every box on it. This is one toggle and
8
+ * one honest estimate, so a person meets the same field and the same judgement
9
+ * in every app.
10
+ *
11
+ * React is the only peer it needs. Nothing here imports a form library — the
12
+ * input forwards its ref and every prop, so react-hook-form's `register`, a
13
+ * `Controller` and plain state all fit — and nothing imports a design system:
14
+ * the look is theme-token classes replaced through `classNames`, as in
15
+ * `wizard` and `markdown`. The estimator alone, for a server, is
16
+ * `@connextar/house/password/estimate`.
17
+ */
18
+ export { estimatePasswordStrength, MAX_ANALYSED_LENGTH, PASSWORD_STRENGTH_MESSAGES, type EstimatePasswordStrengthOptions, type PasswordScore, type PasswordStrengthEstimate, type PasswordStrengthMessages, type PasswordWeakness, } from "./estimate.js";
19
+ export { PASSWORD_INPUT_CLASS_NAMES, PasswordInput, type PasswordInputClassNames, type PasswordInputProps, } from "./password-input.js";
20
+ export { PASSWORD_STRENGTH_CLASS_NAMES, PasswordStrength, type PasswordStrengthClassNames, type PasswordStrengthProps, } from "./password-strength.js";
21
+ export { usePasswordReveal, type PasswordReveal, type PasswordRevealOptions } from "./reveal.js";
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/password/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,EAC1B,KAAK,+BAA+B,EACpC,KAAK,aAAa,EAClB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,GACtB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,aAAa,EACb,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,EAChB,KAAK,0BAA0B,EAC/B,KAAK,qBAAqB,GAC3B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@connextar/house/password` — the password field every form uses, and the
3
+ * strength meter for the ones where a password is being chosen.
4
+ *
5
+ * Ten apps had password fields and not one could show what had been typed.
6
+ * One showed a strength meter — a hand-rolled checklist, with an unused copy in
7
+ * a second app — and "Password1!" ticks every box on it. This is one toggle and
8
+ * one honest estimate, so a person meets the same field and the same judgement
9
+ * in every app.
10
+ *
11
+ * React is the only peer it needs. Nothing here imports a form library — the
12
+ * input forwards its ref and every prop, so react-hook-form's `register`, a
13
+ * `Controller` and plain state all fit — and nothing imports a design system:
14
+ * the look is theme-token classes replaced through `classNames`, as in
15
+ * `wizard` and `markdown`. The estimator alone, for a server, is
16
+ * `@connextar/house/password/estimate`.
17
+ */
18
+ export { estimatePasswordStrength, MAX_ANALYSED_LENGTH, PASSWORD_STRENGTH_MESSAGES, } from "./estimate.js";
19
+ export { PASSWORD_INPUT_CLASS_NAMES, PasswordInput, } from "./password-input.js";
20
+ export { PASSWORD_STRENGTH_CLASS_NAMES, PasswordStrength, } from "./password-strength.js";
21
+ export { usePasswordReveal } from "./reveal.js";
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/password/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,0BAA0B,GAM3B,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,0BAA0B,EAC1B,aAAa,GAGd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,6BAA6B,EAC7B,gBAAgB,GAGjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAmD,MAAM,aAAa,CAAC"}
@@ -0,0 +1,55 @@
1
+ import * as React from "react";
2
+ /** Every element the input draws. Each value replaces the default for that part. */
3
+ export interface PasswordInputClassNames {
4
+ wrapper: string;
5
+ input: string;
6
+ toggle: string;
7
+ icon: string;
8
+ }
9
+ /**
10
+ * The house look: the shadcn input on the shared theme tokens, with room on the
11
+ * right for the toggle. An app whose own `Input` differs passes its classes as
12
+ * `classNames.input`; one without theme tokens replaces the parts it needs.
13
+ *
14
+ * `[&::-ms-reveal]:hidden` removes the eye Edge draws in every password field,
15
+ * which would otherwise sit beside ours.
16
+ */
17
+ export declare const PASSWORD_INPUT_CLASS_NAMES: PasswordInputClassNames;
18
+ export interface PasswordInputProps extends Omit<React.ComponentPropsWithoutRef<"input">, "type"> {
19
+ /**
20
+ * What the field is for, which decides `autoComplete`: `"current"` for
21
+ * signing in and for confirming who you are (two-factor, deleting an
22
+ * account); `"new"` wherever a password is being chosen, confirm fields
23
+ * included. An explicit `autoComplete` wins.
24
+ */
25
+ purpose?: "current" | "new";
26
+ /** Controlled reveal — one toggle shared by a new and a confirm field, say. */
27
+ revealed?: boolean;
28
+ defaultRevealed?: boolean;
29
+ onRevealedChange?: (revealed: boolean) => void;
30
+ /** The toggle's accessible name. Constant: the pressed state says whether it is on. */
31
+ toggleLabel?: string;
32
+ /** Appended to the input's classes, as with the app's own `Input`. */
33
+ className?: string;
34
+ classNames?: Partial<PasswordInputClassNames>;
35
+ }
36
+ /**
37
+ * A password field with a show/hide toggle — the one every form in every app
38
+ * uses, whatever it is asking for.
39
+ *
40
+ * A drop-in for `<Input type="password">`: every input prop and the ref pass
41
+ * straight through, so `{...register("password")}`, a `Controller`'s `field`
42
+ * and plain `value`/`onChange` state all work unchanged.
43
+ *
44
+ * The toggle is a real `<button type="button">` inside the field, so it never
45
+ * submits the form and is reached with Tab. Its accessible name stays
46
+ * "Show password" and `aria-pressed` carries the state — a toggle whose label
47
+ * changed as well would be read as "Hide password, pressed", which says the
48
+ * opposite of what is on screen. The eye becomes a struck-through eye for
49
+ * everyone else.
50
+ *
51
+ * See `usePasswordReveal` for what else the toggle takes care of: focus and
52
+ * caret kept, hidden again on submit, no spellcheck.
53
+ */
54
+ export declare const PasswordInput: React.ForwardRefExoticComponent<PasswordInputProps & React.RefAttributes<HTMLInputElement>>;
55
+ //# sourceMappingURL=password-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-input.d.ts","sourceRoot":"","sources":["../../src/password/password-input.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,oFAAoF;AACpF,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,EAAE,uBAOxC,CAAC;AAEF,MAAM,WAAW,kBAAmB,SAAQ,IAAI,CAAC,KAAK,CAAC,wBAAwB,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC/F;;;;;OAKG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAC5B,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAC;CAC/C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,aAAa,6FA6CxB,CAAC"}
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Eye, EyeOff } from "lucide-react";
4
+ import * as React from "react";
5
+ import { cx } from "../internal/cx.js";
6
+ import { mergeRefs, usePasswordReveal } from "./reveal.js";
7
+ /**
8
+ * The house look: the shadcn input on the shared theme tokens, with room on the
9
+ * right for the toggle. An app whose own `Input` differs passes its classes as
10
+ * `classNames.input`; one without theme tokens replaces the parts it needs.
11
+ *
12
+ * `[&::-ms-reveal]:hidden` removes the eye Edge draws in every password field,
13
+ * which would otherwise sit beside ours.
14
+ */
15
+ export const PASSWORD_INPUT_CLASS_NAMES = {
16
+ wrapper: "relative w-full",
17
+ input: "flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent py-1 pr-10 pl-3 text-base shadow-xs transition-[color,box-shadow] outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive md:text-sm [&::-ms-reveal]:hidden",
18
+ toggle: "absolute inset-y-0 right-0 flex w-9 items-center justify-center rounded-r-md text-muted-foreground transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50",
19
+ icon: "size-4",
20
+ };
21
+ /**
22
+ * A password field with a show/hide toggle — the one every form in every app
23
+ * uses, whatever it is asking for.
24
+ *
25
+ * A drop-in for `<Input type="password">`: every input prop and the ref pass
26
+ * straight through, so `{...register("password")}`, a `Controller`'s `field`
27
+ * and plain `value`/`onChange` state all work unchanged.
28
+ *
29
+ * The toggle is a real `<button type="button">` inside the field, so it never
30
+ * submits the form and is reached with Tab. Its accessible name stays
31
+ * "Show password" and `aria-pressed` carries the state — a toggle whose label
32
+ * changed as well would be read as "Hide password, pressed", which says the
33
+ * opposite of what is on screen. The eye becomes a struck-through eye for
34
+ * everyone else.
35
+ *
36
+ * See `usePasswordReveal` for what else the toggle takes care of: focus and
37
+ * caret kept, hidden again on submit, no spellcheck.
38
+ */
39
+ export const PasswordInput = React.forwardRef(function PasswordInput({ purpose = "current", revealed: revealedProp, defaultRevealed, onRevealedChange, toggleLabel = "Show password", className, classNames, id: idProp, autoComplete, disabled, ...props }, ref) {
40
+ const c = { ...PASSWORD_INPUT_CLASS_NAMES, ...classNames };
41
+ const generatedId = React.useId();
42
+ const id = idProp ?? generatedId;
43
+ const reveal = usePasswordReveal({
44
+ revealed: revealedProp,
45
+ defaultRevealed,
46
+ onRevealedChange,
47
+ inputId: id,
48
+ disabled,
49
+ });
50
+ const inputRef = React.useMemo(() => mergeRefs(ref, reveal.inputRef), [ref, reveal.inputRef]);
51
+ const Icon = reveal.revealed ? EyeOff : Eye;
52
+ return (_jsxs("div", { className: c.wrapper, children: [_jsx("input", { ...props, ...reveal.inputProps, ref: inputRef, id: id, disabled: disabled, autoComplete: autoComplete ?? (purpose === "new" ? "new-password" : "current-password"), className: cx(c.input, className) }), _jsx("button", { ...reveal.toggleProps, "aria-label": toggleLabel, className: c.toggle, children: _jsx(Icon, { "aria-hidden": "true", className: c.icon }) })] }));
53
+ });
54
+ //# sourceMappingURL=password-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-input.js","sourceRoot":"","sources":["../../src/password/password-input.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,EAAE,EAAE,MAAM,mBAAmB,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAU3D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAA4B;IACjE,OAAO,EAAE,iBAAiB;IAC1B,KAAK,EACH,wXAAwX;IAC1X,MAAM,EACJ,qQAAqQ;IACvQ,IAAI,EAAE,QAAQ;CACf,CAAC;AAqBF;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,UAAU,CAAuC,SAAS,aAAa,CACxG,EACE,OAAO,GAAG,SAAS,EACnB,QAAQ,EAAE,YAAY,EACtB,eAAe,EACf,gBAAgB,EAChB,WAAW,GAAG,eAAe,EAC7B,SAAS,EACT,UAAU,EACV,EAAE,EAAE,MAAM,EACV,YAAY,EACZ,QAAQ,EACR,GAAG,KAAK,EACT,EACD,GAAG;IAEH,MAAM,CAAC,GAA4B,EAAE,GAAG,0BAA0B,EAAE,GAAG,UAAU,EAAE,CAAC;IACpF,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IAClC,MAAM,EAAE,GAAG,MAAM,IAAI,WAAW,CAAC;IACjC,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAC/B,QAAQ,EAAE,YAAY;QACtB,eAAe;QACf,gBAAgB;QAChB,OAAO,EAAE,EAAE;QACX,QAAQ;KACT,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9F,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;IAE5C,OAAO,CACL,eAAK,SAAS,EAAE,CAAC,CAAC,OAAO,aACvB,mBACM,KAAK,KACL,MAAM,CAAC,UAAU,EACrB,GAAG,EAAE,QAAQ,EACb,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,QAAQ,EAClB,YAAY,EAAE,YAAY,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,kBAAkB,CAAC,EACvF,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,SAAS,CAAC,GACjC,EACF,oBAAY,MAAM,CAAC,WAAW,gBAAc,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,YAC1E,KAAC,IAAI,mBAAa,MAAM,EAAC,SAAS,EAAE,CAAC,CAAC,IAAI,GAAI,GACvC,IACL,CACP,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -0,0 +1,59 @@
1
+ import * as React from "react";
2
+ import { type PasswordStrengthMessages } from "./estimate.js";
3
+ /** Every element the meter draws. Each value replaces the default for that part. */
4
+ export interface PasswordStrengthClassNames {
5
+ root: string;
6
+ bar: string;
7
+ segment: string;
8
+ /** A filled segment, by score. */
9
+ score0: string;
10
+ score1: string;
11
+ score2: string;
12
+ score3: string;
13
+ score4: string;
14
+ text: string;
15
+ label: string;
16
+ }
17
+ /**
18
+ * The house look on the shared theme tokens, with amber and green for the two
19
+ * scores no theme token names. The root also carries `data-score`, for an app
20
+ * that styles the meter from its own stylesheet instead.
21
+ */
22
+ export declare const PASSWORD_STRENGTH_CLASS_NAMES: PasswordStrengthClassNames;
23
+ export interface PasswordStrengthProps {
24
+ /** The password being typed — the field's current value. */
25
+ password: string;
26
+ /** The person's email, name, username, organisation, the app's name. */
27
+ userInputs?: ReadonlyArray<string | null | undefined>;
28
+ /** The app's own minimum, so the sentence can say it while the password is shorter. */
29
+ minLength?: number;
30
+ messages?: Partial<PasswordStrengthMessages>;
31
+ /**
32
+ * Put on the sentence, for the field's `aria-describedby`, so the strength is
33
+ * read with the field when someone returns to it.
34
+ */
35
+ id?: string;
36
+ /** How long typing must pause before a screen reader hears the new strength. */
37
+ announceDelay?: number;
38
+ className?: string;
39
+ classNames?: Partial<PasswordStrengthClassNames>;
40
+ }
41
+ /**
42
+ * How guessable a new password is: four bars and one plain sentence.
43
+ *
44
+ * **Only where a password is being chosen** — sign-up, reset, set, change, and a
45
+ * person setting one for someone else. Never on sign-in or a "confirm it's you"
46
+ * field: rating a password someone already has tells them nothing they can act
47
+ * on, and tells anyone watching the screen something about it.
48
+ *
49
+ * **It refuses nothing.** The meter is advice; whether a password is allowed is
50
+ * the app's rule — its minimum length, and a server check with
51
+ * `estimatePasswordStrength` if it chooses to refuse the weakest. So there is no
52
+ * `valid` here to wire a submit button to.
53
+ *
54
+ * Nothing shows for an empty field. Screen readers hear the strength once typing
55
+ * pauses and only when it has changed, through a polite live region — never a
56
+ * word per keystroke.
57
+ */
58
+ export declare function PasswordStrength({ password, userInputs, minLength, messages, id, announceDelay, className, classNames, }: PasswordStrengthProps): React.JSX.Element;
59
+ //# sourceMappingURL=password-strength.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-strength.d.ts","sourceRoot":"","sources":["../../src/password/password-strength.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAIL,KAAK,wBAAwB,EAC9B,MAAM,eAAe,CAAC;AAEvB,oFAAoF;AACpF,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;GAIG;AACH,eAAO,MAAM,6BAA6B,EAAE,0BAW3C,CAAC;AAeF,MAAM,WAAW,qBAAqB;IACpC,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,UAAU,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACtD,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAC7C;;;OAGG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gFAAgF;IAChF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC,0BAA0B,CAAC,CAAC;CAClD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,QAAQ,EACR,UAAU,EACV,SAAS,EACT,QAAQ,EACR,EAAE,EACF,aAAoB,EACpB,SAAS,EACT,UAAU,GACX,EAAE,qBAAqB,qBA8CvB"}
@@ -0,0 +1,74 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { cx } from "../internal/cx.js";
5
+ import { estimatePasswordStrength, } from "./estimate.js";
6
+ /**
7
+ * The house look on the shared theme tokens, with amber and green for the two
8
+ * scores no theme token names. The root also carries `data-score`, for an app
9
+ * that styles the meter from its own stylesheet instead.
10
+ */
11
+ export const PASSWORD_STRENGTH_CLASS_NAMES = {
12
+ root: "mt-2 space-y-1.5",
13
+ bar: "grid grid-cols-4 gap-1",
14
+ segment: "h-1 rounded-full bg-muted transition-colors",
15
+ score0: "bg-destructive",
16
+ score1: "bg-destructive",
17
+ score2: "bg-amber-500",
18
+ score3: "bg-emerald-500",
19
+ score4: "bg-emerald-600",
20
+ text: "text-xs text-muted-foreground",
21
+ label: "font-medium text-foreground",
22
+ };
23
+ /** Visually hidden, from inline style so it cannot depend on the app's CSS. */
24
+ const VISUALLY_HIDDEN = {
25
+ position: "absolute",
26
+ width: 1,
27
+ height: 1,
28
+ padding: 0,
29
+ margin: -1,
30
+ overflow: "hidden",
31
+ clip: "rect(0, 0, 0, 0)",
32
+ whiteSpace: "nowrap",
33
+ border: 0,
34
+ };
35
+ /**
36
+ * How guessable a new password is: four bars and one plain sentence.
37
+ *
38
+ * **Only where a password is being chosen** — sign-up, reset, set, change, and a
39
+ * person setting one for someone else. Never on sign-in or a "confirm it's you"
40
+ * field: rating a password someone already has tells them nothing they can act
41
+ * on, and tells anyone watching the screen something about it.
42
+ *
43
+ * **It refuses nothing.** The meter is advice; whether a password is allowed is
44
+ * the app's rule — its minimum length, and a server check with
45
+ * `estimatePasswordStrength` if it chooses to refuse the weakest. So there is no
46
+ * `valid` here to wire a submit button to.
47
+ *
48
+ * Nothing shows for an empty field. Screen readers hear the strength once typing
49
+ * pauses and only when it has changed, through a polite live region — never a
50
+ * word per keystroke.
51
+ */
52
+ export function PasswordStrength({ password, userInputs, minLength, messages, id, announceDelay = 1000, className, classNames, }) {
53
+ const c = { ...PASSWORD_STRENGTH_CLASS_NAMES, ...classNames };
54
+ const inputsKey = (userInputs ?? []).join("\u0000");
55
+ const estimate = React.useMemo(() => estimatePasswordStrength(password, {
56
+ userInputs: inputsKey ? inputsKey.split("\u0000") : [],
57
+ minLength,
58
+ messages,
59
+ }), [password, inputsKey, minLength, messages]);
60
+ const message = password ? `${estimate.label}. ${estimate.sentence}` : "";
61
+ const [announced, setAnnounced] = React.useState("");
62
+ React.useEffect(() => {
63
+ if (!message) {
64
+ setAnnounced("");
65
+ return;
66
+ }
67
+ const timer = setTimeout(() => setAnnounced(message), announceDelay);
68
+ return () => clearTimeout(timer);
69
+ }, [message, announceDelay]);
70
+ const filled = Math.max(estimate.score, 1);
71
+ const tone = c[`score${estimate.score}`];
72
+ return (_jsxs("div", { className: cx(c.root, className), "data-score": password ? estimate.score : undefined, hidden: !password, children: [password ? (_jsxs(_Fragment, { children: [_jsx("div", { className: c.bar, "aria-hidden": "true", children: [0, 1, 2, 3].map((segment) => (_jsx("span", { className: cx(c.segment, segment < filled && tone) }, segment))) }), _jsxs("p", { id: id, className: c.text, children: [_jsxs("span", { className: c.label, children: [estimate.label, "."] }), " ", estimate.sentence] })] })) : null, _jsx("span", { role: "status", "aria-live": "polite", style: VISUALLY_HIDDEN, children: announced })] }));
73
+ }
74
+ //# sourceMappingURL=password-strength.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"password-strength.js","sourceRoot":"","sources":["../../src/password/password-strength.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import * as React from "react";
2
+ export interface PasswordRevealOptions {
3
+ /** Controlled: whether the password is shown. Pair with `onRevealedChange`. */
4
+ revealed?: boolean;
5
+ /** Uncontrolled starting state. Hidden unless said otherwise. */
6
+ defaultRevealed?: boolean;
7
+ onRevealedChange?: (revealed: boolean) => void;
8
+ /** The input's id, for the toggle's `aria-controls`. */
9
+ inputId: string;
10
+ disabled?: boolean;
11
+ }
12
+ export interface PasswordReveal {
13
+ revealed: boolean;
14
+ setRevealed: (revealed: boolean) => void;
15
+ toggle: () => void;
16
+ /** Attach to the password input, merged with any ref of the host's own. */
17
+ inputRef: React.RefCallback<HTMLInputElement>;
18
+ /** Spread onto the input, after the host's own props. */
19
+ inputProps: {
20
+ type: "password" | "text";
21
+ spellCheck: false;
22
+ autoCapitalize: "off";
23
+ autoCorrect: "off";
24
+ "data-revealed": boolean;
25
+ };
26
+ /** Spread onto the toggle button. It supplies no label: give it one. */
27
+ toggleProps: {
28
+ type: "button";
29
+ "aria-pressed": boolean;
30
+ "aria-controls": string;
31
+ disabled: boolean | undefined;
32
+ onClick: () => void;
33
+ onMouseDown: (event: React.MouseEvent) => void;
34
+ };
35
+ }
36
+ /**
37
+ * Show and hide a password, with everything a bare `type` switch gets wrong.
38
+ * `PasswordInput` is built on this; an app whose field is not a plain input —
39
+ * an MUI `TextField`, a floating-label row — spreads the two prop sets itself
40
+ * and keeps the same behaviour.
41
+ *
42
+ * - **The field keeps focus and the caret stays put.** Clicking the toggle
43
+ * would move focus to it, and switching `type` resets the selection in some
44
+ * browsers; so a pointer press never takes focus, and the caret is put back
45
+ * where it was. A keyboard user who tabbed to the toggle stays on it.
46
+ * - **It is hidden again the moment its form submits**, synchronously, before
47
+ * the browser reads the form. A password submitted from a text field is a
48
+ * value the browser may keep in its ordinary autofill history and offer in
49
+ * any other text box — the odd autocomplete a reveal must never cause.
50
+ * - **Spellcheck and autocorrect are off, always.** A revealed field is a text
51
+ * field, and enhanced spellcheck sends the text of text fields to a server.
52
+ */
53
+ export declare function usePasswordReveal({ revealed: controlled, defaultRevealed, onRevealedChange, inputId, disabled, }: PasswordRevealOptions): PasswordReveal;
54
+ /** One ref from several — the host's (react-hook-form's `register`, say) and ours. */
55
+ export declare function mergeRefs<T>(...refs: Array<React.Ref<T> | undefined>): React.RefCallback<T>;
56
+ //# sourceMappingURL=reveal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reveal.d.ts","sourceRoot":"","sources":["../../src/password/reveal.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,WAAW,qBAAqB;IACpC,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,iEAAiE;IACjE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACzC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,2EAA2E;IAC3E,QAAQ,EAAE,KAAK,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;IAC9C,yDAAyD;IACzD,UAAU,EAAE;QACV,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;QAC1B,UAAU,EAAE,KAAK,CAAC;QAClB,cAAc,EAAE,KAAK,CAAC;QACtB,WAAW,EAAE,KAAK,CAAC;QACnB,eAAe,EAAE,OAAO,CAAC;KAC1B,CAAC;IACF,wEAAwE;IACxE,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ,CAAC;QACf,cAAc,EAAE,OAAO,CAAC;QACxB,eAAe,EAAE,MAAM,CAAC;QACxB,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;QAC9B,OAAO,EAAE,MAAM,IAAI,CAAC;QACpB,WAAW,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;KAChD,CAAC;CACH;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EAAE,UAAU,EACpB,eAAuB,EACvB,gBAAgB,EAChB,OAAO,EACP,QAAQ,GACT,EAAE,qBAAqB,GAAG,cAAc,CA6ExC;AAED,sFAAsF;AACtF,wBAAgB,SAAS,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAO3F"}
@@ -0,0 +1,109 @@
1
+ "use client";
2
+ import * as React from "react";
3
+ /**
4
+ * Show and hide a password, with everything a bare `type` switch gets wrong.
5
+ * `PasswordInput` is built on this; an app whose field is not a plain input —
6
+ * an MUI `TextField`, a floating-label row — spreads the two prop sets itself
7
+ * and keeps the same behaviour.
8
+ *
9
+ * - **The field keeps focus and the caret stays put.** Clicking the toggle
10
+ * would move focus to it, and switching `type` resets the selection in some
11
+ * browsers; so a pointer press never takes focus, and the caret is put back
12
+ * where it was. A keyboard user who tabbed to the toggle stays on it.
13
+ * - **It is hidden again the moment its form submits**, synchronously, before
14
+ * the browser reads the form. A password submitted from a text field is a
15
+ * value the browser may keep in its ordinary autofill history and offer in
16
+ * any other text box — the odd autocomplete a reveal must never cause.
17
+ * - **Spellcheck and autocorrect are off, always.** A revealed field is a text
18
+ * field, and enhanced spellcheck sends the text of text fields to a server.
19
+ */
20
+ export function usePasswordReveal({ revealed: controlled, defaultRevealed = false, onRevealedChange, inputId, disabled, }) {
21
+ const [uncontrolled, setUncontrolled] = React.useState(defaultRevealed);
22
+ const revealed = controlled ?? uncontrolled;
23
+ const input = React.useRef(null);
24
+ const selection = React.useRef(null);
25
+ const latest = React.useRef({ controlled, onRevealedChange });
26
+ latest.current = { controlled, onRevealedChange };
27
+ const setRevealed = React.useCallback((next) => {
28
+ if (latest.current.controlled === undefined)
29
+ setUncontrolled(next);
30
+ latest.current.onRevealedChange?.(next);
31
+ }, []);
32
+ const toggle = React.useCallback(() => {
33
+ const node = input.current;
34
+ selection.current =
35
+ node && node.ownerDocument.activeElement === node ? [node.selectionStart, node.selectionEnd] : null;
36
+ setRevealed(!revealed);
37
+ }, [revealed, setRevealed]);
38
+ // Put the caret back after the type switch, while the field still has focus.
39
+ React.useLayoutEffect(() => {
40
+ const node = input.current;
41
+ const kept = selection.current;
42
+ selection.current = null;
43
+ if (!node || !kept || node.ownerDocument.activeElement !== node)
44
+ return;
45
+ const [start, end] = kept;
46
+ if (start !== null && end !== null)
47
+ node.setSelectionRange(start, end);
48
+ }, [revealed]);
49
+ const hideOnSubmit = React.useRef(null);
50
+ hideOnSubmit.current = () => {
51
+ // Before React re-renders: the browser reads the form as soon as this returns.
52
+ if (input.current)
53
+ input.current.type = "password";
54
+ if (revealed)
55
+ setRevealed(false);
56
+ };
57
+ const [form, setForm] = React.useState(null);
58
+ const inputRef = React.useCallback((node) => {
59
+ input.current = node;
60
+ // Only on attach: a ref detached and re-attached between renders must not churn state.
61
+ if (node)
62
+ setForm(node.form);
63
+ }, []);
64
+ React.useEffect(() => {
65
+ if (!form)
66
+ return;
67
+ const hide = () => hideOnSubmit.current?.();
68
+ form.addEventListener("submit", hide);
69
+ form.addEventListener("reset", hide);
70
+ return () => {
71
+ form.removeEventListener("submit", hide);
72
+ form.removeEventListener("reset", hide);
73
+ };
74
+ }, [form]);
75
+ return {
76
+ revealed,
77
+ setRevealed,
78
+ toggle,
79
+ inputRef,
80
+ inputProps: {
81
+ type: revealed ? "text" : "password",
82
+ spellCheck: false,
83
+ autoCapitalize: "off",
84
+ autoCorrect: "off",
85
+ "data-revealed": revealed,
86
+ },
87
+ toggleProps: {
88
+ type: "button",
89
+ "aria-pressed": revealed,
90
+ "aria-controls": inputId,
91
+ disabled,
92
+ onClick: toggle,
93
+ // A pointer press must not take focus from the field.
94
+ onMouseDown: (event) => event.preventDefault(),
95
+ },
96
+ };
97
+ }
98
+ /** One ref from several — the host's (react-hook-form's `register`, say) and ours. */
99
+ export function mergeRefs(...refs) {
100
+ return (node) => {
101
+ for (const ref of refs) {
102
+ if (typeof ref === "function")
103
+ ref(node);
104
+ else if (ref)
105
+ ref.current = node;
106
+ }
107
+ };
108
+ }
109
+ //# sourceMappingURL=reveal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reveal.js","sourceRoot":"","sources":["../../src/password/reveal.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@connextar/house",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "description": "The pieces every app we build needs and none of them should own a copy of.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -30,6 +30,10 @@
30
30
  "types": "./dist/auth/index.d.ts",
31
31
  "default": "./dist/auth/index.js"
32
32
  },
33
+ "./auth/second-factor": {
34
+ "types": "./dist/auth/second-factor-index.d.ts",
35
+ "default": "./dist/auth/second-factor-index.js"
36
+ },
33
37
  "./account": {
34
38
  "types": "./dist/account/index.d.ts",
35
39
  "default": "./dist/account/index.js"
@@ -98,6 +102,14 @@
98
102
  "types": "./dist/editor/emoji-index.d.ts",
99
103
  "default": "./dist/editor/emoji-index.js"
100
104
  },
105
+ "./password": {
106
+ "types": "./dist/password/index.d.ts",
107
+ "default": "./dist/password/index.js"
108
+ },
109
+ "./password/estimate": {
110
+ "types": "./dist/password/estimate-index.d.ts",
111
+ "default": "./dist/password/estimate-index.js"
112
+ },
101
113
  "./house.css": {
102
114
  "style": "./dist/house.css",
103
115
  "default": "./dist/house.css"
@@ -120,6 +132,7 @@
120
132
  },
121
133
  "peerDependencies": {
122
134
  "@anthropic-ai/sdk": ">=0.122.0",
135
+ "better-auth": ">=1.6.33 <1.8.0",
123
136
  "next": "^16.0.0",
124
137
  "openai": ">=7.10.0",
125
138
  "react": "^19.0.0",
@@ -142,6 +155,9 @@
142
155
  },
143
156
  "zod": {
144
157
  "optional": true
158
+ },
159
+ "better-auth": {
160
+ "optional": true
145
161
  }
146
162
  },
147
163
  "devDependencies": {
@@ -153,6 +169,8 @@
153
169
  "@types/react-dom": "^19.3.0",
154
170
  "@typescript-eslint/eslint-plugin": "^8.0.0",
155
171
  "@typescript-eslint/parser": "^8.0.0",
172
+ "better-auth": "1.7.2",
173
+ "better-auth-1-6": "npm:better-auth@1.6.33",
156
174
  "eslint": "^9.0.0",
157
175
  "jsdom": "^27.4.0",
158
176
  "next": "^16.3.3",