@udibo/oauth2 0.3.1 → 0.4.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.
|
@@ -28,7 +28,6 @@ export declare function AuthFormShell<V extends AuthFormValues>(props: {
|
|
|
28
28
|
method?: "get" | "post";
|
|
29
29
|
formRef?: Ref<HTMLFormElement>;
|
|
30
30
|
}): ReactNode;
|
|
31
|
-
/** The actions row and its submit button, disabled while the form is in flight. */
|
|
32
31
|
export declare function SubmitButton(props: {
|
|
33
32
|
isSubmitting: boolean;
|
|
34
33
|
label: string;
|
|
@@ -51,8 +50,8 @@ export declare function ErrorSummary(props: {
|
|
|
51
50
|
/**
|
|
52
51
|
* Moves keyboard focus to the first field that came back with an error after a
|
|
53
52
|
* failed submit, so a screen-reader / keyboard user lands on the control to fix
|
|
54
|
-
* (its label + error are read via `aria-describedby`) instead of being
|
|
55
|
-
*
|
|
53
|
+
* (its label + error are read via `aria-describedby`) instead of being left on
|
|
54
|
+
* the submit button. No-ops on the initial render and when the form
|
|
56
55
|
* carries a form-level error ({@link ErrorSummary} owns that focus). Call it
|
|
57
56
|
* once, unconditionally, from a form component built on {@link useAuthForm}.
|
|
58
57
|
*/
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { useEffect, useRef } from "react";
|
|
2
|
+
import { useEffect, useRef, } from "react";
|
|
3
3
|
import { AuthFormClassNamesScope, useAuthFormClassNames, } from "./class-names.js";
|
|
4
4
|
/**
|
|
5
5
|
* The single exit every default form component returns through — it owns both
|
|
@@ -18,11 +18,13 @@ export function AuthFormShell(props) {
|
|
|
18
18
|
const { name, form, className, classNames, render, rootProps, aboveForm, succeeded, children, action, method, formRef, } = props;
|
|
19
19
|
return (_jsx(AuthFormClassNamesScope, { classNames: classNames, children: render ? render(form) : (_jsxs("div", { "data-oauth2-form": name, ...rootProps, className: combineClassNames(className, classNames.root), children: [aboveForm, succeeded ?? (_jsxs("form", { onSubmit: form.handleSubmit, action: action, method: method ?? (action ? "post" : undefined), ref: formRef, noValidate: true, "data-oauth2-form-element": "", className: classNames.form, children: [_jsx(ErrorSummary, { error: form.formError, focusTrigger: form.submitCount }), children] }))] })) }));
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
function ignoreActivation(event) {
|
|
22
|
+
event.preventDefault();
|
|
23
|
+
}
|
|
22
24
|
export function SubmitButton(props) {
|
|
23
25
|
const { isSubmitting, label, submittingLabel } = props;
|
|
24
26
|
const classNames = useAuthFormClassNames();
|
|
25
|
-
return (_jsx("div", { "data-oauth2-actions": "", className: classNames.actions, children: _jsx("button", { type: "submit", disabled: isSubmitting, "data-oauth2-submit": "", className: classNames.submit, children: isSubmitting ? submittingLabel : label }) }));
|
|
27
|
+
return (_jsx("div", { "data-oauth2-actions": "", className: classNames.actions, children: _jsx("button", { type: "submit", "aria-disabled": isSubmitting ? true : undefined, onClick: isSubmitting ? ignoreActivation : undefined, "data-oauth2-submit": "", className: classNames.submit, children: isSubmitting ? submittingLabel : label }) }));
|
|
26
28
|
}
|
|
27
29
|
export function TextField(props) {
|
|
28
30
|
const { fieldProps, label, type = "text", autoComplete, required, error, inputRef, children, } = props;
|
|
@@ -46,8 +48,8 @@ export function ErrorSummary(props) {
|
|
|
46
48
|
/**
|
|
47
49
|
* Moves keyboard focus to the first field that came back with an error after a
|
|
48
50
|
* failed submit, so a screen-reader / keyboard user lands on the control to fix
|
|
49
|
-
* (its label + error are read via `aria-describedby`) instead of being
|
|
50
|
-
*
|
|
51
|
+
* (its label + error are read via `aria-describedby`) instead of being left on
|
|
52
|
+
* the submit button. No-ops on the initial render and when the form
|
|
51
53
|
* carries a form-level error ({@link ErrorSummary} owns that focus). Call it
|
|
52
54
|
* once, unconditionally, from a form component built on {@link useAuthForm}.
|
|
53
55
|
*/
|
|
@@ -113,7 +113,10 @@ export interface AuthFormClassNames extends BaseClassNames {
|
|
|
113
113
|
hint?: string;
|
|
114
114
|
/** The actions row wrapping the submit button (`data-oauth2-actions`). */
|
|
115
115
|
actions?: string;
|
|
116
|
-
/**
|
|
116
|
+
/**
|
|
117
|
+
* The submit `<button>` (`data-oauth2-submit`). It carries
|
|
118
|
+
* `aria-disabled="true"` while a submit is in flight.
|
|
119
|
+
*/
|
|
117
120
|
submit?: string;
|
|
118
121
|
/**
|
|
119
122
|
* A secondary action below the submit button (`data-oauth2-secondary`) — the
|
|
@@ -70,7 +70,11 @@ export interface AuthFormState<V extends AuthFormValues> {
|
|
|
70
70
|
formError: string | null;
|
|
71
71
|
/** Lifecycle status. */
|
|
72
72
|
status: AuthFormStatus;
|
|
73
|
-
/**
|
|
73
|
+
/**
|
|
74
|
+
* `true` while a submit is in flight (`status === "submitting"`). Mark the
|
|
75
|
+
* submit button `aria-disabled` with it, not `disabled`: disabling the
|
|
76
|
+
* focused button drops keyboard focus to `<body>`.
|
|
77
|
+
*/
|
|
74
78
|
isSubmitting: boolean;
|
|
75
79
|
/** `true` once a submit has completed successfully. */
|
|
76
80
|
succeeded: boolean;
|
|
@@ -82,7 +86,10 @@ export interface AuthFormState<V extends AuthFormValues> {
|
|
|
82
86
|
setValues(next: Partial<V>): void;
|
|
83
87
|
/** Reset values to `initialValues` and clear all errors/status. */
|
|
84
88
|
reset(): void;
|
|
85
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* Submit handler for a `<form onSubmit>`. It always calls `preventDefault`,
|
|
91
|
+
* and a submit that arrives while one is in flight is ignored.
|
|
92
|
+
*/
|
|
86
93
|
handleSubmit(event?: {
|
|
87
94
|
preventDefault(): void;
|
|
88
95
|
}): Promise<void>;
|
|
@@ -110,7 +117,9 @@ export interface AuthFormState<V extends AuthFormValues> {
|
|
|
110
117
|
* <input {...form.getFieldProps("identifier")} />
|
|
111
118
|
* <input {...form.getFieldProps("password")} type="password" />
|
|
112
119
|
* {form.formError ? <p role="alert">{form.formError}</p> : null}
|
|
113
|
-
* <button type="submit" disabled={form.isSubmitting}>
|
|
120
|
+
* <button type="submit" aria-disabled={form.isSubmitting || undefined}>
|
|
121
|
+
* Sign in
|
|
122
|
+
* </button>
|
|
114
123
|
* </form>
|
|
115
124
|
* );
|
|
116
125
|
* ```
|
|
@@ -34,7 +34,9 @@ import { useCallback, useId, useMemo, useRef, useState, } from "react";
|
|
|
34
34
|
* <input {...form.getFieldProps("identifier")} />
|
|
35
35
|
* <input {...form.getFieldProps("password")} type="password" />
|
|
36
36
|
* {form.formError ? <p role="alert">{form.formError}</p> : null}
|
|
37
|
-
* <button type="submit" disabled={form.isSubmitting}>
|
|
37
|
+
* <button type="submit" aria-disabled={form.isSubmitting || undefined}>
|
|
38
|
+
* Sign in
|
|
39
|
+
* </button>
|
|
38
40
|
* </form>
|
|
39
41
|
* );
|
|
40
42
|
* ```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@udibo/oauth2",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "A flexible OAuth2 toolkit: framework-agnostic authorization & resource servers, a typed client, Hono adapters (including a backend-for-frontend), and React bindings.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|