@godxjp/ui 23.0.0 → 23.2.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.
Files changed (93) hide show
  1. package/dist/app/date-format-labels.d.ts +14 -2
  2. package/dist/app/date-format-labels.js +1 -1
  3. package/dist/app/date-formats.d.ts +14 -2
  4. package/dist/app/date-formats.js +9 -2
  5. package/dist/components/data-display/card.d.ts +45 -2
  6. package/dist/components/data-display/card.js +4 -2
  7. package/dist/components/data-display/data-table.d.ts +8 -1
  8. package/dist/components/data-display/data-table.js +9 -2
  9. package/dist/components/data-display/feature-list.d.ts +26 -0
  10. package/dist/components/data-display/feature-list.js +29 -0
  11. package/dist/components/data-display/index.d.ts +6 -0
  12. package/dist/components/data-display/index.js +6 -0
  13. package/dist/components/data-display/swatch.d.ts +24 -0
  14. package/dist/components/data-display/swatch.js +19 -0
  15. package/dist/components/data-display/thumbnail.d.ts +37 -0
  16. package/dist/components/data-display/thumbnail.js +20 -0
  17. package/dist/components/data-entry/checkbox.js +1 -1
  18. package/dist/components/data-entry/form-field.js +2 -2
  19. package/dist/components/data-entry/input.js +1 -1
  20. package/dist/components/data-entry/number-input.js +27 -6
  21. package/dist/components/data-entry/radio.js +1 -1
  22. package/dist/components/data-entry/switch.js +1 -1
  23. package/dist/components/feedback/dialog.js +2 -2
  24. package/dist/components/feedback/index.d.ts +2 -2
  25. package/dist/components/feedback/index.js +19 -1
  26. package/dist/components/feedback/sheet.js +2 -22
  27. package/dist/components/feedback/skeleton.d.ts +33 -3
  28. package/dist/components/feedback/skeleton.js +154 -3
  29. package/dist/components/layout/flex.d.ts +1 -1
  30. package/dist/components/layout/flex.js +17 -5
  31. package/dist/components/layout/sidebar.js +9 -2
  32. package/dist/components/navigation/filter-bar.js +2 -1
  33. package/dist/components/navigation/tabs-scroll.d.ts +27 -0
  34. package/dist/components/navigation/tabs-scroll.js +36 -1
  35. package/dist/components/navigation/tabs.d.ts +2 -2
  36. package/dist/components/navigation/tabs.js +60 -16
  37. package/dist/i18n/messages/en.json +10 -1
  38. package/dist/i18n/messages/ja.json +10 -1
  39. package/dist/i18n/messages/vi.json +10 -1
  40. package/dist/lib/breakpoint-token.d.ts +8 -0
  41. package/dist/lib/breakpoint-token.js +29 -0
  42. package/dist/props/components/data-display.prop.d.ts +101 -1
  43. package/dist/props/components/feedback.prop.d.ts +85 -1
  44. package/dist/props/components/layout.prop.d.ts +72 -1
  45. package/dist/props/components/navigation.prop.d.ts +80 -2
  46. package/dist/props/registry.d.ts +124 -1
  47. package/dist/props/registry.js +140 -0
  48. package/dist/props/vocabulary/data.prop.d.ts +5 -0
  49. package/dist/props/vocabulary/index.d.ts +1 -1
  50. package/dist/styles/alert-layout.css +139 -0
  51. package/dist/styles/card-layout.css +48 -0
  52. package/dist/styles/control.css +41 -5
  53. package/dist/styles/data-display-layout.css +88 -0
  54. package/dist/styles/focus-ring.css +28 -0
  55. package/dist/styles/form-layout.css +4 -0
  56. package/dist/styles/layout.css +2 -1
  57. package/dist/styles/navigation-layout.css +89 -5
  58. package/dist/styles/shell-layout.css +22 -0
  59. package/dist/styles/table-layout.css +5 -2
  60. package/dist/tokens/components/card.css +2 -0
  61. package/dist/tokens/components/control.css +8 -3
  62. package/dist/tokens/components/data-display.css +23 -0
  63. package/dist/tokens/components/feedback.css +18 -0
  64. package/dist/tokens/components/navigation.css +4 -0
  65. package/dist/tokens/foundation.css +18 -16
  66. package/docs/CONSUMER-RULES.md +8 -3
  67. package/docs/CUSTOMER-THEMING.md +18 -8
  68. package/docs/DATETIME.md +11 -2
  69. package/docs/DESIGN-AUTHORITY.md +2 -1
  70. package/docs/FRAME-COVERAGE-REPORT.md +29 -3
  71. package/docs/SPACING.md +35 -5
  72. package/docs/TOKENS.md +1 -1
  73. package/docs/assets/shot-landscape.svg +12 -0
  74. package/docs/assets/shot-portrait.svg +10 -0
  75. package/docs/data-display/card/index.tsx +40 -0
  76. package/docs/data-display/data-table/index.tsx +17 -2
  77. package/docs/data-display/feature-list.tsx +159 -0
  78. package/docs/data-display/swatch.tsx +107 -0
  79. package/docs/data-display/table.tsx +1 -1
  80. package/docs/data-display/thumbnail.tsx +128 -0
  81. package/docs/data-entry/segmented-in-filter-row.tsx +77 -0
  82. package/docs/feedback/skeleton.tsx +57 -0
  83. package/docs/layout/flex.tsx +29 -0
  84. package/docs/layout/sidebar.tsx +66 -10
  85. package/docs/navigation/dropdown-menu.tsx +4 -4
  86. package/docs/navigation/tabs.tsx +131 -0
  87. package/docs/roadmap/ai-chat-components.md +1 -2
  88. package/docs/roadmap/tree-components.md +0 -1
  89. package/package.json +12 -21
  90. package/scripts/_agent-setup.mjs +18 -0
  91. package/scripts/consumer-rule.md +16 -0
  92. package/scripts/guinea-pig-skill.md +12 -6
  93. package/scripts/ui-audit.mjs +184 -7
@@ -6,8 +6,8 @@ export { TwoFactorSetup } from "./two-factor-setup.js";
6
6
  export type { TwoFactorSetupLabels, TwoFactorSetupProps } from "./two-factor-setup.js";
7
7
  export { Toaster } from "./sonner.js";
8
8
  export { toast } from "./use-toast.js";
9
- export { Skeleton, SkeletonRows, SkeletonTable, SkeletonDetail, SkeletonStat } from "./skeleton.js";
10
- export type { SkeletonProps } from "./skeleton.js";
9
+ export { Skeleton, SkeletonRows, SkeletonTable, SkeletonDetail, SkeletonStat, SkeletonArticle, SkeletonAvatar, SkeletonButton, SkeletonInput, SkeletonNode, SkeletonImage, } from "./skeleton.js";
10
+ export type { SkeletonProp, SkeletonProps, SkeletonWidth, SkeletonArticleProp, SkeletonArticleProps, SkeletonAvatarProp, SkeletonAvatarProps, SkeletonButtonProp, SkeletonButtonProps, SkeletonInputProp, SkeletonInputProps, SkeletonNodeProp, SkeletonNodeProps, SkeletonImageProp, SkeletonImageProps, } from "./skeleton.js";
11
11
  export { Banner } from "./banner.js";
12
12
  export type { BannerProp, BannerProps } from "./banner.js";
13
13
  export { Alert, AlertTitle, AlertContent, AlertDescription, AlertActions, AlertQueryError, } from "./alert.js";
@@ -42,7 +42,19 @@ import {
42
42
  import { TwoFactorSetup } from "./two-factor-setup.js";
43
43
  import { Toaster } from "./sonner.js";
44
44
  import { toast } from "./use-toast.js";
45
- import { Skeleton, SkeletonRows, SkeletonTable, SkeletonDetail, SkeletonStat } from "./skeleton.js";
45
+ import {
46
+ Skeleton,
47
+ SkeletonRows,
48
+ SkeletonTable,
49
+ SkeletonDetail,
50
+ SkeletonStat,
51
+ SkeletonArticle,
52
+ SkeletonAvatar,
53
+ SkeletonButton,
54
+ SkeletonInput,
55
+ SkeletonNode,
56
+ SkeletonImage
57
+ } from "./skeleton.js";
46
58
  import { Banner } from "./banner.js";
47
59
  import {
48
60
  Alert,
@@ -98,7 +110,13 @@ export {
98
110
  SheetTitle,
99
111
  SheetTrigger,
100
112
  Skeleton,
113
+ SkeletonArticle,
114
+ SkeletonAvatar,
115
+ SkeletonButton,
101
116
  SkeletonDetail,
117
+ SkeletonImage,
118
+ SkeletonInput,
119
+ SkeletonNode,
102
120
  SkeletonRows,
103
121
  SkeletonStat,
104
122
  SkeletonTable,
@@ -6,7 +6,7 @@ import { chain, mergeRefs } from "@react-aria/utils";
6
6
  import { Dialog as RacDialog, Modal, ModalOverlay } from "react-aria-components";
7
7
  import { cva } from "class-variance-authority";
8
8
  import { X } from "lucide-react";
9
- import { useMediaQuery } from "../../lib/hooks.js";
9
+ import { useMaxWidthBreakpoint } from "../../lib/breakpoint-token.js";
10
10
  import { cn } from "../../lib/utils.js";
11
11
  import { Slot } from "../../lib/slot.js";
12
12
  import { overlayHeaderToneClass } from "./overlay-header-tone.js";
@@ -15,28 +15,8 @@ import { useTranslation } from "../../i18n/use-translation.js";
15
15
  const toCssLength = (v) => typeof v === "number" ? `${v}px` : v;
16
16
  const SHEET_BREAKPOINT_TOKEN = "--sheet-responsive-breakpoint-width";
17
17
  const SHEET_BREAKPOINT_FALLBACK_QUERY = "(max-width: 768px)";
18
- function cssLengthToPx(value, rootFontSize) {
19
- const match = /^(-?\d*\.?\d+)(px|rem|em)?$/.exec(value.trim());
20
- if (match == null) return void 0;
21
- const amount = Number(match[1]);
22
- if (!Number.isFinite(amount)) return void 0;
23
- return match[2] === "rem" || match[2] === "em" ? amount * rootFontSize : amount;
24
- }
25
- function readSheetBreakpointQuery() {
26
- if (typeof document === "undefined" || typeof window.getComputedStyle !== "function") {
27
- return SHEET_BREAKPOINT_FALLBACK_QUERY;
28
- }
29
- const rootStyle = window.getComputedStyle(document.documentElement);
30
- const rootFontSize = cssLengthToPx(rootStyle.fontSize || "16px", 16) ?? 16;
31
- const px = cssLengthToPx(rootStyle.getPropertyValue(SHEET_BREAKPOINT_TOKEN), rootFontSize);
32
- return px == null ? SHEET_BREAKPOINT_FALLBACK_QUERY : `(max-width: ${String(px)}px)`;
33
- }
34
18
  function useSheetResponsiveMode(responsive = "side") {
35
- const [query, setQuery] = React.useState(SHEET_BREAKPOINT_FALLBACK_QUERY);
36
- React.useEffect(() => {
37
- setQuery(readSheetBreakpointQuery());
38
- }, []);
39
- const compact = useMediaQuery(query);
19
+ const compact = useMaxWidthBreakpoint(SHEET_BREAKPOINT_TOKEN, SHEET_BREAKPOINT_FALLBACK_QUERY);
40
20
  if (responsive === "side" || responsive === "bottom") return responsive;
41
21
  return compact ? "bottom" : "side";
42
22
  }
@@ -1,6 +1,37 @@
1
1
  import * as React from "react";
2
- export type SkeletonProps = React.HTMLAttributes<HTMLDivElement>;
3
- export declare function Skeleton({ className, ...props }: SkeletonProps): React.JSX.Element;
2
+ import type { SkeletonArticleProp, SkeletonAvatarProp, SkeletonButtonProp, SkeletonImageProp, SkeletonInputProp, SkeletonNodeProp, SkeletonProp } from "../../props/components/feedback.prop.js";
3
+ export type { SkeletonProp, SkeletonProp as SkeletonProps, SkeletonWidth, SkeletonArticleProp, SkeletonArticleProp as SkeletonArticleProps, SkeletonAvatarProp, SkeletonAvatarProp as SkeletonAvatarProps, SkeletonButtonProp, SkeletonButtonProp as SkeletonButtonProps, SkeletonInputProp, SkeletonInputProp as SkeletonInputProps, SkeletonNodeProp, SkeletonNodeProp as SkeletonNodeProps, SkeletonImageProp, SkeletonImageProp as SkeletonImageProps, } from "../../props/components/feedback.prop.js";
4
+ declare function SkeletonBlock({ active, loading, className, children, ...props }: SkeletonProp): React.JSX.Element;
5
+ /** Stands in for an `Avatar` — circle for a person, square for an entity mark. */
6
+ export declare function SkeletonAvatar({ size, shape, active, className }: SkeletonAvatarProp): React.JSX.Element;
7
+ /** Stands in for a `Button` — two control-heights wide, like antd's `controlHeight * 2`. */
8
+ export declare function SkeletonButton({ size, shape, block, active, className }: SkeletonButtonProp): React.JSX.Element;
9
+ /** Stands in for an `Input` — five control-heights wide, like antd's `controlHeight * 5`. */
10
+ export declare function SkeletonInput({ size, block, active, className }: SkeletonInputProp): React.JSX.Element;
11
+ /** A square placeholder for a media or custom slot; `children` centre inside it. */
12
+ export declare function SkeletonNode({ active, children, className }: SkeletonNodeProp): React.JSX.Element;
13
+ /** `SkeletonNode` carrying the image glyph — antd ships its own path; here it is the DS icon. */
14
+ export declare function SkeletonImage({ active, className }: SkeletonImageProp): React.JSX.Element;
15
+ /**
16
+ * SkeletonArticle — antd's own `<Skeleton>` shape: an optional avatar beside a heading line and a
17
+ * paragraph. Reach for it for a comment, a profile card or a feed item; `Skeleton` stays the bare
18
+ * block, and `SkeletonRows` / `SkeletonTable` / `SkeletonDetail` / `SkeletonStat` stay the house
19
+ * shapes for a list, a table, a record and a KPI tile.
20
+ */
21
+ export declare function SkeletonArticle({ avatar, title, paragraph, round, active, loading, children, className, }: SkeletonArticleProp): React.JSX.Element;
22
+ /**
23
+ * Skeleton — the placeholder BLOCK, and the namespace antd hangs its element presets on. The
24
+ * statics are the antd spelling (`Skeleton.Button`); the same components are also named exports, so
25
+ * a consumer importing `SkeletonButton` finds it in the catalog.
26
+ */
27
+ export declare const Skeleton: typeof SkeletonBlock & {
28
+ Avatar: typeof SkeletonAvatar;
29
+ Button: typeof SkeletonButton;
30
+ Input: typeof SkeletonInput;
31
+ Node: typeof SkeletonNode;
32
+ Image: typeof SkeletonImage;
33
+ Article: typeof SkeletonArticle;
34
+ };
4
35
  interface SkeletonRowsProps {
5
36
  rows?: number;
6
37
  columns?: number;
@@ -14,4 +45,3 @@ export declare function SkeletonTable({ rows, columns }: SkeletonRowsProps): Rea
14
45
  export declare function SkeletonDetail(): React.JSX.Element;
15
46
  /** Skeleton matching a stat card / dashboard tile. */
16
47
  export declare function SkeletonStat(): React.JSX.Element;
17
- export {};
@@ -1,17 +1,162 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { ImageIcon } from "lucide-react";
2
3
  import { cn } from "../../lib/utils.js";
3
4
  import { tableCellPaddingClass, tableRowHeightClass } from "../../lib/control-styles.js";
4
- function Skeleton({ className, ...props }) {
5
+ function measureStyle(width) {
6
+ if (width === void 0) return void 0;
7
+ const value = typeof width === "number" ? `${width}px` : width;
8
+ return { "--skeleton-line-width": value };
9
+ }
10
+ function SkeletonBlock({ active, loading, className, children, ...props }) {
11
+ if (loading === false) return /* @__PURE__ */ jsx(Fragment, { children });
5
12
  return /* @__PURE__ */ jsx(
6
13
  "div",
7
14
  {
8
15
  "aria-busy": "true",
9
16
  "aria-live": "polite",
17
+ "data-active": active ? "" : void 0,
10
18
  className: cn("ui-skeleton-block", className),
11
- ...props
19
+ ...props,
20
+ children
21
+ }
22
+ );
23
+ }
24
+ function SkeletonElement({
25
+ kind,
26
+ size,
27
+ shape,
28
+ block,
29
+ active,
30
+ className,
31
+ children
32
+ }) {
33
+ return /* @__PURE__ */ jsx(
34
+ SkeletonBlock,
35
+ {
36
+ active,
37
+ "data-skeleton-element": kind,
38
+ "data-size": size,
39
+ "data-shape": shape,
40
+ "data-block": block ? "" : void 0,
41
+ className,
42
+ children
43
+ }
44
+ );
45
+ }
46
+ function SkeletonAvatar({ size, shape = "circle", active, className }) {
47
+ return /* @__PURE__ */ jsx(
48
+ SkeletonElement,
49
+ {
50
+ kind: "avatar",
51
+ size,
52
+ shape,
53
+ active,
54
+ className
55
+ }
56
+ );
57
+ }
58
+ function SkeletonButton({ size, shape, block, active, className }) {
59
+ return /* @__PURE__ */ jsx(
60
+ SkeletonElement,
61
+ {
62
+ kind: "button",
63
+ size,
64
+ shape,
65
+ block,
66
+ active,
67
+ className
68
+ }
69
+ );
70
+ }
71
+ function SkeletonInput({ size, block, active, className }) {
72
+ return /* @__PURE__ */ jsx(SkeletonElement, { kind: "input", size, block, active, className });
73
+ }
74
+ function SkeletonNode({ active, children, className }) {
75
+ return /* @__PURE__ */ jsx(SkeletonElement, { kind: "node", active, className, children });
76
+ }
77
+ function SkeletonImage({ active, className }) {
78
+ return /* @__PURE__ */ jsx(SkeletonElement, { kind: "image", active, className, children: /* @__PURE__ */ jsx(ImageIcon, { "aria-hidden": "true", focusable: "false", className: "ui-skeleton-image-glyph" }) });
79
+ }
80
+ function avatarDefaults(hasTitle, hasParagraph) {
81
+ if (hasTitle && !hasParagraph) return { size: "lg", shape: "square" };
82
+ return { size: "lg", shape: "circle" };
83
+ }
84
+ function titleDefaultWidth(hasAvatar, hasParagraph) {
85
+ if (!hasAvatar && hasParagraph) return "38%";
86
+ if (hasAvatar && hasParagraph) return "50%";
87
+ return void 0;
88
+ }
89
+ function paragraphDefaults(hasAvatar, hasTitle) {
90
+ return {
91
+ rows: !hasAvatar && hasTitle ? 3 : 2,
92
+ width: !hasAvatar || !hasTitle ? "61%" : void 0
93
+ };
94
+ }
95
+ function rowWidth(index, rows, width) {
96
+ if (Array.isArray(width)) return width[index];
97
+ return rows - 1 === index ? width : void 0;
98
+ }
99
+ function SkeletonArticle({
100
+ avatar = false,
101
+ title = true,
102
+ paragraph = true,
103
+ round,
104
+ active,
105
+ loading,
106
+ children,
107
+ className
108
+ }) {
109
+ if (loading === false) return /* @__PURE__ */ jsx(Fragment, { children });
110
+ const hasAvatar = Boolean(avatar);
111
+ const hasTitle = Boolean(title);
112
+ const hasParagraph = Boolean(paragraph);
113
+ const avatarProps = {
114
+ ...avatarDefaults(hasTitle, hasParagraph),
115
+ ...typeof avatar === "object" ? avatar : {}
116
+ };
117
+ const titleWidth = (typeof title === "object" ? title.width : void 0) ?? titleDefaultWidth(hasAvatar, hasParagraph);
118
+ const paragraphBase = paragraphDefaults(hasAvatar, hasTitle);
119
+ const paragraphProps = typeof paragraph === "object" ? paragraph : {};
120
+ const rows = paragraphProps.rows ?? paragraphBase.rows;
121
+ const paragraphWidth = paragraphProps.width ?? paragraphBase.width;
122
+ return /* @__PURE__ */ jsxs(
123
+ "div",
124
+ {
125
+ "aria-busy": "true",
126
+ "data-slot": "skeleton-article",
127
+ "data-avatar": hasAvatar ? "" : void 0,
128
+ "data-active": active ? "" : void 0,
129
+ "data-round": round ? "" : void 0,
130
+ className: cn("ui-skeleton-article", className),
131
+ children: [
132
+ hasAvatar ? /* @__PURE__ */ jsx("div", { className: "ui-skeleton-article-header", children: /* @__PURE__ */ jsx(SkeletonAvatar, { ...avatarProps }) }) : null,
133
+ hasTitle || hasParagraph ? /* @__PURE__ */ jsxs("div", { className: "ui-skeleton-article-section", children: [
134
+ hasTitle ? /* @__PURE__ */ jsx(SkeletonBlock, { className: "ui-skeleton-article-title", style: measureStyle(titleWidth) }) : null,
135
+ hasParagraph ? (
136
+ // Deliberately divs, not antd's <ul><li>: its rows carry no text, so a real list would
137
+ // announce "list, 3 items" out of an already `aria-busy` region.
138
+ /* @__PURE__ */ jsx("div", { className: "ui-skeleton-article-paragraph", children: Array.from({ length: rows }).map((_, index) => /* @__PURE__ */ jsx(
139
+ SkeletonBlock,
140
+ {
141
+ className: "ui-skeleton-article-line",
142
+ style: measureStyle(rowWidth(index, rows, paragraphWidth))
143
+ },
144
+ index
145
+ )) })
146
+ ) : null
147
+ ] }) : null
148
+ ]
12
149
  }
13
150
  );
14
151
  }
152
+ const Skeleton = Object.assign(SkeletonBlock, {
153
+ Avatar: SkeletonAvatar,
154
+ Button: SkeletonButton,
155
+ Input: SkeletonInput,
156
+ Node: SkeletonNode,
157
+ Image: SkeletonImage,
158
+ Article: SkeletonArticle
159
+ });
15
160
  function SkeletonRows({ rows = 6, columns = 4, className }) {
16
161
  return /* @__PURE__ */ jsx("div", { className: cn("ui-skeleton-rows", className), "aria-busy": "true", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsx("div", { className: "ui-skeleton-row", children: Array.from({ length: columns }).map((_2, j) => /* @__PURE__ */ jsx(
17
162
  Skeleton,
@@ -56,7 +201,13 @@ function SkeletonStat() {
56
201
  }
57
202
  export {
58
203
  Skeleton,
204
+ SkeletonArticle,
205
+ SkeletonAvatar,
206
+ SkeletonButton,
59
207
  SkeletonDetail,
208
+ SkeletonImage,
209
+ SkeletonInput,
210
+ SkeletonNode,
60
211
  SkeletonRows,
61
212
  SkeletonStat,
62
213
  SkeletonTable
@@ -1,3 +1,3 @@
1
1
  import type { FlexProp } from "../../props/components/layout.prop.js";
2
2
  export type { FlexAlignProp, FlexDirectionProp, FlexJustifyProp, FlexProp, FlexProp as FlexProps, } from "../../props/components/layout.prop.js";
3
- export declare function Flex({ as: Element, direction, grow, shrink, surface, bleed, reveal, gap, gapRaw, pad, padRaw, align, justify, wrap, hideBelow, hideFrom, fill, width, className, style, children, ...props }: FlexProp): import("react").JSX.Element;
3
+ export declare function Flex({ as: Element, direction, grow, shrink, surface, bleed, reveal, gap, gapRaw, pad, padRaw, align, justify, wrap, hideBelow, hideFrom, hideBelowRaw, hideFromRaw, fill, width, className, style, children, ...props }: FlexProp): import("react").JSX.Element;
@@ -1,9 +1,11 @@
1
1
  "use client";
2
- import { jsx } from "react/jsx-runtime";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { mergeAriaIds } from "../../lib/field-a11y.js";
4
4
  import { cn } from "../../lib/utils.js";
5
5
  import { flexGapClass, padStyle, padStepToken } from "../../lib/variants.js";
6
6
  const toCssLength = (value) => typeof value === "number" ? `${value}px` : value;
7
+ const rawBreakpoint = (value) => typeof value === "number" && Number.isFinite(value) ? value : void 0;
8
+ const rawBreakpointRule = (axis, px) => `@media (width ${axis === "below" ? "<" : ">="} ${px}px){.ui-flex[data-hide-${axis}-raw="${px}"]{display:none}}`;
7
9
  function Flex({
8
10
  as: Element = "div",
9
11
  direction = "row",
@@ -21,6 +23,8 @@ function Flex({
21
23
  wrap = false,
22
24
  hideBelow,
23
25
  hideFrom,
26
+ hideBelowRaw,
27
+ hideFromRaw,
24
28
  fill = false,
25
29
  width,
26
30
  className,
@@ -42,6 +46,8 @@ function Flex({
42
46
  "aria-describedby": mergeAriaIds(props["aria-describedby"], ariaErrorMessage)
43
47
  };
44
48
  }
49
+ const belowRaw = rawBreakpoint(hideBelowRaw);
50
+ const fromRaw = rawBreakpoint(hideFromRaw);
45
51
  const responsive = typeof direction === "object";
46
52
  const axes = responsive ? direction : { base: direction };
47
53
  const cssDirection = (axis) => axis === "col" ? "column" : axis;
@@ -51,7 +57,7 @@ function Flex({
51
57
  cssDirection(axis)
52
58
  ])
53
59
  ) : {};
54
- return /* @__PURE__ */ jsx(
60
+ return /* @__PURE__ */ jsxs(
55
61
  Element,
56
62
  {
57
63
  "data-direction": responsive ? "responsive" : direction,
@@ -63,8 +69,10 @@ function Flex({
63
69
  "data-align": align,
64
70
  "data-justify": justify,
65
71
  "data-wrap": wrap ? "true" : void 0,
66
- "data-hide-below": hideBelow,
67
- "data-hide-from": hideFrom,
72
+ "data-hide-below": belowRaw === void 0 ? hideBelow : void 0,
73
+ "data-hide-from": fromRaw === void 0 ? hideFrom : void 0,
74
+ "data-hide-below-raw": belowRaw,
75
+ "data-hide-from-raw": fromRaw,
68
76
  "data-fill": fill ? "" : void 0,
69
77
  "data-width-raw": width === void 0 ? void 0 : "",
70
78
  "data-gap-raw": gapRaw,
@@ -79,7 +87,11 @@ function Flex({
79
87
  ...padStyle(pad, padRaw)
80
88
  },
81
89
  ...domProps,
82
- children
90
+ children: [
91
+ belowRaw === void 0 ? null : /* @__PURE__ */ jsx("style", { href: `ui-flex-hide-below-raw-${belowRaw}`, precedence: "ui-flex-raw-breakpoint", children: rawBreakpointRule("below", belowRaw) }),
92
+ fromRaw === void 0 ? null : /* @__PURE__ */ jsx("style", { href: `ui-flex-hide-from-raw-${fromRaw}`, precedence: "ui-flex-raw-breakpoint", children: rawBreakpointRule("from", fromRaw) }),
93
+ children
94
+ ]
83
95
  }
84
96
  );
85
97
  }
@@ -27,6 +27,11 @@ function SidebarSection({
27
27
  function SidebarIcon({ icon: Icon }) {
28
28
  return /* @__PURE__ */ jsx("span", { className: "sb-icon", children: Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) : null });
29
29
  }
30
+ function SidebarTrailingIcon({
31
+ icon: Icon
32
+ }) {
33
+ return /* @__PURE__ */ jsx("span", { className: "sb-trailing-icon", children: /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) });
34
+ }
30
35
  function SidebarRowContent({
31
36
  item,
32
37
  sub = false,
@@ -48,7 +53,8 @@ function SidebarRowContent({
48
53
  children: item.badge
49
54
  }
50
55
  )
51
- ) : null
56
+ ) : null,
57
+ item.trailingIcon ? /* @__PURE__ */ jsx(SidebarTrailingIcon, { icon: item.trailingIcon }) : null
52
58
  ] });
53
59
  }
54
60
  function SidebarItem({
@@ -305,6 +311,7 @@ function Sidebar({
305
311
  const surface = useNavSurface();
306
312
  collapsed = surface === "drawer" ? false : collapsed;
307
313
  const brandNode = typeof brand === "function" ? brand(collapsed) : brand;
314
+ const footerNode = typeof footer === "function" ? footer(collapsed) : footer;
308
315
  return /* @__PURE__ */ jsxs("div", { className: "sb-root", "data-collapsed": collapsed ? "true" : void 0, children: [
309
316
  brand !== void 0 ? /* @__PURE__ */ jsx(SidebarHeader, { children: brandNode }) : product ? (() => {
310
317
  const interactive = onProductClick != null;
@@ -385,7 +392,7 @@ function Sidebar({
385
392
  ))
386
393
  }
387
394
  ),
388
- footer ? /* @__PURE__ */ jsx("div", { className: "sb-footer", children: footer }) : null
395
+ footerNode ? /* @__PURE__ */ jsx("div", { className: "sb-footer", children: footerNode }) : null
389
396
  ] });
390
397
  }
391
398
  export {
@@ -96,7 +96,8 @@ function Toolbar({
96
96
  defaultValue: filter.defaultSelected,
97
97
  onValueChange: (selected) => filter.onSelectedChange?.(selected),
98
98
  placeholder: filter.placeholder,
99
- disabled: disabled || filter.disabled
99
+ disabled: disabled || filter.disabled,
100
+ clearLabel: typeof filter.label === "string" ? t("navigation.filterBar.clearFilter", { label: filter.label }) : void 0
100
101
  }
101
102
  )
102
103
  },
@@ -47,6 +47,33 @@ export declare function useKeepActiveTabVisible(listRef: React.RefObject<HTMLEle
47
47
  * it are the ones that hand it real geometry.
48
48
  */
49
49
  export declare function resolveHiddenTabValues(list: HTMLElement, values: readonly string[]): string[];
50
+ /**
51
+ * The LOGICAL scroll offset of a strip: how far it has moved from its own start edge, growing
52
+ * towards `end` on whichever axis the strip is on and in whichever direction it is written.
53
+ *
54
+ * `scrollLeft` cannot be read raw. Per CSSOM-View an RTL scroller reports `0` at its START edge
55
+ * (the right one) and goes NEGATIVE towards the end, so "scrollLeft went up" means opposite things
56
+ * in the two directions — exactly the bug `start`/`end` exist to prevent, and it would have been
57
+ * invisible in an LTR test suite.
58
+ */
59
+ export declare function readTabsScrollOffset(list: HTMLElement, vertical: boolean): number;
60
+ /**
61
+ * Ant Design `onTabScroll`'s one piece of logic: which edge a movement of the scroll offset went
62
+ * towards. `null` when the offset did not move, so a scroll event that reports the same position
63
+ * (momentum settling, a programmatic re-pin that was already in place) reports nothing.
64
+ */
65
+ export declare function resolveTabsScrollDirection(previous: number, next: number): "start" | "end" | null;
66
+ /**
67
+ * Reports every real movement of the strip's own scrollport to `onScroll` — Ant Design
68
+ * `onTabScroll`. The handler is held in a ref so a consumer's inline arrow function does not
69
+ * re-arm the listener on every render (same contract as `useTabsOverflowValues` above).
70
+ *
71
+ * It reports a `scrollIntoView` re-pin too, and deliberately: antd's does the same, and "the strip
72
+ * moved" is the fact a consumer is subscribing to — not "the user moved it".
73
+ */
74
+ export declare function useTabsScrollReporter(listRef: React.RefObject<HTMLElement | null>, vertical: boolean, onScroll: ((info: {
75
+ direction: "start" | "end";
76
+ }) => void) | undefined): void;
50
77
  /**
51
78
  * Keeps `onChange` fed with the values currently out of the scrollport, recomputing on the two
52
79
  * things that can move them: the strip resizing (a viewport change, a font swap, a tab added or
@@ -78,6 +78,38 @@ function resolveHiddenTabValues(list, values) {
78
78
  });
79
79
  return hidden;
80
80
  }
81
+ function readTabsScrollOffset(list, vertical) {
82
+ if (vertical) return list.scrollTop;
83
+ const rtl = list.ownerDocument?.defaultView?.getComputedStyle(list).direction === "rtl" || list.closest("[dir]")?.getAttribute("dir") === "rtl";
84
+ return rtl ? -list.scrollLeft : list.scrollLeft;
85
+ }
86
+ function resolveTabsScrollDirection(previous, next) {
87
+ if (next === previous) return null;
88
+ return next > previous ? "end" : "start";
89
+ }
90
+ function useTabsScrollReporter(listRef, vertical, onScroll) {
91
+ const onScrollRef = React.useRef(onScroll);
92
+ React.useEffect(() => {
93
+ onScrollRef.current = onScroll;
94
+ });
95
+ const armed = onScroll !== void 0;
96
+ React.useEffect(() => {
97
+ if (!armed) return void 0;
98
+ const list = listRef.current;
99
+ if (!list) return void 0;
100
+ let last = readTabsScrollOffset(list, vertical);
101
+ const report = () => {
102
+ const next = readTabsScrollOffset(list, vertical);
103
+ const direction = resolveTabsScrollDirection(last, next);
104
+ last = next;
105
+ if (direction) onScrollRef.current?.({ direction });
106
+ };
107
+ list.addEventListener("scroll", report, { passive: true });
108
+ return () => {
109
+ list.removeEventListener("scroll", report);
110
+ };
111
+ }, [armed, listRef, vertical]);
112
+ }
81
113
  function useTabsOverflowValues(listRef, values, onChange) {
82
114
  const onChangeRef = React.useRef(onChange);
83
115
  React.useEffect(() => {
@@ -119,9 +151,12 @@ function useTabsOverflowValues(listRef, values, onChange) {
119
151
  export {
120
152
  isTabFullyVisible,
121
153
  prefersReducedMotion,
154
+ readTabsScrollOffset,
122
155
  resolveHiddenTabValues,
123
156
  resolveTabScrollTarget,
157
+ resolveTabsScrollDirection,
124
158
  syncActiveTabIntoView,
125
159
  useKeepActiveTabVisible,
126
- useTabsOverflowValues
160
+ useTabsOverflowValues,
161
+ useTabsScrollReporter
127
162
  };
@@ -1,6 +1,6 @@
1
1
  import * as React from "react";
2
2
  import type { TabItemProp, TabsProp } from "../../props/components/navigation.prop.js";
3
- export type { TabItemProp, TabsProp, TabsVariantProp, TabsPlacementProp, TabsExtraProp, TabsOverflowProp, } from "../../props/components/navigation.prop.js";
3
+ export type { TabItemProp, TabsProp, TabsVariantProp, TabsPlacementProp, TabsExtraProp, TabsOverflowProp, TabsAnimatedProp, TabsIndicatorProp, TabsIndicatorSizeProp, TabsScrollDirectionProp, TabsOnScrollProp, } from "../../props/components/navigation.prop.js";
4
4
  export type TabsOrientation = "vertical" | "horizontal";
5
5
  export type TabsItem = TabItemProp;
6
6
  export type TabsProps = Omit<React.ComponentPropsWithoutRef<"div">, "defaultValue" | "dir"> & TabsProp & {
@@ -8,7 +8,7 @@ export type TabsProps = Omit<React.ComponentPropsWithoutRef<"div">, "defaultValu
8
8
  dir?: "ltr" | "rtl";
9
9
  activationMode?: "manual" | "automatic";
10
10
  };
11
- export declare function Tabs({ className, orientation, items, value, defaultValue, onValueChange, activationMode, dir, variant, tabPlacement, size, centered, extra, destroyOnHidden, onEdit, addIcon, hideAdd, closeIcon, onTabClick, overflow, listClassName, contentClassName, children, ...props }: TabsProps): React.JSX.Element;
11
+ export declare function Tabs({ className, orientation, items, value, defaultValue, onValueChange, activationMode, dir, variant, tabPlacement, size, centered, extra, destroyOnHidden, onEdit, addIcon, hideAdd, closeIcon, onTabClick, overflow, animated, indicator, moreIcon, onTabScroll, listClassName, contentClassName, children, ...props }: TabsProps): React.JSX.Element;
12
12
  export declare const TabsList: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
13
13
  variant?: "default" | "line";
14
14
  /**