@godxjp/ui 18.3.0 → 18.5.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/README.md +18 -3
- package/dist/app/theme-axes.d.ts +11 -3
- package/dist/app/theme-axes.js +2 -1
- package/dist/components/charts/chart-frame.d.ts +17 -3
- package/dist/components/charts/chart-frame.js +7 -1
- package/dist/components/charts/chart-summary.d.ts +21 -0
- package/dist/components/charts/chart-summary.js +32 -5
- package/dist/components/charts/compact-bar-trend.d.ts +29 -0
- package/dist/components/charts/compact-bar-trend.js +74 -0
- package/dist/components/charts/index.d.ts +3 -0
- package/dist/components/charts/index.js +2 -0
- package/dist/components/data-display/badge.d.ts +8 -0
- package/dist/components/data-display/badge.js +7 -1
- package/dist/components/data-display/data-table.d.ts +16 -1
- package/dist/components/data-display/data-table.js +56 -0
- package/dist/components/data-display/index.d.ts +3 -1
- package/dist/components/data-display/index.js +10 -1
- package/dist/components/data-display/list-row.d.ts +22 -4
- package/dist/components/data-display/list-row.js +21 -3
- package/dist/components/data-display/service-launcher-card.d.ts +40 -0
- package/dist/components/data-display/service-launcher-card.js +97 -0
- package/dist/components/data-entry/command-palette.d.ts +37 -0
- package/dist/components/data-entry/command-palette.js +125 -0
- package/dist/components/data-entry/index.d.ts +2 -0
- package/dist/components/data-entry/index.js +2 -0
- package/dist/components/feedback/dialog.d.ts +2 -0
- package/dist/components/feedback/dialog.js +42 -33
- package/dist/components/feedback/index.d.ts +4 -1
- package/dist/components/feedback/index.js +6 -2
- package/dist/components/feedback/sheet.d.ts +26 -4
- package/dist/components/feedback/sheet.js +54 -7
- package/dist/components/feedback/two-factor-setup.d.ts +31 -0
- package/dist/components/feedback/two-factor-setup.js +97 -0
- package/dist/components/general/index.d.ts +1 -1
- package/dist/components/general/logo.d.ts +42 -8
- package/dist/components/general/logo.js +67 -14
- package/dist/components/layout/app-shell.js +22 -6
- package/dist/components/layout/auth-divider.d.ts +7 -0
- package/dist/components/layout/auth-divider.js +21 -0
- package/dist/components/layout/auth-footer.d.ts +5 -0
- package/dist/components/layout/auth-footer.js +24 -0
- package/dist/components/layout/auth-identity.d.ts +5 -0
- package/dist/components/layout/auth-identity.js +17 -0
- package/dist/components/layout/auth-shell.d.ts +8 -1
- package/dist/components/layout/auth-shell.js +25 -6
- package/dist/components/layout/auth-stack.d.ts +4 -0
- package/dist/components/layout/auth-stack.js +8 -0
- package/dist/components/layout/centered-shell.d.ts +5 -2
- package/dist/components/layout/centered-shell.js +2 -1
- package/dist/components/layout/index.d.ts +18 -3
- package/dist/components/layout/index.js +17 -2
- package/dist/components/layout/legal-document-shell.d.ts +34 -0
- package/dist/components/layout/legal-document-shell.js +186 -0
- package/dist/components/layout/master-detail.d.ts +24 -0
- package/dist/components/layout/master-detail.js +48 -0
- package/dist/components/layout/org-switcher.d.ts +9 -0
- package/dist/components/layout/org-switcher.js +218 -0
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +3 -2
- package/dist/components/layout/sidebar-link.d.ts +43 -0
- package/dist/components/layout/sidebar-link.js +13 -0
- package/dist/components/layout/sidebar.d.ts +42 -5
- package/dist/components/layout/sidebar.js +170 -85
- package/dist/components/navigation/app-setting-picker.js +17 -6
- package/dist/components/navigation/filter-bar.d.ts +12 -3
- package/dist/components/navigation/filter-bar.js +8 -2
- package/dist/components/navigation/index.d.ts +2 -2
- package/dist/components/navigation/index.js +3 -1
- package/dist/components/navigation/tabs-scroll.d.ts +70 -0
- package/dist/components/navigation/tabs-scroll.js +76 -0
- package/dist/components/navigation/tabs.js +35 -20
- package/dist/email/brand-mark.d.ts +92 -0
- package/dist/email/brand-mark.js +83 -0
- package/dist/email/color.d.ts +52 -0
- package/dist/email/color.js +37 -0
- package/dist/email/geometry.d.ts +112 -0
- package/dist/email/geometry.js +89 -0
- package/dist/email/index.d.ts +78 -0
- package/dist/email/index.js +76 -0
- package/dist/email/inline-style.d.ts +25 -0
- package/dist/email/inline-style.js +21 -0
- package/dist/email/tokens.generated.d.ts +147 -0
- package/dist/email/tokens.generated.js +142 -0
- package/dist/i18n/messages/en.json +21 -2
- package/dist/i18n/messages/ja.json +21 -2
- package/dist/i18n/messages/vi.json +21 -2
- package/dist/inertia/index.d.ts +50 -0
- package/dist/inertia/index.js +5 -0
- package/dist/props/components/app.prop.d.ts +11 -1
- package/dist/props/components/charts.prop.d.ts +40 -1
- package/dist/props/components/data-display.prop.d.ts +13 -1
- package/dist/props/components/feedback.prop.d.ts +10 -0
- package/dist/props/components/index.d.ts +2 -2
- package/dist/props/components/layout.prop.d.ts +374 -11
- package/dist/props/components/layout.prop.js +1 -0
- package/dist/props/components/navigation.prop.d.ts +19 -1
- package/dist/props/registry.d.ts +291 -7
- package/dist/props/registry.js +341 -7
- package/dist/props/vocabulary/index.d.ts +1 -1
- package/dist/props/vocabulary/interaction.prop.d.ts +1 -1
- package/dist/props/vocabulary/layout.prop.d.ts +18 -0
- package/dist/styles/base.css +9 -3
- package/dist/styles/card-layout.css +162 -8
- package/dist/styles/chart-layout.css +97 -0
- package/dist/styles/control.css +48 -2
- package/dist/styles/data-display-layout.css +52 -6
- package/dist/styles/dialog-layout.css +105 -4
- package/dist/styles/fonts.css +29 -20
- package/dist/styles/index.css +11 -3
- package/dist/styles/layout.css +368 -2
- package/dist/styles/logo-layout.css +62 -0
- package/dist/styles/navigation-layout.css +43 -0
- package/dist/styles/shell-layout.css +505 -62
- package/dist/theme/dxs.canonical.css +76 -0
- package/dist/tokens/axes.css +39 -0
- package/dist/tokens/base.css +5 -0
- package/dist/tokens/components/card.css +52 -5
- package/dist/tokens/components/chart.css +47 -0
- package/dist/tokens/components/control.css +16 -0
- package/dist/tokens/components/email.css +66 -0
- package/dist/tokens/components/feedback.css +17 -0
- package/dist/tokens/components/legal-document.css +67 -0
- package/dist/tokens/components/list-row.css +23 -2
- package/dist/tokens/components/logo.css +32 -0
- package/dist/tokens/components/navigation.css +13 -0
- package/dist/tokens/components/sheet.css +19 -0
- package/dist/tokens/components/shell.css +149 -1
- package/dist/tokens/components/sidebar.css +33 -0
- package/dist/tokens/foundation.css +5 -2
- package/dist/tokens/semantic/layout.css +44 -2
- package/package.json +17 -6
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { SidebarLinkComponentProp } from "../../props/components/layout.prop.js";
|
|
3
|
+
/**
|
|
4
|
+
* Adapt a framework router `Link` to {@link SidebarLinkComponentProp} (gh#213) — a dependency-free
|
|
5
|
+
* factory, so `@godxjp/ui` still ships ZERO router/framework dependencies.
|
|
6
|
+
*
|
|
7
|
+
* It lives in its own module (imports only React + the prop types) so `@godxjp/ui/inertia` can build
|
|
8
|
+
* on it without pulling the whole Sidebar — and its Collapsible/Popover/Tooltip tree — into a
|
|
9
|
+
* form-only consumer's bundle.
|
|
10
|
+
*
|
|
11
|
+
* It normalizes only the two things that differ between routers:
|
|
12
|
+
* 1. **Which prop carries the destination** — `"href"` (Inertia, Next.js) or `"to"` (React Router,
|
|
13
|
+
* TanStack Router).
|
|
14
|
+
* 2. **A row with no destination** — a disabled row must never mount a router link (Inertia and
|
|
15
|
+
* React Router both require a string destination and would navigate to `""`); it falls back to an
|
|
16
|
+
* inert `<a>` that keeps the canonical row class and `aria-disabled`. That fallback carries an
|
|
17
|
+
* explicit `role="link"`: an `<a>` without `href` has NO implicit role, so a screen reader would
|
|
18
|
+
* announce it as plain text and `aria-label` would be a prohibited attribute — which is exactly
|
|
19
|
+
* how the icon-only collapsed rail (where the label lives on `aria-label`) would have lost the
|
|
20
|
+
* name of every disabled row. Callers that supply their own role — the collapsed flyout's
|
|
21
|
+
* `menuitem` — still win, because `rest` is spread after it.
|
|
22
|
+
*
|
|
23
|
+
* Everything else — the icon, the label, the badge, `data-active`/`aria-current`, the collapsed
|
|
24
|
+
* rail's `aria-label` — is composed by the LIBRARY and arrives as `children`. The consumer never
|
|
25
|
+
* reconstructs row markup, which is what makes the reported "every sidebar icon disappeared"
|
|
26
|
+
* regression impossible.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```tsx
|
|
30
|
+
* // React Router / TanStack Router — destination prop is `to`.
|
|
31
|
+
* import { Link } from "react-router-dom";
|
|
32
|
+
* const RouterLink = createSidebarLink(Link, "to");
|
|
33
|
+
* <Sidebar linkComponent={RouterLink} sections={sections} activeId={activeId} />
|
|
34
|
+
*
|
|
35
|
+
* // Inertia / Next.js — destination prop is `href` (the default).
|
|
36
|
+
* import { Link } from "@inertiajs/react";
|
|
37
|
+
* const InertiaLink = createSidebarLink(Link);
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export declare function createSidebarLink<P extends {
|
|
41
|
+
className?: string;
|
|
42
|
+
children?: React.ReactNode;
|
|
43
|
+
}>(Link: React.ComponentType<P>, hrefProp?: "href" | "to"): SidebarLinkComponentProp;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
function createSidebarLink(Link, hrefProp = "href") {
|
|
4
|
+
const Adapter = React.forwardRef(function SidebarLinkAdapter({ href, ...rest }, ref) {
|
|
5
|
+
if (!href) return /* @__PURE__ */ jsx("a", { ref, role: "link", ...rest });
|
|
6
|
+
const routed = { [hrefProp]: href, ...rest, ref };
|
|
7
|
+
return /* @__PURE__ */ jsx(Link, { ...routed });
|
|
8
|
+
});
|
|
9
|
+
return Adapter;
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
createSidebarLink
|
|
13
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import type { SidebarItemData, SidebarProp } from "../../props/components/layout.prop.js";
|
|
3
|
-
export type { SidebarItemData, SidebarProductProp as SidebarProduct, SidebarProp, SidebarProp as SidebarProps, } from "../../props/components/layout.prop.js";
|
|
4
|
-
type RenderItem = (item: SidebarItemData) => React.ReactNode;
|
|
2
|
+
import type { SidebarItemData, SidebarLinkComponentProp, SidebarProp, SidebarRenderItemProp } from "../../props/components/layout.prop.js";
|
|
3
|
+
export type { SidebarItemData, SidebarLinkComponentProp, SidebarLinkProp, SidebarProductProp as SidebarProduct, SidebarProp, SidebarProp as SidebarProps, SidebarRenderItemProp, } from "../../props/components/layout.prop.js";
|
|
4
|
+
type RenderItem = (item: SidebarItemData, rowProps: SidebarRenderItemProp) => React.ReactNode;
|
|
5
5
|
type SidebarHeaderProps = React.HTMLAttributes<HTMLDivElement>;
|
|
6
6
|
type SidebarSectionProps = {
|
|
7
7
|
label?: string;
|
|
@@ -13,9 +13,46 @@ type SidebarItemProps = {
|
|
|
13
13
|
active?: boolean;
|
|
14
14
|
sub?: boolean;
|
|
15
15
|
onActivate?: (id: string) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Framework-router link element TYPE (gh#213). The row content stays library-composed — see
|
|
18
|
+
* {@link SidebarLinkProp}. Applied only when `item.href` is set.
|
|
19
|
+
*/
|
|
20
|
+
linkComponent?: SidebarLinkComponentProp;
|
|
21
|
+
/**
|
|
22
|
+
* Radix-style element swap: the single child element (a router `<Link>`) BECOMES the row and the
|
|
23
|
+
* library injects its composed icon + label + badge as that element's children (gh#213). Use it
|
|
24
|
+
* when you compose `SidebarItem` by hand instead of passing `sections` + `linkComponent`.
|
|
25
|
+
*/
|
|
26
|
+
asChild?: boolean;
|
|
27
|
+
/** @deprecated Use `linkComponent` / `asChild` — see {@link SidebarProp.renderItem}. */
|
|
16
28
|
renderItem?: RenderItem;
|
|
17
29
|
};
|
|
18
30
|
export declare function SidebarHeader({ children, className, ...props }: SidebarHeaderProps): React.JSX.Element;
|
|
19
31
|
export declare function SidebarSection({ label, collapsed, children, className, ...props }: SidebarSectionProps & React.HTMLAttributes<HTMLDivElement>): React.JSX.Element;
|
|
20
|
-
export declare function SidebarItem({ item, active, sub, onActivate, renderItem, children, ...props }: SidebarItemProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onClick">): React.JSX.Element;
|
|
21
|
-
export
|
|
32
|
+
export declare function SidebarItem({ item, active, sub, onActivate, linkComponent: LinkComponent, asChild, renderItem, children, ...props }: SidebarItemProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onClick">): React.JSX.Element;
|
|
33
|
+
export { createSidebarLink } from "./sidebar-link.js";
|
|
34
|
+
/**
|
|
35
|
+
* Sidebar — data-driven vertical nav rail.
|
|
36
|
+
*
|
|
37
|
+
* ROUTER LINKS (gh#213): pass `linkComponent` and the LIBRARY keeps composing every row (icon slot,
|
|
38
|
+
* label, badge, active state, the icon-only collapsed rail and its tooltip name) — the consumer
|
|
39
|
+
* supplies only the link ELEMENT. Use {@link createSidebarLink} to adapt a router `Link`, or
|
|
40
|
+
* `SidebarItem asChild` when composing rows by hand. `renderItem` is DEPRECATED: it left row content
|
|
41
|
+
* to the consumer, so a `<Link>{item.label}</Link>` dropped every icon and badge.
|
|
42
|
+
*
|
|
43
|
+
* THEMING (gh#228): the row/label and the nav ICON read SEPARATE component tokens, so a service can
|
|
44
|
+
* match a canonical shell's darker 16px icons without page-local CSS and without re-tinting every
|
|
45
|
+
* muted text globally:
|
|
46
|
+
*
|
|
47
|
+
* - `--sidebar-nav-item-foreground` (row + label, incl. sub rows) · default `hsl(var(--muted-foreground))`
|
|
48
|
+
* - `--sidebar-nav-item-hover-foreground` · default `hsl(var(--foreground))`
|
|
49
|
+
* - `--sidebar-nav-item-disabled-foreground` · default = the resting row colour
|
|
50
|
+
* - `--sidebar-nav-icon-foreground` (`.sb-icon`, incl. the collapsed rail + group triggers) ·
|
|
51
|
+
* default `currentColor` = the row colour
|
|
52
|
+
* - `--sidebar-nav-icon-{hover,active,disabled}-foreground` · each defaults to the base icon knob
|
|
53
|
+
*
|
|
54
|
+
* The active row keeps `--sidebar-item-active-background` / `--sidebar-item-active-foreground`.
|
|
55
|
+
* These are COLOUR knobs only — icon size stays `--sidebar-nav-icon-size` (16px) and row geometry
|
|
56
|
+
* stays `--sidebar-nav-item-height` / `-gap` / `-padding-x`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function Sidebar({ ariaLabel: ariaLabelCamel, activeId, onSelect, sections, product, onProductClick, brand, collapsed, children, linkComponent, renderItem, footer, "aria-label": ariaLabel, }: SidebarProp): React.JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Slot } from "@radix-ui/react-slot";
|
|
5
5
|
import { ChevronDown } from "lucide-react";
|
|
@@ -23,72 +23,91 @@ function SidebarSection({
|
|
|
23
23
|
/* @__PURE__ */ jsx("div", { className: "sb-nav", children })
|
|
24
24
|
] });
|
|
25
25
|
}
|
|
26
|
+
function SidebarIcon({ icon: Icon }) {
|
|
27
|
+
return /* @__PURE__ */ jsx("span", { className: "sb-icon", children: Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) : null });
|
|
28
|
+
}
|
|
29
|
+
function SidebarRowContent({
|
|
30
|
+
item,
|
|
31
|
+
sub = false,
|
|
32
|
+
iconOnly = false
|
|
33
|
+
}) {
|
|
34
|
+
if (iconOnly) return /* @__PURE__ */ jsx(SidebarIcon, { icon: item.icon });
|
|
35
|
+
const showBadge = item.badge !== void 0 && item.badge !== "";
|
|
36
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37
|
+
!sub ? /* @__PURE__ */ jsx(SidebarIcon, { icon: item.icon }) : null,
|
|
38
|
+
/* @__PURE__ */ jsx("span", { className: "sb-label", children: item.label }),
|
|
39
|
+
showBadge ? /* @__PURE__ */ jsx("span", { className: "sb-badge", children: item.badge }) : null
|
|
40
|
+
] });
|
|
41
|
+
}
|
|
26
42
|
function SidebarItem({
|
|
27
43
|
item,
|
|
28
44
|
active = false,
|
|
29
45
|
sub = false,
|
|
30
46
|
onActivate,
|
|
47
|
+
linkComponent: LinkComponent,
|
|
48
|
+
asChild = false,
|
|
31
49
|
renderItem,
|
|
32
50
|
children,
|
|
33
51
|
...props
|
|
34
52
|
}) {
|
|
35
|
-
const Icon = item.icon;
|
|
36
|
-
const showBadge = item.badge !== void 0 && item.badge !== "";
|
|
37
53
|
const disabled = item.disabled || props.disabled;
|
|
38
|
-
const custom = children ?? (renderItem ? renderItem(item) : void 0);
|
|
39
54
|
const rowClass = cn("sb-nav-item", sub && "sb-nav-item--sub");
|
|
40
55
|
const stateProps = {
|
|
41
56
|
className: rowClass,
|
|
42
57
|
"data-active": active ? "true" : void 0,
|
|
43
|
-
"aria-current": active ? "page" : void 0
|
|
58
|
+
"aria-current": active ? "page" : void 0,
|
|
59
|
+
"aria-disabled": disabled ? true : void 0
|
|
60
|
+
};
|
|
61
|
+
const content = /* @__PURE__ */ jsx(SidebarRowContent, { item, sub });
|
|
62
|
+
const activate = (event) => {
|
|
63
|
+
if (disabled) {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
onActivate?.(item.id);
|
|
44
68
|
};
|
|
69
|
+
if (asChild && React.isValidElement(children)) {
|
|
70
|
+
return /* @__PURE__ */ jsx(Slot, { ...stateProps, onClick: activate, children: React.cloneElement(children, void 0, content) });
|
|
71
|
+
}
|
|
72
|
+
const custom = children ?? (renderItem ? renderItem(item, { ...stateProps, children: content }) : void 0);
|
|
45
73
|
if (custom !== void 0) {
|
|
46
|
-
return /* @__PURE__ */ jsx(Slot, { ...stateProps,
|
|
74
|
+
return /* @__PURE__ */ jsx(Slot, { ...stateProps, children: custom });
|
|
75
|
+
}
|
|
76
|
+
if (LinkComponent && item.href) {
|
|
77
|
+
return /* @__PURE__ */ jsx(
|
|
78
|
+
LinkComponent,
|
|
79
|
+
{
|
|
80
|
+
...stateProps,
|
|
81
|
+
href: disabled ? void 0 : item.href,
|
|
82
|
+
"aria-disabled": disabled || void 0,
|
|
83
|
+
onClick: activate,
|
|
84
|
+
children: content
|
|
85
|
+
}
|
|
86
|
+
);
|
|
47
87
|
}
|
|
48
88
|
if (item.href) {
|
|
49
|
-
return /* @__PURE__ */
|
|
89
|
+
return /* @__PURE__ */ jsx(
|
|
50
90
|
"a",
|
|
51
91
|
{
|
|
52
92
|
...props,
|
|
53
93
|
href: disabled ? void 0 : item.href,
|
|
54
94
|
...stateProps,
|
|
55
95
|
"aria-disabled": disabled || void 0,
|
|
56
|
-
onClick:
|
|
57
|
-
|
|
58
|
-
else onActivate?.(item.id);
|
|
59
|
-
},
|
|
60
|
-
children: [
|
|
61
|
-
!sub ? /* @__PURE__ */ jsx("span", { className: "sb-icon", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) }) : null,
|
|
62
|
-
/* @__PURE__ */ jsx("span", { className: "sb-label", children: item.label }),
|
|
63
|
-
showBadge ? /* @__PURE__ */ jsx("span", { className: "sb-badge", children: item.badge }) : null
|
|
64
|
-
]
|
|
96
|
+
onClick: activate,
|
|
97
|
+
children: content
|
|
65
98
|
}
|
|
66
99
|
);
|
|
67
100
|
}
|
|
68
|
-
return
|
|
69
|
-
|
|
70
|
-
{
|
|
71
|
-
type: "button",
|
|
72
|
-
...stateProps,
|
|
73
|
-
"aria-disabled": disabled,
|
|
74
|
-
...props,
|
|
75
|
-
onClick: () => {
|
|
76
|
-
if (disabled) return;
|
|
77
|
-
onActivate?.(item.id);
|
|
78
|
-
},
|
|
79
|
-
children: [
|
|
80
|
-
!sub ? /* @__PURE__ */ jsx("span", { className: "sb-icon", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) }) : null,
|
|
81
|
-
/* @__PURE__ */ jsx("span", { className: "sb-label", children: item.label }),
|
|
82
|
-
showBadge ? /* @__PURE__ */ jsx("span", { className: "sb-badge", children: item.badge }) : null
|
|
83
|
-
]
|
|
84
|
-
}
|
|
101
|
+
return (
|
|
102
|
+
// ui-audit-disable-next-line no-raw-button — raw <button> is the correct element here.
|
|
103
|
+
/* @__PURE__ */ jsx("button", { type: "button", ...stateProps, "aria-disabled": disabled, ...props, onClick: activate, children: content })
|
|
85
104
|
);
|
|
86
105
|
}
|
|
87
106
|
function isItemActive(item, activeId) {
|
|
88
107
|
if (item.id === activeId) return true;
|
|
89
108
|
return (item.children ?? []).some((child) => isItemActive(child, activeId));
|
|
90
109
|
}
|
|
91
|
-
function NavLeaf({ item, activeId, onSelect, sub = false, renderItem }) {
|
|
110
|
+
function NavLeaf({ item, activeId, onSelect, sub = false, linkComponent, renderItem }) {
|
|
92
111
|
const active = item.id === activeId;
|
|
93
112
|
return /* @__PURE__ */ jsx(
|
|
94
113
|
SidebarItem,
|
|
@@ -97,6 +116,7 @@ function NavLeaf({ item, activeId, onSelect, sub = false, renderItem }) {
|
|
|
97
116
|
active,
|
|
98
117
|
onActivate: onSelect,
|
|
99
118
|
sub,
|
|
119
|
+
linkComponent,
|
|
100
120
|
renderItem
|
|
101
121
|
}
|
|
102
122
|
);
|
|
@@ -105,6 +125,7 @@ function NavLeafsInGroup({
|
|
|
105
125
|
children,
|
|
106
126
|
activeId,
|
|
107
127
|
onSelect,
|
|
128
|
+
linkComponent,
|
|
108
129
|
renderItem
|
|
109
130
|
}) {
|
|
110
131
|
return children.map((child) => /* @__PURE__ */ jsx(
|
|
@@ -114,13 +135,13 @@ function NavLeafsInGroup({
|
|
|
114
135
|
activeId,
|
|
115
136
|
onSelect,
|
|
116
137
|
sub: true,
|
|
138
|
+
linkComponent,
|
|
117
139
|
renderItem
|
|
118
140
|
},
|
|
119
141
|
child.id
|
|
120
142
|
));
|
|
121
143
|
}
|
|
122
|
-
function NavGroup({ item, activeId, onSelect, renderItem }) {
|
|
123
|
-
const Icon = item.icon;
|
|
144
|
+
function NavGroup({ item, activeId, onSelect, linkComponent, renderItem }) {
|
|
124
145
|
const active = isItemActive(item, activeId);
|
|
125
146
|
const children = item.children ?? [];
|
|
126
147
|
const [open, setOpen] = React.useState(active);
|
|
@@ -134,18 +155,25 @@ function NavGroup({ item, activeId, onSelect, renderItem }) {
|
|
|
134
155
|
className: "sb-nav-item sb-nav-group-trigger",
|
|
135
156
|
"data-active": active ? "true" : void 0,
|
|
136
157
|
children: [
|
|
137
|
-
/* @__PURE__ */ jsx(
|
|
138
|
-
/* @__PURE__ */ jsx("span", { className: "sb-label", children: item.label }),
|
|
158
|
+
/* @__PURE__ */ jsx(SidebarRowContent, { item }),
|
|
139
159
|
/* @__PURE__ */ jsx(ChevronDown, { className: "sb-chevron", "aria-hidden": "true" })
|
|
140
160
|
]
|
|
141
161
|
}
|
|
142
162
|
),
|
|
143
|
-
/* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", { className: "sb-nav-sub", children: children.length > 0 ? /* @__PURE__ */ jsx(
|
|
163
|
+
/* @__PURE__ */ jsx(CollapsibleContent, { children: /* @__PURE__ */ jsx("div", { className: "sb-nav-sub", children: children.length > 0 ? /* @__PURE__ */ jsx(
|
|
164
|
+
NavLeafsInGroup,
|
|
165
|
+
{
|
|
166
|
+
activeId,
|
|
167
|
+
onSelect,
|
|
168
|
+
linkComponent,
|
|
169
|
+
renderItem,
|
|
170
|
+
children
|
|
171
|
+
}
|
|
172
|
+
) : null }) })
|
|
144
173
|
] });
|
|
145
174
|
}
|
|
146
|
-
function CollapsedRow({ item, activeId, onSelect }) {
|
|
175
|
+
function CollapsedRow({ item, activeId, onSelect, linkComponent: LinkComponent }) {
|
|
147
176
|
const [menuOpen, setMenuOpen] = React.useState(false);
|
|
148
|
-
const Icon = item.icon;
|
|
149
177
|
const active = isItemActive(item, activeId);
|
|
150
178
|
const children = item.children ?? [];
|
|
151
179
|
const hasChildren = children.length > 0;
|
|
@@ -163,12 +191,31 @@ function CollapsedRow({ item, activeId, onSelect }) {
|
|
|
163
191
|
onClick: () => {
|
|
164
192
|
if (!hasChildren && !item.disabled) onSelect?.(item.id);
|
|
165
193
|
},
|
|
166
|
-
children: /* @__PURE__ */ jsx(
|
|
194
|
+
children: /* @__PURE__ */ jsx(SidebarIcon, { icon: item.icon })
|
|
167
195
|
}
|
|
168
196
|
);
|
|
197
|
+
const iconLink = LinkComponent && !hasChildren && item.href ? /* @__PURE__ */ jsx(
|
|
198
|
+
LinkComponent,
|
|
199
|
+
{
|
|
200
|
+
className: "sb-nav-item",
|
|
201
|
+
"data-active": active ? "true" : void 0,
|
|
202
|
+
"aria-current": active ? "page" : void 0,
|
|
203
|
+
"aria-disabled": item.disabled || void 0,
|
|
204
|
+
"aria-label": item.label,
|
|
205
|
+
href: item.disabled ? void 0 : item.href,
|
|
206
|
+
onClick: (event) => {
|
|
207
|
+
if (item.disabled) {
|
|
208
|
+
event.preventDefault();
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
onSelect?.(item.id);
|
|
212
|
+
},
|
|
213
|
+
children: /* @__PURE__ */ jsx(SidebarRowContent, { item, iconOnly: true })
|
|
214
|
+
}
|
|
215
|
+
) : null;
|
|
169
216
|
if (!hasChildren) {
|
|
170
217
|
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
171
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: iconButton }),
|
|
218
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: iconLink ?? iconButton }),
|
|
172
219
|
/* @__PURE__ */ jsx(TooltipContent, { side: "right", children: item.label })
|
|
173
220
|
] });
|
|
174
221
|
}
|
|
@@ -187,27 +234,45 @@ function CollapsedRow({ item, activeId, onSelect }) {
|
|
|
187
234
|
className: "sb-flyout-pop",
|
|
188
235
|
children: [
|
|
189
236
|
/* @__PURE__ */ jsx("div", { className: "sb-flyout-title", children: item.label }),
|
|
190
|
-
children.map((child) =>
|
|
191
|
-
|
|
192
|
-
{
|
|
193
|
-
|
|
237
|
+
children.map((child) => {
|
|
238
|
+
const childActive = child.id === activeId;
|
|
239
|
+
const select = (event) => {
|
|
240
|
+
setMenuOpen(false);
|
|
241
|
+
if (child.disabled) {
|
|
242
|
+
event.preventDefault();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
onSelect?.(child.id);
|
|
246
|
+
};
|
|
247
|
+
const flyoutState = {
|
|
194
248
|
role: "menuitem",
|
|
195
249
|
className: "sb-nav-item",
|
|
196
|
-
"data-active":
|
|
197
|
-
"aria-current":
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
250
|
+
"data-active": childActive ? "true" : void 0,
|
|
251
|
+
"aria-current": childActive ? "page" : void 0,
|
|
252
|
+
"aria-disabled": child.disabled || void 0
|
|
253
|
+
};
|
|
254
|
+
return LinkComponent && child.href ? /* @__PURE__ */ jsx(
|
|
255
|
+
LinkComponent,
|
|
256
|
+
{
|
|
257
|
+
...flyoutState,
|
|
258
|
+
href: child.disabled ? void 0 : child.href,
|
|
259
|
+
onClick: select,
|
|
260
|
+
children: /* @__PURE__ */ jsx(SidebarRowContent, { item: child, sub: true })
|
|
201
261
|
},
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
262
|
+
child.id
|
|
263
|
+
) : (
|
|
264
|
+
// A collapsed-rail flyout entry is a `menuitem`-styled nav row owning `.sb-nav-item`
|
|
265
|
+
// composition, not a <Button> — same contract as the leaf row above.
|
|
266
|
+
// ui-audit-disable-next-line no-raw-button
|
|
267
|
+
/* @__PURE__ */ jsx("button", { type: "button", ...flyoutState, onClick: select, children: /* @__PURE__ */ jsx(SidebarRowContent, { item: child, sub: true }) }, child.id)
|
|
268
|
+
);
|
|
269
|
+
})
|
|
206
270
|
]
|
|
207
271
|
}
|
|
208
272
|
)
|
|
209
273
|
] });
|
|
210
274
|
}
|
|
275
|
+
import { createSidebarLink } from "./sidebar-link.js";
|
|
211
276
|
function Sidebar({
|
|
212
277
|
ariaLabel: ariaLabelCamel,
|
|
213
278
|
activeId,
|
|
@@ -218,6 +283,7 @@ function Sidebar({
|
|
|
218
283
|
brand,
|
|
219
284
|
collapsed = false,
|
|
220
285
|
children,
|
|
286
|
+
linkComponent,
|
|
221
287
|
renderItem,
|
|
222
288
|
footer,
|
|
223
289
|
"aria-label": ariaLabel
|
|
@@ -257,35 +323,53 @@ function Sidebar({
|
|
|
257
323
|
meta
|
|
258
324
|
] });
|
|
259
325
|
})() : null,
|
|
260
|
-
/* @__PURE__ */ jsx(
|
|
261
|
-
|
|
326
|
+
/* @__PURE__ */ jsx(
|
|
327
|
+
"nav",
|
|
262
328
|
{
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
children:
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
329
|
+
className: "sb-nav-scroll",
|
|
330
|
+
"aria-label": ariaLabel ?? ariaLabelCamel ?? t("layout.sidebar.ariaLabel"),
|
|
331
|
+
children: children ?? resolvedSections.map((section, sectionIndex) => /* @__PURE__ */ jsx(
|
|
332
|
+
SidebarSection,
|
|
333
|
+
{
|
|
334
|
+
label: section.label,
|
|
335
|
+
collapsed,
|
|
336
|
+
children: section.items.map(
|
|
337
|
+
(item) => collapsed ? /* @__PURE__ */ jsx(
|
|
338
|
+
CollapsedRow,
|
|
339
|
+
{
|
|
340
|
+
item,
|
|
341
|
+
activeId,
|
|
342
|
+
onSelect,
|
|
343
|
+
linkComponent
|
|
344
|
+
},
|
|
345
|
+
item.id
|
|
346
|
+
) : item.children && item.children.length > 0 ? /* @__PURE__ */ jsx(
|
|
347
|
+
NavGroup,
|
|
348
|
+
{
|
|
349
|
+
item,
|
|
350
|
+
activeId,
|
|
351
|
+
onSelect,
|
|
352
|
+
linkComponent,
|
|
353
|
+
renderItem
|
|
354
|
+
},
|
|
355
|
+
item.id
|
|
356
|
+
) : /* @__PURE__ */ jsx(
|
|
357
|
+
NavLeaf,
|
|
358
|
+
{
|
|
359
|
+
item,
|
|
360
|
+
activeId,
|
|
361
|
+
onSelect,
|
|
362
|
+
linkComponent,
|
|
363
|
+
renderItem
|
|
364
|
+
},
|
|
365
|
+
item.id
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
},
|
|
369
|
+
section.label ?? sectionIndex
|
|
370
|
+
))
|
|
371
|
+
}
|
|
372
|
+
),
|
|
289
373
|
footer ? /* @__PURE__ */ jsx("div", { className: "sb-footer", children: footer }) : null
|
|
290
374
|
] });
|
|
291
375
|
}
|
|
@@ -293,5 +377,6 @@ export {
|
|
|
293
377
|
Sidebar,
|
|
294
378
|
SidebarHeader,
|
|
295
379
|
SidebarItem,
|
|
296
|
-
SidebarSection
|
|
380
|
+
SidebarSection,
|
|
381
|
+
createSidebarLink
|
|
297
382
|
};
|
|
@@ -63,7 +63,7 @@ const ARIA_KEY = {
|
|
|
63
63
|
};
|
|
64
64
|
const BRAND_NONE = "__app__";
|
|
65
65
|
const AppSettingPicker = React.forwardRef(
|
|
66
|
-
function AppSettingPicker2({ kind, appearance, className, disabled, id, name, value, onValueChange }, ref) {
|
|
66
|
+
function AppSettingPicker2({ kind, appearance, compact = false, className, disabled, id, name, value, onValueChange }, ref) {
|
|
67
67
|
const resolvedAppearance = appearance ?? (kind === "locale" ? "icon" : "labeled");
|
|
68
68
|
const ctx = useOptionalAppContext();
|
|
69
69
|
const { t, locale, fallbackLocale } = useTranslation();
|
|
@@ -121,6 +121,8 @@ const AppSettingPicker = React.forwardRef(
|
|
|
121
121
|
const unbound = current === void 0 || !handleChange;
|
|
122
122
|
const Icon = ICON[kind];
|
|
123
123
|
const iconOnly = resolvedAppearance === "icon";
|
|
124
|
+
const inline = resolvedAppearance === "inline";
|
|
125
|
+
const isCompact = compact && !inline;
|
|
124
126
|
return /* @__PURE__ */ jsxs(
|
|
125
127
|
Select,
|
|
126
128
|
{
|
|
@@ -135,9 +137,9 @@ const AppSettingPicker = React.forwardRef(
|
|
|
135
137
|
{
|
|
136
138
|
ref,
|
|
137
139
|
id,
|
|
138
|
-
showIndicator: !iconOnly,
|
|
140
|
+
showIndicator: !iconOnly && !inline,
|
|
139
141
|
className: cn(
|
|
140
|
-
iconOnly ? (
|
|
142
|
+
inline ? "ui-app-setting-picker-inline h-auto min-h-0 w-auto rounded-none border-0 bg-transparent p-0 shadow-none" : iconOnly ? (
|
|
141
143
|
// Structurally icon-only: drop the owned width + value spacing and square the box to
|
|
142
144
|
// the density-aware --control-height tap target, centring the icon.
|
|
143
145
|
"w-[length:var(--control-height)] justify-center ps-0 pe-0"
|
|
@@ -147,16 +149,25 @@ const AppSettingPicker = React.forwardRef(
|
|
|
147
149
|
// `w-full` — so a labeled picker dropped into a narrow topbar no longer stretches to
|
|
148
150
|
// fill the bar (gh#165). A form field that wants a full-width control passes
|
|
149
151
|
// `className="w-full"`, which wins over `w-auto`.
|
|
150
|
-
|
|
152
|
+
// `compact` drops the per-kind width entirely so the trigger hugs its value.
|
|
153
|
+
cn("w-auto max-w-full", !isCompact && TRIGGER_WIDTH[kind])
|
|
151
154
|
),
|
|
155
|
+
// Compact re-tiers the box through tokens (--app-setting-picker-compact-*); the height
|
|
156
|
+
// still comes from the official --control-height-sm tier, never a literal. The gap is a
|
|
157
|
+
// utility (not the class rule) so it beats SelectTrigger's own `gap-2`.
|
|
158
|
+
isCompact && "ui-app-setting-picker-compact gap-[length:var(--app-setting-picker-compact-gap)]",
|
|
152
159
|
className
|
|
153
160
|
),
|
|
154
161
|
"aria-label": t(ARIA_KEY[kind]),
|
|
155
162
|
children: [
|
|
156
|
-
/* @__PURE__ */ jsx(
|
|
163
|
+
inline ? null : /* @__PURE__ */ jsx(
|
|
157
164
|
Icon,
|
|
158
165
|
{
|
|
159
|
-
className: cn(
|
|
166
|
+
className: cn(
|
|
167
|
+
"size-4 shrink-0 opacity-70",
|
|
168
|
+
// Compact relies on the trigger's tokenized flex gap instead of an icon margin.
|
|
169
|
+
!iconOnly && !isCompact && "me-2"
|
|
170
|
+
),
|
|
160
171
|
"aria-hidden": "true"
|
|
161
172
|
}
|
|
162
173
|
),
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { ToolbarGroupProp, ToolbarProp } from "../../props/components/navigation.prop.js";
|
|
2
|
-
export type { ToolbarGroupProp, ToolbarGroupProp as ToolbarGroupProps, ToolbarProp, ToolbarProp as ToolbarProps, } from "../../props/components/navigation.prop.js";
|
|
3
|
-
export declare function Toolbar({ onClear, hasActiveFilters, sticky, className, children, }: ToolbarProp): import("react").JSX.Element;
|
|
4
|
-
export declare function ToolbarGroup({ label, className, children }: ToolbarGroupProp): import("react").JSX.Element;
|
|
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;
|
|
4
|
+
export declare function ToolbarGroup({ label, controlId, className, children }: ToolbarGroupProp): import("react").JSX.Element;
|
|
5
|
+
/**
|
|
6
|
+
* Canonical list-page filter strip.
|
|
7
|
+
*
|
|
8
|
+
* `Toolbar` remains available for backwards compatibility. `FilterBar` is the
|
|
9
|
+
* public domain-neutral name used by application design specifications.
|
|
10
|
+
*/
|
|
11
|
+
export declare const FilterBar: typeof Toolbar;
|
|
12
|
+
/** Labelled control group for {@link FilterBar}. */
|
|
13
|
+
export declare const FilterBarGroup: typeof ToolbarGroup;
|
|
@@ -9,6 +9,7 @@ function Toolbar({
|
|
|
9
9
|
onClear,
|
|
10
10
|
hasActiveFilters = true,
|
|
11
11
|
sticky = false,
|
|
12
|
+
overflow = "wrap",
|
|
12
13
|
className,
|
|
13
14
|
children
|
|
14
15
|
}) {
|
|
@@ -18,6 +19,7 @@ function Toolbar({
|
|
|
18
19
|
{
|
|
19
20
|
role: "toolbar",
|
|
20
21
|
"aria-label": t("navigation.toolbar.ariaLabel"),
|
|
22
|
+
"data-overflow": overflow,
|
|
21
23
|
className: cn("ui-toolbar", sticky && "ui-toolbar-sticky", className),
|
|
22
24
|
children: [
|
|
23
25
|
children,
|
|
@@ -29,7 +31,7 @@ function Toolbar({
|
|
|
29
31
|
}
|
|
30
32
|
);
|
|
31
33
|
}
|
|
32
|
-
function ToolbarGroup({ label, className, children }) {
|
|
34
|
+
function ToolbarGroup({ label, controlId, className, children }) {
|
|
33
35
|
const labelId = useId();
|
|
34
36
|
return /* @__PURE__ */ jsxs(
|
|
35
37
|
"div",
|
|
@@ -38,13 +40,17 @@ function ToolbarGroup({ label, className, children }) {
|
|
|
38
40
|
"aria-labelledby": label ? labelId : void 0,
|
|
39
41
|
className: cn("ui-stack-xs ui-toolbar-group", className),
|
|
40
42
|
children: [
|
|
41
|
-
label ? /* @__PURE__ */ jsx("div", { id: labelId, className: "ui-toolbar-label", children: label }) : null,
|
|
43
|
+
label ? controlId ? /* @__PURE__ */ jsx("label", { id: labelId, htmlFor: controlId, className: "ui-toolbar-label", children: label }) : /* @__PURE__ */ jsx("div", { id: labelId, className: "ui-toolbar-label", children: label }) : null,
|
|
42
44
|
children
|
|
43
45
|
]
|
|
44
46
|
}
|
|
45
47
|
);
|
|
46
48
|
}
|
|
49
|
+
const FilterBar = Toolbar;
|
|
50
|
+
const FilterBarGroup = ToolbarGroup;
|
|
47
51
|
export {
|
|
52
|
+
FilterBar,
|
|
53
|
+
FilterBarGroup,
|
|
48
54
|
Toolbar,
|
|
49
55
|
ToolbarGroup
|
|
50
56
|
};
|
|
@@ -4,8 +4,8 @@ export { Pagination, PaginationContent, PaginationItem, PaginationLink, Paginati
|
|
|
4
4
|
export { Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger, } from "./menubar.js";
|
|
5
5
|
export { NavigationMenu, NavigationMenuContent, NavigationMenuIndicator, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport, } from "./navigation-menu.js";
|
|
6
6
|
export { Steps } from "./steps.js";
|
|
7
|
-
export { Toolbar, ToolbarGroup } from "./filter-bar.js";
|
|
8
|
-
export type { ToolbarGroupProps, ToolbarProps } from "./filter-bar.js";
|
|
7
|
+
export { FilterBar, FilterBarGroup, Toolbar, ToolbarGroup } from "./filter-bar.js";
|
|
8
|
+
export type { 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";
|
|
@@ -51,7 +51,7 @@ import {
|
|
|
51
51
|
NavigationMenuViewport
|
|
52
52
|
} from "./navigation-menu.js";
|
|
53
53
|
import { Steps } from "./steps.js";
|
|
54
|
-
import { Toolbar, ToolbarGroup } from "./filter-bar.js";
|
|
54
|
+
import { FilterBar, FilterBarGroup, Toolbar, ToolbarGroup } from "./filter-bar.js";
|
|
55
55
|
import { AppSettingPicker } from "./app-setting-picker.js";
|
|
56
56
|
import {
|
|
57
57
|
DropdownMenu,
|
|
@@ -101,6 +101,8 @@ export {
|
|
|
101
101
|
DropdownMenuSubContent,
|
|
102
102
|
DropdownMenuSubTrigger,
|
|
103
103
|
DropdownMenuTrigger,
|
|
104
|
+
FilterBar,
|
|
105
|
+
FilterBarGroup,
|
|
104
106
|
Menubar,
|
|
105
107
|
MenubarCheckboxItem,
|
|
106
108
|
MenubarContent,
|