@godxjp/ui 18.6.0 → 18.8.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/components/data-display/card.d.ts +27 -3
- package/dist/components/data-display/card.js +4 -1
- package/dist/components/data-entry/input-otp.d.ts +1 -1
- package/dist/components/feedback/alert.d.ts +20 -2
- package/dist/components/feedback/alert.js +11 -1
- package/dist/components/feedback/index.d.ts +2 -2
- package/dist/components/feedback/index.js +3 -1
- package/dist/components/layout/auth-shell.d.ts +4 -2
- package/dist/components/layout/index.d.ts +2 -0
- package/dist/components/layout/index.js +2 -0
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +19 -41
- package/dist/components/layout/page-header.d.ts +22 -0
- package/dist/components/layout/page-header.js +89 -0
- package/dist/components/navigation/filter-bar.d.ts +2 -2
- package/dist/components/navigation/filter-bar.js +44 -1
- package/dist/components/navigation/index.d.ts +1 -1
- package/dist/components/navigation/steps.d.ts +2 -2
- package/dist/components/navigation/steps.js +4 -2
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.js +2 -1
- package/dist/components/ui/input-otp.d.ts +15 -3
- package/dist/components/ui/input-otp.js +2 -1
- package/dist/email/tokens.generated.d.ts +2 -2
- package/dist/email/tokens.generated.js +2 -2
- package/dist/i18n/messages/en.json +11 -0
- package/dist/i18n/messages/ja.json +8 -0
- package/dist/i18n/messages/vi.json +8 -0
- package/dist/props/components/data-display.prop.d.ts +16 -0
- package/dist/props/components/data-entry.prop.d.ts +7 -0
- package/dist/props/components/feedback.prop.d.ts +6 -0
- package/dist/props/components/layout.prop.d.ts +53 -0
- package/dist/props/components/navigation.prop.d.ts +61 -0
- package/dist/props/registry.d.ts +75 -1
- package/dist/props/registry.js +96 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +10 -2
- package/dist/props/vocabulary/layout.prop.d.ts +5 -2
- package/dist/styles/alert-layout.css +36 -0
- package/dist/styles/card-layout.css +49 -13
- package/dist/styles/control.css +12 -2
- package/dist/styles/data-display-layout.css +16 -0
- package/dist/styles/layout.css +113 -0
- package/dist/styles/navigation-layout.css +8 -3
- package/dist/styles/shell-layout.css +44 -1
- package/dist/tokens/components/card.css +12 -0
- package/dist/tokens/components/control.css +16 -0
- package/dist/tokens/components/data-display.css +12 -0
- package/dist/tokens/components/email.css +8 -2
- package/dist/tokens/components/feedback.css +20 -0
- package/dist/tokens/components/navigation.css +35 -0
- package/dist/tokens/components/shell.css +64 -4
- package/dist/tokens/semantic/layout.css +13 -0
- package/package.json +2 -2
|
@@ -3,9 +3,21 @@ import { type VariantProps } from "class-variance-authority";
|
|
|
3
3
|
import type { LucideIcon } from "lucide-react";
|
|
4
4
|
import type { HeadingLevelProp } from "../../props/vocabulary/index.js";
|
|
5
5
|
type CardSize = "md" | "compact";
|
|
6
|
-
/** Semantic
|
|
7
|
-
*
|
|
6
|
+
/** Semantic accent tone. `accentPlacement` decides WHERE it is drawn — a leading-edge
|
|
7
|
+
* stripe (default) or the full perimeter. */
|
|
8
8
|
type CardAccent = "primary" | "success" | "warning" | "info" | "attention" | "destructive";
|
|
9
|
+
/**
|
|
10
|
+
* Where the semantic `accent` tone is drawn.
|
|
11
|
+
*
|
|
12
|
+
* - `"edge"` (default) — the leading-edge stripe on `border-inline-start` only, at the
|
|
13
|
+
* `--card-accent-rail-width` measure (6px). The classic "this row needs a look" rail.
|
|
14
|
+
* - `"perimeter"` — a full attention border around the WHOLE card in the same semantic
|
|
15
|
+
* tone, measured by `--card-accent-perimeter-width` + `--card-accent-perimeter-ring-width`.
|
|
16
|
+
* This is what `variant="featured"` does, except the tone is yours instead of `--primary`,
|
|
17
|
+
* so a card can shout "action required" (`accent="attention"`) or "this failed"
|
|
18
|
+
* (`accent="destructive"`) without borrowing the brand colour.
|
|
19
|
+
*/
|
|
20
|
+
type CardAccentPlacement = "edge" | "perimeter";
|
|
9
21
|
/** Surface fill — plain card, muted band, borderless outline, or emphasized featured ring. */
|
|
10
22
|
type CardVariant = "default" | "muted" | "outline" | "featured";
|
|
11
23
|
/** Padding density — base 16px · tight 12px · cozy 20px. */
|
|
@@ -16,6 +28,11 @@ declare const cardVariants: (props?: ({
|
|
|
16
28
|
export type CardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof cardVariants> & {
|
|
17
29
|
size?: CardSize;
|
|
18
30
|
accent?: CardAccent;
|
|
31
|
+
/**
|
|
32
|
+
* Where `accent` is drawn — `"edge"` (default, the leading-edge stripe) or `"perimeter"`
|
|
33
|
+
* (a full attention border in the accent tone). Inert without `accent`.
|
|
34
|
+
*/
|
|
35
|
+
accentPlacement?: CardAccentPlacement;
|
|
19
36
|
variant?: CardVariant;
|
|
20
37
|
density?: CardDensity;
|
|
21
38
|
};
|
|
@@ -24,6 +41,11 @@ export declare const Card: React.ForwardRefExoticComponent<React.HTMLAttributes<
|
|
|
24
41
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string> & {
|
|
25
42
|
size?: CardSize;
|
|
26
43
|
accent?: CardAccent;
|
|
44
|
+
/**
|
|
45
|
+
* Where `accent` is drawn — `"edge"` (default, the leading-edge stripe) or `"perimeter"`
|
|
46
|
+
* (a full attention border in the accent tone). Inert without `accent`.
|
|
47
|
+
*/
|
|
48
|
+
accentPlacement?: CardAccentPlacement;
|
|
27
49
|
variant?: CardVariant;
|
|
28
50
|
density?: CardDensity;
|
|
29
51
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -136,9 +158,11 @@ export type StatCardProps = React.HTMLAttributes<HTMLDivElement> & VariantProps<
|
|
|
136
158
|
inverse?: boolean;
|
|
137
159
|
/** Semantic leading-edge rail (Card accent) — flags a KPI needing attention. */
|
|
138
160
|
accent?: CardAccent;
|
|
161
|
+
/** Where `accent` is drawn — `"edge"` (default rail) or `"perimeter"` (full attention border). */
|
|
162
|
+
accentPlacement?: CardAccentPlacement;
|
|
139
163
|
};
|
|
140
164
|
/** KPI / stat tile — token-driven layout aligned to dashboard KPI cards. */
|
|
141
|
-
export declare function StatCard({ label, value, hint, icon: Icon, delta, layout, align, inverse, accent, className, size, ...props }: StatCardProps): React.JSX.Element;
|
|
165
|
+
export declare function StatCard({ label, value, hint, icon: Icon, delta, layout, align, inverse, accent, accentPlacement, className, size, ...props }: StatCardProps): React.JSX.Element;
|
|
142
166
|
/** Header actions slot — pair with `CardHeader className="flex flex-row …"`. */
|
|
143
167
|
export declare const CardAction: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
144
168
|
export {};
|
|
@@ -12,7 +12,7 @@ const cardVariants = cva("group/card", {
|
|
|
12
12
|
defaultVariants: { size: "md" }
|
|
13
13
|
});
|
|
14
14
|
const Card = React.forwardRef(
|
|
15
|
-
({ className, size = "md", accent, variant, density, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
15
|
+
({ className, size = "md", accent, accentPlacement, variant, density, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
16
16
|
"div",
|
|
17
17
|
{
|
|
18
18
|
ref,
|
|
@@ -20,6 +20,7 @@ const Card = React.forwardRef(
|
|
|
20
20
|
"data-slot": "card",
|
|
21
21
|
"data-size": size === "compact" ? "compact" : void 0,
|
|
22
22
|
"data-accent": accent,
|
|
23
|
+
"data-accent-placement": accentPlacement === "perimeter" ? "perimeter" : void 0,
|
|
23
24
|
"data-variant": variant && variant !== "default" ? variant : void 0,
|
|
24
25
|
"data-density": density,
|
|
25
26
|
...props
|
|
@@ -108,6 +109,7 @@ function StatCard({
|
|
|
108
109
|
align = "start",
|
|
109
110
|
inverse = false,
|
|
110
111
|
accent,
|
|
112
|
+
accentPlacement,
|
|
111
113
|
className,
|
|
112
114
|
size = "compact",
|
|
113
115
|
...props
|
|
@@ -118,6 +120,7 @@ function StatCard({
|
|
|
118
120
|
{
|
|
119
121
|
size: size ?? "compact",
|
|
120
122
|
accent,
|
|
123
|
+
accentPlacement,
|
|
121
124
|
className: cn("ui-stat-card", className),
|
|
122
125
|
"data-stat-card": "",
|
|
123
126
|
"data-stat-layout": layout,
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator } from "../ui/input-otp.js";
|
|
2
|
-
export type { InputOTPGroupAppearanceProp, InputOTPGroupProp, InputOTPGroupProps, } from "../ui/input-otp.js";
|
|
2
|
+
export type { InputOTPAlignProp, InputOTPGroupAppearanceProp, InputOTPGroupProp, InputOTPGroupProps, } from "../ui/input-otp.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { ToneProp } from "../../props/vocabulary/index.js";
|
|
3
|
-
import type { AlertQueryErrorProp } from "../../props/components/feedback.prop.js";
|
|
4
|
-
export type { AlertProp, AlertProp as AlertProps, AlertTitleProp, AlertTitleProp as AlertTitleProps, AlertContentProp, AlertContentProp as AlertContentProps, AlertDescriptionProp, AlertDescriptionProp as AlertDescriptionProps, AlertActionsProp, AlertActionsProp as AlertActionsProps, AlertQueryErrorProp, AlertQueryErrorProp as AlertQueryErrorProps, } from "../../props/components/feedback.prop.js";
|
|
3
|
+
import type { AlertQueryErrorProp, BannerProp } from "../../props/components/feedback.prop.js";
|
|
4
|
+
export type { BannerProp, BannerProp as BannerProps, AlertProp, AlertProp as AlertProps, AlertTitleProp, AlertTitleProp as AlertTitleProps, AlertContentProp, AlertContentProp as AlertContentProps, AlertDescriptionProp, AlertDescriptionProp as AlertDescriptionProps, AlertActionsProp, AlertActionsProp as AlertActionsProps, AlertQueryErrorProp, AlertQueryErrorProp as AlertQueryErrorProps, } from "../../props/components/feedback.prop.js";
|
|
5
5
|
declare const AlertBase: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
6
6
|
variant?: import("../../props/index.js").AlertVariantProp;
|
|
7
7
|
tone?: ToneProp;
|
|
@@ -63,4 +63,22 @@ export declare const Alert: React.ForwardRefExoticComponent<React.HTMLAttributes
|
|
|
63
63
|
} & React.RefAttributes<HTMLDivElement>>;
|
|
64
64
|
QueryError: typeof AlertQueryError;
|
|
65
65
|
};
|
|
66
|
+
export declare const Banner: React.ForwardRefExoticComponent<BannerProp & React.RefAttributes<HTMLDivElement>> & {
|
|
67
|
+
Title: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & {
|
|
68
|
+
className?: import("../../props/index.js").ClassNameProp;
|
|
69
|
+
children?: import("../../props/index.js").ChildrenProp;
|
|
70
|
+
} & React.RefAttributes<HTMLParagraphElement>>;
|
|
71
|
+
Content: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
72
|
+
className?: import("../../props/index.js").ClassNameProp;
|
|
73
|
+
children?: import("../../props/index.js").ChildrenProp;
|
|
74
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
75
|
+
Description: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLParagraphElement> & {
|
|
76
|
+
className?: import("../../props/index.js").ClassNameProp;
|
|
77
|
+
children?: import("../../props/index.js").ChildrenProp;
|
|
78
|
+
} & React.RefAttributes<HTMLParagraphElement>>;
|
|
79
|
+
Actions: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
80
|
+
className?: import("../../props/index.js").ClassNameProp;
|
|
81
|
+
children?: import("../../props/index.js").ChildrenProp;
|
|
82
|
+
} & React.RefAttributes<HTMLDivElement>>;
|
|
83
|
+
};
|
|
66
84
|
export { AlertBase };
|
|
@@ -159,6 +159,15 @@ const Alert = Object.assign(AlertBase, {
|
|
|
159
159
|
Actions: AlertActions,
|
|
160
160
|
QueryError: AlertQueryError
|
|
161
161
|
});
|
|
162
|
+
const BannerBase = React.forwardRef(function Banner(props, ref) {
|
|
163
|
+
return /* @__PURE__ */ jsx(AlertBase, { ...props, ref, variant: "banner" });
|
|
164
|
+
});
|
|
165
|
+
const Banner2 = Object.assign(BannerBase, {
|
|
166
|
+
Title: AlertTitle,
|
|
167
|
+
Content: AlertContent,
|
|
168
|
+
Description: AlertDescription,
|
|
169
|
+
Actions: AlertActions
|
|
170
|
+
});
|
|
162
171
|
export {
|
|
163
172
|
Alert,
|
|
164
173
|
AlertActions,
|
|
@@ -166,5 +175,6 @@ export {
|
|
|
166
175
|
AlertContent,
|
|
167
176
|
AlertDescription,
|
|
168
177
|
AlertQueryError,
|
|
169
|
-
AlertTitle
|
|
178
|
+
AlertTitle,
|
|
179
|
+
Banner2 as Banner
|
|
170
180
|
};
|
|
@@ -8,6 +8,6 @@ export { Toaster } from "./sonner.js";
|
|
|
8
8
|
export { toast } from "./use-toast.js";
|
|
9
9
|
export { Skeleton, SkeletonRows, SkeletonTable, SkeletonDetail, SkeletonStat } from "./skeleton.js";
|
|
10
10
|
export type { SkeletonProps } from "./skeleton.js";
|
|
11
|
-
export { Alert, AlertTitle, AlertContent, AlertDescription, AlertActions, AlertQueryError, } from "./alert.js";
|
|
12
|
-
export type { AlertProp, AlertProps, AlertTitleProp, AlertTitleProps, AlertContentProp, AlertContentProps, AlertDescriptionProp, AlertDescriptionProps, AlertActionsProp, AlertActionsProps, AlertQueryErrorProp, AlertQueryErrorProps, } from "./alert.js";
|
|
11
|
+
export { Alert, AlertTitle, AlertContent, AlertDescription, AlertActions, AlertQueryError, Banner, } from "./alert.js";
|
|
12
|
+
export type { BannerProp, BannerProps, AlertProp, AlertProps, AlertTitleProp, AlertTitleProps, AlertContentProp, AlertContentProps, AlertDescriptionProp, AlertDescriptionProps, AlertActionsProp, AlertActionsProps, AlertQueryErrorProp, AlertQueryErrorProps, } from "./alert.js";
|
|
13
13
|
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "./tooltip.js";
|
|
@@ -49,7 +49,8 @@ import {
|
|
|
49
49
|
AlertContent,
|
|
50
50
|
AlertDescription,
|
|
51
51
|
AlertActions,
|
|
52
|
-
AlertQueryError
|
|
52
|
+
AlertQueryError,
|
|
53
|
+
Banner
|
|
53
54
|
} from "./alert.js";
|
|
54
55
|
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from "./tooltip.js";
|
|
55
56
|
export {
|
|
@@ -71,6 +72,7 @@ export {
|
|
|
71
72
|
AlertDialogTrigger,
|
|
72
73
|
AlertQueryError,
|
|
73
74
|
AlertTitle,
|
|
75
|
+
Banner,
|
|
74
76
|
Dialog,
|
|
75
77
|
DialogAction,
|
|
76
78
|
DialogBody,
|
|
@@ -10,8 +10,10 @@ export type { AuthShellProp, AuthShellProp as AuthShellProps, } from "../../prop
|
|
|
10
10
|
*
|
|
11
11
|
* `preset` names the flow MEASURE (card max-width + desktop/mobile page gutters) so a consumer
|
|
12
12
|
* never overrides page geometry by hand: `"login"` = SCR-001's stable identity/card/footer anchor
|
|
13
|
-
* for standalone and real requester states; `"
|
|
14
|
-
*
|
|
13
|
+
* for standalone and real requester states; `"registration"` = the 360px sign-up measure, the only
|
|
14
|
+
* START-aligned preset (a tall sign-up card must scroll, not clip its own top above the scroll
|
|
15
|
+
* origin) and the only one with its own footer clearance; `"device-authorization"` = 380px card
|
|
16
|
+
* with a 5px inline gutter at 390px; `"context-selection"` = 25rem card, edge-to-edge on mobile;
|
|
15
17
|
* `"account-recovery"` = the 432px SCR-008 panel measure shared by password recovery and the
|
|
16
18
|
* sign-in MFA challenge, with a 15px inline gutter at 390px. It is orthogonal to `variant` —
|
|
17
19
|
* combine `variant="canonical"` with any preset.
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { PageContainer } from "./page-container.js";
|
|
2
2
|
export type { PageContainerProp, PageContainerProps, BreadcrumbItem, BreadcrumbItemProp, } from "./page-container.js";
|
|
3
|
+
export { PageHeader } from "./page-header.js";
|
|
4
|
+
export type { PageHeaderProp, PageHeaderProps } from "./page-header.js";
|
|
3
5
|
export { Flex } from "./flex.js";
|
|
4
6
|
export type { FlexAlignProp, FlexDirectionProp, FlexJustifyProp, FlexProp, FlexProps, } from "./flex.js";
|
|
5
7
|
export { ResizablePanel, ResizablePanelGroup, ResizableHandle } from "./resizable.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { PageContainer } from "./page-container.js";
|
|
2
|
+
import { PageHeader } from "./page-header.js";
|
|
2
3
|
import { Flex } from "./flex.js";
|
|
3
4
|
import { ResizablePanel, ResizablePanelGroup, ResizableHandle } from "./resizable.js";
|
|
4
5
|
import { AppShell } from "./app-shell.js";
|
|
@@ -37,6 +38,7 @@ export {
|
|
|
37
38
|
MasterDetail,
|
|
38
39
|
OrgSwitcher,
|
|
39
40
|
PageContainer,
|
|
41
|
+
PageHeader,
|
|
40
42
|
ResizableHandle,
|
|
41
43
|
ResizablePanel,
|
|
42
44
|
ResizablePanelGroup,
|
|
@@ -2,7 +2,7 @@ import type { PageContainerProp, PageInsetProp } from "../../props/components/la
|
|
|
2
2
|
export type { PageContainerProp, PageContainerProp as PageContainerProps, } from "../../props/components/layout.prop.js";
|
|
3
3
|
export type { BreadcrumbItemProp, BreadcrumbItemProp as BreadcrumbItem, } from "../../props/vocabulary/navigation.prop.js";
|
|
4
4
|
export declare function PageContainerInset({ className, children, ...props }: PageInsetProp): import("react").JSX.Element;
|
|
5
|
-
declare function PageContainerRoot({ title, subtitle, extra, footer, breadcrumb, breadcrumbLabel, breadcrumbAriaLabel, linkComponent: LinkComponent, density, variant, preset, headerLayout, measure, stickyFooter, footerReveal, fill, children, className, }: PageContainerProp): import("react").JSX.Element;
|
|
5
|
+
declare function PageContainerRoot({ title, subtitle, meta, headerLoading, extra, footer, breadcrumb, breadcrumbLabel, breadcrumbAriaLabel, linkComponent: LinkComponent, density, variant, preset, headerLayout, measure, stickyFooter, footerReveal, fill, children, className, }: PageContainerProp): import("react").JSX.Element;
|
|
6
6
|
export declare const PageContainer: typeof PageContainerRoot & {
|
|
7
7
|
Inset: typeof PageContainerInset;
|
|
8
8
|
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
|
-
import { ChevronRight } from "lucide-react";
|
|
5
|
-
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
4
|
import { cn } from "../../lib/utils.js";
|
|
7
5
|
import { densityClass, pageContainerVariantClass } from "../../lib/variants.js";
|
|
6
|
+
import { PageHeader } from "./page-header.js";
|
|
8
7
|
function scrollParent(el) {
|
|
9
8
|
let node = el?.parentElement ?? null;
|
|
10
9
|
while (node) {
|
|
@@ -36,6 +35,8 @@ function PageContainerInset({ className, children, ...props }) {
|
|
|
36
35
|
function PageContainerRoot({
|
|
37
36
|
title,
|
|
38
37
|
subtitle,
|
|
38
|
+
meta,
|
|
39
|
+
headerLoading,
|
|
39
40
|
extra,
|
|
40
41
|
footer,
|
|
41
42
|
breadcrumb,
|
|
@@ -55,7 +56,6 @@ function PageContainerRoot({
|
|
|
55
56
|
}) {
|
|
56
57
|
const reveal = stickyFooter && footer != null && footerReveal === "onScroll";
|
|
57
58
|
const { headerRef, revealed } = useFooterReveal(reveal);
|
|
58
|
-
const { t } = useTranslation();
|
|
59
59
|
return /* @__PURE__ */ jsxs(
|
|
60
60
|
"div",
|
|
61
61
|
{
|
|
@@ -74,44 +74,22 @@ function PageContainerRoot({
|
|
|
74
74
|
className
|
|
75
75
|
),
|
|
76
76
|
children: [
|
|
77
|
-
/* @__PURE__ */
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
) : /* @__PURE__ */ jsx(
|
|
95
|
-
"span",
|
|
96
|
-
{
|
|
97
|
-
className: isLast ? "text-foreground" : "",
|
|
98
|
-
"aria-current": isLast ? "page" : void 0,
|
|
99
|
-
children: item.label
|
|
100
|
-
}
|
|
101
|
-
),
|
|
102
|
-
!isLast && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3", "aria-hidden": "true" })
|
|
103
|
-
] }, i);
|
|
104
|
-
}) })
|
|
105
|
-
}
|
|
106
|
-
),
|
|
107
|
-
/* @__PURE__ */ jsxs("div", { className: "ui-page-header-row", children: [
|
|
108
|
-
/* @__PURE__ */ jsxs("div", { className: "ui-page-header-heading min-w-0", children: [
|
|
109
|
-
/* @__PURE__ */ jsx("h1", { className: "ui-page-title", children: title }),
|
|
110
|
-
subtitle && /* @__PURE__ */ jsx("p", { className: "ui-page-subtitle", children: subtitle })
|
|
111
|
-
] }),
|
|
112
|
-
extra && /* @__PURE__ */ jsx("div", { className: "ui-page-header-extra", children: extra })
|
|
113
|
-
] })
|
|
114
|
-
] }),
|
|
77
|
+
/* @__PURE__ */ jsx(
|
|
78
|
+
PageHeader,
|
|
79
|
+
{
|
|
80
|
+
ref: headerRef,
|
|
81
|
+
title,
|
|
82
|
+
subtitle,
|
|
83
|
+
meta,
|
|
84
|
+
extra,
|
|
85
|
+
breadcrumb,
|
|
86
|
+
breadcrumbLabel,
|
|
87
|
+
breadcrumbAriaLabel,
|
|
88
|
+
linkComponent: LinkComponent,
|
|
89
|
+
layout: headerLayout,
|
|
90
|
+
loading: headerLoading
|
|
91
|
+
}
|
|
92
|
+
),
|
|
115
93
|
children != null && /* @__PURE__ */ jsx("div", { className: "ui-page-body", children }),
|
|
116
94
|
footer && /* @__PURE__ */ jsx("footer", { className: "ui-page-footer", children: footer })
|
|
117
95
|
]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PageHeader — the canonical page title band (gh#255).
|
|
3
|
+
*
|
|
4
|
+
* This is the geometry `PageContainer` has always rendered, lifted into its own export so a
|
|
5
|
+
* consumer can mount it OUTSIDE a full page shell — a Sheet detail, a `MasterDetail` detail pane, a
|
|
6
|
+
* tab body, a nested route header — without re-authoring `.ui-page-header` CSS locally. There is
|
|
7
|
+
* exactly ONE implementation: `PageContainer` renders this component, so the two can never drift.
|
|
8
|
+
*
|
|
9
|
+
* The band owns: breadcrumbs (a named `<nav>` landmark with `aria-current="page"` on the leaf), the
|
|
10
|
+
* `<h1>` title, the subtitle/description, a status/meta slot, the `extra` action region, the
|
|
11
|
+
* responsive overflow arrangement (`layout`), and the pending state (`loading`). It owns no page
|
|
12
|
+
* chrome — padding, measure and body rhythm stay with `PageContainer`.
|
|
13
|
+
*
|
|
14
|
+
* DENIED / ERROR are deliberately NOT states of this component: a page the user may not see must
|
|
15
|
+
* not render its title, breadcrumb trail or actions at all (they leak the resource's existence and
|
|
16
|
+
* its name). That whole-surface contract belongs to `ErrorSurface`, which is the canonical public
|
|
17
|
+
* replacement — see `docs/CANONICAL-CONTRACTS.md`.
|
|
18
|
+
*/
|
|
19
|
+
import * as React from "react";
|
|
20
|
+
import type { PageHeaderProp } from "../../props/components/layout.prop.js";
|
|
21
|
+
export type { PageHeaderProp, PageHeaderProp as PageHeaderProps, } from "../../props/components/layout.prop.js";
|
|
22
|
+
export declare const PageHeader: React.ForwardRefExoticComponent<PageHeaderProp & React.RefAttributes<HTMLElement>>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { ChevronRight } from "lucide-react";
|
|
5
|
+
import { useTranslation } from "../../i18n/use-translation.js";
|
|
6
|
+
import { cn } from "../../lib/utils.js";
|
|
7
|
+
const PageHeader = React.forwardRef(function PageHeader2({
|
|
8
|
+
title,
|
|
9
|
+
subtitle,
|
|
10
|
+
meta,
|
|
11
|
+
extra,
|
|
12
|
+
breadcrumb,
|
|
13
|
+
breadcrumbLabel,
|
|
14
|
+
breadcrumbAriaLabel,
|
|
15
|
+
linkComponent: LinkComponent = "a",
|
|
16
|
+
layout = "stack",
|
|
17
|
+
loading = false,
|
|
18
|
+
className
|
|
19
|
+
}, ref) {
|
|
20
|
+
const { t } = useTranslation();
|
|
21
|
+
return (
|
|
22
|
+
// `data-layout` is the only hook the header arrangement needs: `stack` (the default)
|
|
23
|
+
// matches no rule, so the historical geometry is untouched, while `responsive-inline`
|
|
24
|
+
// selects the compact-range rules that keep `extra` beside the title band (gh#231).
|
|
25
|
+
/* @__PURE__ */ jsxs(
|
|
26
|
+
"header",
|
|
27
|
+
{
|
|
28
|
+
ref,
|
|
29
|
+
className: cn("ui-page-header", className),
|
|
30
|
+
"data-layout": layout,
|
|
31
|
+
"aria-busy": loading ? "true" : void 0,
|
|
32
|
+
children: [
|
|
33
|
+
breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx(
|
|
34
|
+
"nav",
|
|
35
|
+
{
|
|
36
|
+
"aria-label": breadcrumbLabel ?? breadcrumbAriaLabel ?? t("navigation.breadcrumb.ariaLabel"),
|
|
37
|
+
className: "ui-breadcrumb",
|
|
38
|
+
children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: breadcrumb.map((item, i) => {
|
|
39
|
+
const isLast = i === breadcrumb.length - 1;
|
|
40
|
+
return /* @__PURE__ */ jsxs("li", { className: "ui-inline-xs", children: [
|
|
41
|
+
item.to && !isLast ? /* @__PURE__ */ jsx(
|
|
42
|
+
LinkComponent,
|
|
43
|
+
{
|
|
44
|
+
href: item.to,
|
|
45
|
+
to: item.to,
|
|
46
|
+
className: "hover:text-foreground hover:underline",
|
|
47
|
+
children: item.label
|
|
48
|
+
}
|
|
49
|
+
) : /* @__PURE__ */ jsx(
|
|
50
|
+
"span",
|
|
51
|
+
{
|
|
52
|
+
className: isLast ? "text-foreground" : "",
|
|
53
|
+
"aria-current": isLast ? "page" : void 0,
|
|
54
|
+
children: item.label
|
|
55
|
+
}
|
|
56
|
+
),
|
|
57
|
+
!isLast && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3", "aria-hidden": "true" })
|
|
58
|
+
] }, i);
|
|
59
|
+
}) })
|
|
60
|
+
}
|
|
61
|
+
),
|
|
62
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-page-header-row", children: [
|
|
63
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-page-header-heading min-w-0", children: [
|
|
64
|
+
loading ? /* @__PURE__ */ jsx("h1", { className: "ui-page-title ui-skeleton-block ui-page-title-placeholder", children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("layout.pageHeader.loading") }) }) : meta != null ? /* @__PURE__ */ jsxs("div", { className: "ui-page-title-band", children: [
|
|
65
|
+
/* @__PURE__ */ jsx("h1", { className: "ui-page-title", children: title }),
|
|
66
|
+
/* @__PURE__ */ jsx("div", { className: "ui-page-header-meta", children: meta })
|
|
67
|
+
] }) : /* @__PURE__ */ jsx("h1", { className: "ui-page-title", children: title }),
|
|
68
|
+
loading ? (
|
|
69
|
+
// Decorative only — the pending state is already announced once by the heading above,
|
|
70
|
+
// so a second live placeholder here would double-announce it.
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
"p",
|
|
73
|
+
{
|
|
74
|
+
className: "ui-page-subtitle ui-skeleton-block ui-page-subtitle-placeholder",
|
|
75
|
+
"aria-hidden": "true"
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
) : subtitle && /* @__PURE__ */ jsx("p", { className: "ui-page-subtitle", children: subtitle })
|
|
79
|
+
] }),
|
|
80
|
+
extra && /* @__PURE__ */ jsx("div", { className: "ui-page-header-extra", children: extra })
|
|
81
|
+
] })
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
);
|
|
86
|
+
});
|
|
87
|
+
export {
|
|
88
|
+
PageHeader
|
|
89
|
+
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ToolbarGroupProp, ToolbarProp } from "../../props/components/navigation.prop.js";
|
|
2
|
-
export type { FilterBarOverflowProp, ToolbarGroupProp, ToolbarGroupProp as ToolbarGroupProps, ToolbarGroupProp as FilterBarGroupProp, ToolbarGroupProp as FilterBarGroupProps, ToolbarProp, ToolbarProp as ToolbarProps, ToolbarProp as FilterBarProp, ToolbarProp as FilterBarProps, } from "../../props/components/navigation.prop.js";
|
|
3
|
-
export declare function Toolbar({ onClear, hasActiveFilters, sticky, overflow, className, children, }: ToolbarProp): import("react").JSX.Element;
|
|
2
|
+
export type { FilterBarChipProp, FilterBarChipProp as FilterBarChipProps, FilterBarOverflowProp, ToolbarGroupProp, ToolbarGroupProp as ToolbarGroupProps, ToolbarGroupProp as FilterBarGroupProp, ToolbarGroupProp as FilterBarGroupProps, ToolbarProp, ToolbarProp as ToolbarProps, ToolbarProp as FilterBarProp, ToolbarProp as FilterBarProps, } from "../../props/components/navigation.prop.js";
|
|
3
|
+
export declare function Toolbar({ onClear, hasActiveFilters, sticky, overflow, search, chips, onChipRemove, resultCount, actions, className, children, }: ToolbarProp): import("react").JSX.Element;
|
|
4
4
|
export declare function ToolbarGroup({ label, controlId, className, children }: ToolbarGroupProp): import("react").JSX.Element;
|
|
5
5
|
/**
|
|
6
6
|
* Canonical list-page filter strip.
|
|
@@ -10,10 +10,16 @@ function Toolbar({
|
|
|
10
10
|
hasActiveFilters = true,
|
|
11
11
|
sticky = false,
|
|
12
12
|
overflow = "wrap",
|
|
13
|
+
search,
|
|
14
|
+
chips,
|
|
15
|
+
onChipRemove,
|
|
16
|
+
resultCount,
|
|
17
|
+
actions,
|
|
13
18
|
className,
|
|
14
19
|
children
|
|
15
20
|
}) {
|
|
16
21
|
const { t } = useTranslation();
|
|
22
|
+
const hasChips = chips != null && chips.length > 0;
|
|
17
23
|
return /* @__PURE__ */ jsxs(
|
|
18
24
|
"div",
|
|
19
25
|
{
|
|
@@ -22,11 +28,48 @@ function Toolbar({
|
|
|
22
28
|
"data-overflow": overflow,
|
|
23
29
|
className: cn("ui-toolbar", sticky && "ui-toolbar-sticky", className),
|
|
24
30
|
children: [
|
|
31
|
+
search != null && // A region, not a bare child, so the search control gets ONE measure
|
|
32
|
+
// (--filter-bar-search-width) across every list page instead of whatever width the
|
|
33
|
+
// caller's control happened to have.
|
|
34
|
+
/* @__PURE__ */ jsx("div", { className: "ui-filter-bar-search", children: search }),
|
|
25
35
|
children,
|
|
36
|
+
hasChips && // `group` (not a second toolbar) — a toolbar may own a group, and the chips are a labelled
|
|
37
|
+
// set of related controls rather than an independent toolbar competing for the same role.
|
|
38
|
+
/* @__PURE__ */ jsx(
|
|
39
|
+
"div",
|
|
40
|
+
{
|
|
41
|
+
role: "group",
|
|
42
|
+
"aria-label": t("navigation.filterBar.appliedFilters"),
|
|
43
|
+
className: "ui-filter-bar-chips",
|
|
44
|
+
children: chips.map((chip) => /* @__PURE__ */ jsxs("span", { className: "ui-filter-bar-chip", children: [
|
|
45
|
+
/* @__PURE__ */ jsx("span", { className: "ui-filter-bar-chip-label", children: chip.label }),
|
|
46
|
+
(chip.onRemove || onChipRemove) && /* @__PURE__ */ jsx(
|
|
47
|
+
Button,
|
|
48
|
+
{
|
|
49
|
+
variant: "ghost",
|
|
50
|
+
size: "xs",
|
|
51
|
+
className: "ui-filter-bar-chip-remove",
|
|
52
|
+
"aria-label": t("navigation.filterBar.removeFilter", { label: chip.label }),
|
|
53
|
+
onClick: () => {
|
|
54
|
+
chip.onRemove?.();
|
|
55
|
+
onChipRemove?.(chip.id);
|
|
56
|
+
},
|
|
57
|
+
children: /* @__PURE__ */ jsx(X, { "aria-hidden": "true" })
|
|
58
|
+
}
|
|
59
|
+
)
|
|
60
|
+
] }, chip.id))
|
|
61
|
+
}
|
|
62
|
+
),
|
|
63
|
+
resultCount !== void 0 && // The whole reason this is a prop rather than caller markup: a sighted user SEES the table
|
|
64
|
+
// change, and a polite live region is what tells everyone else that filtering happened.
|
|
65
|
+
// The number is grouped by `Intl.NumberFormat` and the noun selected by CLDR plural rules
|
|
66
|
+
// for the active locale — never a hand-built "N items".
|
|
67
|
+
/* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", className: "ui-filter-bar-count", children: t("navigation.filterBar.resultCount", { count: resultCount }) }),
|
|
26
68
|
onClear && hasActiveFilters && /* @__PURE__ */ jsxs(Button, { variant: "ghost", size: "sm", onClick: onClear, className: "ui-toolbar-clear", children: [
|
|
27
69
|
/* @__PURE__ */ jsx(X, { "aria-hidden": "true" }),
|
|
28
70
|
t("common.clearFilters")
|
|
29
|
-
] })
|
|
71
|
+
] }),
|
|
72
|
+
actions != null && /* @__PURE__ */ jsx("div", { className: "ui-filter-bar-actions", children: actions })
|
|
30
73
|
]
|
|
31
74
|
}
|
|
32
75
|
);
|
|
@@ -5,7 +5,7 @@ export { Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarLabel
|
|
|
5
5
|
export { NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, } from "./navigation-menu.js";
|
|
6
6
|
export { Steps } from "./steps.js";
|
|
7
7
|
export { FilterBar, FilterBarGroup, Toolbar, ToolbarGroup } from "./filter-bar.js";
|
|
8
|
-
export type { FilterBarGroupProp, FilterBarGroupProps, FilterBarProp, FilterBarProps, ToolbarGroupProps, ToolbarProps, } from "./filter-bar.js";
|
|
8
|
+
export type { FilterBarChipProp, FilterBarChipProps, FilterBarGroupProp, FilterBarGroupProps, FilterBarProp, FilterBarProps, ToolbarGroupProps, ToolbarProps, } from "./filter-bar.js";
|
|
9
9
|
export { AppSettingPicker } from "./app-setting-picker.js";
|
|
10
10
|
export type { AppSettingPickerProp, AppSettingPickerProps, AppSettingKind, } from "./app-setting-picker.js";
|
|
11
11
|
export type { BreadcrumbItemProp as BreadcrumbItem } from "../../props/vocabulary/navigation.prop.js";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { StepsProp } from "../../props/components/navigation.prop.js";
|
|
3
|
-
export type { StepsProp, StepsProp as StepsProps, StepItemProp, StepStatusProp, } from "../../props/components/navigation.prop.js";
|
|
4
|
-
export declare function Steps({ items, value: current, defaultValue, status: currentStatus, orientation, type, size, titlePlacement, onValueChange, className, }: StepsProp): React.JSX.Element;
|
|
3
|
+
export type { StepsProp, StepsProp as StepsProps, StepItemProp, StepStatusProp, StepsSeparatorProp, } from "../../props/components/navigation.prop.js";
|
|
4
|
+
export declare function Steps({ items, value: current, defaultValue, status: currentStatus, orientation, type, size, titlePlacement, separator, onValueChange, className, }: StepsProp): React.JSX.Element;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Check, ChevronRight, Circle, Loader2, X } from "lucide-react";
|
|
3
|
+
import { ArrowRight, Check, ChevronRight, Circle, Loader2, X } from "lucide-react";
|
|
4
4
|
import { useTranslation } from "../../i18n/use-translation.js";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
6
|
import { controlIconClass } from "../../lib/control-styles.js";
|
|
@@ -61,6 +61,7 @@ function Steps({
|
|
|
61
61
|
type = "default",
|
|
62
62
|
size = "md",
|
|
63
63
|
titlePlacement = "horizontal",
|
|
64
|
+
separator = "chevron",
|
|
64
65
|
onValueChange,
|
|
65
66
|
className
|
|
66
67
|
}) {
|
|
@@ -69,6 +70,7 @@ function Steps({
|
|
|
69
70
|
const isVertical = orientation === "vertical";
|
|
70
71
|
const compact = size === "sm";
|
|
71
72
|
const inline = type === "inline";
|
|
73
|
+
const SeparatorIcon = separator === "arrow" ? ArrowRight : ChevronRight;
|
|
72
74
|
return /* @__PURE__ */ jsx(
|
|
73
75
|
"ol",
|
|
74
76
|
{
|
|
@@ -151,7 +153,7 @@ function Steps({
|
|
|
151
153
|
}
|
|
152
154
|
) : /* @__PURE__ */ jsx("span", { className: stepClassName, children: stepInner }),
|
|
153
155
|
inline && index < items.length - 1 ? /* @__PURE__ */ jsx(
|
|
154
|
-
|
|
156
|
+
SeparatorIcon,
|
|
155
157
|
{
|
|
156
158
|
className: "ui-steps-inline-separator rtl:rotate-180",
|
|
157
159
|
"aria-hidden": "true"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
3
3
|
import type { AvatarProp } from "../../props/components/data-display.prop.js";
|
|
4
|
-
export declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & Pick<AvatarProp, "shape"> & React.RefAttributes<HTMLSpanElement>>;
|
|
4
|
+
export declare const Avatar: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarProps & React.RefAttributes<HTMLSpanElement>, "ref"> & Pick<AvatarProp, "shape" | "appearance"> & React.RefAttributes<HTMLSpanElement>>;
|
|
5
5
|
export declare const AvatarImage: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarImageProps & React.RefAttributes<HTMLImageElement>, "ref"> & React.RefAttributes<HTMLImageElement>>;
|
|
6
6
|
export declare const AvatarFallback: React.ForwardRefExoticComponent<Omit<AvatarPrimitive.AvatarFallbackProps & React.RefAttributes<HTMLSpanElement>, "ref"> & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -3,12 +3,13 @@ import { jsx } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import * as AvatarPrimitive from "@radix-ui/react-avatar";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const Avatar = React.forwardRef(({ className, shape = "circle", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
6
|
+
const Avatar = React.forwardRef(({ className, shape = "circle", appearance = "default", ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7
7
|
AvatarPrimitive.Root,
|
|
8
8
|
{
|
|
9
9
|
ref,
|
|
10
10
|
"data-slot": "avatar",
|
|
11
11
|
"data-shape": shape === "square" ? "square" : void 0,
|
|
12
|
+
"data-appearance": appearance === "tinted" ? "tinted" : void 0,
|
|
12
13
|
className: cn("ui-avatar", className),
|
|
13
14
|
...props
|
|
14
15
|
}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
|
|
2
|
+
import type { InputOTPAlignProp } from "../../props/components/data-entry.prop.js";
|
|
3
|
+
/**
|
|
4
|
+
* InputOTP — the code-challenge field.
|
|
5
|
+
*
|
|
6
|
+
* `align` positions the whole row (groups + separators) on the main axis: `start` (default,
|
|
7
|
+
* unchanged), `center` — the canonical auth challenge — or `end`. The attribute lands on the
|
|
8
|
+
* hidden input because `input-otp` owns the container element; `.ui-otp-container` reads it back
|
|
9
|
+
* through `:has()`, exactly as it already does for the invalid and disabled states. A service that
|
|
10
|
+
* wants every code field centred sets `--otp-container-align` once instead.
|
|
11
|
+
*/
|
|
12
|
+
export declare const InputOTP: React.ForwardRefExoticComponent<((Omit<Omit<React.InputHTMLAttributes<HTMLInputElement>, "onChange" | "value" | "maxLength" | "textAlign" | "onComplete" | "pushPasswordManagerStrategy" | "pasteTransformer" | "containerClassName" | "noScriptCSSFallback"> & {
|
|
3
13
|
value?: string;
|
|
4
14
|
onChange?: (newValue: string) => unknown;
|
|
5
15
|
maxLength: number;
|
|
@@ -25,8 +35,10 @@ export declare const InputOTP: React.ForwardRefExoticComponent<(Omit<Omit<React.
|
|
|
25
35
|
} & {
|
|
26
36
|
render?: never;
|
|
27
37
|
children: React.ReactNode;
|
|
28
|
-
} & React.RefAttributes<HTMLInputElement>, "ref">) &
|
|
29
|
-
|
|
38
|
+
} & React.RefAttributes<HTMLInputElement>, "ref">) & {
|
|
39
|
+
align?: InputOTPAlignProp;
|
|
40
|
+
}) & React.RefAttributes<HTMLInputElement>>;
|
|
41
|
+
export type { InputOTPAlignProp, InputOTPGroupAppearanceProp, InputOTPGroupProp, InputOTPGroupProp as InputOTPGroupProps, } from "../../props/components/data-entry.prop.js";
|
|
30
42
|
export declare const InputOTPGroup: React.ForwardRefExoticComponent<React.HTMLAttributes<HTMLDivElement> & {
|
|
31
43
|
appearance?: import("./input-otp.js").InputOTPGroupAppearanceProp;
|
|
32
44
|
} & React.RefAttributes<HTMLDivElement>>;
|