@godxjp/ui 17.0.1 → 18.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/dist/components/data-display/card.d.ts +37 -1
  2. package/dist/components/data-display/card.js +7 -1
  3. package/dist/components/data-display/data-table.js +19 -4
  4. package/dist/components/data-display/empty-state.d.ts +1 -1
  5. package/dist/components/data-display/empty-state.js +5 -1
  6. package/dist/components/data-display/scroll-area.js +1 -1
  7. package/dist/components/data-display/table.d.ts +20 -1
  8. package/dist/components/data-display/table.js +23 -9
  9. package/dist/components/data-entry/calendar.js +4 -0
  10. package/dist/components/data-entry/cascader.d.ts +1 -1
  11. package/dist/components/data-entry/cascader.js +10 -1
  12. package/dist/components/data-entry/checkbox-group.d.ts +1 -1
  13. package/dist/components/data-entry/checkbox-group.js +13 -4
  14. package/dist/components/data-entry/color-picker.d.ts +1 -1
  15. package/dist/components/data-entry/color-picker.js +5 -2
  16. package/dist/components/data-entry/command.d.ts +2 -2
  17. package/dist/components/data-entry/date-picker.d.ts +1 -1
  18. package/dist/components/data-entry/date-picker.js +11 -1
  19. package/dist/components/data-entry/date-range-picker.d.ts +1 -1
  20. package/dist/components/data-entry/date-range-picker.js +11 -3
  21. package/dist/components/data-entry/form-field.js +7 -3
  22. package/dist/components/data-entry/month-picker.d.ts +1 -1
  23. package/dist/components/data-entry/month-picker.js +13 -1
  24. package/dist/components/data-entry/month-range-picker.d.ts +1 -1
  25. package/dist/components/data-entry/month-range-picker.js +11 -3
  26. package/dist/components/data-entry/number-input.d.ts +19 -2
  27. package/dist/components/data-entry/number-input.js +5 -7
  28. package/dist/components/data-entry/radio.d.ts +1 -1
  29. package/dist/components/data-entry/radio.js +11 -3
  30. package/dist/components/data-entry/search-input.d.ts +3 -2
  31. package/dist/components/data-entry/search-input.js +5 -2
  32. package/dist/components/data-entry/search-select.d.ts +1 -1
  33. package/dist/components/data-entry/search-select.js +51 -10
  34. package/dist/components/data-entry/select.d.ts +7 -0
  35. package/dist/components/data-entry/select.js +21 -3
  36. package/dist/components/data-entry/time-picker.d.ts +1 -1
  37. package/dist/components/data-entry/time-picker.js +11 -1
  38. package/dist/components/data-entry/transfer.d.ts +1 -1
  39. package/dist/components/data-entry/transfer.js +73 -59
  40. package/dist/components/data-entry/tree-select.d.ts +1 -1
  41. package/dist/components/data-entry/tree-select.js +10 -1
  42. package/dist/components/data-entry/upload.d.ts +1 -1
  43. package/dist/components/data-entry/upload.js +7 -2
  44. package/dist/components/layout/app-shell.d.ts +1 -1
  45. package/dist/components/layout/app-shell.js +42 -2
  46. package/dist/components/layout/breadcrumb.d.ts +7 -1
  47. package/dist/components/layout/breadcrumb.js +6 -2
  48. package/dist/components/layout/page-container.d.ts +1 -1
  49. package/dist/components/layout/page-container.js +32 -22
  50. package/dist/components/layout/responsive-grid.js +1 -1
  51. package/dist/components/layout/sidebar.d.ts +1 -1
  52. package/dist/components/layout/sidebar.js +44 -11
  53. package/dist/components/layout/split-pane.js +2 -2
  54. package/dist/components/navigation/app-setting-picker.js +15 -7
  55. package/dist/components/navigation/pagination.d.ts +1 -1
  56. package/dist/components/navigation/pagination.js +84 -95
  57. package/dist/components/navigation/tabs.js +21 -4
  58. package/dist/components/ui/tag-input.js +1 -0
  59. package/dist/i18n/messages/en.json +3 -1
  60. package/dist/i18n/messages/ja.json +3 -1
  61. package/dist/i18n/messages/vi.json +3 -1
  62. package/dist/lib/field-a11y.d.ts +66 -0
  63. package/dist/lib/field-a11y.js +44 -0
  64. package/dist/props/components/app.prop.d.ts +9 -5
  65. package/dist/props/components/data-display.prop.d.ts +16 -1
  66. package/dist/props/components/data-entry.prop.d.ts +69 -19
  67. package/dist/props/components/layout.prop.d.ts +42 -0
  68. package/dist/props/components/navigation.prop.d.ts +16 -0
  69. package/dist/props/registry.d.ts +8 -3
  70. package/dist/props/registry.js +21 -3
  71. package/dist/props/vocabulary/data.prop.d.ts +9 -0
  72. package/dist/styles/layout.css +46 -9
  73. package/dist/styles/shell-layout.css +19 -0
  74. package/package.json +8 -4
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import { ChevronDown, ChevronRight, ChevronsUpDown, X } from "lucide-react";
5
5
  import { useTranslation } from "../../i18n/use-translation.js";
6
6
  import { cn } from "../../lib/utils.js";
7
+ import { pickFieldA11y } from "../../lib/field-a11y.js";
7
8
  import { controlOpenRingClass } from "../../lib/control-styles.js";
8
9
  import { Button } from "../general/button.js";
9
10
  import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
@@ -57,9 +58,13 @@ function TreeSelectRoot({
57
58
  allowClear = true,
58
59
  className,
59
60
  id,
60
- fieldNames
61
+ fieldNames,
62
+ ...ariaProps
61
63
  }) {
62
64
  const { t } = useTranslation();
65
+ const fieldA11y = pickFieldA11y(ariaProps);
66
+ const reactId = React.useId();
67
+ const treeId = `${id ?? reactId}-tree`;
63
68
  const options = React.useMemo(
64
69
  () => normalizeTreeOptions(treeDataProp, fieldNames),
65
70
  [treeDataProp, fieldNames]
@@ -177,6 +182,9 @@ function TreeSelectRoot({
177
182
  variant: "outline",
178
183
  role: "combobox",
179
184
  "aria-expanded": open,
185
+ "aria-haspopup": "tree",
186
+ "aria-controls": open ? treeId : void 0,
187
+ ...fieldA11y,
180
188
  disabled,
181
189
  className: cn(
182
190
  "w-full justify-between font-normal",
@@ -211,6 +219,7 @@ function TreeSelectRoot({
211
219
  /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-[min(300px,50vh)]", children: /* @__PURE__ */ jsx(
212
220
  "div",
213
221
  {
222
+ id: treeId,
214
223
  role: "tree",
215
224
  "aria-multiselectable": Boolean(checkable) || Boolean(multiple),
216
225
  className: "p-1",
@@ -3,4 +3,4 @@ export type { UploadProp, UploadProp as UploadProps, UploadFileItemProp, UploadV
3
3
  export type { UploadFileItem, UploadVariant, UploadCommitAction } from "./upload-types.js";
4
4
  export { collectUploadCommitActions, createUploadItem } from "./upload-types.js";
5
5
  export { useUploadDraft } from "./use-upload-draft.js";
6
- export declare function Upload({ variant, value, defaultValue, onValueChange, accept: acceptProp, multiple: multipleProp, maxCount: maxCountProp, maxSizeBytes, disabled, removable, onUpload, className, children, }: UploadProp): import("react/jsx-runtime").JSX.Element;
6
+ export declare function Upload({ variant, value, defaultValue, onValueChange, accept: acceptProp, multiple: multipleProp, maxCount: maxCountProp, maxSizeBytes, disabled, removable, onUpload, id, className, children, ...ariaProps }: UploadProp): import("react/jsx-runtime").JSX.Element;
@@ -5,6 +5,7 @@ import { Camera, ImagePlus, RotateCcw, Trash2, Upload as UploadIcon, X } from "l
5
5
  import { useTranslation } from "../../i18n/use-translation.js";
6
6
  import { formatBytes } from "../../lib/format.js";
7
7
  import { cn } from "../../lib/utils.js";
8
+ import { resolveFieldA11y } from "../../lib/field-a11y.js";
8
9
  import { controlIconClass } from "../../lib/control-styles.js";
9
10
  import { Button } from "../general/button.js";
10
11
  import { UploadCropDialog } from "./upload-crop-dialog.js";
@@ -84,10 +85,13 @@ function Upload({
84
85
  disabled,
85
86
  removable = true,
86
87
  onUpload,
88
+ id,
87
89
  className,
88
- children
90
+ children,
91
+ ...ariaProps
89
92
  }) {
90
93
  const { t } = useTranslation();
94
+ const inputA11y = resolveFieldA11y(ariaProps, t("dataEntry.upload.inputLabel"));
91
95
  const accept = acceptProp ?? defaultAcceptForVariant(variant);
92
96
  const maxCount = maxCountProp ?? defaultMaxCount(variant);
93
97
  const multiple = multipleProp ?? (maxCount === 1 ? false : true);
@@ -144,12 +148,13 @@ function Upload({
144
148
  "input",
145
149
  {
146
150
  ref: inputRef,
151
+ id,
147
152
  type: "file",
148
153
  className: "sr-only",
149
154
  accept,
150
155
  multiple: multiple && !isSingleAvatar,
151
156
  disabled,
152
- "aria-label": t("dataEntry.upload.inputLabel"),
157
+ ...inputA11y,
153
158
  onChange: (e) => {
154
159
  pickFiles(e.target.files);
155
160
  e.target.value = "";
@@ -1,3 +1,3 @@
1
1
  import type { AppShellProp } from "../../props/components/layout.prop.js";
2
2
  export type { AppShellProp, AppShellProp as AppShellProps, } from "../../props/components/layout.prop.js";
3
- export declare function AppShell({ sidebar, topbar, topbarLeft, topbarRight, logo, breadcrumb, footer, children, sidebarCollapsed, }: AppShellProp): import("react/jsx-runtime").JSX.Element;
3
+ export declare function AppShell({ sidebar, topbar, topbarLeft, topbarRight, logo, breadcrumb, footer, children, sidebarCollapsed, mobileNav, mobileNavLabel, mobileNavOpen, onMobileNavOpenChange, }: AppShellProp): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,10 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Menu } from "lucide-react";
3
5
  import { useTranslation } from "../../i18n/use-translation.js";
6
+ import { Button } from "../general/button.js";
7
+ import { Sheet, SheetBody, SheetContent, SheetHeader, SheetTrigger } from "../feedback/sheet.js";
4
8
  function AppShell({
5
9
  sidebar,
6
10
  topbar,
@@ -10,9 +14,25 @@ function AppShell({
10
14
  breadcrumb,
11
15
  footer,
12
16
  children,
13
- sidebarCollapsed = false
17
+ sidebarCollapsed = false,
18
+ mobileNav,
19
+ mobileNavLabel,
20
+ mobileNavOpen,
21
+ onMobileNavOpenChange
14
22
  }) {
15
23
  const { t } = useTranslation();
24
+ const drawerNav = mobileNav !== void 0 ? mobileNav : sidebar;
25
+ const hasDrawer = drawerNav != null;
26
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(false);
27
+ const drawerOpen = mobileNavOpen ?? uncontrolledOpen;
28
+ const setDrawerOpen = onMobileNavOpenChange ?? setUncontrolledOpen;
29
+ const handleDrawerClick = (event) => {
30
+ const target = event.target;
31
+ const hit = target.closest("a[href], button, [role='menuitem']");
32
+ if (hit && !hit.classList.contains("sb-nav-group-trigger")) {
33
+ setDrawerOpen(false);
34
+ }
35
+ };
16
36
  const resolvedTopbar = topbar !== void 0 ? topbar : /* @__PURE__ */ jsxs("div", { className: "app-topbar-rail", children: [
17
37
  logo !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-logo", children: logo }),
18
38
  topbarLeft !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-topbar-left", children: topbarLeft }),
@@ -21,7 +41,27 @@ function AppShell({
21
41
  ] });
22
42
  return /* @__PURE__ */ jsxs("div", { className: "app-root", "data-collapsed": sidebarCollapsed ? "true" : void 0, children: [
23
43
  /* @__PURE__ */ jsx("aside", { className: "app-sidebar", "aria-label": t("layout.appShell.sidebarLabel"), children: sidebar }),
24
- /* @__PURE__ */ jsx("header", { className: "app-topbar ui-scale-fixed", "aria-label": t("layout.appShell.headerLabel"), children: resolvedTopbar }),
44
+ /* @__PURE__ */ jsxs("header", { className: "app-topbar ui-scale-fixed", "aria-label": t("layout.appShell.headerLabel"), children: [
45
+ hasDrawer && /* @__PURE__ */ jsxs(Sheet, { open: drawerOpen, onOpenChange: setDrawerOpen, children: [
46
+ /* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
47
+ Button,
48
+ {
49
+ type: "button",
50
+ variant: "ghost",
51
+ size: "sm",
52
+ className: "app-mobile-nav-trigger",
53
+ "aria-label": t("layout.appShell.openNav"),
54
+ "aria-haspopup": "dialog",
55
+ children: /* @__PURE__ */ jsx(Menu, { className: "size-5", "aria-hidden": "true" })
56
+ }
57
+ ) }),
58
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "app-mobile-nav-drawer", children: [
59
+ /* @__PURE__ */ jsx(SheetHeader, { title: mobileNavLabel ?? t("layout.appShell.navLabel") }),
60
+ /* @__PURE__ */ jsx(SheetBody, { className: "app-mobile-nav-body", onClick: handleDrawerClick, children: drawerNav })
61
+ ] })
62
+ ] }),
63
+ resolvedTopbar
64
+ ] }),
25
65
  /* @__PURE__ */ jsxs("main", { className: "app-main", "aria-label": t("layout.appShell.mainLabel"), children: [
26
66
  breadcrumb !== void 0 && /* @__PURE__ */ jsx("div", { className: "app-breadcrumb", children: breadcrumb }),
27
67
  children
@@ -3,5 +3,11 @@ import type { BreadcrumbProp } from "../../props/vocabulary/navigation.prop.js";
3
3
  export type BreadcrumbProps = {
4
4
  items: BreadcrumbProp;
5
5
  linkComponent?: ElementType;
6
+ /**
7
+ * Override the `<nav>` landmark's accessible name. Defaults to a localized "Breadcrumb".
8
+ * Multiple Breadcrumb instances on one page/view need a DISTINCT name each — two `<nav>`
9
+ * landmarks sharing one name/role fail axe's `landmark-unique` (WCAG 2.4.1 / 1.3.1).
10
+ */
11
+ "aria-label"?: string;
6
12
  };
7
- export declare function Breadcrumb({ items, linkComponent: LinkComponent }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function Breadcrumb({ items, linkComponent: LinkComponent, "aria-label": ariaLabel, }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
@@ -2,9 +2,13 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { ChevronRight } from "lucide-react";
4
4
  import { useTranslation } from "../../i18n/use-translation.js";
5
- function Breadcrumb({ items, linkComponent: LinkComponent = "a" }) {
5
+ function Breadcrumb({
6
+ items,
7
+ linkComponent: LinkComponent = "a",
8
+ "aria-label": ariaLabel
9
+ }) {
6
10
  const { t } = useTranslation();
7
- return /* @__PURE__ */ jsx("nav", { "aria-label": t("navigation.breadcrumb.ariaLabel"), className: "ui-breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: items.map((item, index) => {
11
+ return /* @__PURE__ */ jsx("nav", { "aria-label": ariaLabel ?? t("navigation.breadcrumb.ariaLabel"), className: "ui-breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: items.map((item, index) => {
8
12
  const isLast = index === items.length - 1;
9
13
  return /* @__PURE__ */ jsxs("li", { className: "ui-breadcrumb-item", children: [
10
14
  item.to && !isLast ? /* @__PURE__ */ jsx(LinkComponent, { href: item.to, to: item.to, className: "ui-breadcrumb-link", children: item.label }) : /* @__PURE__ */ jsx("span", { className: "ui-breadcrumb-current", "aria-current": isLast ? "page" : void 0, children: item.label }),
@@ -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-runtime").JSX.Element;
5
- declare function PageContainerRoot({ title, subtitle, extra, footer, breadcrumb, linkComponent: LinkComponent, density, variant, stickyFooter, footerReveal, fill, children, className, }: PageContainerProp): import("react/jsx-runtime").JSX.Element;
5
+ declare function PageContainerRoot({ title, subtitle, extra, footer, breadcrumb, breadcrumbAriaLabel, linkComponent: LinkComponent, density, variant, stickyFooter, footerReveal, fill, children, className, }: PageContainerProp): import("react/jsx-runtime").JSX.Element;
6
6
  export declare const PageContainer: typeof PageContainerRoot & {
7
7
  Inset: typeof PageContainerInset;
8
8
  };
@@ -2,6 +2,7 @@
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { ChevronRight } from "lucide-react";
5
+ import { useTranslation } from "../../i18n/use-translation.js";
5
6
  import { cn } from "../../lib/utils.js";
6
7
  import { densityClass, pageContainerVariantClass } from "../../lib/variants.js";
7
8
  function scrollParent(el) {
@@ -38,6 +39,7 @@ function PageContainerRoot({
38
39
  extra,
39
40
  footer,
40
41
  breadcrumb,
42
+ breadcrumbAriaLabel,
41
43
  linkComponent: LinkComponent = "a",
42
44
  density,
43
45
  variant = "default",
@@ -49,6 +51,7 @@ function PageContainerRoot({
49
51
  }) {
50
52
  const reveal = stickyFooter && footer != null && footerReveal === "onScroll";
51
53
  const { headerRef, revealed } = useFooterReveal(reveal);
54
+ const { t } = useTranslation();
52
55
  return /* @__PURE__ */ jsxs(
53
56
  "div",
54
57
  {
@@ -66,28 +69,35 @@ function PageContainerRoot({
66
69
  ),
67
70
  children: [
68
71
  /* @__PURE__ */ jsxs("header", { ref: headerRef, className: "ui-page-header", children: [
69
- breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "ui-breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: breadcrumb.map((item, i) => {
70
- const isLast = i === breadcrumb.length - 1;
71
- return /* @__PURE__ */ jsxs("li", { className: "ui-inline-xs", children: [
72
- item.to && !isLast ? /* @__PURE__ */ jsx(
73
- LinkComponent,
74
- {
75
- href: item.to,
76
- to: item.to,
77
- className: "hover:text-foreground hover:underline",
78
- children: item.label
79
- }
80
- ) : /* @__PURE__ */ jsx(
81
- "span",
82
- {
83
- className: isLast ? "text-foreground" : "",
84
- "aria-current": isLast ? "page" : void 0,
85
- children: item.label
86
- }
87
- ),
88
- !isLast && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3", "aria-hidden": "true" })
89
- ] }, i);
90
- }) }) }),
72
+ breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx(
73
+ "nav",
74
+ {
75
+ "aria-label": breadcrumbAriaLabel ?? t("navigation.breadcrumb.ariaLabel"),
76
+ className: "ui-breadcrumb",
77
+ children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: breadcrumb.map((item, i) => {
78
+ const isLast = i === breadcrumb.length - 1;
79
+ return /* @__PURE__ */ jsxs("li", { className: "ui-inline-xs", children: [
80
+ item.to && !isLast ? /* @__PURE__ */ jsx(
81
+ LinkComponent,
82
+ {
83
+ href: item.to,
84
+ to: item.to,
85
+ className: "hover:text-foreground hover:underline",
86
+ children: item.label
87
+ }
88
+ ) : /* @__PURE__ */ jsx(
89
+ "span",
90
+ {
91
+ className: isLast ? "text-foreground" : "",
92
+ "aria-current": isLast ? "page" : void 0,
93
+ children: item.label
94
+ }
95
+ ),
96
+ !isLast && /* @__PURE__ */ jsx(ChevronRight, { className: "size-3", "aria-hidden": "true" })
97
+ ] }, i);
98
+ }) })
99
+ }
100
+ ),
91
101
  /* @__PURE__ */ jsxs("div", { className: "ui-page-header-row", children: [
92
102
  /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
93
103
  /* @__PURE__ */ jsx("h1", { className: "ui-page-title", children: title }),
@@ -14,7 +14,7 @@ function resolveColumns(columns) {
14
14
  };
15
15
  }
16
16
  function ResponsiveGrid({ columns = 4, children }) {
17
- return /* @__PURE__ */ jsx("div", { className: "ui-responsive-grid", style: resolveColumns(columns), children });
17
+ return /* @__PURE__ */ jsx("div", { className: "ui-responsive-grid-scope", children: /* @__PURE__ */ jsx("div", { className: "ui-responsive-grid", style: resolveColumns(columns), children }) });
18
18
  }
19
19
  export {
20
20
  ResponsiveGrid
@@ -18,4 +18,4 @@ type SidebarItemProps = {
18
18
  export declare function SidebarHeader({ children, className, ...props }: SidebarHeaderProps): import("react/jsx-runtime").JSX.Element;
19
19
  export declare function SidebarSection({ label, collapsed, children, className, ...props }: SidebarSectionProps & React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
20
20
  export declare function SidebarItem({ item, active, sub, onActivate, renderItem, children, ...props }: SidebarItemProps & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "onClick">): import("react/jsx-runtime").JSX.Element;
21
- export declare function Sidebar({ activeId, onSelect, sections, product, onProductClick, brand, collapsed, children, renderItem, footer, }: SidebarProp): import("react/jsx-runtime").JSX.Element;
21
+ export declare function Sidebar({ activeId, onSelect, sections, product, onProductClick, brand, collapsed, children, renderItem, footer, "aria-label": ariaLabel, }: SidebarProp): import("react/jsx-runtime").JSX.Element;
@@ -1,6 +1,7 @@
1
1
  "use client";
2
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import * as React from "react";
4
+ import { Slot } from "@radix-ui/react-slot";
4
5
  import { ChevronDown } from "lucide-react";
5
6
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "../data-display/collapsible.js";
6
7
  import { Popover, PopoverContent, PopoverTrigger } from "../data-display/popover.js";
@@ -34,25 +35,52 @@ function SidebarItem({
34
35
  const Icon = item.icon;
35
36
  const showBadge = item.badge !== void 0 && item.badge !== "";
36
37
  const disabled = item.disabled || props.disabled;
37
- const content = children ?? (renderItem ? renderItem(item) : void 0);
38
- return /* @__PURE__ */ jsx(
38
+ const custom = children ?? (renderItem ? renderItem(item) : void 0);
39
+ const rowClass = cn("sb-nav-item", sub && "sb-nav-item--sub");
40
+ const stateProps = {
41
+ className: rowClass,
42
+ "data-active": active ? "true" : void 0,
43
+ "aria-current": active ? "page" : void 0
44
+ };
45
+ if (custom !== void 0) {
46
+ return /* @__PURE__ */ jsx(Slot, { ...stateProps, "aria-disabled": disabled || void 0, children: custom });
47
+ }
48
+ if (item.href) {
49
+ return /* @__PURE__ */ jsxs(
50
+ "a",
51
+ {
52
+ ...props,
53
+ href: disabled ? void 0 : item.href,
54
+ ...stateProps,
55
+ "aria-disabled": disabled || void 0,
56
+ onClick: (event) => {
57
+ if (disabled) event.preventDefault();
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
+ ]
65
+ }
66
+ );
67
+ }
68
+ return /* @__PURE__ */ jsxs(
39
69
  "button",
40
70
  {
41
71
  type: "button",
42
- className: cn("sb-nav-item", sub && "sb-nav-item--sub"),
43
- "data-active": active ? "true" : void 0,
44
- "aria-current": active ? "page" : void 0,
72
+ ...stateProps,
45
73
  "aria-disabled": disabled,
46
74
  ...props,
47
75
  onClick: () => {
48
76
  if (disabled) return;
49
77
  onActivate?.(item.id);
50
78
  },
51
- children: content ? content : /* @__PURE__ */ jsxs(Fragment, { children: [
79
+ children: [
52
80
  !sub ? /* @__PURE__ */ jsx("span", { className: "sb-icon", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) }) : null,
53
81
  /* @__PURE__ */ jsx("span", { className: "sb-label", children: item.label }),
54
82
  showBadge ? /* @__PURE__ */ jsx("span", { className: "sb-badge", children: item.badge }) : null
55
- ] })
83
+ ]
56
84
  }
57
85
  );
58
86
  }
@@ -95,7 +123,11 @@ function NavGroup({ item, activeId, onSelect, renderItem }) {
95
123
  const Icon = item.icon;
96
124
  const active = isItemActive(item, activeId);
97
125
  const children = item.children ?? [];
98
- return /* @__PURE__ */ jsxs(Collapsible, { defaultOpen: active, className: "sb-nav-group", children: [
126
+ const [open, setOpen] = React.useState(active);
127
+ React.useEffect(() => {
128
+ if (active) setOpen(true);
129
+ }, [active]);
130
+ return /* @__PURE__ */ jsxs(Collapsible, { open, onOpenChange: setOpen, className: "sb-nav-group", children: [
99
131
  /* @__PURE__ */ jsxs(
100
132
  CollapsibleTrigger,
101
133
  {
@@ -186,7 +218,8 @@ function Sidebar({
186
218
  collapsed = false,
187
219
  children,
188
220
  renderItem,
189
- footer
221
+ footer,
222
+ "aria-label": ariaLabel
190
223
  }) {
191
224
  const { t } = useTranslation();
192
225
  const resolvedSections = sections ?? [];
@@ -223,7 +256,7 @@ function Sidebar({
223
256
  meta
224
257
  ] });
225
258
  })() : null,
226
- /* @__PURE__ */ jsx("nav", { className: "sb-nav-scroll", "aria-label": t("layout.sidebar.ariaLabel"), children: children ?? resolvedSections.map((section, sectionIndex) => /* @__PURE__ */ jsx(
259
+ /* @__PURE__ */ jsx("nav", { className: "sb-nav-scroll", "aria-label": ariaLabel ?? t("layout.sidebar.ariaLabel"), children: children ?? resolvedSections.map((section, sectionIndex) => /* @__PURE__ */ jsx(
227
260
  SidebarSection,
228
261
  {
229
262
  label: section.label,
@@ -1,9 +1,9 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  function SplitPane({ children, aside, asideWidth = "md" }) {
3
- return /* @__PURE__ */ jsxs("div", { className: "ui-split-pane", "data-aside-width": asideWidth, children: [
3
+ return /* @__PURE__ */ jsx("div", { className: "ui-split-pane-scope", children: /* @__PURE__ */ jsxs("div", { className: "ui-split-pane", "data-aside-width": asideWidth, children: [
4
4
  /* @__PURE__ */ jsx("div", { className: "ui-split-pane-main", children }),
5
5
  /* @__PURE__ */ jsx("aside", { className: "ui-split-pane-aside", children: aside })
6
- ] });
6
+ ] }) });
7
7
  }
8
8
  export {
9
9
  SplitPane
@@ -63,7 +63,8 @@ const ARIA_KEY = {
63
63
  };
64
64
  const BRAND_NONE = "__app__";
65
65
  const AppSettingPicker = React.forwardRef(
66
- function AppSettingPicker2({ kind, appearance = "labeled", className, disabled, id, name, value, onValueChange }, ref) {
66
+ function AppSettingPicker2({ kind, appearance, className, disabled, id, name, value, onValueChange }, ref) {
67
+ const resolvedAppearance = appearance ?? (kind === "locale" ? "icon" : "labeled");
67
68
  const ctx = useOptionalAppContext();
68
69
  const { t, locale, fallbackLocale } = useTranslation();
69
70
  const raw = value ?? ctx?.[kind];
@@ -119,7 +120,7 @@ const AppSettingPicker = React.forwardRef(
119
120
  }, [kind, ctx?.timezoneOptions, current, t, locale, fallbackLocale]);
120
121
  const unbound = current === void 0 || !handleChange;
121
122
  const Icon = ICON[kind];
122
- const iconOnly = appearance === "icon";
123
+ const iconOnly = resolvedAppearance === "icon";
123
124
  return /* @__PURE__ */ jsxs(
124
125
  Select,
125
126
  {
@@ -134,13 +135,20 @@ const AppSettingPicker = React.forwardRef(
134
135
  {
135
136
  ref,
136
137
  id,
138
+ showIndicator: !iconOnly,
137
139
  className: cn(
138
140
  iconOnly ? (
139
- // Structurally icon-only: drop the owned width + value spacing, square the box to
140
- // the density-aware --control-height tap target, centre the icon and hide the
141
- // trailing chevron — no consumer descendant-selector overrides required.
142
- "w-[length:var(--control-height)] justify-center ps-0 pe-0 [&_[data-slot=select-chevron]]:hidden"
143
- ) : cn("w-full", TRIGGER_WIDTH[kind]),
141
+ // Structurally icon-only: drop the owned width + value spacing and square the box to
142
+ // the density-aware --control-height tap target, centring the icon.
143
+ "w-[length:var(--control-height)] justify-center ps-0 pe-0"
144
+ ) : (
145
+ // Labeled: sized to a per-kind width from `sm` up; below `sm` it hugs its content and
146
+ // caps at the container (`w-auto max-w-full`) instead of the old UNCONDITIONAL
147
+ // `w-full` — so a labeled picker dropped into a narrow topbar no longer stretches to
148
+ // fill the bar (gh#165). A form field that wants a full-width control passes
149
+ // `className="w-full"`, which wins over `w-auto`.
150
+ cn("w-auto max-w-full", TRIGGER_WIDTH[kind])
151
+ ),
144
152
  className
145
153
  ),
146
154
  "aria-label": t(ARIA_KEY[kind]),
@@ -22,5 +22,5 @@ declare const PaginationNext: React.ForwardRefExoticComponent<Omit<Omit<React.De
22
22
  disabled?: boolean;
23
23
  href?: string;
24
24
  } & React.RefAttributes<HTMLButtonElement>>;
25
- export declare function Pagination({ value, total, pageSize, pageSizeOptions, showSizeChanger, showTotal, simple, disabled, className, onValueChange, }: PaginationProp): import("react/jsx-runtime").JSX.Element | null;
25
+ export declare function Pagination({ value, total, pageSize, pageSizeOptions, showSizeChanger, showTotal, hideOnSinglePage, simple, disabled, className, onValueChange, "aria-label": ariaLabel, }: PaginationProp): import("react/jsx-runtime").JSX.Element | null;
26
26
  export { PaginationContent, PaginationItem, PaginationLink, PaginationEllipsis, PaginationPrevious, PaginationNext, };