@godxjp/ui 18.0.1 → 18.0.2

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 (37) hide show
  1. package/dist/components/charts/chart-cartesian.js +1 -1
  2. package/dist/components/charts/pie-chart.js +1 -1
  3. package/dist/components/data-display/data-table.js +13 -5
  4. package/dist/components/data-entry/calendar.d.ts +1 -1
  5. package/dist/components/data-entry/calendar.js +7 -0
  6. package/dist/components/data-entry/search-select.js +13 -6
  7. package/dist/components/data-entry/transfer.js +1 -1
  8. package/dist/components/data-entry/tree-select.js +37 -33
  9. package/dist/components/data-entry/upload.js +1 -1
  10. package/dist/components/feedback/dialog.js +4 -2
  11. package/dist/components/feedback/sheet.js +4 -2
  12. package/dist/components/general/button.js +2 -2
  13. package/dist/components/layout/breadcrumb.d.ts +2 -2
  14. package/dist/components/layout/breadcrumb.js +1 -1
  15. package/dist/components/layout/page-container.d.ts +1 -1
  16. package/dist/components/layout/page-container.js +2 -1
  17. package/dist/components/layout/sidebar.d.ts +1 -1
  18. package/dist/components/layout/sidebar.js +2 -1
  19. package/dist/components/layout/split-pane.d.ts +3 -1
  20. package/dist/components/layout/split-pane.js +2 -2
  21. package/dist/components/navigation/pagination.d.ts +1 -1
  22. package/dist/components/navigation/pagination.js +2 -2
  23. package/dist/components/navigation/tabs.js +1 -1
  24. package/dist/components/query/infinite-query-state.d.ts +1 -1
  25. package/dist/components/query/infinite-query-state.js +14 -2
  26. package/dist/props/components/data-entry.prop.d.ts +12 -0
  27. package/dist/props/components/layout.prop.d.ts +4 -0
  28. package/dist/props/components/navigation.prop.d.ts +8 -8
  29. package/dist/props/components/query.prop.d.ts +2 -0
  30. package/dist/styles/chart-layout.css +2 -0
  31. package/dist/styles/control.css +15 -0
  32. package/dist/styles/layout.css +27 -2
  33. package/dist/styles/navigation-layout.css +7 -0
  34. package/dist/styles/table-layout.css +25 -0
  35. package/dist/tokens/components/navigation.css +2 -0
  36. package/dist/tokens/semantic/layout.css +10 -0
  37. package/package.json +19 -4
@@ -165,7 +165,7 @@ function CartesianChart({
165
165
  height: resolvedHeight,
166
166
  className,
167
167
  id,
168
- children: hasData ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: chart() }) : /* @__PURE__ */ jsx(EmptyState, { title: emptyMessage ?? t("chart.empty") })
168
+ children: hasData ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", minWidth: 0, children: chart() }) : /* @__PURE__ */ jsx(EmptyState, { title: emptyMessage ?? t("chart.empty") })
169
169
  }
170
170
  );
171
171
  }
@@ -43,7 +43,7 @@ function PieChart({
43
43
  height: resolvedHeight,
44
44
  className,
45
45
  id,
46
- children: hasData ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(RPieChart, { children: [
46
+ children: hasData ? /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", minWidth: 0, children: /* @__PURE__ */ jsxs(RPieChart, { children: [
47
47
  /* @__PURE__ */ jsx(
48
48
  Pie,
49
49
  {
@@ -640,23 +640,31 @@ function NumberedPagination({
640
640
  justify: "between",
641
641
  gap: "md",
642
642
  wrap: true,
643
- className: cn("ui-data-table-pagination", className),
643
+ className: cn("ui-data-table-pagination ui-data-table-pagination--numbered", className),
644
644
  children: [
645
- /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", children: [
646
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: t("dataGrid.rowsPerPage") }),
645
+ /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", className: "ui-data-table-page-size", children: [
646
+ /* @__PURE__ */ jsx("span", { className: "ui-data-table-page-size-label text-muted-foreground text-sm", children: t("dataGrid.rowsPerPage") }),
647
647
  /* @__PURE__ */ jsxs(
648
648
  Select,
649
649
  {
650
650
  value: String(pageSize),
651
651
  onValueChange: (v) => table.setPageSize(Number(v)),
652
652
  children: [
653
- /* @__PURE__ */ jsx(SelectTrigger, { size: "sm", "aria-label": t("dataGrid.rowsPerPage"), className: "tabular-nums", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
653
+ /* @__PURE__ */ jsx(
654
+ SelectTrigger,
655
+ {
656
+ size: "sm",
657
+ "aria-label": t("dataGrid.rowsPerPage"),
658
+ className: "ui-data-table-page-size-trigger w-auto shrink-0 tabular-nums",
659
+ children: /* @__PURE__ */ jsx(SelectValue, {})
660
+ }
661
+ ),
654
662
  /* @__PURE__ */ jsx(SelectContent, { children: pageSizeOptions.map((n) => /* @__PURE__ */ jsx(SelectItem, { value: String(n), className: "tabular-nums", children: n }, n)) })
655
663
  ]
656
664
  }
657
665
  )
658
666
  ] }),
659
- /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", children: [
667
+ /* @__PURE__ */ jsxs(Flex, { direction: "row", align: "center", gap: "sm", className: "ui-data-table-page-nav", children: [
660
668
  /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm tabular-nums", children: t("dataGrid.pageOf", { page: pageIndex + 1, total: Math.max(1, pageCount) }) }),
661
669
  /* @__PURE__ */ jsx(
662
670
  Button,
@@ -1,3 +1,3 @@
1
1
  import type { CalendarProp } from "../../props/components/data-entry.prop.js";
2
2
  export type { CalendarProp, CalendarProp as CalendarProps, } from "../../props/components/data-entry.prop.js";
3
- export declare function Calendar({ className, classNames, showOutsideDays, ...props }: CalendarProp): import("react/jsx-runtime").JSX.Element;
3
+ export declare function Calendar({ className, classNames, showOutsideDays, "aria-label": ariaLabel, labels, ...props }: CalendarProp): import("react/jsx-runtime").JSX.Element;
@@ -9,6 +9,8 @@ function Calendar({
9
9
  className,
10
10
  classNames,
11
11
  showOutsideDays = true,
12
+ "aria-label": ariaLabel,
13
+ labels,
12
14
  ...props
13
15
  }) {
14
16
  const rangeDefaults = props.mode === "range" ? { resetOnSelect: props.resetOnSelect ?? true } : null;
@@ -16,6 +18,11 @@ function Calendar({
16
18
  DayPicker,
17
19
  {
18
20
  showOutsideDays,
21
+ "aria-label": ariaLabel,
22
+ labels: {
23
+ ...labels,
24
+ labelNav: labels?.labelNav ?? (() => `${ariaLabel ?? "Calendar"} navigation`)
25
+ },
19
26
  className: cn("relative w-fit p-3", className),
20
27
  classNames: {
21
28
  months: cn("flex flex-col gap-4 sm:flex-row", classNames?.months),
@@ -373,13 +373,20 @@ function SearchSelect({
373
373
  ]
374
374
  }
375
375
  ),
376
- renderLoadMore && hasMore ? /* @__PURE__ */ jsx("div", { className: "border-border shrink-0 border-t p-1", children: renderLoadMore({
377
- hasMore,
378
- loading,
379
- loadMore: () => {
380
- if (!loading) void fetchPage(page + 1, debouncedQuery, true);
376
+ renderLoadMore && hasMore ? /* @__PURE__ */ jsx(
377
+ "div",
378
+ {
379
+ className: "border-border shrink-0 border-t p-1",
380
+ onKeyDown: (event) => event.stopPropagation(),
381
+ children: renderLoadMore({
382
+ hasMore,
383
+ loading,
384
+ loadMore: () => {
385
+ if (!loading) void fetchPage(page + 1, debouncedQuery, true);
386
+ }
387
+ })
381
388
  }
382
- }) }) : null
389
+ ) : null
383
390
  ] })
384
391
  }
385
392
  )
@@ -76,7 +76,7 @@ function TransferPanel({
76
76
  className: cn(
77
77
  "flex cursor-pointer items-start gap-2 rounded-sm px-2 py-2 text-sm",
78
78
  "hover:bg-accent hover:text-accent-foreground",
79
- item.disabled && "pointer-events-none opacity-50"
79
+ item.disabled && "bg-muted/40 text-muted-foreground pointer-events-none"
80
80
  ),
81
81
  children: [
82
82
  /* @__PURE__ */ jsx(
@@ -174,39 +174,43 @@ function TreeSelectRoot({
174
174
  }
175
175
  };
176
176
  return /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, children: [
177
- /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
178
- Button,
179
- {
180
- id,
181
- type: "button",
182
- variant: "outline",
183
- role: "combobox",
184
- "aria-expanded": open,
185
- "aria-haspopup": "tree",
186
- "aria-controls": open ? treeId : void 0,
187
- ...fieldA11y,
188
- disabled,
189
- className: cn(
190
- "w-full justify-between font-normal",
191
- controlOpenRingClass,
192
- !displayKeys.length && "text-muted-foreground",
193
- className
194
- ),
195
- children: [
196
- /* @__PURE__ */ jsx("span", { className: "truncate", children: displayKeys.length ? displayLabel : resolvedPlaceholder }),
197
- /* @__PURE__ */ jsx("span", { className: "ms-2 flex shrink-0 items-center", children: allowClear && displayKeys.length > 0 && !disabled ? /* @__PURE__ */ jsx(
198
- "button",
199
- {
200
- type: "button",
201
- "aria-label": t("dataEntry.treeSelect.clear"),
202
- className: "flex size-4 items-center justify-center rounded-sm opacity-50 hover:opacity-100 focus-visible:opacity-100",
203
- onClick: clearValue,
204
- children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
205
- }
206
- ) : /* @__PURE__ */ jsx(ChevronsUpDown, { className: "size-4 opacity-50", "aria-hidden": "true" }) })
207
- ]
208
- }
209
- ) }),
177
+ /* @__PURE__ */ jsxs("div", { className: "relative", children: [
178
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
179
+ Button,
180
+ {
181
+ id,
182
+ type: "button",
183
+ variant: "outline",
184
+ role: "combobox",
185
+ "aria-expanded": open,
186
+ "aria-haspopup": "tree",
187
+ "aria-controls": open ? treeId : void 0,
188
+ ...fieldA11y,
189
+ disabled,
190
+ className: cn(
191
+ "w-full justify-between font-normal",
192
+ allowClear && displayKeys.length > 0 && !disabled && "pe-10",
193
+ controlOpenRingClass,
194
+ !displayKeys.length && "text-muted-foreground",
195
+ className
196
+ ),
197
+ children: [
198
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: displayKeys.length ? displayLabel : resolvedPlaceholder }),
199
+ /* @__PURE__ */ jsx("span", { className: "ms-2 flex shrink-0 items-center", children: !(allowClear && displayKeys.length > 0 && !disabled) && /* @__PURE__ */ jsx(ChevronsUpDown, { className: "size-4 opacity-50", "aria-hidden": "true" }) })
200
+ ]
201
+ }
202
+ ) }),
203
+ allowClear && displayKeys.length > 0 && !disabled && /* @__PURE__ */ jsx(
204
+ "button",
205
+ {
206
+ type: "button",
207
+ "aria-label": t("dataEntry.treeSelect.clear"),
208
+ className: "absolute end-3 top-1/2 z-10 flex size-6 -translate-y-1/2 items-center justify-center rounded-sm opacity-50 hover:opacity-100 focus-visible:opacity-100",
209
+ onClick: clearValue,
210
+ children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
211
+ }
212
+ )
213
+ ] }),
210
214
  /* @__PURE__ */ jsxs(PopoverContent, { className: "w-[var(--radix-popover-trigger-width)] p-0", align: "start", children: [
211
215
  showSearch && /* @__PURE__ */ jsx(Command, { shouldFilter: false, children: /* @__PURE__ */ jsx(
212
216
  CommandInput,
@@ -319,7 +319,7 @@ function Upload({
319
319
  "aria-label": t("dataEntry.upload.avatarLabel"),
320
320
  children: [
321
321
  !showPlaceholder && item?.previewUrl ? /* @__PURE__ */ jsx("img", { src: item.previewUrl, alt: "", className: "size-full object-cover" }) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground flex size-full items-center justify-center", children: /* @__PURE__ */ jsx(Camera, { className: controlIconClass, "aria-hidden": "true" }) }),
322
- !disabled && /* @__PURE__ */ jsx("span", { className: "text-2xs absolute inset-x-0 bottom-0 bg-black/50 py-1 text-center text-white", children: t("dataEntry.upload.change") })
322
+ !disabled && /* @__PURE__ */ jsx("span", { className: "text-2xs absolute inset-x-0 bottom-0 bg-black/70 py-1 text-center text-white", children: t("dataEntry.upload.change") })
323
323
  ]
324
324
  }
325
325
  ),
@@ -37,6 +37,7 @@ const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__P
37
37
  ));
38
38
  DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
39
39
  const DialogContent = React.forwardRef(({ className, children, showClose, showCloseButton: showCloseButtonProp, ...props }, ref) => {
40
+ const { t } = useTranslation();
40
41
  const showCloseButton = showCloseButtonProp ?? showClose ?? true;
41
42
  return /* @__PURE__ */ jsxs(DialogPortal, { children: [
42
43
  /* @__PURE__ */ jsx(DialogOverlay, {}),
@@ -59,7 +60,7 @@ const DialogContent = React.forwardRef(({ className, children, showClose, showCl
59
60
  className: "ring-offset-background focus:ring-ring transition-opacity focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none",
60
61
  children: [
61
62
  /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" }),
62
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
63
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("feedback.alert.dismiss") })
63
64
  ]
64
65
  }
65
66
  ) : null
@@ -138,6 +139,7 @@ const AlertDialogOverlay = React.forwardRef(({ className, ...props }, ref) => /*
138
139
  ));
139
140
  AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
140
141
  const AlertDialogContent = React.forwardRef(({ className, children, showClose, showCloseButton: showCloseButtonProp, ...props }, ref) => {
142
+ const { t } = useTranslation();
141
143
  const showCloseButton = showCloseButtonProp ?? showClose ?? false;
142
144
  return /* @__PURE__ */ jsxs(
143
145
  AlertDialogPrimitive.Content,
@@ -156,7 +158,7 @@ const AlertDialogContent = React.forwardRef(({ className, children, showClose, s
156
158
  {
157
159
  type: "button",
158
160
  className: "ring-offset-background focus:ring-ring transition-opacity focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none",
159
- "aria-label": "Close",
161
+ "aria-label": t("feedback.alert.dismiss"),
160
162
  children: /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" })
161
163
  }
162
164
  ) }) : null
@@ -6,6 +6,7 @@ import { cva } from "class-variance-authority";
6
6
  import { X } from "lucide-react";
7
7
  import { cn } from "../../lib/utils.js";
8
8
  import { overlayHeaderToneClass } from "./overlay-header-tone.js";
9
+ import { useTranslation } from "../../i18n/use-translation.js";
9
10
  const toCssLength = (v) => typeof v === "number" ? `${v}px` : v;
10
11
  function Sheet(props) {
11
12
  return /* @__PURE__ */ jsx(DialogPrimitive.Root, { "data-slot": "sheet", ...props });
@@ -55,6 +56,7 @@ const sheetVariants = cva(
55
56
  );
56
57
  const SheetContent = React.forwardRef(
57
58
  ({ side = "right", className, children, showCloseButton = true, width, style, ...props }, ref) => {
59
+ const { t } = useTranslation();
58
60
  const horizontal = side === "left" || side === "right";
59
61
  const widthSet = width != null && horizontal;
60
62
  const mergedStyle = widthSet ? { ...style, ["--sheet-width"]: toCssLength(width) } : style;
@@ -82,7 +84,7 @@ const SheetContent = React.forwardRef(
82
84
  className: "ring-offset-background focus:ring-ring absolute end-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none",
83
85
  children: [
84
86
  /* @__PURE__ */ jsx(X, { className: "size-4", "aria-hidden": "true" }),
85
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
87
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("feedback.alert.dismiss") })
86
88
  ]
87
89
  }
88
90
  ) : null
@@ -175,7 +177,7 @@ const SheetDescription = React.forwardRef(({ className, ...props }, ref) => /* @
175
177
  {
176
178
  ref,
177
179
  "data-slot": "sheet-description",
178
- className: cn("text-muted-foreground text-sm", className),
180
+ className: cn("text-foreground/80 text-sm", className),
179
181
  ...props
180
182
  }
181
183
  ));
@@ -33,7 +33,7 @@ const buttonVariants = cva("ui-button", {
33
33
  sm: "ui-button--sm gap-1.5 has-[>svg]:px-2.5",
34
34
  lg: "ui-button--lg has-[>svg]:px-4",
35
35
  icon: "ui-button--icon",
36
- "icon-xs": "size-[calc(var(--control-height)-0.75rem)] [&_svg:not([class*='size-'])]:size-3",
36
+ "icon-xs": "ui-button--icon-xs [&_svg]:size-3 [&_svg]:shrink-0",
37
37
  "icon-sm": "ui-button--icon-sm",
38
38
  "icon-lg": "ui-button--icon-lg"
39
39
  },
@@ -105,7 +105,7 @@ const Button = React.forwardRef(
105
105
  "disabled:pointer-events-none disabled:opacity-50",
106
106
  "data-[loading]:pointer-events-none",
107
107
  "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
108
- "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
108
+ "[&_svg]:pointer-events-none [&_svg]:shrink-0",
109
109
  buttonVariants({ variant, size, shape, className })
110
110
  ),
111
111
  ref,
@@ -8,6 +8,6 @@ export type BreadcrumbProps = {
8
8
  * Multiple Breadcrumb instances on one page/view need a DISTINCT name each — two `<nav>`
9
9
  * landmarks sharing one name/role fail axe's `landmark-unique` (WCAG 2.4.1 / 1.3.1).
10
10
  */
11
- "aria-label"?: string;
11
+ ariaLabel?: string;
12
12
  };
13
- export declare function Breadcrumb({ items, linkComponent: LinkComponent, "aria-label": ariaLabel, }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function Breadcrumb({ items, linkComponent: LinkComponent, ariaLabel, }: BreadcrumbProps): import("react/jsx-runtime").JSX.Element;
@@ -5,7 +5,7 @@ import { useTranslation } from "../../i18n/use-translation.js";
5
5
  function Breadcrumb({
6
6
  items,
7
7
  linkComponent: LinkComponent = "a",
8
- "aria-label": ariaLabel
8
+ ariaLabel
9
9
  }) {
10
10
  const { t } = useTranslation();
11
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) => {
@@ -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, breadcrumbAriaLabel, 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, breadcrumbLabel, 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
  };
@@ -39,6 +39,7 @@ function PageContainerRoot({
39
39
  extra,
40
40
  footer,
41
41
  breadcrumb,
42
+ breadcrumbLabel,
42
43
  breadcrumbAriaLabel,
43
44
  linkComponent: LinkComponent = "a",
44
45
  density,
@@ -72,7 +73,7 @@ function PageContainerRoot({
72
73
  breadcrumb && breadcrumb.length > 0 && /* @__PURE__ */ jsx(
73
74
  "nav",
74
75
  {
75
- "aria-label": breadcrumbAriaLabel ?? t("navigation.breadcrumb.ariaLabel"),
76
+ "aria-label": breadcrumbLabel ?? breadcrumbAriaLabel ?? t("navigation.breadcrumb.ariaLabel"),
76
77
  className: "ui-breadcrumb",
77
78
  children: /* @__PURE__ */ jsx("ol", { className: "ui-breadcrumb-list", children: breadcrumb.map((item, i) => {
78
79
  const isLast = i === breadcrumb.length - 1;
@@ -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, "aria-label": ariaLabel, }: SidebarProp): import("react/jsx-runtime").JSX.Element;
21
+ export declare function Sidebar({ ariaLabel: ariaLabelCamel, activeId, onSelect, sections, product, onProductClick, brand, collapsed, children, renderItem, footer, "aria-label": ariaLabel, }: SidebarProp): import("react/jsx-runtime").JSX.Element;
@@ -209,6 +209,7 @@ function CollapsedRow({ item, activeId, onSelect }) {
209
209
  ] });
210
210
  }
211
211
  function Sidebar({
212
+ ariaLabel: ariaLabelCamel,
212
213
  activeId,
213
214
  onSelect,
214
215
  sections,
@@ -256,7 +257,7 @@ function Sidebar({
256
257
  meta
257
258
  ] });
258
259
  })() : null,
259
- /* @__PURE__ */ jsx("nav", { className: "sb-nav-scroll", "aria-label": ariaLabel ?? t("layout.sidebar.ariaLabel"), children: children ?? resolvedSections.map((section, sectionIndex) => /* @__PURE__ */ jsx(
260
+ /* @__PURE__ */ jsx("nav", { className: "sb-nav-scroll", "aria-label": ariaLabel ?? ariaLabelCamel ?? t("layout.sidebar.ariaLabel"), children: children ?? resolvedSections.map((section, sectionIndex) => /* @__PURE__ */ jsx(
260
261
  SidebarSection,
261
262
  {
262
263
  label: section.label,
@@ -3,5 +3,7 @@ export type SplitPaneProps = {
3
3
  children: ReactNode;
4
4
  aside: ReactNode;
5
5
  asideWidth?: "sm" | "md";
6
+ /** Accessible complementary landmark name; required when multiple panes share a document. */
7
+ asideLabel?: string;
6
8
  };
7
- export declare function SplitPane({ children, aside, asideWidth }: SplitPaneProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function SplitPane({ children, aside, asideWidth, asideLabel }: SplitPaneProps): import("react/jsx-runtime").JSX.Element;
@@ -1,8 +1,8 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- function SplitPane({ children, aside, asideWidth = "md" }) {
2
+ function SplitPane({ children, aside, asideWidth = "md", asideLabel }) {
3
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
- /* @__PURE__ */ jsx("aside", { className: "ui-split-pane-aside", children: aside })
5
+ /* @__PURE__ */ jsx("aside", { className: "ui-split-pane-aside", "aria-label": asideLabel, children: aside })
6
6
  ] }) });
7
7
  }
8
8
  export {
@@ -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, hideOnSinglePage, simple, disabled, className, onValueChange, "aria-label": ariaLabel, }: PaginationProp): import("react/jsx-runtime").JSX.Element | null;
25
+ export declare function Pagination({ ariaLabel, value, total, pageSize, pageSizeOptions, showSizeChanger, showTotal, hideOnSinglePage, simple, disabled, className, onValueChange, }: PaginationProp): import("react/jsx-runtime").JSX.Element | null;
26
26
  export { PaginationContent, PaginationItem, PaginationLink, PaginationEllipsis, PaginationPrevious, PaginationNext, };
@@ -82,6 +82,7 @@ const PaginationNext = React.forwardRef(
82
82
  );
83
83
  PaginationNext.displayName = "PaginationNext";
84
84
  function Pagination({
85
+ ariaLabel,
85
86
  value = 1,
86
87
  total = 0,
87
88
  pageSize = 10,
@@ -92,8 +93,7 @@ function Pagination({
92
93
  simple,
93
94
  disabled,
94
95
  className,
95
- onValueChange,
96
- "aria-label": ariaLabel
96
+ onValueChange
97
97
  }) {
98
98
  const { t } = useTranslation();
99
99
  const navLabel = ariaLabel ?? t("navigation.pagination.ariaLabel");
@@ -102,7 +102,7 @@ const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => /* @__PUR
102
102
  ref,
103
103
  "data-slot": "tabs-trigger",
104
104
  className: cn(
105
- "text-foreground/60 ring-offset-background hover:text-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-ring/50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:ring-primary/25 after:bg-foreground relative inline-flex flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-3 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:ring-1 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
105
+ "text-muted-foreground ring-offset-background hover:text-foreground focus-visible:border-ring focus-visible:outline-ring focus-visible:ring-ring/50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:ring-primary/25 after:bg-foreground relative inline-flex flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-3 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:ring-1 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
106
106
  className
107
107
  ),
108
108
  ...props
@@ -10,4 +10,4 @@ export declare function flattenItemPages<TItem, TPage extends {
10
10
  * `useInfiniteQuery` lifecycle widget — flatten pages, load-more footer.
11
11
  * Cursor / activity feeds where user accumulates pages (vs DataTable cursor buttons).
12
12
  */
13
- export declare function InfiniteQueryState<TPage, TFlat>({ query, skeleton, empty, flatten, isEmpty, errorRenderer, showRetry, onRetry, loadingMore, loadMore, showLoadMore, children, }: InfiniteQueryStateProp<TPage, TFlat>): import("react/jsx-runtime").JSX.Element;
13
+ export declare function InfiniteQueryState<TPage, TFlat>({ query, skeleton, empty, flatten, isEmpty, errorRenderer, showRetry, onRetry, onAuthError, loadingMore, loadMore, showLoadMore, children, }: InfiniteQueryStateProp<TPage, TFlat>): import("react/jsx-runtime").JSX.Element;
@@ -4,6 +4,7 @@ import * as React from "react";
4
4
  import { AlertQueryError } from "../feedback/alert.js";
5
5
  import { Button } from "../general/button.js";
6
6
  import { useTranslation } from "../../i18n/use-translation.js";
7
+ import { classifyQueryError } from "../../lib/query-error.js";
7
8
  function flattenItemPages(data) {
8
9
  if (!data) return [];
9
10
  return data.pages.flatMap((page) => page.items);
@@ -19,8 +20,9 @@ function InfiniteQueryState({
19
20
  flatten,
20
21
  isEmpty = defaultIsEmptyFlat,
21
22
  errorRenderer,
22
- showRetry = true,
23
+ showRetry = false,
23
24
  onRetry,
25
+ onAuthError,
24
26
  loadingMore,
25
27
  loadMore,
26
28
  showLoadMore = true,
@@ -38,7 +40,17 @@ function InfiniteQueryState({
38
40
  if (query.isError) {
39
41
  if (query.isFetching && !query.isFetchingNextPage) return /* @__PURE__ */ jsx(Fragment, { children: skeleton });
40
42
  if (errorRenderer) return /* @__PURE__ */ jsx(Fragment, { children: errorRenderer(query.error, retry) });
41
- return /* @__PURE__ */ jsx(AlertQueryError, { error: query.error, onRetry: showRetry ? retry : void 0 });
43
+ const info = classifyQueryError(query.error);
44
+ const canRetry = (info.category === "transient" || info.category === "unknown") && (info.retryable || showRetry || Boolean(onRetry));
45
+ return /* @__PURE__ */ jsx(
46
+ AlertQueryError,
47
+ {
48
+ error: query.error,
49
+ category: info.category,
50
+ onRetry: canRetry ? retry : void 0,
51
+ onAuthAction: info.category === "auth" ? onAuthError : void 0
52
+ }
53
+ );
42
54
  }
43
55
  const data = query.data;
44
56
  if (!data) return /* @__PURE__ */ jsx(Fragment, { children: skeleton });
@@ -449,6 +449,12 @@ export type CascaderProp = FieldA11yProps & {
449
449
  expandTrigger?: "click" | "hover";
450
450
  fieldNames?: TreeFieldNamesProp;
451
451
  allowClear?: boolean;
452
+ "aria-label"?: string;
453
+ "aria-labelledby"?: string;
454
+ "aria-describedby"?: string;
455
+ "aria-errormessage"?: string;
456
+ "aria-invalid"?: boolean | "true" | "false";
457
+ "aria-required"?: boolean | "true" | "false";
452
458
  };
453
459
  export type ShowCheckedStrategyProp = "SHOW_CHILD" | "SHOW_PARENT" | "SHOW_ALL";
454
460
  /** @see TreeSelect — tree in Popover (cmdk search + expand/collapse). */
@@ -469,6 +475,12 @@ export type TreeSelectProp = FieldA11yProps & {
469
475
  className?: ClassNameProp;
470
476
  id?: IdProp;
471
477
  fieldNames?: TreeFieldNamesProp;
478
+ "aria-label"?: string;
479
+ "aria-labelledby"?: string;
480
+ "aria-describedby"?: string;
481
+ "aria-errormessage"?: string;
482
+ "aria-invalid"?: boolean | "true" | "false";
483
+ "aria-required"?: boolean | "true" | "false";
472
484
  };
473
485
  /** @see TransferItem */
474
486
  export type TransferItemProp = {
@@ -15,6 +15,8 @@ export type PageContainerProp = {
15
15
  * renders on the same page/view — two `<nav>` landmarks sharing one name/role fail axe's
16
16
  * `landmark-unique` (WCAG 2.4.1 / 1.3.1).
17
17
  */
18
+ breadcrumbLabel?: string;
19
+ /** Kebab/DOM-style alias of `breadcrumbLabel` (same landmark-unique override). */
18
20
  breadcrumbAriaLabel?: string;
19
21
  linkComponent?: React.ElementType;
20
22
  density?: PageDensityProp;
@@ -138,6 +140,8 @@ export type SidebarSectionProp = {
138
140
  };
139
141
  /** @see Sidebar */
140
142
  export type SidebarProp = {
143
+ /** Accessible navigation landmark name; make it unique when multiple sidebars share a document. */
144
+ ariaLabel?: string;
141
145
  activeId: string;
142
146
  onSelect?: (id: string) => void;
143
147
  sections?: SidebarSectionProp[];
@@ -16,6 +16,14 @@ export type ToolbarGroupProp = {
16
16
  };
17
17
  /** @see Pagination — offset/page-based (distinct from DataTable cursor pagination). */
18
18
  export type PaginationProp = {
19
+ /**
20
+ * Override the `<nav>` landmark's accessible name. Defaults to a localized "Pagination".
21
+ * Multiple Pagination instances on one page/view (e.g. two independent result lists) need a
22
+ * DISTINCT name each — two `<nav>` landmarks sharing one name/role fail axe's `landmark-unique`
23
+ * (WCAG 2.4.1 / 1.3.1). Pass something that names what is being paged, e.g. `"注文一覧の
24
+ * ページネーション"` vs `"請求書一覧のページネーション"`.
25
+ */
26
+ ariaLabel?: string;
19
27
  value?: number;
20
28
  total?: number;
21
29
  pageSize?: number;
@@ -34,14 +42,6 @@ export type PaginationProp = {
34
42
  disabled?: DisabledProp;
35
43
  className?: ClassNameProp;
36
44
  onValueChange?: (page: number, pageSize: number) => void;
37
- /**
38
- * Override the `<nav>` landmark's accessible name. Defaults to a localized "Pagination".
39
- * Multiple Pagination instances on one page/view (e.g. two independent result lists) need a
40
- * DISTINCT name each — two `<nav>` landmarks sharing one name/role fail axe's `landmark-unique`
41
- * (WCAG 2.4.1 / 1.3.1). Pass something that names what is being paged, e.g. `"注文一覧の
42
- * ページネーション"` vs `"請求書一覧のページネーション"`.
43
- */
44
- "aria-label"?: string;
45
45
  };
46
46
  export type StepStatusProp = "wait" | "process" | "finish" | "error";
47
47
  /** @see StepItem */
@@ -57,6 +57,8 @@ export type InfiniteQueryStateProp<TPage, TFlat> = {
57
57
  errorRenderer?: (error: unknown, retry: () => void) => React.ReactNode;
58
58
  showRetry?: boolean;
59
59
  onRetry?: HandlerProp;
60
+ /** Recovery for authentication errors (401 / expired token), shown instead of Retry. */
61
+ onAuthError?: HandlerProp;
60
62
  loadingMore?: React.ReactNode;
61
63
  /** Custom load-more footer; `false` hides footer entirely. */
62
64
  loadMore?: React.ReactNode | false;
@@ -8,6 +8,7 @@
8
8
  gap: var(--space-stack-sm);
9
9
  margin: 0;
10
10
  inline-size: 100%;
11
+ min-inline-size: 0;
11
12
  }
12
13
 
13
14
  .ui-chart-title {
@@ -18,6 +19,7 @@
18
19
 
19
20
  .ui-chart-canvas {
20
21
  inline-size: 100%;
22
+ min-inline-size: 0;
21
23
  }
22
24
 
23
25
  /* recharts legend/axis text inherits the design typography + muted tone. */
@@ -202,6 +202,21 @@
202
202
  * icon button can sit flush beside a labelled one (split buttons, toolbars). Derive them from
203
203
  * the density tokens — never from a hand-written offset off the base --control-height, which
204
204
  * is how icon-sm drifted a step down to the xs height (issue #133). */
205
+ .ui-button--icon-xs {
206
+ width: var(--control-height-xs);
207
+ height: var(--control-height-xs);
208
+ padding: 0;
209
+ }
210
+
211
+ /* Rule #24: compact visual tiers never shrink the actual coarse-pointer hit target below 44px.
212
+ * The glyph remains 12px; only the interactive square expands. */
213
+ @media (pointer: coarse) {
214
+ .ui-button--icon-xs {
215
+ width: var(--control-height-default);
216
+ height: var(--control-height-default);
217
+ }
218
+ }
219
+
205
220
  .ui-button--icon-sm {
206
221
  width: var(--control-height-sm);
207
222
  height: var(--control-height-sm);
@@ -403,13 +403,38 @@
403
403
  }
404
404
 
405
405
  .ui-page-title {
406
- font-size: var(--heading-h1);
406
+ font-size: var(--page-title-font-size);
407
407
  font-weight: var(--font-weight-medium);
408
408
  letter-spacing: var(--letter-spacing-tight);
409
409
  line-height: var(--line-height-tight);
410
410
  overflow-wrap: anywhere;
411
411
  }
412
412
 
413
+ /* Compact viewports use a responsive type step, not compact density: body/control text and
414
+ * touch targets remain readable while page chrome stops competing with primary actions. A
415
+ * single Flex action group must wrap even when the consumer omitted `wrap`, because clipping
416
+ * header actions makes functionality unreachable. */
417
+ @media (max-width: 639px) {
418
+ .ui-page-container {
419
+ --space-page-active-x: var(--space-page-compact-x);
420
+ --space-page-active-y: var(--space-page-compact-y);
421
+ --space-section-active: var(--space-section-compact);
422
+ }
423
+
424
+ .ui-page-title {
425
+ font-size: var(--page-title-font-size-compact);
426
+ }
427
+
428
+ .ui-page-header .ui-page-subtitle {
429
+ font-size: var(--page-subtitle-font-size-compact);
430
+ }
431
+
432
+ .ui-page-header-extra > .ui-flex[data-direction="row"] {
433
+ flex-wrap: wrap;
434
+ max-width: 100%;
435
+ }
436
+ }
437
+
413
438
  @media (min-width: 640px) {
414
439
  .ui-page-header-row {
415
440
  flex-direction: row;
@@ -426,7 +451,7 @@
426
451
  }
427
452
 
428
453
  .ui-page-subtitle {
429
- font-size: var(--font-size-base);
454
+ font-size: var(--page-subtitle-font-size);
430
455
  color: hsl(var(--muted-foreground));
431
456
  margin-top: var(--space-1);
432
457
  }
@@ -1,4 +1,11 @@
1
1
  @layer components {
2
+ [data-slot="tabs-list"] {
3
+ max-inline-size: var(--tabs-list-max-inline-size);
4
+ overflow-x: var(--tabs-list-overflow);
5
+ overscroll-behavior-inline: contain;
6
+ scrollbar-width: thin;
7
+ }
8
+
2
9
  .ui-context-menu-content {
3
10
  z-index: 50;
4
11
  min-width: 10rem;
@@ -82,6 +82,31 @@
82
82
  padding-top: var(--space-stack-sm);
83
83
  }
84
84
 
85
+ /* Numbered footer may wrap only between its two semantic groups. The supported JA/EN/VI locale
86
+ * label and select stay fully visible together (gh#184). */
87
+ .ui-data-table-pagination--numbered {
88
+ flex-wrap: wrap;
89
+ min-width: 0;
90
+ }
91
+
92
+ .ui-data-table-page-size {
93
+ flex: 0 0 auto;
94
+ flex-wrap: nowrap;
95
+ max-width: 100%;
96
+ min-width: 0;
97
+ }
98
+
99
+ .ui-data-table-page-size-label {
100
+ flex: 0 0 auto;
101
+ white-space: nowrap;
102
+ }
103
+
104
+ .ui-data-table-page-size-trigger,
105
+ .ui-data-table-page-nav {
106
+ flex: 0 0 auto;
107
+ white-space: nowrap;
108
+ }
109
+
85
110
  .ui-data-table-root {
86
111
  display: flex;
87
112
  flex-direction: column;
@@ -12,6 +12,8 @@
12
12
  --filter-picker-width-md: 14rem;
13
13
  --breadcrumb-font-size: var(--font-size-xs);
14
14
  --menubar-shortcut-font-size: var(--font-size-xs);
15
+ --tabs-list-max-inline-size: 100%;
16
+ --tabs-list-overflow: auto;
15
17
 
16
18
  /* Menu item hover/highlight tint — `initial` so the --accent default re-resolves at the call site
17
19
  * under a scoped theme (a :root binding to a role var freezes at :root).
@@ -21,6 +21,9 @@
21
21
  --space-page-active-x: var(--space-page-x);
22
22
  --space-page-active-y: var(--space-page-y);
23
23
  --space-section-active: var(--space-section);
24
+ --space-page-compact-x: var(--space-4); /* 16px mobile page gutter */
25
+ --space-page-compact-y: var(--space-4);
26
+ --space-section-compact: var(--space-4);
24
27
 
25
28
  /* Modal scrim — the single backdrop colour shared by EVERY overlay (Dialog, AlertDialog, Sheet,
26
29
  * Drawer). Themeable (rule #44) so a service tints the wash to its brand once, e.g. a navy
@@ -38,6 +41,13 @@
38
41
  * old fixed 16px pad that left 24 above vs 32 below. */
39
42
  --page-header-pad-bottom: calc(var(--space-page-active-y) - var(--space-section-active));
40
43
 
44
+ /* Responsive page typography is independent from density. Density changes information spacing;
45
+ * these tokens change only page chrome so mobile keeps readable body text and touch targets. */
46
+ --page-title-font-size: var(--heading-h1);
47
+ --page-title-font-size-compact: var(--heading-h2);
48
+ --page-subtitle-font-size: var(--font-size-base);
49
+ --page-subtitle-font-size-compact: var(--font-size-sm);
50
+
41
51
  /* Section "chrome" padding — the SHARED inset for header / body / footer of every overlay-ish
42
52
  * surface (Dialog · Sheet · Drawer · Card). One global knob: a service sets these once instead of
43
53
  * per-component. Vertical is tightened (16 vs the old 24) and density-aware (see density.css);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@godxjp/ui",
3
- "version": "18.0.1",
4
- "godxUiMcp": "18.0.0",
3
+ "version": "18.0.2",
4
+ "godxUiMcp": "18.0.1",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.29.1",
7
7
  "sideEffects": false,
@@ -276,8 +276,24 @@
276
276
  "test:watch": "vitest",
277
277
  "test:coverage": "vitest run --coverage",
278
278
  "check:example-imports": "node scripts/check-example-imports.mjs",
279
+ "check:frame-coverage": "node scripts/frame-coverage.mjs",
280
+ "check:screen-reader-evidence": "node scripts/check-screen-reader-evidence.mjs",
281
+ "check:data-entry-frame-runtime": "node scripts/check-data-entry-frame-runtime.mjs",
282
+ "check:data-entry-owner-source": "node scripts/check-data-entry-owner-source.mjs",
283
+ "check:data-entry-touch-aria": "node scripts/check-data-entry-touch-aria.mjs",
284
+ "check:layout-nav-frames": "node scripts/check-layout-nav-frames.mjs",
285
+ "check:provider-feedback-query-runtime": "for frames in navigation-app-setting-picker,feedback-dialog,feedback-sheet,feedback-alert-dialog feedback-tooltip,feedback-toast,feedback-skeleton,query-data-state query-infinite-query-state,query-mutation-feedback,query-prefetch-link; do FRAMES=$frames node scripts/check-provider-feedback-query-runtime.mjs || exit 1; done",
286
+ "check:layout-nav-closure": "for frames in layout-flex,layout-app-shell,layout-aspect-ratio,layout-auth-shell layout-page-container,layout-resizable-panel,layout-separator,layout-sidebar layout-split-pane,layout-topbar,navigation-breadcrumb,navigation-app-setting-picker navigation-context-menu,navigation-dropdown-menu,navigation-menubar,navigation-navigation-menu navigation-steps,navigation-toolbar,navigation-tabs,navigation-pagination; do FRAMES=$frames node scripts/check-layout-nav-closure.mjs || exit 1; done",
287
+ "check:display-runtime-evidence": "node scripts/check-display-runtime-evidence.mjs",
288
+ "check:data-table-pagination-wrap": "node scripts/check-data-table-pagination-wrap.mjs",
289
+ "check:button-icon-xs": "node scripts/check-button-icon-xs.mjs",
290
+ "check:frame-contracts": "pnpm check:frame-coverage && pnpm check:screen-reader-evidence && pnpm check:data-entry-owner-source && pnpm check:display-runtime-evidence",
291
+ "check:final-touch-rtl": "node scripts/check-final-touch-rtl.mjs",
292
+ "check:frame-runtime": "pnpm check:data-entry-frame-runtime && pnpm check:data-entry-touch-aria && pnpm check:layout-nav-frames && pnpm check:provider-feedback-query-runtime && pnpm check:layout-nav-closure && pnpm check:final-touch-rtl && pnpm check:data-table-pagination-wrap && pnpm check:button-icon-xs",
293
+ "pretest": "pnpm check:frame-coverage",
279
294
  "verify": "pnpm typecheck && pnpm lint && pnpm format && pnpm build && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:frame-coverage && pnpm test",
280
- "verify:release": "pnpm build && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm check:visual-audit && pnpm check:frame-coverage && pnpm check:frame-axe && pnpm test",
295
+ "verify:static": "pnpm build && pnpm typecheck && pnpm typecheck:docs && pnpm lint && pnpm preview:build && pnpm check:example-imports && pnpm check:core-isolation && pnpm check:no-consumer-coupling && pnpm check:use-client && pnpm check:prop-vocabulary && pnpm check:token-tiers && pnpm check:control-sizing && pnpm check:rtl && pnpm check:typography && pnpm check:mcp-token-sync && pnpm check:mcp-lockstep && pnpm check:mcp-sync && pnpm check:mcp-orphans && pnpm check:mcp-pattern-imports && pnpm check:audit-sync && pnpm check:mcp-prop-sync && pnpm check:contrast && pnpm check:visual-audit && pnpm test",
296
+ "verify:release": "pnpm verify:static && pnpm check:frame-contracts && pnpm check:frame-coverage && pnpm check:frame-axe",
281
297
  "check:mcp-lockstep": "node scripts/check-release-lockstep.mjs",
282
298
  "check:mcp-pattern-imports": "node scripts/check-mcp-pattern-imports.mjs",
283
299
  "check:mcp-sync": "node scripts/check-mcp-sync.mjs",
@@ -307,7 +323,6 @@
307
323
  "check:visual-audit": "node scripts/visual-audit-smoke.mjs",
308
324
  "check:frame-axe": "node scripts/check-frame-axe.mjs",
309
325
  "check:frame-geometry": "node scripts/frame-geometry.mjs",
310
- "check:frame-coverage": "node scripts/frame-coverage.mjs",
311
326
  "postinstall": "node scripts/postinstall.mjs",
312
327
  "init-agent": "node scripts/init-agent-kit.mjs",
313
328
  "check:use-client": "node scripts/check-use-client.mjs"