@hjmds/react 1.29.0 → 1.31.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/auth-screen.d.ts +18 -3
- package/dist/auth-screen.d.ts.map +1 -1
- package/dist/auth-screen.js +22 -6
- package/dist/auth-screen.js.map +1 -1
- package/dist/bottom-navigation.d.ts +7 -0
- package/dist/bottom-navigation.d.ts.map +1 -1
- package/dist/bottom-navigation.js +64 -8
- package/dist/bottom-navigation.js.map +1 -1
- package/dist/carousel.d.ts +29 -1
- package/dist/carousel.d.ts.map +1 -1
- package/dist/carousel.js +27 -3
- package/dist/carousel.js.map +1 -1
- package/dist/display.d.ts +8 -2
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +12 -7
- package/dist/display.js.map +1 -1
- package/dist/evidence.d.ts +3 -1862
- package/dist/evidence.d.ts.map +1 -1
- package/dist/evidence.js +112 -300
- package/dist/evidence.js.map +1 -1
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +2 -1
- package/dist/forms.js.map +1 -1
- package/dist/image-choice.d.ts +5 -0
- package/dist/image-choice.d.ts.map +1 -1
- package/dist/image-choice.js +4 -3
- package/dist/image-choice.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/internal/field-error.d.ts +19 -0
- package/dist/internal/field-error.d.ts.map +1 -0
- package/dist/internal/field-error.js +19 -0
- package/dist/internal/field-error.js.map +1 -0
- package/dist/internal/initial-focus.d.ts.map +1 -1
- package/dist/internal/initial-focus.js +49 -7
- package/dist/internal/initial-focus.js.map +1 -1
- package/dist/internal/media-album.d.ts +49 -0
- package/dist/internal/media-album.d.ts.map +1 -0
- package/dist/internal/media-album.js +31 -0
- package/dist/internal/media-album.js.map +1 -0
- package/dist/internal/message-reactions.d.ts +28 -2
- package/dist/internal/message-reactions.d.ts.map +1 -1
- package/dist/internal/message-reactions.js +21 -5
- package/dist/internal/message-reactions.js.map +1 -1
- package/dist/layout.d.ts +19 -3
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +10 -3
- package/dist/layout.js.map +1 -1
- package/dist/navigation.d.ts +3 -1
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +4 -2
- package/dist/navigation.js.map +1 -1
- package/dist/number-field.d.ts.map +1 -1
- package/dist/number-field.js +2 -1
- package/dist/number-field.js.map +1 -1
- package/dist/overlays.d.ts +65 -0
- package/dist/overlays.d.ts.map +1 -1
- package/dist/overlays.js +36 -3
- package/dist/overlays.js.map +1 -1
- package/dist/public-exports.generated.d.ts +221 -0
- package/dist/public-exports.generated.d.ts.map +1 -0
- package/dist/public-exports.generated.js +670 -0
- package/dist/public-exports.generated.js.map +1 -0
- package/dist/screen-flows.d.ts +104 -12
- package/dist/screen-flows.d.ts.map +1 -1
- package/dist/screen-flows.js +87 -18
- package/dist/screen-flows.js.map +1 -1
- package/dist/screens.d.ts +59 -8
- package/dist/screens.d.ts.map +1 -1
- package/dist/screens.js +57 -15
- package/dist/screens.js.map +1 -1
- package/dist/select.d.ts.map +1 -1
- package/dist/select.js +2 -1
- package/dist/select.js.map +1 -1
- package/dist/selection.d.ts.map +1 -1
- package/dist/selection.js +3 -2
- package/dist/selection.js.map +1 -1
- package/dist/steps.d.ts +11 -1
- package/dist/steps.d.ts.map +1 -1
- package/dist/steps.js +11 -6
- package/dist/steps.js.map +1 -1
- package/dist/styles.css +139 -20
- package/dist/styles.layered.css +139 -20
- package/dist/supplemental-display.d.ts.map +1 -1
- package/dist/supplemental-display.js +2 -48
- package/dist/supplemental-display.js.map +1 -1
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +1 -0
- package/dist/theme.js.map +1 -1
- package/package.json +3 -3
package/dist/auth-screen.d.ts
CHANGED
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { type AuthScreenDensity, type AuthScreenDescriptor, type AuthScreenHeroDescriptor, type AuthScreenPolicyLinkDescriptor } from "@hjmds/design-contracts/components/auth-screen";
|
|
2
2
|
import { type HTMLAttributeAnchorTarget, type HTMLAttributes, type ReactNode } from "react";
|
|
3
3
|
import { type ScreenInitialFocus } from "@hjmds/design-contracts/screen-patterns";
|
|
4
|
+
import { type ScreenExit } from "./internal/screen-exit.js";
|
|
4
5
|
import type { HjmCompositionStyleProp } from "./composition-style.js";
|
|
5
|
-
export type AuthScreenLayoutProps = Omit<HTMLAttributes<HTMLElement>, "children"> & AuthScreenDescriptor & Readonly<{
|
|
6
|
+
export type AuthScreenLayoutProps = Omit<HTMLAttributes<HTMLElement>, "children" | "title"> & AuthScreenDescriptor & Readonly<{
|
|
6
7
|
/** Use section inside a product shell that already owns the main landmark. */
|
|
7
8
|
as?: "main" | "section";
|
|
9
|
+
/**
|
|
10
|
+
* Route name in the shared screen header band (screenHeaderRecipe, centered like ScreenLayout). Login and signup
|
|
11
|
+
* routes kept a TopBar above this layout only for the route name + back/close (2026-10-18: utilverse, burntok).
|
|
12
|
+
*/
|
|
13
|
+
title?: string;
|
|
14
|
+
/** Leaving the route: the same icon-only back/close as ScreenLayout `exit`, at the header's leading edge. */
|
|
15
|
+
exit?: ScreenExit;
|
|
8
16
|
/** Product mark, title and description. The product owns every string here. */
|
|
9
17
|
hero: ReactNode;
|
|
10
18
|
/** The primary action block — provider buttons, or a product's own sign-in bundle. */
|
|
@@ -29,12 +37,19 @@ export type AuthScreenLayoutProps = Omit<HTMLAttributes<HTMLElement>, "children"
|
|
|
29
37
|
* the bottom. The measurements come from the resolved descriptor as custom
|
|
30
38
|
* properties so the stylesheet keeps one source of truth with the contract.
|
|
31
39
|
*/
|
|
32
|
-
export declare const AuthScreenLayout: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "children"> & Readonly<{
|
|
40
|
+
export declare const AuthScreenLayout: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLElement>, "title" | "children"> & Readonly<{
|
|
33
41
|
density?: AuthScreenDensity;
|
|
34
42
|
hasFooter?: boolean;
|
|
35
43
|
}> & Readonly<{
|
|
36
44
|
/** Use section inside a product shell that already owns the main landmark. */
|
|
37
45
|
as?: "main" | "section";
|
|
46
|
+
/**
|
|
47
|
+
* Route name in the shared screen header band (screenHeaderRecipe, centered like ScreenLayout). Login and signup
|
|
48
|
+
* routes kept a TopBar above this layout only for the route name + back/close (2026-10-18: utilverse, burntok).
|
|
49
|
+
*/
|
|
50
|
+
title?: string;
|
|
51
|
+
/** Leaving the route: the same icon-only back/close as ScreenLayout `exit`, at the header's leading edge. */
|
|
52
|
+
exit?: ScreenExit;
|
|
38
53
|
/** Product mark, title and description. The product owns every string here. */
|
|
39
54
|
hero: ReactNode;
|
|
40
55
|
/** The primary action block — provider buttons, or a product's own sign-in bundle. */
|
|
@@ -63,7 +78,7 @@ export type AuthScreenHeroProps = AuthScreenHeroDescriptor & Readonly<{
|
|
|
63
78
|
* product supplies the strings and mark; the type steps, tones and gaps come from
|
|
64
79
|
* `authScreenRecipe.hero` so a login slogan never borrows the page-heading size.
|
|
65
80
|
*/
|
|
66
|
-
export declare function AuthScreenHero({ mark, title, eyebrow, description, headingLevel }: AuthScreenHeroProps): import("react").JSX.Element;
|
|
81
|
+
export declare function AuthScreenHero({ mark, title, eyebrow, description, headingLevel: suppliedHeadingLevel }: AuthScreenHeroProps): import("react").JSX.Element;
|
|
67
82
|
export type AuthScreenPolicyLink = AuthScreenPolicyLinkDescriptor & Readonly<{
|
|
68
83
|
/** Document URL; renders an anchor. */
|
|
69
84
|
href?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-screen.d.ts","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EACpC,MAAM,gDAAgD,CAAC;AAExD,OAAO,EAA+G,KAAK,yBAAyB,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAS,MAAM,OAAO,CAAC;AAChN,OAAO,
|
|
1
|
+
{"version":3,"file":"auth-screen.d.ts","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,iBAAiB,EACtB,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,8BAA8B,EACpC,MAAM,gDAAgD,CAAC;AAExD,OAAO,EAA+G,KAAK,yBAAyB,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAS,MAAM,OAAO,CAAC;AAChN,OAAO,EAAqF,KAAK,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAGrK,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE9E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAOtE,MAAM,MAAM,qBAAqB,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC,GACzF,oBAAoB,GACpB,QAAQ,CAAC;IACP,8EAA8E;IAC9E,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6GAA6G;IAC7G,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,+EAA+E;IAC/E,IAAI,EAAE,SAAS,CAAC;IAChB,sFAAsF;IACtF,IAAI,EAAE,SAAS,CAAC;IAChB,2FAA2F;IAC3F,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4FAA4F;IAC5F,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qEAAqE;IACrE,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;IACtC;;;OAGG;IACH,YAAY,CAAC,EAAE,kBAAkB,CAAC;CACnC,CAAC,CAAC;AAEL;;;;GAIG;AACH,eAAO,MAAM,gBAAgB;;;;IAlCzB,8EAA8E;SACzE,MAAM,GAAG,SAAS;IACvB;;;OAGG;YACK,MAAM;IACd,6GAA6G;WACtG,UAAU;IACjB,+EAA+E;UACzE,SAAS;IACf,sFAAsF;UAChF,SAAS;IACf,2FAA2F;mBAC5E,MAAM;IACrB,4FAA4F;eACjF,OAAO;IAClB,qEAAqE;aAC5D,SAAS;gBACN,MAAM;IAClB,gGAAgG;kBAClF,uBAAuB;IACrC;;;OAGG;mBACY,kBAAkB;gDAmFpC,CAAC;AASF,MAAM,MAAM,mBAAmB,GAAG,wBAAwB,GACxD,QAAQ,CAAC;IACP,yDAAyD;IACzD,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,CAAC,CAAC;AAEL;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,oBAAoB,EAAE,EAAE,mBAAmB,+BA8B5H;AAED,MAAM,MAAM,oBAAoB,GAAG,8BAA8B,GAC/D,QAAQ,CAAC;IACP,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,MAAM,CAAC,EAAE,yBAAyB,CAAC;IACnC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB,CAAC,CAAC;AAEL,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,uCAAuC;IACvC,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,iEAAiE;IACjE,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAC;IACvC,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,CAAC,CAAC;AAEH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,qBAAqB,+BA8BlF"}
|
package/dist/auth-screen.js
CHANGED
|
@@ -2,17 +2,26 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { authScreenRecipe, resolveAuthScreenDescriptor, validateAuthScreenHeroDescriptor, validateAuthScreenPolicyLinks, } from "@hjmds/design-contracts/components/auth-screen";
|
|
3
3
|
import { typography } from "@hjmds/design-contracts/foundations";
|
|
4
4
|
import { createContext, createElement, forwardRef, Fragment, useContext, useLayoutEffect, useRef, useId } from "react";
|
|
5
|
-
import { initialFocusDefaults } from "@hjmds/design-contracts/screen-patterns";
|
|
5
|
+
import { initialFocusDefaults, screenHeaderRecipe, screenPatternRecipe, validateScreenExit } from "@hjmds/design-contracts/screen-patterns";
|
|
6
6
|
import { classNames, useDesignProfileDefaults } from "./internal.js";
|
|
7
7
|
import { InitialFocusScope } from "./internal/initial-focus.js";
|
|
8
|
+
import { ScreenExitButton } from "./internal/screen-exit.js";
|
|
9
|
+
import { Heading } from "./heading.js";
|
|
8
10
|
// The hero follows the layout density without the product passing it twice.
|
|
9
11
|
const AuthScreenDensityContext = createContext(undefined);
|
|
12
|
+
// With a header title the route name is the page heading (h1), so the hero tagline steps down to h2 by default.
|
|
13
|
+
const AuthScreenTitledContext = createContext(false);
|
|
10
14
|
/**
|
|
11
15
|
* Two regions: hero + main stay one vertically centred block, the footer sits at
|
|
12
16
|
* the bottom. The measurements come from the resolved descriptor as custom
|
|
13
17
|
* properties so the stylesheet keeps one source of truth with the contract.
|
|
14
18
|
*/
|
|
15
|
-
export const AuthScreenLayout = forwardRef(function AuthScreenLayout({ hero, main, footer, density, hasFooter, pendingLabel, mainCard = false, className, as: Element = "main", layoutStyle, initialFocus = initialFocusDefaults.auth, ...props }, forwardedRef) {
|
|
19
|
+
export const AuthScreenLayout = forwardRef(function AuthScreenLayout({ title, exit, hero, main, footer, density, hasFooter, pendingLabel, mainCard = false, className, as: Element = "main", layoutStyle, initialFocus = initialFocusDefaults.auth, ...props }, forwardedRef) {
|
|
20
|
+
if (title !== undefined && !title.trim())
|
|
21
|
+
throw new TypeError("AuthScreenLayout title must not be empty");
|
|
22
|
+
if (exit)
|
|
23
|
+
validateScreenExit(exit, false);
|
|
24
|
+
const hasHeader = title !== undefined || exit !== undefined;
|
|
16
25
|
const resolved = resolveAuthScreenDescriptor({
|
|
17
26
|
...(density === undefined ? {} : { density }),
|
|
18
27
|
...(hasFooter === undefined ? {} : { hasFooter }),
|
|
@@ -33,17 +42,22 @@ export const AuthScreenLayout = forwardRef(function AuthScreenLayout({ hero, mai
|
|
|
33
42
|
}, [pending]);
|
|
34
43
|
if (pending && !pendingLabel.trim())
|
|
35
44
|
throw new TypeError("AuthScreen pendingLabel must not be empty");
|
|
36
|
-
return (
|
|
45
|
+
return (_jsxs(Element, { ...props, ref: forwardedRef, className: classNames("hjm-auth-screen", className), "data-density": resolved.density, "data-header": hasHeader || undefined, style: {
|
|
37
46
|
["--hjm-auth-screen-max-width"]: `${resolved.maxWidth}px`,
|
|
38
47
|
["--hjm-auth-screen-hero-gap"]: `${resolved.heroGap}px`,
|
|
39
48
|
["--hjm-auth-screen-main-gap"]: `${resolved.mainGap}px`,
|
|
40
49
|
["--hjm-auth-screen-footer-gap"]: `${resolved.footerGap}px`,
|
|
41
50
|
["--hjm-auth-screen-padding-inline"]: `${resolved.paddingInline}px`,
|
|
42
51
|
["--hjm-auth-screen-padding-block"]: `${resolved.paddingBlock}px`,
|
|
52
|
+
...(hasHeader ? {
|
|
53
|
+
["--hjm-auth-screen-header-padding-inline"]: `${screenPatternRecipe.padding}px`,
|
|
54
|
+
["--hjm-auth-screen-header-padding-block"]: `${screenHeaderRecipe.paddingVertical}px`,
|
|
55
|
+
["--hjm-auth-screen-header-min-height"]: `${screenHeaderRecipe.minHeight}px`,
|
|
56
|
+
} : {}),
|
|
43
57
|
...props.style,
|
|
44
58
|
...layoutStyle,
|
|
45
|
-
}, children: _jsxs(InitialFocusScope, { mode: initialFocus, children: [_jsxs("div", { className: "hjm-auth-screen__block", children: [_jsx(AuthScreenDensityContext.Provider, { value: resolved.density, children: _jsx("div", { className: "hjm-auth-screen__hero", children: hero }) }), _jsxs("div", { className: "hjm-auth-screen__main", "data-card": mainCard || undefined, "aria-busy": pending || undefined, children: [_jsx("div", { ref: actionsRef, className: "hjm-auth-screen__actions", inert: pending, "aria-hidden": pending || undefined, onFocusCapture: event => { focusedAction.current = event.target; }, onBlurCapture: event => { if (!pending && !event.currentTarget.contains(event.relatedTarget))
|
|
46
|
-
|
|
59
|
+
}, children: [hasHeader ? _jsxs("header", { className: "hjm-auth-screen__header", children: [_jsx("div", { children: exit ? _jsx(ScreenExitButton, { ...exit }) : null }), _jsx("div", { className: "hjm-auth-screen__header-title", children: title === undefined ? null : _jsx(Heading, { level: screenHeaderRecipe.centeredTitleLevel, semanticLevel: 1, children: title }) }), _jsx("div", {})] }) : null, _jsxs(InitialFocusScope, { mode: initialFocus, children: [_jsxs("div", { className: "hjm-auth-screen__block", children: [_jsx(AuthScreenDensityContext.Provider, { value: resolved.density, children: _jsx(AuthScreenTitledContext.Provider, { value: title !== undefined, children: _jsx("div", { className: "hjm-auth-screen__hero", children: hero }) }) }), _jsxs("div", { className: "hjm-auth-screen__main", "data-card": mainCard || undefined, "aria-busy": pending || undefined, children: [_jsx("div", { ref: actionsRef, className: "hjm-auth-screen__actions", inert: pending, "aria-hidden": pending || undefined, onFocusCapture: event => { focusedAction.current = event.target; }, onBlurCapture: event => { if (!pending && !event.currentTarget.contains(event.relatedTarget))
|
|
60
|
+
focusedAction.current = null; }, style: pending ? { visibility: "hidden" } : undefined, children: main }), pending ? _jsx("div", { className: "hjm-auth-screen__pending", role: "status", "aria-label": pendingLabel, children: _jsx("span", { className: "hjm-auth-provider-button__spinner", "aria-hidden": "true" }) }) : null] })] }), showFooter ? _jsx("div", { className: "hjm-auth-screen__footer", children: footer }) : null] })] }));
|
|
47
61
|
});
|
|
48
62
|
/** Token weight per variant, following the nearest design profile like `Text` does. */
|
|
49
63
|
function useTypeWeight() {
|
|
@@ -56,7 +70,9 @@ function useTypeWeight() {
|
|
|
56
70
|
* product supplies the strings and mark; the type steps, tones and gaps come from
|
|
57
71
|
* `authScreenRecipe.hero` so a login slogan never borrows the page-heading size.
|
|
58
72
|
*/
|
|
59
|
-
export function AuthScreenHero({ mark, title, eyebrow, description, headingLevel
|
|
73
|
+
export function AuthScreenHero({ mark, title, eyebrow, description, headingLevel: suppliedHeadingLevel }) {
|
|
74
|
+
const titled = useContext(AuthScreenTitledContext);
|
|
75
|
+
const headingLevel = suppliedHeadingLevel ?? (titled ? 2 : 1);
|
|
60
76
|
validateAuthScreenHeroDescriptor({ title, ...(eyebrow === undefined ? {} : { eyebrow }), ...(description === undefined ? {} : { description }), headingLevel });
|
|
61
77
|
const density = useContext(AuthScreenDensityContext);
|
|
62
78
|
const variant = resolveAuthScreenDescriptor(density === undefined ? {} : { density }).titleVariant;
|
package/dist/auth-screen.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-screen.js","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n authScreenRecipe,\n resolveAuthScreenDescriptor,\n validateAuthScreenHeroDescriptor,\n validateAuthScreenPolicyLinks,\n type AuthScreenDensity,\n type AuthScreenDescriptor,\n type AuthScreenHeroDescriptor,\n type AuthScreenPolicyLinkDescriptor,\n} from \"@hjmds/design-contracts/components/auth-screen\";\nimport { typography, type TextVariant } from \"@hjmds/design-contracts/foundations\";\nimport { createContext, createElement, forwardRef, Fragment, useContext, useLayoutEffect, useRef, type CSSProperties, type HTMLAttributeAnchorTarget, type HTMLAttributes, type ReactNode, useId } from \"react\";\nimport { initialFocusDefaults, type ScreenInitialFocus } from \"@hjmds/design-contracts/screen-patterns\";\nimport { classNames, useDesignProfileDefaults } from \"./internal.js\";\nimport { InitialFocusScope } from \"./internal/initial-focus.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\n// The hero follows the layout density without the product passing it twice.\nconst AuthScreenDensityContext = createContext<AuthScreenDensity | undefined>(undefined);\n\nexport type AuthScreenLayoutProps = Omit<HTMLAttributes<HTMLElement>, \"children\"> &\n AuthScreenDescriptor &\n Readonly<{\n /** Use section inside a product shell that already owns the main landmark. */\n as?: \"main\" | \"section\";\n /** Product mark, title and description. The product owns every string here. */\n hero: ReactNode;\n /** The primary action block — provider buttons, or a product's own sign-in bundle. */\n main: ReactNode;\n /** Product-localized progress label; presence replaces actions with one centred loader. */\n pendingLabel?: string;\n /** Let the layout own the action card; omit when the product already supplies a surface. */\n mainCard?: boolean;\n /** Consent notice and policy links. Omit with `hasFooter: false`. */\n footer?: ReactNode;\n className?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n /**\n * Entry focus, same rules as ScreenLayout `initialFocus`. Off by default because auth screens lead with provider\n * buttons; a signup nickname step opts in with `first-input` (2026-10-18 adoption, same as Native).\n */\n initialFocus?: ScreenInitialFocus;\n }>;\n\n/**\n * Two regions: hero + main stay one vertically centred block, the footer sits at\n * the bottom. The measurements come from the resolved descriptor as custom\n * properties so the stylesheet keeps one source of truth with the contract.\n */\nexport const AuthScreenLayout = forwardRef<HTMLElement, AuthScreenLayoutProps>(\n function AuthScreenLayout(\n { hero, main, footer, density, hasFooter, pendingLabel, mainCard = false, className, as: Element = \"main\", layoutStyle, initialFocus = initialFocusDefaults.auth, ...props },\n forwardedRef,\n ) {\n const resolved = resolveAuthScreenDescriptor({\n ...(density === undefined ? {} : { density }),\n ...(hasFooter === undefined ? {} : { hasFooter }),\n });\n const showFooter = resolved.hasFooter && footer !== undefined && footer !== null;\n const pending = pendingLabel !== undefined;\n const actionsRef = useRef<HTMLDivElement>(null);\n const focusedAction = useRef<HTMLElement | null>(null);\n const wasPending = useRef(pending);\n useLayoutEffect(() => {\n // Inert loading content sends keyboard focus to body. Resume at the same\n // action after failure/cancellation, unless the user moved somewhere else.\n const target = focusedAction.current;\n if (wasPending.current && !pending && document.activeElement === document.body && target?.isConnected && actionsRef.current?.contains(target)) {\n target.focus({ preventScroll: true });\n }\n wasPending.current = pending;\n }, [pending]);\n if (pending && !pendingLabel.trim()) throw new TypeError(\"AuthScreen pendingLabel must not be empty\");\n return (\n <Element\n {...props}\n ref={forwardedRef}\n className={classNames(\"hjm-auth-screen\", className)}\n data-density={resolved.density}\n style={{\n [\"--hjm-auth-screen-max-width\" as string]: `${resolved.maxWidth}px`,\n [\"--hjm-auth-screen-hero-gap\" as string]: `${resolved.heroGap}px`,\n [\"--hjm-auth-screen-main-gap\" as string]: `${resolved.mainGap}px`,\n [\"--hjm-auth-screen-footer-gap\" as string]: `${resolved.footerGap}px`,\n [\"--hjm-auth-screen-padding-inline\" as string]: `${resolved.paddingInline}px`,\n [\"--hjm-auth-screen-padding-block\" as string]: `${resolved.paddingBlock}px`,\n ...props.style,\n ...layoutStyle,\n }}\n >\n <InitialFocusScope mode={initialFocus}>\n <div className=\"hjm-auth-screen__block\">\n <AuthScreenDensityContext.Provider value={resolved.density}><div className=\"hjm-auth-screen__hero\">{hero}</div></AuthScreenDensityContext.Provider>\n <div className=\"hjm-auth-screen__main\" data-card={mainCard || undefined} aria-busy={pending || undefined}>\n {/* Keep the action block in flow so the card never collapses; inert also removes keyboard access. */}\n <div ref={actionsRef} className=\"hjm-auth-screen__actions\" inert={pending} aria-hidden={pending || undefined}\n onFocusCapture={event => { focusedAction.current = event.target; }}\n onBlurCapture={event => { if (!pending && !event.currentTarget.contains(event.relatedTarget)) focusedAction.current = null; }}\n style={pending ? { visibility: \"hidden\" } : undefined}>{main}</div>\n {pending ? <div className=\"hjm-auth-screen__pending\" role=\"status\" aria-label={pendingLabel}>\n <span className=\"hjm-auth-provider-button__spinner\" aria-hidden=\"true\" />\n </div> : null}\n </div>\n </div>\n {showFooter ? <div className=\"hjm-auth-screen__footer\">{footer}</div> : null}\n </InitialFocusScope>\n </Element>\n );\n },\n);\n\n/** Token weight per variant, following the nearest design profile like `Text` does. */\nfunction useTypeWeight(): (variant: TextVariant) => number | string {\n const profile = useDesignProfileDefaults();\n const tokens = profile?.tokens.typography ?? typography;\n return variant => tokens[variant].fontWeight;\n}\n\nexport type AuthScreenHeroProps = AuthScreenHeroDescriptor &\n Readonly<{\n /** Product mark asset. HJM never ships product marks. */\n mark?: ReactNode;\n }>;\n\n/**\n * The `hero` slot content: mark, eyebrow, tagline and one description line. The\n * product supplies the strings and mark; the type steps, tones and gaps come from\n * `authScreenRecipe.hero` so a login slogan never borrows the page-heading size.\n */\nexport function AuthScreenHero({ mark, title, eyebrow, description, headingLevel = 1 }: AuthScreenHeroProps) {\n validateAuthScreenHeroDescriptor({ title, ...(eyebrow === undefined ? {} : { eyebrow }), ...(description === undefined ? {} : { description }), headingLevel });\n const density = useContext(AuthScreenDensityContext);\n const variant = resolveAuthScreenDescriptor(density === undefined ? {} : { density }).titleVariant;\n const weight = useTypeWeight();\n const recipe = authScreenRecipe.hero;\n // Fragment: the mark and the copy are direct children of the hero so the\n // recipe hero gap separates them on both platforms.\n return (\n <Fragment>\n {mark ? <div className=\"hjm-auth-screen__mark\">{mark}</div> : null}\n <div className=\"hjm-auth-screen__copy\">\n {eyebrow ? <p className=\"hjm-text hjm-auth-screen__eyebrow\" data-variant={recipe.eyebrow.textVariant} data-font-role=\"ui\" data-tone={recipe.eyebrow.tone}\n style={{ marginBlockEnd: recipe.eyebrow.gapBelow, fontWeight: weight(recipe.eyebrow.textVariant) }}>{eyebrow}</p> : null}\n {/* A real heading element: the tagline is the route's first heading. */}\n {createElement(`h${headingLevel}`, {\n className: \"hjm-text hjm-auth-screen__title\",\n \"data-variant\": variant,\n \"data-font-role\": \"display\",\n \"data-tone\": recipe.title.tone,\n // The title step's own weight (500), not Text's regular default outside a profile.\n style: { fontWeight: weight(variant) },\n }, title)}\n {description ? <p className=\"hjm-text hjm-auth-screen__description\" data-variant={recipe.description.textVariant} data-font-role=\"ui\" data-tone={recipe.description.tone}\n style={{ marginBlockStart: recipe.description.gapAbove, fontWeight: weight(recipe.description.textVariant) }}>{description}</p> : null}\n </div>\n </Fragment>\n );\n}\n\nexport type AuthScreenPolicyLink = AuthScreenPolicyLinkDescriptor &\n Readonly<{\n /** Document URL; renders an anchor. */\n href?: string;\n /**\n * Anchor target with `href`, e.g. `_blank` for policy documents that open beside the app (diairy web lost its\n * new-tab links on adoption, 2026-10-17). `rel` defaults to \"noreferrer noopener\" for `_blank`, as on Link.\n */\n target?: HTMLAttributeAnchorTarget;\n rel?: string;\n /** In-app handler; renders a button when there is no `href`. */\n onClick?: () => void;\n }>;\n\nexport type AuthScreenFooterProps = Readonly<{\n /** Optional consent notice (LS-04). */\n notice?: ReactNode;\n /** Terms and privacy links; at least one is required (LS-04). */\n links: readonly AuthScreenPolicyLink[];\n /** Extra product content under the links. */\n children?: ReactNode;\n}>;\n\n/**\n * The `footer` slot content: consent notice plus dot-separated policy links. The\n * visible gap between two links is `linkGap` + separator + `linkGap`; the 44px\n * touch target is an invisible hit area, not visible padding.\n */\nexport function AuthScreenFooter({ notice, links, children }: AuthScreenFooterProps) {\n validateAuthScreenPolicyLinks(links);\n const recipe = authScreenRecipe.footer;\n const weight = useTypeWeight();\n const linkStyle = { fontWeight: weight(recipe.link.textVariant) };\n const hintId = useId();\n return (\n <div className=\"hjm-auth-screen__footer-content\" style={{ gap: recipe.noticeGap }}>\n {notice ? <p className=\"hjm-text\" data-variant={recipe.notice.textVariant} data-font-role=\"ui\" data-tone={recipe.notice.tone} style={{ fontWeight: weight(recipe.notice.textVariant) }}>{notice}</p> : null}\n <div className=\"hjm-auth-screen__links\" style={{\n [\"--hjm-auth-screen-link-gap\" as string]: `${recipe.linkGap}px`,\n [\"--hjm-auth-screen-link-target\" as string]: `${authScreenRecipe.footerMinTouchTarget}px`,\n } as CSSProperties}>\n {links.map((link, index) => (\n <Fragment key={`${index}:${link.label}`}>\n {index > 0 ? <span className=\"hjm-text hjm-auth-screen__separator\" data-variant={recipe.link.textVariant} data-tone={recipe.notice.tone} aria-hidden=\"true\">{recipe.separator}</span> : null}\n {link.href !== undefined\n ? <a className=\"hjm-text hjm-auth-screen__link\" data-variant={recipe.link.textVariant} data-font-role=\"ui\" data-tone={recipe.link.tone} style={linkStyle} href={link.href}\n target={link.target} rel={link.rel ?? (link.target === \"_blank\" ? \"noreferrer noopener\" : undefined)}\n aria-describedby={link.accessibilityHint === undefined ? undefined : `${hintId}-${index}`} onClick={link.onClick}>{link.label}</a>\n : <button type=\"button\" className=\"hjm-text hjm-auth-screen__link\" data-variant={recipe.link.textVariant} data-font-role=\"ui\" data-tone={recipe.link.tone} style={linkStyle}\n aria-describedby={link.accessibilityHint === undefined ? undefined : `${hintId}-${index}`} onClick={link.onClick}>{link.label}</button>}\n {/* Native announces the hint after the label; Web reads the same text as the link's description. */}\n {link.accessibilityHint === undefined ? null : <span id={`${hintId}-${index}`} className=\"hjm-visually-hidden\">{link.accessibilityHint}</span>}\n </Fragment>\n ))}\n </div>\n {children}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth-screen.js","sourceRoot":"","sources":["../src/auth-screen.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,gBAAgB,EAChB,2BAA2B,EAC3B,gCAAgC,EAChC,6BAA6B,GAK9B,MAAM,gDAAgD,CAAC;AACxD,OAAO,EAAE,UAAU,EAAoB,MAAM,qCAAqC,CAAC;AACnF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAA2F,KAAK,EAAE,MAAM,OAAO,CAAC;AAChN,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,kBAAkB,EAA2B,MAAM,yCAAyC,CAAC;AACrK,OAAO,EAAE,UAAU,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAmB,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,4EAA4E;AAC5E,MAAM,wBAAwB,GAAG,aAAa,CAAgC,SAAS,CAAC,CAAC;AACzF,gHAAgH;AAChH,MAAM,uBAAuB,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;AAkCrD;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,UAAU,CACxC,SAAS,gBAAgB,CACvB,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,QAAQ,GAAG,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,GAAG,MAAM,EAAE,WAAW,EAAE,YAAY,GAAG,oBAAoB,CAAC,IAAI,EAAE,GAAG,KAAK,EAAE,EACzL,YAAY;IAEZ,IAAI,KAAK,KAAK,SAAS,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,0CAA0C,CAAC,CAAC;IAC1G,IAAI,IAAI;QAAE,kBAAkB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,KAAK,KAAK,SAAS,IAAI,IAAI,KAAK,SAAS,CAAC;IAC5D,MAAM,QAAQ,GAAG,2BAA2B,CAAC;QAC3C,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC;QAC7C,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC;KAClD,CAAC,CAAC;IACH,MAAM,UAAU,GAAG,QAAQ,CAAC,SAAS,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,CAAC;IACjF,MAAM,OAAO,GAAG,YAAY,KAAK,SAAS,CAAC;IAC3C,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAChD,MAAM,aAAa,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IACvD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,eAAe,CAAC,GAAG,EAAE;QACnB,yEAAyE;QACzE,2EAA2E;QAC3E,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC;QACrC,IAAI,UAAU,CAAC,OAAO,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC,aAAa,KAAK,QAAQ,CAAC,IAAI,IAAI,MAAM,EAAE,WAAW,IAAI,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YAC9I,MAAM,CAAC,KAAK,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACxC,CAAC;QACD,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC/B,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACd,IAAI,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE;QAAE,MAAM,IAAI,SAAS,CAAC,2CAA2C,CAAC,CAAC;IACtG,OAAO,CACL,MAAC,OAAO,OACF,KAAK,EACT,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,UAAU,CAAC,iBAAiB,EAAE,SAAS,CAAC,kBACrC,QAAQ,CAAC,OAAO,iBACjB,SAAS,IAAI,SAAS,EACnC,KAAK,EAAE;YACL,CAAC,6BAAuC,CAAC,EAAE,GAAG,QAAQ,CAAC,QAAQ,IAAI;YACnE,CAAC,4BAAsC,CAAC,EAAE,GAAG,QAAQ,CAAC,OAAO,IAAI;YACjE,CAAC,4BAAsC,CAAC,EAAE,GAAG,QAAQ,CAAC,OAAO,IAAI;YACjE,CAAC,8BAAwC,CAAC,EAAE,GAAG,QAAQ,CAAC,SAAS,IAAI;YACrE,CAAC,kCAA4C,CAAC,EAAE,GAAG,QAAQ,CAAC,aAAa,IAAI;YAC7E,CAAC,iCAA2C,CAAC,EAAE,GAAG,QAAQ,CAAC,YAAY,IAAI;YAC3E,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;gBACd,CAAC,yCAAmD,CAAC,EAAE,GAAG,mBAAmB,CAAC,OAAO,IAAI;gBACzF,CAAC,wCAAkD,CAAC,EAAE,GAAG,kBAAkB,CAAC,eAAe,IAAI;gBAC/F,CAAC,qCAA+C,CAAC,EAAE,GAAG,kBAAkB,CAAC,SAAS,IAAI;aACvF,CAAC,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,KAAK,CAAC,KAAK;YACd,GAAG,WAAW;SACf,aAGA,SAAS,CAAC,CAAC,CAAC,kBAAQ,SAAS,EAAC,yBAAyB,aACtD,wBAAM,IAAI,CAAC,CAAC,CAAC,KAAC,gBAAgB,OAAK,IAAI,GAAI,CAAC,CAAC,CAAC,IAAI,GAAO,EACzD,cAAK,SAAS,EAAC,+BAA+B,YAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAC,OAAO,IAAC,KAAK,EAAE,kBAAkB,CAAC,kBAAkB,EAAE,aAAa,EAAE,CAAC,YAAG,KAAK,GAAW,GAAO,EAC9K,eAAO,IACA,CAAC,CAAC,CAAC,IAAI,EAChB,MAAC,iBAAiB,IAAC,IAAI,EAAE,YAAY,aACrC,eAAK,SAAS,EAAC,wBAAwB,aACrC,KAAC,wBAAwB,CAAC,QAAQ,IAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,YAAE,KAAC,uBAAuB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,KAAK,SAAS,YAAE,cAAK,SAAS,EAAC,uBAAuB,YAAE,IAAI,GAAO,GAAmC,GAAoC,EACpP,eAAK,SAAS,EAAC,uBAAuB,eAAY,QAAQ,IAAI,SAAS,eAAa,OAAO,IAAI,SAAS,aAEtG,cAAK,GAAG,EAAE,UAAU,EAAE,SAAS,EAAC,0BAA0B,EAAC,KAAK,EAAE,OAAO,iBAAe,OAAO,IAAI,SAAS,EAC1G,cAAc,EAAE,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAClE,aAAa,EAAE,KAAK,CAAC,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC;4CAAE,aAAa,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,EAC7H,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS,YAAG,IAAI,GAAO,EACpE,OAAO,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,0BAA0B,EAAC,IAAI,EAAC,QAAQ,gBAAa,YAAY,YACzF,eAAM,SAAS,EAAC,mCAAmC,iBAAa,MAAM,GAAG,GACrE,CAAC,CAAC,CAAC,IAAI,IACT,IACF,EACL,UAAU,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,yBAAyB,YAAE,MAAM,GAAO,CAAC,CAAC,CAAC,IAAI,IACxD,IACZ,CACX,CAAC;AACJ,CAAC,CACF,CAAC;AAEF,uFAAuF;AACvF,SAAS,aAAa;IACpB,MAAM,OAAO,GAAG,wBAAwB,EAAE,CAAC;IAC3C,MAAM,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC,UAAU,IAAI,UAAU,CAAC;IACxD,OAAO,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC;AAC/C,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,oBAAoB,EAAuB;IAC3H,MAAM,MAAM,GAAG,UAAU,CAAC,uBAAuB,CAAC,CAAC;IACnD,MAAM,YAAY,GAAG,oBAAoB,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9D,gCAAgC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,CAAC;IAChK,MAAM,OAAO,GAAG,UAAU,CAAC,wBAAwB,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,2BAA2B,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,YAAY,CAAC;IACnG,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC;IACrC,yEAAyE;IACzE,oDAAoD;IACpD,OAAO,CACL,MAAC,QAAQ,eACN,IAAI,CAAC,CAAC,CAAC,cAAK,SAAS,EAAC,uBAAuB,YAAE,IAAI,GAAO,CAAC,CAAC,CAAC,IAAI,EAClE,eAAK,SAAS,EAAC,uBAAuB,aACnC,OAAO,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,mCAAmC,kBAAe,MAAM,CAAC,OAAO,CAAC,WAAW,oBAAiB,IAAI,eAAY,MAAM,CAAC,OAAO,CAAC,IAAI,EACtJ,KAAK,EAAE,EAAE,cAAc,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,YAAG,OAAO,GAAK,CAAC,CAAC,CAAC,IAAI,EAEzH,aAAa,CAAC,IAAI,YAAY,EAAE,EAAE;wBACjC,SAAS,EAAE,iCAAiC;wBAC5C,cAAc,EAAE,OAAO;wBACvB,gBAAgB,EAAE,SAAS;wBAC3B,WAAW,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI;wBAC9B,mFAAmF;wBACnF,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,OAAO,CAAC,EAAE;qBACvC,EAAE,KAAK,CAAC,EACR,WAAW,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,uCAAuC,kBAAe,MAAM,CAAC,WAAW,CAAC,WAAW,oBAAiB,IAAI,eAAY,MAAM,CAAC,WAAW,CAAC,IAAI,EACtK,KAAK,EAAE,EAAE,gBAAgB,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE,YAAG,WAAW,GAAK,CAAC,CAAC,CAAC,IAAI,IACpI,IACG,CACZ,CAAC;AACJ,CAAC;AAyBD;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAyB;IACjF,6BAA6B,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,CAAC;IACvC,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;IAClE,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;IACvB,OAAO,CACL,eAAK,SAAS,EAAC,iCAAiC,EAAC,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,aAC9E,MAAM,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,UAAU,kBAAe,MAAM,CAAC,MAAM,CAAC,WAAW,oBAAiB,IAAI,eAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,YAAG,MAAM,GAAK,CAAC,CAAC,CAAC,IAAI,EAC3M,cAAK,SAAS,EAAC,wBAAwB,EAAC,KAAK,EAAE;oBAC7C,CAAC,4BAAsC,CAAC,EAAE,GAAG,MAAM,CAAC,OAAO,IAAI;oBAC/D,CAAC,+BAAyC,CAAC,EAAE,GAAG,gBAAgB,CAAC,oBAAoB,IAAI;iBACzE,YACf,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,MAAC,QAAQ,eACN,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,eAAM,SAAS,EAAC,qCAAqC,kBAAe,MAAM,CAAC,IAAI,CAAC,WAAW,eAAa,MAAM,CAAC,MAAM,CAAC,IAAI,iBAAc,MAAM,YAAE,MAAM,CAAC,SAAS,GAAQ,CAAC,CAAC,CAAC,IAAI,EAC3L,IAAI,CAAC,IAAI,KAAK,SAAS;4BACtB,CAAC,CAAC,YAAG,SAAS,EAAC,gCAAgC,kBAAe,MAAM,CAAC,IAAI,CAAC,WAAW,oBAAiB,IAAI,eAAY,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EACrK,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS,CAAC,sBAClF,IAAI,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,YAAG,IAAI,CAAC,KAAK,GAAK;4BACtI,CAAC,CAAC,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,gCAAgC,kBAAe,MAAM,CAAC,IAAI,CAAC,WAAW,oBAAiB,IAAI,eAAY,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,sBACrJ,IAAI,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,YAAG,IAAI,CAAC,KAAK,GAAU,EAE5I,IAAI,CAAC,iBAAiB,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,eAAM,EAAE,EAAE,GAAG,MAAM,IAAI,KAAK,EAAE,EAAE,SAAS,EAAC,qBAAqB,YAAE,IAAI,CAAC,iBAAiB,GAAQ,KATjI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,EAAE,CAU5B,CACZ,CAAC,GACE,EACL,QAAQ,IACL,CACP,CAAC;AACJ,CAAC","sourcesContent":["import {\n authScreenRecipe,\n resolveAuthScreenDescriptor,\n validateAuthScreenHeroDescriptor,\n validateAuthScreenPolicyLinks,\n type AuthScreenDensity,\n type AuthScreenDescriptor,\n type AuthScreenHeroDescriptor,\n type AuthScreenPolicyLinkDescriptor,\n} from \"@hjmds/design-contracts/components/auth-screen\";\nimport { typography, type TextVariant } from \"@hjmds/design-contracts/foundations\";\nimport { createContext, createElement, forwardRef, Fragment, useContext, useLayoutEffect, useRef, type CSSProperties, type HTMLAttributeAnchorTarget, type HTMLAttributes, type ReactNode, useId } from \"react\";\nimport { initialFocusDefaults, screenHeaderRecipe, screenPatternRecipe, validateScreenExit, type ScreenInitialFocus } from \"@hjmds/design-contracts/screen-patterns\";\nimport { classNames, useDesignProfileDefaults } from \"./internal.js\";\nimport { InitialFocusScope } from \"./internal/initial-focus.js\";\nimport { ScreenExitButton, type ScreenExit } from \"./internal/screen-exit.js\";\nimport { Heading } from \"./heading.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\n\n// The hero follows the layout density without the product passing it twice.\nconst AuthScreenDensityContext = createContext<AuthScreenDensity | undefined>(undefined);\n// With a header title the route name is the page heading (h1), so the hero tagline steps down to h2 by default.\nconst AuthScreenTitledContext = createContext(false);\n\nexport type AuthScreenLayoutProps = Omit<HTMLAttributes<HTMLElement>, \"children\" | \"title\"> &\n AuthScreenDescriptor &\n Readonly<{\n /** Use section inside a product shell that already owns the main landmark. */\n as?: \"main\" | \"section\";\n /**\n * Route name in the shared screen header band (screenHeaderRecipe, centered like ScreenLayout). Login and signup\n * routes kept a TopBar above this layout only for the route name + back/close (2026-10-18: utilverse, burntok).\n */\n title?: string;\n /** Leaving the route: the same icon-only back/close as ScreenLayout `exit`, at the header's leading edge. */\n exit?: ScreenExit;\n /** Product mark, title and description. The product owns every string here. */\n hero: ReactNode;\n /** The primary action block — provider buttons, or a product's own sign-in bundle. */\n main: ReactNode;\n /** Product-localized progress label; presence replaces actions with one centred loader. */\n pendingLabel?: string;\n /** Let the layout own the action card; omit when the product already supplies a surface. */\n mainCard?: boolean;\n /** Consent notice and policy links. Omit with `hasFooter: false`. */\n footer?: ReactNode;\n className?: string;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n /**\n * Entry focus, same rules as ScreenLayout `initialFocus`. Off by default because auth screens lead with provider\n * buttons; a signup nickname step opts in with `first-input` (2026-10-18 adoption, same as Native).\n */\n initialFocus?: ScreenInitialFocus;\n }>;\n\n/**\n * Two regions: hero + main stay one vertically centred block, the footer sits at\n * the bottom. The measurements come from the resolved descriptor as custom\n * properties so the stylesheet keeps one source of truth with the contract.\n */\nexport const AuthScreenLayout = forwardRef<HTMLElement, AuthScreenLayoutProps>(\n function AuthScreenLayout(\n { title, exit, hero, main, footer, density, hasFooter, pendingLabel, mainCard = false, className, as: Element = \"main\", layoutStyle, initialFocus = initialFocusDefaults.auth, ...props },\n forwardedRef,\n ) {\n if (title !== undefined && !title.trim()) throw new TypeError(\"AuthScreenLayout title must not be empty\");\n if (exit) validateScreenExit(exit, false);\n const hasHeader = title !== undefined || exit !== undefined;\n const resolved = resolveAuthScreenDescriptor({\n ...(density === undefined ? {} : { density }),\n ...(hasFooter === undefined ? {} : { hasFooter }),\n });\n const showFooter = resolved.hasFooter && footer !== undefined && footer !== null;\n const pending = pendingLabel !== undefined;\n const actionsRef = useRef<HTMLDivElement>(null);\n const focusedAction = useRef<HTMLElement | null>(null);\n const wasPending = useRef(pending);\n useLayoutEffect(() => {\n // Inert loading content sends keyboard focus to body. Resume at the same\n // action after failure/cancellation, unless the user moved somewhere else.\n const target = focusedAction.current;\n if (wasPending.current && !pending && document.activeElement === document.body && target?.isConnected && actionsRef.current?.contains(target)) {\n target.focus({ preventScroll: true });\n }\n wasPending.current = pending;\n }, [pending]);\n if (pending && !pendingLabel.trim()) throw new TypeError(\"AuthScreen pendingLabel must not be empty\");\n return (\n <Element\n {...props}\n ref={forwardedRef}\n className={classNames(\"hjm-auth-screen\", className)}\n data-density={resolved.density}\n data-header={hasHeader || undefined}\n style={{\n [\"--hjm-auth-screen-max-width\" as string]: `${resolved.maxWidth}px`,\n [\"--hjm-auth-screen-hero-gap\" as string]: `${resolved.heroGap}px`,\n [\"--hjm-auth-screen-main-gap\" as string]: `${resolved.mainGap}px`,\n [\"--hjm-auth-screen-footer-gap\" as string]: `${resolved.footerGap}px`,\n [\"--hjm-auth-screen-padding-inline\" as string]: `${resolved.paddingInline}px`,\n [\"--hjm-auth-screen-padding-block\" as string]: `${resolved.paddingBlock}px`,\n ...(hasHeader ? {\n [\"--hjm-auth-screen-header-padding-inline\" as string]: `${screenPatternRecipe.padding}px`,\n [\"--hjm-auth-screen-header-padding-block\" as string]: `${screenHeaderRecipe.paddingVertical}px`,\n [\"--hjm-auth-screen-header-min-height\" as string]: `${screenHeaderRecipe.minHeight}px`,\n } : {}),\n ...props.style,\n ...layoutStyle,\n }}\n >\n {/* The ScreenLayout centered band (same exit, gutter and title step), full-bleed above the padded block. */}\n {hasHeader ? <header className=\"hjm-auth-screen__header\">\n <div>{exit ? <ScreenExitButton {...exit} /> : null}</div>\n <div className=\"hjm-auth-screen__header-title\">{title === undefined ? null : <Heading level={screenHeaderRecipe.centeredTitleLevel} semanticLevel={1}>{title}</Heading>}</div>\n <div />\n </header> : null}\n <InitialFocusScope mode={initialFocus}>\n <div className=\"hjm-auth-screen__block\">\n <AuthScreenDensityContext.Provider value={resolved.density}><AuthScreenTitledContext.Provider value={title !== undefined}><div className=\"hjm-auth-screen__hero\">{hero}</div></AuthScreenTitledContext.Provider></AuthScreenDensityContext.Provider>\n <div className=\"hjm-auth-screen__main\" data-card={mainCard || undefined} aria-busy={pending || undefined}>\n {/* Keep the action block in flow so the card never collapses; inert also removes keyboard access. */}\n <div ref={actionsRef} className=\"hjm-auth-screen__actions\" inert={pending} aria-hidden={pending || undefined}\n onFocusCapture={event => { focusedAction.current = event.target; }}\n onBlurCapture={event => { if (!pending && !event.currentTarget.contains(event.relatedTarget)) focusedAction.current = null; }}\n style={pending ? { visibility: \"hidden\" } : undefined}>{main}</div>\n {pending ? <div className=\"hjm-auth-screen__pending\" role=\"status\" aria-label={pendingLabel}>\n <span className=\"hjm-auth-provider-button__spinner\" aria-hidden=\"true\" />\n </div> : null}\n </div>\n </div>\n {showFooter ? <div className=\"hjm-auth-screen__footer\">{footer}</div> : null}\n </InitialFocusScope>\n </Element>\n );\n },\n);\n\n/** Token weight per variant, following the nearest design profile like `Text` does. */\nfunction useTypeWeight(): (variant: TextVariant) => number | string {\n const profile = useDesignProfileDefaults();\n const tokens = profile?.tokens.typography ?? typography;\n return variant => tokens[variant].fontWeight;\n}\n\nexport type AuthScreenHeroProps = AuthScreenHeroDescriptor &\n Readonly<{\n /** Product mark asset. HJM never ships product marks. */\n mark?: ReactNode;\n }>;\n\n/**\n * The `hero` slot content: mark, eyebrow, tagline and one description line. The\n * product supplies the strings and mark; the type steps, tones and gaps come from\n * `authScreenRecipe.hero` so a login slogan never borrows the page-heading size.\n */\nexport function AuthScreenHero({ mark, title, eyebrow, description, headingLevel: suppliedHeadingLevel }: AuthScreenHeroProps) {\n const titled = useContext(AuthScreenTitledContext);\n const headingLevel = suppliedHeadingLevel ?? (titled ? 2 : 1);\n validateAuthScreenHeroDescriptor({ title, ...(eyebrow === undefined ? {} : { eyebrow }), ...(description === undefined ? {} : { description }), headingLevel });\n const density = useContext(AuthScreenDensityContext);\n const variant = resolveAuthScreenDescriptor(density === undefined ? {} : { density }).titleVariant;\n const weight = useTypeWeight();\n const recipe = authScreenRecipe.hero;\n // Fragment: the mark and the copy are direct children of the hero so the\n // recipe hero gap separates them on both platforms.\n return (\n <Fragment>\n {mark ? <div className=\"hjm-auth-screen__mark\">{mark}</div> : null}\n <div className=\"hjm-auth-screen__copy\">\n {eyebrow ? <p className=\"hjm-text hjm-auth-screen__eyebrow\" data-variant={recipe.eyebrow.textVariant} data-font-role=\"ui\" data-tone={recipe.eyebrow.tone}\n style={{ marginBlockEnd: recipe.eyebrow.gapBelow, fontWeight: weight(recipe.eyebrow.textVariant) }}>{eyebrow}</p> : null}\n {/* A real heading element: the tagline is the route's first heading. */}\n {createElement(`h${headingLevel}`, {\n className: \"hjm-text hjm-auth-screen__title\",\n \"data-variant\": variant,\n \"data-font-role\": \"display\",\n \"data-tone\": recipe.title.tone,\n // The title step's own weight (500), not Text's regular default outside a profile.\n style: { fontWeight: weight(variant) },\n }, title)}\n {description ? <p className=\"hjm-text hjm-auth-screen__description\" data-variant={recipe.description.textVariant} data-font-role=\"ui\" data-tone={recipe.description.tone}\n style={{ marginBlockStart: recipe.description.gapAbove, fontWeight: weight(recipe.description.textVariant) }}>{description}</p> : null}\n </div>\n </Fragment>\n );\n}\n\nexport type AuthScreenPolicyLink = AuthScreenPolicyLinkDescriptor &\n Readonly<{\n /** Document URL; renders an anchor. */\n href?: string;\n /**\n * Anchor target with `href`, e.g. `_blank` for policy documents that open beside the app (diairy web lost its\n * new-tab links on adoption, 2026-10-17). `rel` defaults to \"noreferrer noopener\" for `_blank`, as on Link.\n */\n target?: HTMLAttributeAnchorTarget;\n rel?: string;\n /** In-app handler; renders a button when there is no `href`. */\n onClick?: () => void;\n }>;\n\nexport type AuthScreenFooterProps = Readonly<{\n /** Optional consent notice (LS-04). */\n notice?: ReactNode;\n /** Terms and privacy links; at least one is required (LS-04). */\n links: readonly AuthScreenPolicyLink[];\n /** Extra product content under the links. */\n children?: ReactNode;\n}>;\n\n/**\n * The `footer` slot content: consent notice plus dot-separated policy links. The\n * visible gap between two links is `linkGap` + separator + `linkGap`; the 44px\n * touch target is an invisible hit area, not visible padding.\n */\nexport function AuthScreenFooter({ notice, links, children }: AuthScreenFooterProps) {\n validateAuthScreenPolicyLinks(links);\n const recipe = authScreenRecipe.footer;\n const weight = useTypeWeight();\n const linkStyle = { fontWeight: weight(recipe.link.textVariant) };\n const hintId = useId();\n return (\n <div className=\"hjm-auth-screen__footer-content\" style={{ gap: recipe.noticeGap }}>\n {notice ? <p className=\"hjm-text\" data-variant={recipe.notice.textVariant} data-font-role=\"ui\" data-tone={recipe.notice.tone} style={{ fontWeight: weight(recipe.notice.textVariant) }}>{notice}</p> : null}\n <div className=\"hjm-auth-screen__links\" style={{\n [\"--hjm-auth-screen-link-gap\" as string]: `${recipe.linkGap}px`,\n [\"--hjm-auth-screen-link-target\" as string]: `${authScreenRecipe.footerMinTouchTarget}px`,\n } as CSSProperties}>\n {links.map((link, index) => (\n <Fragment key={`${index}:${link.label}`}>\n {index > 0 ? <span className=\"hjm-text hjm-auth-screen__separator\" data-variant={recipe.link.textVariant} data-tone={recipe.notice.tone} aria-hidden=\"true\">{recipe.separator}</span> : null}\n {link.href !== undefined\n ? <a className=\"hjm-text hjm-auth-screen__link\" data-variant={recipe.link.textVariant} data-font-role=\"ui\" data-tone={recipe.link.tone} style={linkStyle} href={link.href}\n target={link.target} rel={link.rel ?? (link.target === \"_blank\" ? \"noreferrer noopener\" : undefined)}\n aria-describedby={link.accessibilityHint === undefined ? undefined : `${hintId}-${index}`} onClick={link.onClick}>{link.label}</a>\n : <button type=\"button\" className=\"hjm-text hjm-auth-screen__link\" data-variant={recipe.link.textVariant} data-font-role=\"ui\" data-tone={recipe.link.tone} style={linkStyle}\n aria-describedby={link.accessibilityHint === undefined ? undefined : `${hintId}-${index}`} onClick={link.onClick}>{link.label}</button>}\n {/* Native announces the hint after the label; Web reads the same text as the link's description. */}\n {link.accessibilityHint === undefined ? null : <span id={`${hintId}-${index}`} className=\"hjm-visually-hidden\">{link.accessibilityHint}</span>}\n </Fragment>\n ))}\n </div>\n {children}\n </div>\n );\n}\n"]}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { type BottomNavigationActivation, type BottomNavigationConfiguration, type BottomNavigationDescriptor, type ResolvedBottomNavigationItemDescriptor } from "@hjmds/design-contracts/components/bottom-navigation";
|
|
2
2
|
import { type AnchorHTMLAttributes, type HTMLAttributes, type MouseEvent, type ReactElement, type ReactNode, type RefAttributes } from "react";
|
|
3
3
|
import type { HjmCompositionStyleProp } from "./composition-style.js";
|
|
4
|
+
export type BottomNavigationInsetProviderProps = Readonly<{
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
}>;
|
|
7
|
+
/** Wrap the app shell that holds both the screens and the BottomNavigation. */
|
|
8
|
+
export declare function BottomNavigationInsetProvider({ children }: BottomNavigationInsetProviderProps): import("react").JSX.Element;
|
|
9
|
+
/** Bottom height covered by the BottomNavigation inside the nearest provider; 0 outside one. */
|
|
10
|
+
export declare function useBottomNavigationInset(): number;
|
|
4
11
|
export type BottomNavigationIconRenderProps<Key extends string = string, IconName extends string = string> = Readonly<{
|
|
5
12
|
item: ResolvedBottomNavigationItemDescriptor<Key, IconName>;
|
|
6
13
|
name: IconName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottom-navigation.d.ts","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"bottom-navigation.d.ts","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,31 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { resolveBottomNavigationActivation, resolveBottomNavigationConfiguration, resolveBottomNavigationDescriptor, } from "@hjmds/design-contracts/components/bottom-navigation";
|
|
2
|
+
import { resolveBottomNavigationActivation, resolveBottomNavigationConfiguration, resolveBottomNavigationDescriptor, validateBottomNavigationProminence, } from "@hjmds/design-contracts/components/bottom-navigation";
|
|
3
3
|
import { bottomNavigationRecipe, iconRecipe, } from "@hjmds/design-contracts/recipes";
|
|
4
|
-
import { forwardRef, useEffect, useState, } from "react";
|
|
5
|
-
import { classNames } from "./internal.js";
|
|
4
|
+
import { createContext, forwardRef, useContext, useEffect, useMemo, useRef, useState, } from "react";
|
|
5
|
+
import { assignRef, classNames } from "./internal.js";
|
|
6
6
|
import { useOptionalHjmTheme } from "./provider.js";
|
|
7
7
|
const virtualKeyboardMinimumOcclusion = 120;
|
|
8
|
+
/**
|
|
9
|
+
* Height of the viewport bottom covered by the fixed bar (safe area and a raised center circle included); 0 when
|
|
10
|
+
* there is no bar or it is hidden for the keyboard. The provider also exposes it as `--hjm-bottom-navigation-inset`,
|
|
11
|
+
* which ScreenLayout's last region adds to its bottom padding, so products stop hand-keeping a bottom spacer
|
|
12
|
+
* (2026-10-18; Native shares the same API for its `placement="overlay"` bar).
|
|
13
|
+
*/
|
|
14
|
+
const BottomNavigationInsetContext = createContext(0);
|
|
15
|
+
const BottomNavigationInsetReporterContext = createContext(null);
|
|
16
|
+
/** Wrap the app shell that holds both the screens and the BottomNavigation. */
|
|
17
|
+
export function BottomNavigationInsetProvider({ children }) {
|
|
18
|
+
const [inset, setInset] = useState(0);
|
|
19
|
+
const report = useMemo(() => (height) => {
|
|
20
|
+
const next = Number.isFinite(height) && height > 0 ? height : 0;
|
|
21
|
+
setInset(current => current === next ? current : next);
|
|
22
|
+
}, []);
|
|
23
|
+
return (_jsx(BottomNavigationInsetReporterContext.Provider, { value: report, children: _jsx(BottomNavigationInsetContext.Provider, { value: inset, children: _jsx("div", { style: { display: "contents", "--hjm-bottom-navigation-inset": `${inset}px` }, children: children }) }) }));
|
|
24
|
+
}
|
|
25
|
+
/** Bottom height covered by the BottomNavigation inside the nearest provider; 0 outside one. */
|
|
26
|
+
export function useBottomNavigationInset() {
|
|
27
|
+
return useContext(BottomNavigationInsetContext);
|
|
28
|
+
}
|
|
8
29
|
export function isUnmodifiedPrimaryBottomNavigationClick(event) {
|
|
9
30
|
return (!event.defaultPrevented &&
|
|
10
31
|
event.button === 0 &&
|
|
@@ -64,14 +85,47 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
64
85
|
...configuration,
|
|
65
86
|
...(direction === undefined ? {} : { direction }),
|
|
66
87
|
}, resolved.items.length);
|
|
88
|
+
validateBottomNavigationProminence(resolved.items, presentation);
|
|
67
89
|
const hidden = useKeyboardHidden(presentation.keyboardBehavior);
|
|
68
90
|
const density = bottomNavigationRecipe.density[presentation.density];
|
|
69
91
|
const presentationRecipe = bottomNavigationRecipe.presentations[presentation.presentation];
|
|
70
92
|
const centerGap = bottomNavigationRecipe.distributions[presentation.distribution].centerGap;
|
|
71
|
-
const iconSize =
|
|
93
|
+
const iconSize = presentation.iconSize === "standard"
|
|
94
|
+
? iconRecipe.sizes[density.icon]
|
|
95
|
+
: bottomNavigationRecipe.iconSizes[presentation.iconSize];
|
|
96
|
+
const prominentRecipe = bottomNavigationRecipe.prominentDestination;
|
|
97
|
+
// Lifting by (diameter - indicator height) keeps the prominent label on the other labels' line; an app-icon
|
|
98
|
+
// slot taller than the indicator minimum raises that height.
|
|
99
|
+
const prominentLift = prominentRecipe.diameter - Math.max(bottomNavigationRecipe.indicator.minHeight, iconSize);
|
|
100
|
+
// The part of the circle above the nav box still covers content, so the reported inset includes it.
|
|
101
|
+
const prominentOverflow = resolved.items.some((item) => item.prominent)
|
|
102
|
+
? Math.max(0, prominentLift - density.padding - presentationRecipe.outerPaddingTop)
|
|
103
|
+
: 0;
|
|
104
|
+
const navRef = useRef(null);
|
|
105
|
+
const reportInset = useContext(BottomNavigationInsetReporterContext);
|
|
106
|
+
useEffect(() => {
|
|
107
|
+
const nav = navRef.current;
|
|
108
|
+
if (!reportInset)
|
|
109
|
+
return;
|
|
110
|
+
if (hidden || !nav) {
|
|
111
|
+
reportInset(0);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const update = () => reportInset(nav.getBoundingClientRect().height + prominentOverflow);
|
|
115
|
+
update();
|
|
116
|
+
const observer = new ResizeObserver(update);
|
|
117
|
+
observer.observe(nav);
|
|
118
|
+
return () => {
|
|
119
|
+
observer.disconnect();
|
|
120
|
+
reportInset(0);
|
|
121
|
+
};
|
|
122
|
+
}, [reportInset, hidden, prominentOverflow]);
|
|
72
123
|
if (hidden)
|
|
73
124
|
return null;
|
|
74
|
-
return (_jsx("nav", { ...props, ref:
|
|
125
|
+
return (_jsx("nav", { ...props, ref: (node) => {
|
|
126
|
+
navRef.current = node;
|
|
127
|
+
assignRef(ref, node);
|
|
128
|
+
}, "aria-label": resolved.accessibilityLabel, className: classNames("hjm-bottom-navigation", className), "data-expanded-labels": (theme?.environment.textScale ?? 1) >= 1.5 || resolved.items.length > 4 ? "true" : "false", "data-density": presentation.density, "data-distribution": presentation.distribution, "data-keyboard-behavior": presentation.keyboardBehavior, "data-labels": presentation.labels, "data-selection": presentation.selection, "data-surface": presentation.surface, "data-presentation": presentation.presentation, dir: presentation.direction, style: {
|
|
75
129
|
"--hjm-bottom-navigation-center-gap": `${centerGap}px`,
|
|
76
130
|
"--hjm-bottom-navigation-columns": resolved.items.length,
|
|
77
131
|
"--hjm-bottom-navigation-half-columns": resolved.items.length / 2,
|
|
@@ -87,6 +141,8 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
87
141
|
: "none",
|
|
88
142
|
"--hjm-bottom-navigation-outer-inline": `${presentationRecipe.outerPaddingHorizontal}px`,
|
|
89
143
|
"--hjm-bottom-navigation-outer-top": `${presentationRecipe.outerPaddingTop}px`,
|
|
144
|
+
"--hjm-bottom-navigation-prominent-diameter": `${prominentRecipe.diameter}px`,
|
|
145
|
+
"--hjm-bottom-navigation-prominent-lift": `${prominentLift}px`,
|
|
90
146
|
...style,
|
|
91
147
|
...layoutStyle,
|
|
92
148
|
}, children: _jsxs("div", { className: "hjm-bottom-navigation__surface", children: [_jsx("ul", { className: "hjm-bottom-navigation__list", children: resolved.items.map((item, index) => {
|
|
@@ -96,7 +152,7 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
96
152
|
name: item.icon.name,
|
|
97
153
|
selected,
|
|
98
154
|
color: "currentColor",
|
|
99
|
-
size: iconSize,
|
|
155
|
+
size: item.prominent ? iconRecipe.sizes[prominentRecipe.icon] : iconSize,
|
|
100
156
|
strokeWidth: selected
|
|
101
157
|
? bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.selected
|
|
102
158
|
: bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.idle,
|
|
@@ -108,7 +164,7 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
108
164
|
gridColumn: getBottomNavigationGridColumn(index, resolved.items.length, presentation.distribution),
|
|
109
165
|
};
|
|
110
166
|
if (item.disabled) {
|
|
111
|
-
return (_jsx("li", { style: itemStyle, "data-selected": "false", children: _jsx("span", { "aria-disabled": "true", "aria-label": item.resolvedAccessibilityLabel, className: "hjm-bottom-navigation__item", "data-state": "disabled", role: "link", children: content }) }, item.id));
|
|
167
|
+
return (_jsx("li", { style: itemStyle, "data-selected": "false", "data-prominent": item.prominent || undefined, children: _jsx("span", { "aria-disabled": "true", "aria-label": item.resolvedAccessibilityLabel, className: "hjm-bottom-navigation__item", "data-state": "disabled", role: "link", children: content }) }, item.id));
|
|
112
168
|
}
|
|
113
169
|
const href = getHref(item);
|
|
114
170
|
if (!href.trim()) {
|
|
@@ -129,7 +185,7 @@ function BottomNavigationInner({ descriptor, configuration = {}, getHref, render
|
|
|
129
185
|
},
|
|
130
186
|
children: content,
|
|
131
187
|
};
|
|
132
|
-
return (_jsx("li", { style: itemStyle, "data-selected": selected, children: renderLink ? renderLink(linkProps) : _jsx("a", { ...linkProps }) }, item.id));
|
|
188
|
+
return (_jsx("li", { style: itemStyle, "data-selected": selected, "data-prominent": item.prominent || undefined, children: renderLink ? renderLink(linkProps) : _jsx("a", { ...linkProps }) }, item.id));
|
|
133
189
|
}) }), primaryAction ? (_jsx("div", { className: "hjm-bottom-navigation__primary-action", children: primaryAction })) : null] }) }));
|
|
134
190
|
}
|
|
135
191
|
export const BottomNavigation = forwardRef(BottomNavigationInner);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bottom-navigation.js","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveBottomNavigationActivation,\n resolveBottomNavigationConfiguration,\n resolveBottomNavigationDescriptor,\n type BottomNavigationActivation,\n type BottomNavigationConfiguration,\n type BottomNavigationDescriptor,\n type ResolvedBottomNavigationItemDescriptor,\n} from \"@hjmds/design-contracts/components/bottom-navigation\";\nimport {\n bottomNavigationRecipe,\n iconRecipe,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n forwardRef,\n useEffect,\n useState,\n type AnchorHTMLAttributes,\n type CSSProperties,\n type ForwardedRef,\n type HTMLAttributes,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\nimport { classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\n\nconst virtualKeyboardMinimumOcclusion = 120;\n\nexport type BottomNavigationIconRenderProps<\n Key extends string = string,\n IconName extends string = string,\n> = Readonly<{\n item: ResolvedBottomNavigationItemDescriptor<Key, IconName>;\n name: IconName;\n selected: boolean;\n color: \"currentColor\";\n size: number;\n strokeWidth: number;\n scale: number;\n}>;\n\nexport type BottomNavigationLinkRenderProps = AnchorHTMLAttributes<HTMLAnchorElement> &\n Readonly<{\n href: string;\n children: ReactNode;\n \"data-state\": \"idle\" | \"selected\";\n }>;\n\nexport type BottomNavigationProps<\n Key extends string = string,\n IconName extends string = string,\n> = Omit<\n HTMLAttributes<HTMLElement>,\n \"aria-label\" | \"aria-labelledby\" | \"children\" | \"dir\" | \"onChange\" | \"role\"\n> &\n Readonly<{\n descriptor: BottomNavigationDescriptor<Key, IconName>;\n configuration?: BottomNavigationConfiguration;\n getHref: (item: ResolvedBottomNavigationItemDescriptor<Key, IconName>) => string;\n renderIcon: (props: BottomNavigationIconRenderProps<Key, IconName>) => ReactNode;\n /** Framework navigation adapter, for example Next.js Link. */\n renderLink?: (props: BottomNavigationLinkRenderProps) => ReactElement;\n primaryAction?: ReactNode;\n onActivate?: (activation: BottomNavigationActivation<Key>) => void;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\nexport function isUnmodifiedPrimaryBottomNavigationClick(\n event: Pick<\n MouseEvent<HTMLAnchorElement>,\n \"altKey\" | \"button\" | \"ctrlKey\" | \"defaultPrevented\" | \"metaKey\" | \"shiftKey\"\n >,\n): boolean {\n return (\n !event.defaultPrevented &&\n event.button === 0 &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.shiftKey &&\n !event.altKey\n );\n}\n\nexport function shouldHideBottomNavigationForKeyboard(input: Readonly<{\n behavior: \"hide\" | \"remain\";\n layoutViewportHeight: number;\n visualViewportHeight: number;\n visualViewportOffsetTop?: number;\n visualViewportScale?: number;\n}>): boolean {\n if (input.behavior !== \"hide\") return false;\n if ((input.visualViewportScale ?? 1) !== 1) return false;\n const visibleBottom =\n input.visualViewportHeight + (input.visualViewportOffsetTop ?? 0);\n return layoutViewportHeightIsValid(input.layoutViewportHeight) &&\n input.layoutViewportHeight - visibleBottom >= virtualKeyboardMinimumOcclusion;\n}\n\nfunction layoutViewportHeightIsValid(value: number): boolean {\n return Number.isFinite(value) && value >= 0;\n}\n\nexport function getBottomNavigationGridColumn(\n index: number,\n itemCount: number,\n distribution: \"equal\" | \"center-gap\",\n): number | undefined {\n if (distribution !== \"center-gap\") return undefined;\n const middle = itemCount / 2;\n return index < middle ? index + 1 : index + 2;\n}\n\nfunction useKeyboardHidden(behavior: \"hide\" | \"remain\"): boolean {\n const [hidden, setHidden] = useState(false);\n useEffect(() => {\n const viewport = window.visualViewport;\n if (!viewport) return;\n const update = () => {\n setHidden(\n shouldHideBottomNavigationForKeyboard({\n behavior,\n layoutViewportHeight: window.innerHeight,\n visualViewportHeight: viewport.height,\n visualViewportOffsetTop: viewport.offsetTop,\n visualViewportScale: viewport.scale,\n }),\n );\n };\n update();\n viewport.addEventListener(\"resize\", update);\n viewport.addEventListener(\"scroll\", update);\n return () => {\n viewport.removeEventListener(\"resize\", update);\n viewport.removeEventListener(\"scroll\", update);\n };\n }, [behavior]);\n return hidden;\n}\n\nfunction BottomNavigationInner<\n Key extends string = string,\n IconName extends string = string,\n>(\n {\n descriptor,\n configuration = {},\n getHref,\n renderIcon,\n renderLink,\n primaryAction,\n onActivate,\n className,\n style,\n layoutStyle,\n ...props\n }: BottomNavigationProps<Key, IconName>,\n ref: ForwardedRef<HTMLElement>,\n) {\n const resolved = resolveBottomNavigationDescriptor(descriptor);\n const theme = useOptionalHjmTheme();\n const direction = configuration.direction ?? theme?.environment.direction;\n const presentation = resolveBottomNavigationConfiguration(\n {\n ...configuration,\n ...(direction === undefined ? {} : { direction }),\n },\n resolved.items.length,\n );\n const hidden = useKeyboardHidden(presentation.keyboardBehavior);\n const density = bottomNavigationRecipe.density[presentation.density];\n const presentationRecipe =\n bottomNavigationRecipe.presentations[presentation.presentation];\n const centerGap =\n bottomNavigationRecipe.distributions[presentation.distribution].centerGap;\n const iconSize = iconRecipe.sizes[density.icon];\n\n if (hidden) return null;\n\n return (\n <nav\n {...props}\n ref={ref}\n aria-label={resolved.accessibilityLabel}\n className={classNames(\"hjm-bottom-navigation\", className)}\n data-expanded-labels={(theme?.environment.textScale ?? 1) >= 1.5 || resolved.items.length > 4 ? \"true\" : \"false\"}\n data-density={presentation.density}\n data-distribution={presentation.distribution}\n data-keyboard-behavior={presentation.keyboardBehavior}\n data-labels={presentation.labels}\n data-selection={presentation.selection}\n data-surface={presentation.surface}\n data-presentation={presentation.presentation}\n dir={presentation.direction}\n style={{\n \"--hjm-bottom-navigation-center-gap\": `${centerGap}px`,\n \"--hjm-bottom-navigation-columns\": resolved.items.length,\n \"--hjm-bottom-navigation-half-columns\": resolved.items.length / 2,\n \"--hjm-bottom-navigation-item-gap\": `${density.gap}px`,\n \"--hjm-bottom-navigation-item-min-height\": `${density.itemMinHeight}px`,\n \"--hjm-bottom-navigation-item-min-width\": `${density.itemMinWidth}px`,\n \"--hjm-bottom-navigation-item-padding\": `${density.padding}px`,\n \"--hjm-bottom-navigation-max-width\": presentationRecipe.maxWidth\n ? `${presentationRecipe.maxWidth}px`\n : \"none\",\n \"--hjm-bottom-navigation-content-max-width\": presentationRecipe.contentMaxWidth\n ? `${presentationRecipe.contentMaxWidth}px`\n : \"none\",\n \"--hjm-bottom-navigation-outer-inline\": `${presentationRecipe.outerPaddingHorizontal}px`,\n \"--hjm-bottom-navigation-outer-top\": `${presentationRecipe.outerPaddingTop}px`,\n ...style,\n ...layoutStyle,\n } as CSSProperties}\n >\n <div className=\"hjm-bottom-navigation__surface\">\n <ul className=\"hjm-bottom-navigation__list\">\n {resolved.items.map((item, index) => {\n const selected = item.id === resolved.selectedKey;\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"hjm-bottom-navigation__indicator\"\n data-state={selected ? \"selected\" : \"idle\"}\n >\n {renderIcon({\n item,\n name: item.icon.name,\n selected,\n color: \"currentColor\",\n size: iconSize,\n strokeWidth: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.idle,\n scale: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.scale.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.scale.idle,\n })}\n {item.badge ? (\n <span aria-hidden=\"true\" className=\"hjm-bottom-navigation__badge\">\n {item.badge.visibleLabel}\n </span>\n ) : null}\n </span>\n {/* Hidden labels are not rendered: the item link already carries\n resolvedAccessibilityLabel, so a visually-hidden copy would only duplicate it. */}\n {presentation.labels === \"visible\" ? (\n <span className=\"hjm-bottom-navigation__label\">{item.label}</span>\n ) : null}\n </>\n );\n const itemStyle = {\n gridColumn: getBottomNavigationGridColumn(\n index,\n resolved.items.length,\n presentation.distribution,\n ),\n };\n if (item.disabled) {\n return (\n <li key={item.id} style={itemStyle} data-selected=\"false\">\n <span\n aria-disabled=\"true\"\n aria-label={item.resolvedAccessibilityLabel}\n className=\"hjm-bottom-navigation__item\"\n data-state=\"disabled\"\n role=\"link\"\n >\n {content}\n </span>\n </li>\n );\n }\n const href = getHref(item);\n if (!href.trim()) {\n throw new TypeError(`BottomNavigation href must not be empty: ${item.id}`);\n }\n const linkProps: BottomNavigationLinkRenderProps = {\n \"aria-current\": selected ? \"page\" : undefined,\n \"aria-label\": item.resolvedAccessibilityLabel,\n className: \"hjm-bottom-navigation__item\",\n \"data-state\": selected ? \"selected\" : \"idle\",\n href,\n onClick: (event) => {\n if (!isUnmodifiedPrimaryBottomNavigationClick(event)) return;\n const activation = resolveBottomNavigationActivation(descriptor, item.id);\n if (activation) onActivate?.(activation);\n },\n children: content,\n };\n return (\n <li key={item.id} style={itemStyle} data-selected={selected}>\n {renderLink ? renderLink(linkProps) : <a {...linkProps} />}\n </li>\n );\n })}\n </ul>\n {primaryAction ? (\n <div className=\"hjm-bottom-navigation__primary-action\">{primaryAction}</div>\n ) : null}\n </div>\n </nav>\n );\n}\n\nexport const BottomNavigation = forwardRef(BottomNavigationInner) as <\n Key extends string = string,\n IconName extends string = string,\n>(\n props: BottomNavigationProps<Key, IconName> & RefAttributes<HTMLElement>,\n) => ReactElement | null;\n"]}
|
|
1
|
+
{"version":3,"file":"bottom-navigation.js","sourceRoot":"","sources":["../src/bottom-navigation.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n resolveBottomNavigationActivation,\n resolveBottomNavigationConfiguration,\n resolveBottomNavigationDescriptor,\n validateBottomNavigationProminence,\n type BottomNavigationActivation,\n type BottomNavigationConfiguration,\n type BottomNavigationDescriptor,\n type ResolvedBottomNavigationItemDescriptor,\n} from \"@hjmds/design-contracts/components/bottom-navigation\";\nimport {\n bottomNavigationRecipe,\n iconRecipe,\n} from \"@hjmds/design-contracts/recipes\";\nimport {\n createContext,\n forwardRef,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type AnchorHTMLAttributes,\n type CSSProperties,\n type ForwardedRef,\n type HTMLAttributes,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n type RefAttributes,\n} from \"react\";\nimport { assignRef, classNames } from \"./internal.js\";\nimport type { HjmCompositionStyleProp } from \"./composition-style.js\";\nimport { useOptionalHjmTheme } from \"./provider.js\";\n\nconst virtualKeyboardMinimumOcclusion = 120;\n\n/**\n * Height of the viewport bottom covered by the fixed bar (safe area and a raised center circle included); 0 when\n * there is no bar or it is hidden for the keyboard. The provider also exposes it as `--hjm-bottom-navigation-inset`,\n * which ScreenLayout's last region adds to its bottom padding, so products stop hand-keeping a bottom spacer\n * (2026-10-18; Native shares the same API for its `placement=\"overlay\"` bar).\n */\nconst BottomNavigationInsetContext = createContext(0);\nconst BottomNavigationInsetReporterContext = createContext<((height: number) => void) | null>(null);\n\nexport type BottomNavigationInsetProviderProps = Readonly<{ children: ReactNode }>;\n\n/** Wrap the app shell that holds both the screens and the BottomNavigation. */\nexport function BottomNavigationInsetProvider({ children }: BottomNavigationInsetProviderProps) {\n const [inset, setInset] = useState(0);\n const report = useMemo(() => (height: number) => {\n const next = Number.isFinite(height) && height > 0 ? height : 0;\n setInset(current => current === next ? current : next);\n }, []);\n return (\n <BottomNavigationInsetReporterContext.Provider value={report}>\n <BottomNavigationInsetContext.Provider value={inset}>\n {/* `display: contents` adds no box; the custom property still inherits to every screen below. */}\n <div style={{ display: \"contents\", \"--hjm-bottom-navigation-inset\": `${inset}px` } as CSSProperties}>{children}</div>\n </BottomNavigationInsetContext.Provider>\n </BottomNavigationInsetReporterContext.Provider>\n );\n}\n\n/** Bottom height covered by the BottomNavigation inside the nearest provider; 0 outside one. */\nexport function useBottomNavigationInset(): number {\n return useContext(BottomNavigationInsetContext);\n}\n\nexport type BottomNavigationIconRenderProps<\n Key extends string = string,\n IconName extends string = string,\n> = Readonly<{\n item: ResolvedBottomNavigationItemDescriptor<Key, IconName>;\n name: IconName;\n selected: boolean;\n color: \"currentColor\";\n size: number;\n strokeWidth: number;\n scale: number;\n}>;\n\nexport type BottomNavigationLinkRenderProps = AnchorHTMLAttributes<HTMLAnchorElement> &\n Readonly<{\n href: string;\n children: ReactNode;\n \"data-state\": \"idle\" | \"selected\";\n }>;\n\nexport type BottomNavigationProps<\n Key extends string = string,\n IconName extends string = string,\n> = Omit<\n HTMLAttributes<HTMLElement>,\n \"aria-label\" | \"aria-labelledby\" | \"children\" | \"dir\" | \"onChange\" | \"role\"\n> &\n Readonly<{\n descriptor: BottomNavigationDescriptor<Key, IconName>;\n configuration?: BottomNavigationConfiguration;\n getHref: (item: ResolvedBottomNavigationItemDescriptor<Key, IconName>) => string;\n renderIcon: (props: BottomNavigationIconRenderProps<Key, IconName>) => ReactNode;\n /** Framework navigation adapter, for example Next.js Link. */\n renderLink?: (props: BottomNavigationLinkRenderProps) => ReactElement;\n primaryAction?: ReactNode;\n onActivate?: (activation: BottomNavigationActivation<Key>) => void;\n /** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */\n layoutStyle?: HjmCompositionStyleProp;\n }>;\n\nexport function isUnmodifiedPrimaryBottomNavigationClick(\n event: Pick<\n MouseEvent<HTMLAnchorElement>,\n \"altKey\" | \"button\" | \"ctrlKey\" | \"defaultPrevented\" | \"metaKey\" | \"shiftKey\"\n >,\n): boolean {\n return (\n !event.defaultPrevented &&\n event.button === 0 &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.shiftKey &&\n !event.altKey\n );\n}\n\nexport function shouldHideBottomNavigationForKeyboard(input: Readonly<{\n behavior: \"hide\" | \"remain\";\n layoutViewportHeight: number;\n visualViewportHeight: number;\n visualViewportOffsetTop?: number;\n visualViewportScale?: number;\n}>): boolean {\n if (input.behavior !== \"hide\") return false;\n if ((input.visualViewportScale ?? 1) !== 1) return false;\n const visibleBottom =\n input.visualViewportHeight + (input.visualViewportOffsetTop ?? 0);\n return layoutViewportHeightIsValid(input.layoutViewportHeight) &&\n input.layoutViewportHeight - visibleBottom >= virtualKeyboardMinimumOcclusion;\n}\n\nfunction layoutViewportHeightIsValid(value: number): boolean {\n return Number.isFinite(value) && value >= 0;\n}\n\nexport function getBottomNavigationGridColumn(\n index: number,\n itemCount: number,\n distribution: \"equal\" | \"center-gap\",\n): number | undefined {\n if (distribution !== \"center-gap\") return undefined;\n const middle = itemCount / 2;\n return index < middle ? index + 1 : index + 2;\n}\n\nfunction useKeyboardHidden(behavior: \"hide\" | \"remain\"): boolean {\n const [hidden, setHidden] = useState(false);\n useEffect(() => {\n const viewport = window.visualViewport;\n if (!viewport) return;\n const update = () => {\n setHidden(\n shouldHideBottomNavigationForKeyboard({\n behavior,\n layoutViewportHeight: window.innerHeight,\n visualViewportHeight: viewport.height,\n visualViewportOffsetTop: viewport.offsetTop,\n visualViewportScale: viewport.scale,\n }),\n );\n };\n update();\n viewport.addEventListener(\"resize\", update);\n viewport.addEventListener(\"scroll\", update);\n return () => {\n viewport.removeEventListener(\"resize\", update);\n viewport.removeEventListener(\"scroll\", update);\n };\n }, [behavior]);\n return hidden;\n}\n\nfunction BottomNavigationInner<\n Key extends string = string,\n IconName extends string = string,\n>(\n {\n descriptor,\n configuration = {},\n getHref,\n renderIcon,\n renderLink,\n primaryAction,\n onActivate,\n className,\n style,\n layoutStyle,\n ...props\n }: BottomNavigationProps<Key, IconName>,\n ref: ForwardedRef<HTMLElement>,\n) {\n const resolved = resolveBottomNavigationDescriptor(descriptor);\n const theme = useOptionalHjmTheme();\n const direction = configuration.direction ?? theme?.environment.direction;\n const presentation = resolveBottomNavigationConfiguration(\n {\n ...configuration,\n ...(direction === undefined ? {} : { direction }),\n },\n resolved.items.length,\n );\n validateBottomNavigationProminence(resolved.items, presentation);\n const hidden = useKeyboardHidden(presentation.keyboardBehavior);\n const density = bottomNavigationRecipe.density[presentation.density];\n const presentationRecipe =\n bottomNavigationRecipe.presentations[presentation.presentation];\n const centerGap =\n bottomNavigationRecipe.distributions[presentation.distribution].centerGap;\n const iconSize = presentation.iconSize === \"standard\"\n ? iconRecipe.sizes[density.icon]\n : bottomNavigationRecipe.iconSizes[presentation.iconSize];\n const prominentRecipe = bottomNavigationRecipe.prominentDestination;\n // Lifting by (diameter - indicator height) keeps the prominent label on the other labels' line; an app-icon\n // slot taller than the indicator minimum raises that height.\n const prominentLift = prominentRecipe.diameter - Math.max(bottomNavigationRecipe.indicator.minHeight, iconSize);\n // The part of the circle above the nav box still covers content, so the reported inset includes it.\n const prominentOverflow = resolved.items.some((item) => item.prominent)\n ? Math.max(0, prominentLift - density.padding - presentationRecipe.outerPaddingTop)\n : 0;\n const navRef = useRef<HTMLElement | null>(null);\n const reportInset = useContext(BottomNavigationInsetReporterContext);\n useEffect(() => {\n const nav = navRef.current;\n if (!reportInset) return;\n if (hidden || !nav) {\n reportInset(0);\n return;\n }\n const update = () => reportInset(nav.getBoundingClientRect().height + prominentOverflow);\n update();\n const observer = new ResizeObserver(update);\n observer.observe(nav);\n return () => {\n observer.disconnect();\n reportInset(0);\n };\n }, [reportInset, hidden, prominentOverflow]);\n\n if (hidden) return null;\n\n return (\n <nav\n {...props}\n ref={(node) => {\n navRef.current = node;\n assignRef(ref, node);\n }}\n aria-label={resolved.accessibilityLabel}\n className={classNames(\"hjm-bottom-navigation\", className)}\n data-expanded-labels={(theme?.environment.textScale ?? 1) >= 1.5 || resolved.items.length > 4 ? \"true\" : \"false\"}\n data-density={presentation.density}\n data-distribution={presentation.distribution}\n data-keyboard-behavior={presentation.keyboardBehavior}\n data-labels={presentation.labels}\n data-selection={presentation.selection}\n data-surface={presentation.surface}\n data-presentation={presentation.presentation}\n dir={presentation.direction}\n style={{\n \"--hjm-bottom-navigation-center-gap\": `${centerGap}px`,\n \"--hjm-bottom-navigation-columns\": resolved.items.length,\n \"--hjm-bottom-navigation-half-columns\": resolved.items.length / 2,\n \"--hjm-bottom-navigation-item-gap\": `${density.gap}px`,\n \"--hjm-bottom-navigation-item-min-height\": `${density.itemMinHeight}px`,\n \"--hjm-bottom-navigation-item-min-width\": `${density.itemMinWidth}px`,\n \"--hjm-bottom-navigation-item-padding\": `${density.padding}px`,\n \"--hjm-bottom-navigation-max-width\": presentationRecipe.maxWidth\n ? `${presentationRecipe.maxWidth}px`\n : \"none\",\n \"--hjm-bottom-navigation-content-max-width\": presentationRecipe.contentMaxWidth\n ? `${presentationRecipe.contentMaxWidth}px`\n : \"none\",\n \"--hjm-bottom-navigation-outer-inline\": `${presentationRecipe.outerPaddingHorizontal}px`,\n \"--hjm-bottom-navigation-outer-top\": `${presentationRecipe.outerPaddingTop}px`,\n \"--hjm-bottom-navigation-prominent-diameter\": `${prominentRecipe.diameter}px`,\n \"--hjm-bottom-navigation-prominent-lift\": `${prominentLift}px`,\n ...style,\n ...layoutStyle,\n } as CSSProperties}\n >\n <div className=\"hjm-bottom-navigation__surface\">\n <ul className=\"hjm-bottom-navigation__list\">\n {resolved.items.map((item, index) => {\n const selected = item.id === resolved.selectedKey;\n const content = (\n <>\n <span\n aria-hidden=\"true\"\n className=\"hjm-bottom-navigation__indicator\"\n data-state={selected ? \"selected\" : \"idle\"}\n >\n {renderIcon({\n item,\n name: item.icon.name,\n selected,\n color: \"currentColor\",\n size: item.prominent ? iconRecipe.sizes[prominentRecipe.icon] : iconSize,\n strokeWidth: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.strokeWidth.idle,\n scale: selected\n ? bottomNavigationRecipe.icon.selectedEmphasis.scale.selected\n : bottomNavigationRecipe.icon.selectedEmphasis.scale.idle,\n })}\n {item.badge ? (\n <span aria-hidden=\"true\" className=\"hjm-bottom-navigation__badge\">\n {item.badge.visibleLabel}\n </span>\n ) : null}\n </span>\n {/* Hidden labels are not rendered: the item link already carries\n resolvedAccessibilityLabel, so a visually-hidden copy would only duplicate it. */}\n {presentation.labels === \"visible\" ? (\n <span className=\"hjm-bottom-navigation__label\">{item.label}</span>\n ) : null}\n </>\n );\n const itemStyle = {\n gridColumn: getBottomNavigationGridColumn(\n index,\n resolved.items.length,\n presentation.distribution,\n ),\n };\n if (item.disabled) {\n return (\n <li key={item.id} style={itemStyle} data-selected=\"false\" data-prominent={item.prominent || undefined}>\n <span\n aria-disabled=\"true\"\n aria-label={item.resolvedAccessibilityLabel}\n className=\"hjm-bottom-navigation__item\"\n data-state=\"disabled\"\n role=\"link\"\n >\n {content}\n </span>\n </li>\n );\n }\n const href = getHref(item);\n if (!href.trim()) {\n throw new TypeError(`BottomNavigation href must not be empty: ${item.id}`);\n }\n const linkProps: BottomNavigationLinkRenderProps = {\n \"aria-current\": selected ? \"page\" : undefined,\n \"aria-label\": item.resolvedAccessibilityLabel,\n className: \"hjm-bottom-navigation__item\",\n \"data-state\": selected ? \"selected\" : \"idle\",\n href,\n onClick: (event) => {\n if (!isUnmodifiedPrimaryBottomNavigationClick(event)) return;\n const activation = resolveBottomNavigationActivation(descriptor, item.id);\n if (activation) onActivate?.(activation);\n },\n children: content,\n };\n return (\n <li key={item.id} style={itemStyle} data-selected={selected} data-prominent={item.prominent || undefined}>\n {renderLink ? renderLink(linkProps) : <a {...linkProps} />}\n </li>\n );\n })}\n </ul>\n {primaryAction ? (\n <div className=\"hjm-bottom-navigation__primary-action\">{primaryAction}</div>\n ) : null}\n </div>\n </nav>\n );\n}\n\nexport const BottomNavigation = forwardRef(BottomNavigationInner) as <\n Key extends string = string,\n IconName extends string = string,\n>(\n props: BottomNavigationProps<Key, IconName> & RefAttributes<HTMLElement>,\n) => ReactElement | null;\n"]}
|
package/dist/carousel.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type HTMLAttributes, type ReactNode } from "react";
|
|
2
|
-
import { type CarouselSlideDescriptor, type CarouselSelection, type CarouselAutoplayConfig, type ComposeCarouselAccessibleName } from "@hjmds/design-contracts/components/carousel";
|
|
2
|
+
import { type CarouselSlideDescriptor, type CarouselSelection, type CarouselAutoplayConfig, type ComposeCarouselAccessibleName, type ComposePageIndicatorAccessibleName } from "@hjmds/design-contracts/components/carousel";
|
|
3
3
|
import type { HjmCompositionStyleProp } from "./composition-style.js";
|
|
4
4
|
export type CarouselLabels = Readonly<{
|
|
5
5
|
previous: string;
|
|
@@ -18,6 +18,34 @@ export type CarouselProps = Omit<HTMLAttributes<HTMLDivElement>, "children" | "o
|
|
|
18
18
|
/** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */
|
|
19
19
|
layoutStyle?: HjmCompositionStyleProp;
|
|
20
20
|
}>;
|
|
21
|
+
export type PageIndicatorProps = Omit<HTMLAttributes<HTMLDivElement>, "children" | "onChange"> & Readonly<{
|
|
22
|
+
/** Name of the paged region (e.g. "Home pages"); the group's accessible name. */
|
|
23
|
+
label: string;
|
|
24
|
+
count: number;
|
|
25
|
+
/** Zero-based current page; the product pager owns it. */
|
|
26
|
+
currentIndex: number;
|
|
27
|
+
/** Requested page from a dot or an arrow key. It can repeat the current index. */
|
|
28
|
+
onCurrentIndexChange: (index: number) => void;
|
|
29
|
+
composeAccessibleName: ComposePageIndicatorAccessibleName;
|
|
30
|
+
/** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */
|
|
31
|
+
layoutStyle?: HjmCompositionStyleProp;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Carousel's position dots for a product-owned pager (scroll-snap row, virtualized pager). Arrow keys on a dot move
|
|
35
|
+
* one page in reading direction, as in Carousel's controls.
|
|
36
|
+
*/
|
|
37
|
+
export declare const PageIndicator: import("react").ForwardRefExoticComponent<Omit<HTMLAttributes<HTMLDivElement>, "onChange" | "children"> & Readonly<{
|
|
38
|
+
/** Name of the paged region (e.g. "Home pages"); the group's accessible name. */
|
|
39
|
+
label: string;
|
|
40
|
+
count: number;
|
|
41
|
+
/** Zero-based current page; the product pager owns it. */
|
|
42
|
+
currentIndex: number;
|
|
43
|
+
/** Requested page from a dot or an arrow key. It can repeat the current index. */
|
|
44
|
+
onCurrentIndexChange: (index: number) => void;
|
|
45
|
+
composeAccessibleName: ComposePageIndicatorAccessibleName;
|
|
46
|
+
/** Canonical layout-only placement on the root element. Controlled visual keys are excluded. */
|
|
47
|
+
layoutStyle?: HjmCompositionStyleProp;
|
|
48
|
+
}> & import("react").RefAttributes<HTMLDivElement>>;
|
|
21
49
|
/** Finite keyed cards. Hidden slides stay mounted but cannot receive focus. */
|
|
22
50
|
export declare const Carousel: import("react").ForwardRefExoticComponent<CarouselProps & import("react").RefAttributes<HTMLDivElement>>;
|
|
23
51
|
//# sourceMappingURL=carousel.d.ts.map
|
package/dist/carousel.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../src/carousel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACtH,OAAO,
|
|
1
|
+
{"version":3,"file":"carousel.d.ts","sourceRoot":"","sources":["../src/carousel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AACtH,OAAO,EAGL,KAAK,uBAAuB,EAAE,KAAK,iBAAiB,EAAE,KAAK,sBAAsB,EACjF,KAAK,6BAA6B,EAAE,KAAK,kCAAkC,EAC5E,MAAM,6CAA6C,CAAC;AAMrD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEtE,MAAM,MAAM,cAAc,GAAG,QAAQ,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAC7H,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG,iBAAiB,GAAG,QAAQ,CAAC;IACvH,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,SAAS,uBAAuB,EAAE,CAAC;IAC3C,WAAW,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,SAAS,CAAC;IAC3D,qBAAqB,EAAE,6BAA6B,CAAC;IACrD,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAClC,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAEH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,UAAU,GAAG,UAAU,CAAC,GAAG,QAAQ,CAAC;IACxG,iFAAiF;IACjF,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,0DAA0D;IAC1D,YAAY,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,oBAAoB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,qBAAqB,EAAE,kCAAkC,CAAC;IAC1D,gGAAgG;IAChG,WAAW,CAAC,EAAE,uBAAuB,CAAC;CACvC,CAAC,CAAC;AAeH;;;GAGG;AACH,eAAO,MAAM,aAAa;IA7BxB,iFAAiF;WAC1E,MAAM;WACN,MAAM;IACb,0DAA0D;kBAC5C,MAAM;IACpB,kFAAkF;0BAC5D,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI;2BACtB,kCAAkC;IACzD,gGAAgG;kBAClF,uBAAuB;mDAuCrC,CAAC;AAEH,+EAA+E;AAC/E,eAAO,MAAM,QAAQ,0GAmGnB,CAAC"}
|